Import
import { Stat } from '@dnb/eufemia'
Description
Stat contains components for prominent values with a label, where typography and visual emphasis are part of the component.
Available components
-
Stat.Rootrenders a definition list (dl).-
Stat.Labelrenders descriptive text with dedicated typography and color for metric context (dt). -
Stat.Contentrenders the main value as a definition description (dd).
-
-
Stat.Numberis the base value formatter built on the NumberFormat formatting logic. -
Stat.CurrencyandStat.Percentare convenience wrappers aroundStat.Number.- It adds typography-specific properties such as
fontSize,fontWeightandcolorizeBySign, along withmainSizeandauxiliarySizeas well asmainWeightandauxiliaryWeightthat can be used to customize the visual emphasis of the different parts of the value (currency symbol or percent sign).
- It adds typography-specific properties such as
-
Stat.Trendrenders explicit+/-indicators with red/green background states and screen-reader text. -
Stat.Ratingrenders a star rating (defaults to 5 stars) and colorizes stars based onvalue. Themaxprop is clamped to20to prevent excessive DOM output; a console warning is emitted when the limit is exceeded. -
Stat.Inforenders supporting text with a smaller, muted style. -
Stat.Inlineis a horizontal layout container for grouping content elements likeStat.TrendandStat.Infoside by side with consistent spacing and alignment. -
Stat.Textrenders custom content and supports properties such asfontSize,fontWeight, andcolorizeBySign.
Deprecated
Stat.Amountis deprecated and will be removed in a future version. UseStat.Numberinstead.
Accessibility
-
Stat.Rootprovides semantic definition-list markup (dl), whereStat.Labelis rendered asdtandStat.Contentasdd. -
If the label also acts as a section heading, use a heading element inside
Stat.Label(for exampleH3) to preserve a meaningful heading outline. -
Use
srLabelto prepend context in the screen-reader text only, for example turning1,234 krintoRevenue 1,234 krfor screen readers. -
When e.g.
signDisplay="always"is used, the sign is rendered as a separate visual element with CSS spacing, while the accessible text stays based on the formatted number string. -
All Stat variants keep dedicated accessibility handling.
Currency,Percent, andTrenduse a dedicated screen-reader value (.dnb-sr-only) based on the formatted content.Ratinguses an accessible label (role="img"+aria-label) that includes value and max.
Relevant links
Demos
Basic usage
- Revenue growth
- Some additional information.
<Stat.Root> <Stat.Label>Revenue growth</Stat.Label> <Stat.Content direction="vertical"> <Stat.Currency value={1234} signDisplay="always" /> <Stat.Trend srLabel="Change">+12.4%</Stat.Trend> <Stat.Info>Some additional information.</Stat.Info> </Stat.Content> </Stat.Root>
Root and Label
If the label acts as a section heading, place a heading element inside Stat.Label (for example H3).
Revenue growth
- Monthly change
- (some additional information)
<Stat.Root> <Stat.Label> <H3>Revenue growth</H3> </Stat.Label> <Stat.Content direction="vertical"> <Stat.Currency value={1234} mainSize="x-large" auxiliarySize="x-small" /> <Stat.Trend srLabel="Growth trend">+12.4%</Stat.Trend> </Stat.Content> <Stat.Label top>Monthly change</Stat.Label> <Stat.Content direction="vertical"> <Stat.Currency value={-1234} signDisplay="always" mainSize="x-large" auxiliarySize="x-small" /> <Stat.Inline> <Stat.Trend srLabel="Change trend">-2.1%</Stat.Trend> <Stat.Info>(some additional information)</Stat.Info> </Stat.Inline> </Stat.Content> </Stat.Root>
Hidden Label
Use a visually hidden label (srOnly) when the visible UI context already describes the statistic.
- I'm a hidden label
<Stat.Root> <Stat.Label srOnly>I'm a hidden label</Stat.Label> <Stat.Content> <Stat.Currency value={1234} /> </Stat.Content> </Stat.Root>
Currency
You can use mainSize and auxiliarySize to adjust the relative size of the currency symbol and the amount.
- Always show sign
- With suffix
- Colorized using
en-GBlocale
<Stat.Root> <Stat.Label>Always show sign</Stat.Label> <Stat.Content> <Stat.Currency value={1234} mainSize="x-large" signDisplay="always" auxiliarySize="x-small" /> </Stat.Content> <Stat.Label top>With suffix</Stat.Label> <Stat.Content> <Stat.Currency value={1234} currency="USD" suffix="/mnd" mainSize="x-large" auxiliarySize="x-small" /> </Stat.Content> <Stat.Label top> Colorized using <Code>en-GB</Code> locale </Stat.Label> <Stat.Content> <Stat.Currency value={-1234.5} decimals={2} currency="USD" signDisplay="always" fontSize="medium" colorizeBySign locale="en-GB" /> </Stat.Content> </Stat.Root>
Currency within a Trend
- ()
<Stat.Root> <Stat.Label> <DateFormat value="P1Y" /> </Stat.Label> <Stat.Content direction="vertical"> <Stat.Currency value={350234} srLabel="Annual revenue" /> <Stat.Inline> <Stat.Trend> <Stat.Currency value={46692} signDisplay="always" srLabel="Revenue delta" /> </Stat.Trend> <Stat.Info> ( <Stat.Percent value={16.79} decimals={2} srLabel="Relative change" /> ) </Stat.Info> </Stat.Inline> </Stat.Content> </Stat.Root>
Number
- Number
- Number in Trend and Info
- ()
<Stat.Root> <Stat.Label>Number</Stat.Label> <Stat.Content> <Stat.Number value={1234} signDisplay="always" mainSize="x-large" auxiliarySize="x-small" /> </Stat.Content> <Stat.Label top>Number in Trend and Info</Stat.Label> <Stat.Content> <Stat.Trend tone="negative" srLabel="Negative trend"> <Stat.Number value={-1234} signDisplay="always" /> </Stat.Trend> <Stat.Info> ( <Stat.Number value={1234} srLabel="Signed amount with currency" />) </Stat.Info> </Stat.Content> </Stat.Root>
Percent
- Percentage
- Percentage colorized
<Stat.Root> <Stat.Label>Percentage</Stat.Label> <Stat.Content> <Stat.Percent value={12.3} mainSize="x-large" auxiliarySize="x-small" /> </Stat.Content> <Stat.Label top>Percentage colorized</Stat.Label> <Stat.Content> <Stat.Percent value={0.1234} decimals={2} signDisplay="always" fontSize="medium" colorizeBySign /> </Stat.Content> </Stat.Root>
Percent colorized by sign
- Positive without signDisplay
- Negative without signDisplay
- Zero without signDisplay
<Stat.Root> <Stat.Label>Positive without signDisplay</Stat.Label> <Stat.Content> <Stat.Percent value={12.3} fontSize="medium" colorizeBySign /> </Stat.Content> <Stat.Label top>Negative without signDisplay</Stat.Label> <Stat.Content> <Stat.Percent value={-12.3} fontSize="medium" colorizeBySign /> </Stat.Content> <Stat.Label top>Zero without signDisplay</Stat.Label> <Stat.Content> <Stat.Percent value={0} fontSize="medium" colorizeBySign /> </Stat.Content> </Stat.Root>
Rating
- Stars rating
- Progressive rating
<Stat.Root> <Stat.Label>Stars rating</Stat.Label> <Stat.Content> <Stat.Rating value={4} /> </Stat.Content> <Stat.Label top>Progressive rating</Stat.Label> <Stat.Content direction="vertical"> <Stat.Rating variant="progressive" value={5} /> </Stat.Content> </Stat.Root>
Text
- Label
- Custom content
- With medium font weight and size
- Larger and bolder
<Stat.Root> <Stat.Label>Label</Stat.Label> <Stat.Content> <Stat.Text colorizeBySign={-123}>Custom content</Stat.Text> </Stat.Content> <Stat.Label top>With medium font weight and size</Stat.Label> <Stat.Content> <Stat.Text srLabel="Screen reader label" colorizeBySign={123} fontWeight="medium" fontSize="medium" > Larger and bolder </Stat.Text> </Stat.Content> </Stat.Root>
With Subtle Label
Also, the order of the content and label can be switched for visual users (not screen readers), and the label is styled with the subtle variant to further de-emphasize it.
- Yearly cost
- Risiko
- Lav
- Stars rating
- 2 av 5
function Example() { const { rating } = useTranslation().Stat return ( <Grid.Container rowGap columnGap style={{ gridAutoRows: '1fr', }} > <Grid.Item span={{ small: [1, 12], medium: [1, 12], large: [1, 3], }} > <Card style={{ height: '100%', }} > <Stat.Root visualOrder="content-label"> <Stat.Label variant="subtle"> <DateFormat value="P1Y" /> </Stat.Label> <Stat.Content direction="vertical"> <IconPrimary icon="arrow_up" top="x-small" /> <Stat.Percent top="small" value={5.21} decimals={2} fontSize="basis" srLabel="Revenue growth percentage" /> </Stat.Content> </Stat.Root> </Card> </Grid.Item> <Grid.Item span={{ small: [1, 12], medium: [1, 12], large: [4, 6], }} > <Card style={{ height: '100%', }} > <Stat.Root visualOrder="content-label"> <Stat.Label variant="subtle">Yearly cost</Stat.Label> <Stat.Content direction="vertical"> <Icon icon={globe_medium} /> <Stat.Percent top="small" value={0.6} decimals={1} fontSize="basis" /> </Stat.Content> </Stat.Root> </Card> </Grid.Item> <Grid.Item span={{ small: [1, 12], medium: [1, 12], large: [7, 9], }} > <Card style={{ height: '100%', }} > <Stat.Root visualOrder="content-label"> <Stat.Label variant="subtle">Risiko</Stat.Label> <Stat.Content direction="vertical"> <Stat.Rating variant="progressive" value={2} /> <Stat.Info top variant="prominent"> Lav </Stat.Info> </Stat.Content> </Stat.Root> </Card> </Grid.Item> <Grid.Item span={{ small: [1, 12], medium: [1, 12], large: [10, 12], }} > <Card style={{ height: '100%', }} > <Stat.Root visualOrder="content-label"> <Stat.Label variant="subtle">Stars rating</Stat.Label> <Stat.Content direction="vertical"> <Stat.Rating value={2} /> <Stat.Info top variant="prominent"> {rating.replace('%value', '2').replace('%max', '5')} </Stat.Info> </Stat.Content> </Stat.Root> </Card> </Grid.Item> </Grid.Container> ) } render(<Example />)
With AriaLive
Use the AriaLive component to announce dynamic value updates to screen readers. Wrap Stat.Root with AriaLive so that changes are announced when the content updates.
- Revenue
function Example() { const [value, setValue] = React.useState(1234) return ( <Flex.Stack> <AriaLive variant="content"> <Stat.Root> <Stat.Label>Revenue</Stat.Label> <Stat.Content> <Stat.Currency value={value} /> </Stat.Content> </Stat.Root> </AriaLive> <Button text="Update value" variant="secondary" on_click={() => setValue((prev) => prev + 100)} /> </Flex.Stack> ) } render(<Example />)