MeterGroup displays scalar measurements within a known range.
import { MeterGroup } from 'primereact/metergroup';
<MeterGroup>
<MeterGroup.Meters>
<MeterGroup.Meter value={value} color={color} />
</MeterGroup.Meters>
<MeterGroup.Labels>
<MeterGroup.Label>
<MeterGroup.Marker color={color} />
<MeterGroup.Text>Value</MeterGroup.Text>
</MeterGroup.Label>
</MeterGroup.Labels>
</MeterGroup>
MeterGroup
consists of MeterGroup.Meters
and MeterGroup.Labels
components. Data is displayed in the MeterGroup.Meter
component using the value
and color
properties.
import { MeterGroup } from 'primereact/metergroup';
export default function BasicDemo() {
const value = { label: 'Space used', value: 15, color: 'var(--p-primary-color)' };
return (
<div className="card">
<MeterGroup>
<MeterGroup.Meters>
<MeterGroup.Meter value={value.value} color={value.color} />
</MeterGroup.Meters>
<MeterGroup.Labels>
<MeterGroup.Label>
<MeterGroup.Marker color={value.color} />
<MeterGroup.Text>
{value.label} ({value.value}%)
</MeterGroup.Text>
</MeterGroup.Label>
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
Adding more MeterGroup.Meter
components displays the meters in a group. Pass index
to MeterGroup.Meter
and MeterGroup.Marker
to identify the meter's and label's position to get the color.
import { MeterGroup } from 'primereact/metergroup';
export default function MultipleDemo() {
const values = [
{ label: 'Apps', value: 14 },
{ label: 'Messages', value: 12 },
{ label: 'Media', value: 8 },
{ label: 'System', value: 12 },
{ label: 'Documents', value: 6 },
{ label: 'Cache', value: 11 },
{ label: 'Other', value: 9 }
];
return (
<div className="card">
<MeterGroup>
<MeterGroup.Meters>
{values.map((item, index) => (
<MeterGroup.Meter key={`meter_${index}`} index={index} value={item.value} />
))}
</MeterGroup.Meters>
<MeterGroup.Labels>
{values.map((item, index) => (
<MeterGroup.Label key={`label_${index}`}>
<MeterGroup.Marker index={index} />
<MeterGroup.Text>
{item.label} ({item.value}%)
</MeterGroup.Text>
</MeterGroup.Label>
))}
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
MeterGroup.Meter
and MeterGroup.Marker
components supports custom color values. Use color
property or pass color with className or style. color
has custom color names like blue
, emerald
, violet
, amber
, etc. or hex, rgb, hsl, or hsla values.
import { MeterGroup } from 'primereact/metergroup';
export default function ColorDemo() {
return (
<div className="card">
<MeterGroup>
<MeterGroup.Meters>
<MeterGroup.Meter value={12} color="violet" />
<MeterGroup.Meter value={14} color="#10B981" />
<MeterGroup.Meter value={10} color="rgb(244, 63, 94)" />
<MeterGroup.Meter value={8} className="bg-blue-500" />
<MeterGroup.Meter value={10} style={{ backgroundColor: '#EAB308' }} />
</MeterGroup.Meters>
<MeterGroup.Labels>
<MeterGroup.Label>
<MeterGroup.Marker color="violet" />
<MeterGroup.Text>Violet</MeterGroup.Text>
</MeterGroup.Label>
<MeterGroup.Label>
<MeterGroup.Marker color="#10B981" />
<MeterGroup.Text>Emerald</MeterGroup.Text>
</MeterGroup.Label>
<MeterGroup.Label>
<MeterGroup.Marker color="rgb(244, 63, 94)" />
<MeterGroup.Text>Rose</MeterGroup.Text>
</MeterGroup.Label>
<MeterGroup.Label>
<MeterGroup.Marker className="bg-blue-500" />
<MeterGroup.Text>Blue</MeterGroup.Text>
</MeterGroup.Label>
<MeterGroup.Label>
<MeterGroup.Marker style={{ backgroundColor: '#EAB308' }} />
<MeterGroup.Text>Yellow</MeterGroup.Text>
</MeterGroup.Label>
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
Icons can be displayed next to the labels instead of the default MeterGroup.Marker
.
import { MeterGroup } from 'primereact/metergroup';
export default function IconDemo() {
const values = [
{ label: 'Apps', value: 16, icon: 'pi pi-table' },
{ label: 'Messages', value: 8, icon: 'pi pi-inbox' },
{ label: 'Media', value: 24, icon: 'pi pi-image' },
{ label: 'System', value: 10, icon: 'pi pi-cog' }
];
return (
<div className="card">
<MeterGroup>
<MeterGroup.Meters>
{values.map(({ value }, index) => (
<MeterGroup.Meter key={`meter_${index}`} value={value} index={index} />
))}
</MeterGroup.Meters>
<MeterGroup.Labels>
{values.map(({ value, label, icon }, index) => (
<MeterGroup.Label key={`label_${index}`}>
<MeterGroup.Icon className={icon} index={index} />
<MeterGroup.Text>
{label} ({value}%)
</MeterGroup.Text>
</MeterGroup.Label>
))}
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
The default orientation of the labels is horizontal, and the vertical alternative is available through the orientation
option.
import { MeterGroup } from 'primereact/metergroup';
export default function LabelDemo() {
const values = [
{ label: 'Apps', value: 16, icon: 'pi pi-table' },
{ label: 'Messages', value: 8, icon: 'pi pi-inbox' },
{ label: 'Media', value: 24, icon: 'pi pi-image' },
{ label: 'System', value: 10, icon: 'pi pi-cog' }
];
return (
<div className="card">
<MeterGroup>
<MeterGroup.Labels orientation="vertical">
{values.map((item, index) => (
<MeterGroup.Label key={`label_${index}`}>
<MeterGroup.Marker index={index} />
<MeterGroup.Text>
{item.label} ({item.value}%)
</MeterGroup.Text>
</MeterGroup.Label>
))}
</MeterGroup.Labels>
<MeterGroup.Meters>
{values.map((item, index) => (
<MeterGroup.Meter key={`meter_${index}`} value={item.value} index={index} />
))}
</MeterGroup.Meters>
</MeterGroup>
</div>
);
}
Layout of the MeterGroup is configured with the orientation
property that accepts either horizontal
or vertical
as available options.
import { MeterGroup } from 'primereact/metergroup';
export default function VerticalDemo() {
const values = [
{ label: 'Apps', value: 24 },
{ label: 'Messages', value: 16 },
{ label: 'Media', value: 24 },
{ label: 'System', value: 12 }
];
return (
<div className="card flex justify-center" style={{ height: '360px' }}>
<MeterGroup orientation="vertical">
<MeterGroup.Meters>
{values.map((item, index) => (
<MeterGroup.Meter key={index} value={item.value} index={index} />
))}
</MeterGroup.Meters>
<MeterGroup.Labels orientation="vertical">
{values.map((item, index) => (
<MeterGroup.Label key={`label_${index}`}>
<MeterGroup.Marker index={index} />
<MeterGroup.Text>
{item.label} ({item.value}%)
</MeterGroup.Text>
</MeterGroup.Label>
))}
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
Boundaries are configured with the min
and max
values whose defaults are 0 and 100 respectively.
import { MeterGroup } from 'primereact/metergroup';
export default function MinMaxDemo() {
const values = [
{ label: 'Apps', value: 16 },
{ label: 'Messages', value: 8 },
{ label: 'Media', value: 24 },
{ label: 'System', value: 10 }
];
const percent = (meter: number) => {
return Math.round(Math.max(0, Math.min(100, (meter / 200) * 100))) + '%';
};
return (
<div className="card">
<MeterGroup max={200}>
<MeterGroup.Meters>
{values.map((item, index) => (
<MeterGroup.Meter key={`meter_${index}`} value={item.value} index={index} />
))}
</MeterGroup.Meters>
<MeterGroup.Labels>
{values.map((item, index) => (
<MeterGroup.Label key={`label_${index}`}>
<MeterGroup.Marker index={index} />
<MeterGroup.Text>
{item.label} ({percent(item.value)})
</MeterGroup.Text>
</MeterGroup.Label>
))}
</MeterGroup.Labels>
</MeterGroup>
</div>
);
}
MeterGroup provides templating support for labels, meter items, and content around the meters.
import { MeterGroup } from 'primereact/metergroup';
export default function TemplateDemo() {
const values = [
{ label: 'Apps', color1: '#34d399', color2: '#fbbf24', value: 25, icon: 'pi pi-table' },
{ label: 'Messages', color1: '#fbbf24', color2: '#60a5fa', value: 15, icon: 'pi pi-inbox' },
{ label: 'Media', color1: '#60a5fa', color2: '#c084fc', value: 20, icon: 'pi pi-image' },
{ label: 'System', color1: '#c084fc', color2: '#c084fc', value: 10, icon: 'pi pi-cog' }
];
const totalPercent = values.reduce((acc, value) => acc + value.value, 0);
const percent = (meter: number) => {
return Math.round(Math.max(0, Math.min(100, (meter / 100) * 100))) + '%';
};
return (
<div className="card">
<MeterGroup max={200} aria-valuenow={totalPercent}>
<MeterGroup.Labels>
{values.map((value, index) => (
<MeterGroup.Label key={`label_${index}`}>
{/* <Card className="flex-1 border border-surface shadow-none">
<div className="flex justify-between gap-8">
<div className="flex flex-col gap-1">
<span className="text-surface-500 dark:text-surface-400 text-sm">{value.label}</span>
<span className="font-bold text-lg">{value.value}%</span>
</div>
<span className="w-8 h-8 rounded-full inline-flex justify-center items-center text-center" style={{ backgroundColor: `${value.color1}`, color: '#ffffff' }}>
<i className={value.icon} />
</span>
</div>
</Card> */}
</MeterGroup.Label>
))}
</MeterGroup.Labels>
<div className="flex justify-between mt-4 mb-2 relative">
<span>Storage</span>
<span style={{ width: totalPercent + '%' }} className="absolute text-right">
{totalPercent}%
</span>
<span className="font-medium">1TB</span>
</div>
<MeterGroup.Meters>
{values.map((item, index) => (
<MeterGroup.Meter
key={`meter_${index}`}
value={item.value}
style={{
background: `linear-gradient(to right, ${item.color1}, ${item.color2})`,
width: percent(item.value)
}}
></MeterGroup.Meter>
))}
</MeterGroup.Meters>
{/* <div className="flex justify-between mt-4">
<Button label="Manage Storage" outlined size="small" />
<Button label="Update Plan" size="small" />
</div> */}
</MeterGroup>
</div>
);
}
MeterGroup component uses meter role in addition to the aria-valuemin, aria-valuemax and aria-valuenow attributes. Value to describe the component can be defined using aria-labelledby prop.
Component does not include any interactive elements.