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.
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#
Related components#
Stat is part of the Content category. Other components for similar needs:
- Accordion — to let people open and close sections of related content.
- Avatar — to make a person, company, or profile easier to recognize.
- Card — to group related content in a clear, separated area.
- CountryFlag — to show a country by its flag from an ISO country code.
- DateFormat — to show dates in the correct DNB format.
- Heading — to create accessible page headings with the correct level.
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} locale="en-GB" /> <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] = 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" onClick={() => setValue((prev) => prev + 100)} /> </Flex.Stack> ) } render(<Example />)