Skip to content

Rankings & breakdowns

How a total splits and what ranks first: rings and bars, waterfalls, cause rings, budgets, forecasts and plan against actual.

Installation & usage

npx @youj/cli add app-breakdown

Also installs alert, button, card, empty, icon-chevron-right, skeleton, stat-card, use-announcer, use-controllable-state, youj-core, youj-presets, youj-ui-core.

The CLI copies the block to blocks/app/breakdown.tsx with every component it uses, so it’s yours to edit.

Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:

breakdown-view.tsx
'use client'

import { Breakdown, type BreakdownProps } from '@/blocks/app/breakdown'

export function BreakdownView({ items, path }: Pick<BreakdownProps, 'items' | 'path'>) {
  return (
    <Breakdown
      items={items}
      path={path}
      copy={{ title: 'Revenue by region' }}
      onPathChange={(path) => {
        // your code
      }}
      onItemSelect={(item, path) => {
        // your code
      }}
      onRetry={() => {
        // your code
      }}
    />
  )
}

Reference

Props17 props

Props

Breakdown props
PropType
themeThemeInput

Wraps the card in this theme. Default: the theme around it.

–
embeddedboolean

Inside another app: a section named by an h2, without the page around the card.

default true

true
fillboolean

Take the whole width it's given instead of stopping at its natural width (672px at 100% scale).

default false

false
headingLevel1 | 2 | 3

The title's level. Default: 2 when embedded, else 1.

–
copyPartial<BreakdownCopy>

Any of the card's strings, to rewrite or translate.

–
localestring

Formats every figure (BCP 47). Default: copy.locale, else the app's locale (YoujProvider), else en-US.

–
itemsItem[]

The parts of the total, each with its own children to drill into. Default: the demo's revenue by region, country and plan.

–
topnumber

How many parts a level shows before the rest fold into Other.

default 5

5
formatIntl.NumberFormatOptions

Intl.NumberFormat options for every figure. Default: compact US dollars to three digits with the demo's data, else compact numbers.

–
pathstring[]

The level shown, as the ids from the top down (other for a folded rest), controlled: pair it with onPathChange.

–
defaultPathstring[]

The level shown first, uncontrolled.

default []

[]
onPathChange(path: string[]) => void

Called with the path after a zoom in or out.

–
onItemSelect(item: BreakdownItem, path: string[]) => void

A last-level part is pressed (it has no parts to open). Default: those parts aren't buttons.

–
loadingboolean

Skeletons in place of the ring and the list while your data loads.

default false

false
errorReactNode

Shown in place of the breakdown when it fails to load, with Retry when onRetry is set. Default: none.

–
onRetry() => void

Retries after an error. Default: none.

–
emptyReactNode

Replaces the message when there's nothing to split. Default: copy.empty and copy.emptyDescription.

–
Strings19 keys for copy

Strings

copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.

titledescriptionallothertotallistpathitemdrillshareupdownversusopenedloadingretryemptyemptyDescriptionlocale
Built from6 components
Accessibilityimages, tables, switches, motion

Accessibility

Each chart has a name and a one-sentence summary, and the metric chart's numbers are also in a real table behind View data. Wherever you can scrub a chart (the KPI tiles and the metric chart), it is a slider: Left and Right step a bucket, Home and End jump to either end, Escape lets go, and each position is read out as a sentence with the date, the figures and the change. The tile and chart headers update with it.

Loss waterfall draws the isometric bars as an image whose text gives the start, every loss with its figure and the result left. The legend repeats every loss as a button (aria-pressed) that moves the callout, and the drill-in row is a button named by its title.

Cause rings draws the donut as an image whose text lists every cause with its figure and share, and the legend repeats it as buttons (aria-pressed) that light a cause and list where its share came from. Patterns and a hairline edge carry the meaning, never color alone.

The forecast chart is an image with a text alternative and a summary, the scenario switch is labelled, and each series row has a hidden sentence of spent against projected. Limit tracker's rules are switches.

Plan vs actual lists its rows in order of size; each bar is a named group described by its total, the projected part and the plan, and its months are a list one tab stop deep, each read with its amount and whether it is projected. Over and under plan are said in the head's badge and with signed amounts, not by color alone, and the facts are a description list.

Estimate builder names its billing switch, region picker and preset switch. The bar is a meter whose value text names every line with its share, and the key repeats them as a list that is one tab stop walked with the arrow keys. Each line is a slider named by the line and spoken in its unit ("60 GB / day"); the ruler's ticks are decorative. A new preset or billing period announces the new total in a polite live region.

Lollipop ranking filters with status tabs (each counting its items), a labelled search and a group select. The table is named, its value column has aria-sort and sorts from its header button, and each item's name is a button pressed while it is picked; owners are spoken by name, and each trend is an image named for its item. The index is a listbox, one tab stop walked with the arrows, its options named with the item and its value and aria-selected when picked; the picked item's line above it is a polite live region. Statuses are signed amounts and words as well as inks.

Each card is a section named by its title. Under reduced motion the figures, bars, the fan and its particles are drawn in place.