TrendCard
A headline number with its change, a period control and a comparison chart, on Card's surface. Figma's Revenue card is one example of it. Every region is an element slot.
Import
import { TrendCard } from '@nizivo/react/trend-card';
// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css and @nizivo/react/css/card.css and @nizivo/react/css/delta.css and @nizivo/react/css/inline-error.css and @nizivo/react/css/metric.css and @nizivo/react/css/number-value.css and @nizivo/react/css/skeleton.css
import '@nizivo/react/css/trend-card.css';Static or interactive
Server. It ships no client JavaScript when a Server Component renders it, in every Next.js build
mode; its code is bundled only when a client component (a 'use client' file) imports it. Its slots render what you pass: a client Select in action ships its own code, and an
AreaChart in chart ships the charts island. How to
choose.
In a client app (a Vite or React Router single-page app, or a 'use client' file) it is an ordinary React component: event handlers, refs and state work as usual. In a client app.
Tones
tone is Card's. On brand and accent the headline's Delta pill is bg/surface so it shows on
the tint, and the card declares --nz-surface for the chart to read
(Card).
Examples
Basic
The Revenue Card recipe (Figma 7275:13818): a docs example, not an export.
import type { JSX } from 'react';
import { NativeSelect } from '@nizivo/react/native-select';
import { TrendCard } from '@nizivo/react/trend-card';
/**
* Stand-ins for `<AreaChart … />` and `<Legend … />` from @nizivo/charts, which @nizivo/react never
* imports: any element fits the slots.
*/
function Plot(): JSX.Element {
return (
<svg viewBox="0 0 720 280" width="100%" aria-hidden="true">
<path
d="M0 220 L80 190 L160 205 L240 150 L320 165 L400 120 L480 130 L560 80 L640 95 L720 60"
fill="none"
stroke="currentColor"
strokeWidth="2"
/>
<path
d="M0 235 L80 225 L160 228 L240 200 L320 210 L400 185 L480 190 L560 160 L640 170 L720 150"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeDasharray="5 4"
opacity="0.5"
/>
</svg>
);
}
export function TrendCardExample(): JSX.Element {
return (
<TrendCard
label="Total sales"
value={123307.4}
format={{ style: 'currency', currency: 'USD', minimumFractionDigits: 2 }}
delta={0.182}
action={
<NativeSelect aria-label="Period" defaultValue="30d" size="md">
<option value="7d">Last 7 days</option>
<option value="30d">Last 30 days</option>
<option value="90d">Last 90 days</option>
</NativeSelect>
}
chart={<Plot />}
legend={
<>
<span>Oct 1 – Oct 30</span>
<span>Sep 1 – Sep 30</span>
</>
}
/>
);
}
Loading
Loading: the same card; the chart takes the same status in an app (ChartFrame keeps its box).
import type { JSX } from 'react';
import { TrendCard } from '@nizivo/react/trend-card';
/**
* Stand-ins for `<AreaChart … />` and `<Legend … />` from @nizivo/charts, which @nizivo/react never
* imports: any element fits the slots.
*/
function Plot(): JSX.Element {
return (
<svg viewBox="0 0 720 280" width="100%" aria-hidden="true">
<path
d="M0 220 L80 190 L160 205 L240 150 L320 165 L400 120 L480 130 L560 80 L640 95 L720 60"
fill="none"
stroke="currentColor"
strokeWidth="2"
/>
<path
d="M0 235 L80 225 L160 228 L240 200 L320 210 L400 185 L480 190 L560 160 L640 170 L720 150"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeDasharray="5 4"
opacity="0.5"
/>
</svg>
);
}
export function TrendCardLoadingExample(): JSX.Element {
return <TrendCard label="Total sales" status="loading" chart={<Plot />} />;
}
Props
A headline number with its change, a period control and a comparison chart. A role="group" named by the label. The status contract (§16.5) applies to the headline; the slots render as given.
Server component Renders data-slot="trend-card" with the class nz-trend-card. Props: TrendCardProps. Source: src/trend-card/trend-card.tsx.
| Name | Type | Default | Description |
|---|---|---|---|
action | ReactNode | – | The control at the end of the header, for example the period |
chart | ReactNode | – | The chart, for example |
comparison | ReactNode | – | Visible text after the delta, for example "vs last week". From |
delta | number | ReactElement | – | The change. A number renders From |
empty | ReactNode | – | Replaces the "—" of the empty state. From |
error | ReactNode | – | Replaces the InlineError of the error state, for example one with a Retry From |
footer | ReactNode | – | A last row, for example a link to the report. |
format | Intl.NumberFormatOptions | {} |
From |
labelrequired | ReactNode | – | The name of the number, for example "Total sales". Also names the status texts. From |
labels | Partial<MetricLabels> | – | From |
legend | ReactNode | – | The legend under the chart, for example |
locale | string | 'en-US' | BCP 47 tag for the value and a numeric From |
pending | boolean | – | A refresh is in flight while the value shows: From |
render | RenderProp<TrendCardState> | – | |
status | DataStatus"ready""loading""empty""error" | 'ready' | §16.5 lifecycle. From |
tone | CardTone"surface""subtle""inverse""brand""accent" | 'surface' | Card's tone; |
value | number | null | – | The number. From |
- Also takes every attribute of
<div>exceptchildren. (Omit<ComponentPropsWithRef<"div">, "children">)
render takes an element, or, in client code, a function of the props and this state (TrendCardState):
| Name | Type | Default | Description |
|---|---|---|---|
pendingrequired | boolean | – | |
statusrequired | DataStatus"ready""loading""empty""error" | – | The status as rendered: |
tonerequired | CardTone"surface""subtle""inverse""brand""accent" | – |
Other exports
TrendCardPropstypeimport type { TrendCardProps } from '@nizivo/react/trend-card'The props of
TrendCard, listed above.TrendCardStatetypeimport type { TrendCardState } from '@nizivo/react/trend-card'The render state of
TrendCard, listed above.
Data attributes and slots
Style parts by class (.nz-<slot>) and state by data attribute. Attribute meanings come from contracts/vocabulary.json.
| Slot | Rendered by | Data attributes |
|---|---|---|
trend-card.nz-trend-card | TrendCardroot (takes render) |
|
trend-card-action.nz-trend-card-action | TrendCardinner element (CSS only) | none |
trend-card-chart.nz-trend-card-chart | TrendCardinner element (CSS only) | none |
trend-card-footer.nz-trend-card-footer | TrendCardinner element (CSS only) | none |
trend-card-header.nz-trend-card-header | TrendCardinner element (CSS only) | none |
trend-card-legend.nz-trend-card-legend | TrendCardinner element (CSS only) | none |
CSS hooks
Set a hook on the component's class or any ancestor to restyle it without specificity games; leave it unset for the default shown.
| Hook | Default | Read as |
|---|---|---|
--nz-trend-card-gap | --nz-space-6 |
|
Layers: nz.components. Classes: .nz-card, .nz-metric, .nz-metric-value-row, .nz-trend-card, .nz-trend-card-action, .nz-trend-card-chart, .nz-trend-card-footer, .nz-trend-card-header, .nz-trend-card-legend.
Tokens this stylesheet reads (7)
--nz-font-numeric-display-font-size, --nz-font-numeric-display-line-height, --nz-space-2, --nz-space-3, --nz-space-4, --nz-space-5, --nz-space-6
Accessibility
Nothing in this component takes focus or keyboard input.
Keyboard
None.
Figma
Node ids from design/component-map.json, which nz gen writes from component.json. The links open the Nizivo Figma library, which may ask you to sign in.
- Canonical: Figma node
752:385 - Ghost masters: none
TopBar
The bar above the page on screens 640 px and wider, with the page's name or a Breadcrumb at the start, the search, then notifications and the account.
Dashboard
The dashboard parts of @nizivo/react: NumberValue, Metric, KpiTile, TrendCard, RankedList and CountUp. Server Components with one small client part, one loading, empty and error contract, and charts through element slots.