---
title: 'Stat'
description: 'Composable metric components for highlighted values, trends, and labels.'
version: 11.0.0
generatedAt: 2026-04-21T13:57:52.931Z
checksum: 9f97f348797f3f7f76bb39e17f84fe34b688885bf4e9e471db5c2085ddc3c0a1
---

# Stat

## Import

```tsx
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.Root` renders a definition list (`dl`).
  - `Stat.Label` renders descriptive text with dedicated typography and color for metric context (`dt`).

  - `Stat.Content` renders the main value as a definition description (`dd`).

- `Stat.Number` is the base value formatter built on the [NumberFormat](/uilib/components/number-format/) formatting logic.

- `Stat.Currency` and `Stat.Percent` are convenience wrappers around `Stat.Number`.
  - It adds typography-specific properties such as `fontSize`, `fontWeight` and `colorizeBySign`, along with `mainSize` and `auxiliarySize` as well as `mainWeight` and `auxiliaryWeight` that can be used to customize the visual emphasis of the different parts of the value (currency symbol or percent sign).

- `Stat.Trend` renders explicit `+` / `-` indicators with red/green background states and screen-reader text.

- `Stat.Rating` renders a star rating (defaults to 5 stars) and colorizes stars based on `value`. The `max` prop is clamped to `20` to prevent excessive DOM output; a console warning is emitted when the limit is exceeded.

- `Stat.Info` renders supporting text with a smaller, muted style.

- `Stat.Inline` is a horizontal layout container for grouping content elements like `Stat.Trend` and `Stat.Info` side by side with consistent spacing and alignment.

- `Stat.Text` renders custom content and supports properties such as `fontSize`, `fontWeight`, and `colorizeBySign`.

## Accessibility

- `Stat.Root` provides semantic definition-list markup (`dl`), where `Stat.Label` is rendered as `dt` and `Stat.Content` as `dd`.

- If the label also acts as a section heading, use a heading element inside `Stat.Label` (for example `H3`) to preserve a meaningful heading outline.

- Use `srLabel` to prepend context in the screen-reader text only, for example turning `1,234 kr` into `Revenue 1,234 kr` for 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`, and `Trend` use a dedicated screen-reader value (`.dnb-sr-only`) based on the formatted content. `Rating` uses an accessible label (`role="img"` + `aria-label`) that includes value and max.

## Relevant links

- [Source code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-eufemia/src/components/stat)
- [Docs code](https://github.com/dnbexperience/eufemia/tree/main/packages/dnb-design-system-portal/src/docs/uilib/components/stat)

## Demos

### Basic usage

```tsx
render(
  <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`).

```tsx
render(
  <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.

```tsx
render(
  <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.

```tsx
render(
  <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

```tsx
render(
  <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

```tsx
render(
  <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

```tsx
render(
  <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

```tsx
render(
  <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

```tsx
render(
  <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

```tsx
render(
  <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.

```tsx
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](/uilib/components/aria-live/) component to announce dynamic value updates to screen readers. Wrap `Stat.Root` with `AriaLive` so that changes are announced when the content updates.

```tsx
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"
        onClick={() => setValue((prev) => prev + 100)}
      />
    </Flex.Stack>
  )
}
render(<Example />)
```

## Stat.Currency

<PropertiesTable props={CurrencyProperties} />

## Stat.Percent

<PropertiesTable props={PercentProperties} />

## Stat.Number

<PropertiesTable props={NumberProperties} />

## Stat.Trend

<PropertiesTable props={TrendProperties} />

## Stat.Rating

<PropertiesTable props={RatingProperties} />

## Stat.Info

<PropertiesTable props={InfoProperties} />

## Stat.Root

<PropertiesTable props={RootProperties} />

## Stat.Label

<PropertiesTable props={LabelProperties} />

## Stat.Content

<PropertiesTable props={ContentProperties} />

## Stat.Inline

```json
{
  "props": {
    "children": {
      "doc": "Inline layout container for content elements, typically `Stat.Trend` and `Stat.Info`.",
      "type": ["React.ReactNode"],
      "status": "optional"
    },
    "skeleton": {
      "doc": "Applies skeleton state to the inline container.",
      "type": "boolean",
      "status": "optional"
    },
    "[Flex.Horizontal](/uilib/layout/flex/horizontal/properties)": {
      "doc": "Supports all additional `Flex.Horizontal` properties.",
      "type": "Various",
      "status": "optional"
    }
  }
}
```

## Stat.Text

<PropertiesTable props={TextProperties} />

## Translations

```json
{
  "locales": ["da-DK", "en-GB", "nb-NO", "sv-SE"],
  "entries": {
    "Stat.rating": {
      "nb-NO": "%value av %max",
      "en-GB": "%value of %max",
      "sv-SE": "%value av %max",
      "da-DK": "%value af %max"
    }
  }
}
```
