MeterGroup

MeterGroup displays scalar measurements within a known range.

Usage#

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>

Examples#

Basic#

MeterGroup consists of MeterGroup.Meters and MeterGroup.Labels components. Data is displayed in the MeterGroup.Meter component using the value and color properties.

  1. Space used (15%)
basic-demo.tsx
'use client';

import { MeterGroup } from 'primereact/metergroup';

export default function BasicDemo() {
    const value = { label: 'Space used', value: 15, color: 'var(--p-primary-color)' };

    return (
        <div>
            <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>
    );
}

Multiple#

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.

  1. Apps (14%)
  2. Messages (12%)
  3. Media (8%)
  4. System (12%)
  5. Documents (6%)
  6. Cache (11%)
  7. Other (9%)
multiple-demo.tsx
'use client';

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>
            <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>
    );
}

Color#

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.

  1. Violet
  2. Emerald
  3. Rose
  4. Blue
  5. Yellow
color-demo.tsx
'use client';

import { MeterGroup } from 'primereact/metergroup';

export default function ColorDemo() {
    return (
        <div>
            <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>
    );
}

Icon#

Icons can be displayed next to the labels instead of the default MeterGroup.Marker.

  1. Apps (16%)
  2. Messages (8%)
  3. Media (24%)
  4. System (10%)
icon-demo.tsx
'use client';

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>
            <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>
    );
}

Label#

The default orientation of the labels is horizontal, and the vertical alternative is available through the orientation option.

  1. Apps (16%)
  2. Messages (8%)
  3. Media (24%)
  4. System (10%)
label-demo.tsx
'use client';

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>
            <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>
    );
}

Vertical#

Layout of the MeterGroup is configured with the orientation property that accepts either horizontal or vertical as available options.

  1. Apps (24%)
  2. Messages (16%)
  3. Media (24%)
  4. System (12%)
vertical-demo.tsx
'use client';

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="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>
    );
}

Min-Max#

Boundaries are configured with the min and max values whose defaults are 0 and 100 respectively.

  1. Apps (8%)
  2. Messages (4%)
  3. Media (12%)
  4. System (5%)
minmax-demo.tsx
'use client';

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>
            <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>
    );
}

Template#

MeterGroup provides templating support for labels, meter items, and content around the meters.

Storage70%1TB
template-demo.tsx
'use client';

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>
            <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>
    );
}

Accessibility#

Screen Reader#

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.

Keyboard Support#

Component does not include any interactive elements.