Alert
A tinted message with a title, an optional action and an optional dismiss button. Static and server-rendered unless you add the dismiss leaf.
Import
import { Alert, AlertDismiss } from '@nizivo/react/alert';
// Once per app (Getting started), after
// @nizivo/tokens/tokens.css and @nizivo/react/css/base.css and @nizivo/react/css/icon-button.css
import '@nizivo/react/css/alert.css';Static or interactive
Split. An Alert ships one client module, the AlertDismiss leaf, only when you pass it in
dismiss (+1,490 B gzip under Turbopack on the Next.js fixture's /alert-dismiss page). The shell
does not import the leaf, so an Alert without dismiss ships nothing in every build mode. 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.
The dismiss button
Pass an AlertDismiss in dismiss. With no render it is an IconButton (tertiary, sm) showing
the close glyph, named "Dismiss", so it looks, sizes, focuses and responds like every other icon
button. Change the name with labels, or pass aria-label; children replace the glyph.
<Alert
tone="critical"
role="alert"
title="Payment failed for order #1040"
dismiss={<AlertDismiss onDismiss={dismissPaymentAlert} labels={{ dismiss: 'Fermer' }} />}
>
Card was declined.
</Alert>onDismiss is called with no arguments, so a Server Component can pass a Server Action. The Alert
does not hide itself: the caller stops rendering it. An Alert without a dismiss ships no client
JavaScript; AlertDismiss is its only client module.
Its glyph is 16 px and sits where Figma draws the close glyph: 16 px from the inline-end edge and
centred on the title's line. The 32 px button reaches into the padding around it, so the row is no
taller. It has no tooltip, like Dialog.Close: its name is read by assistive technology, and a
tooltip would add the Tooltip code to every page that shows a dismissible alert. Its markup is
IconButton's, so a page that imports per-component stylesheets needs css/icon-button.css too (the
stylesheets list above names it; styles.css already has it).
With render, it is your element. A plain element keeps its own look; an IconButton keeps its
variant and size and takes the slot's placement, which is made for sm. To add a tooltip, compose
one: render={<IconButton icon={<X />} label="Dismiss" variant="tertiary" size="sm" />}.
--nz-alert-dismiss-fg still sets the glyph colour (default --nz-icon-secondary).
Examples
Basic
Server-rendered and static: no live role, no dismiss, no client JS.
import type { JSX } from 'react';
import { Alert } from '@nizivo/react/alert';
/** Stand-ins for `@nizivo/icons` glyphs. */
function Mark(): JSX.Element {
return (
<svg viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor">
<circle cx="12" cy="12" r="9" />
</svg>
);
}
export function AlertExample(): JSX.Element {
return (
<Alert icon={<Mark />} title="Payouts move to daily on Nov 1">
No action needed.
</Alert>
);
}
Dismissible
Injected after a payment attempt, so it is announced. Dismissal is the caller's state: pass onDismiss from a client component, or a Server Action from a Server Component.
import type { JSX } from 'react';
import { Button } from '@nizivo/react/button';
import { Alert, AlertDismiss } from '@nizivo/react/alert';
/** Stand-ins for `@nizivo/icons` glyphs. */
function Mark(): JSX.Element {
return (
<svg viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor">
<circle cx="12" cy="12" r="9" />
</svg>
);
}
function Cross(): JSX.Element {
return (
<svg viewBox="0 0 24 24" width="1em" height="1em" fill="none" stroke="currentColor">
<path d="M7 7l10 10M17 7 7 17" />
</svg>
);
}
export function AlertDismissibleExample({ onDismiss }: { onDismiss?: () => void }): JSX.Element {
return (
<Alert
tone="critical"
role="alert"
icon={<Mark />}
title="Payment failed for order #1040"
action={<Button size="sm">Retry payment</Button>}
dismiss={
<AlertDismiss {...(onDismiss && { onDismiss })}>
<Cross />
</AlertDismiss>
}
>
Card was declined.
</Alert>
);
}
Props
Alert
Server component Renders data-slot="alert" with the class nz-alert. Props: AlertProps. Source: src/alert/alert.tsx.
| Name | Type | Default | Description |
|---|---|---|---|
action | ReactNode | – | Controls under the text, for example |
dismiss | ReactNode | – |
|
icon | ReactNode | – | Decorative tone glyph, for example |
render | RenderProp<AlertState> | – | |
role | ComponentPropsWithRef<"div">["role"] | – | There is no live role by default: an alert present on page load must not interrupt. Pass |
title | ReactNode | – | One line, Label/M Strong. The description is |
tone | AlertTone"info""success""warning""critical" | 'info' |
- Also takes every attribute of
<div>excepttitle;roleis redeclared above. (Omit<ComponentPropsWithRef<"div">, "title">)
render takes an element, or, in client code, a function of the props and this state (AlertState):
| Name | Type | Default | Description |
|---|---|---|---|
tonerequired | AlertTone"info""success""warning""critical" | – |
AlertDismiss
With no render, an IconButton (tertiary, sm: the 16 px glyph Figma draws, in a 32 px target) with no tooltip, as Dialog.Close does.
Client component Renders data-slot="alert-dismiss" with the class nz-alert-dismiss. Props: AlertDismissProps. Source: src/alert/alert-dismiss.client.tsx.
| Name | Type | Default | Description |
|---|---|---|---|
children | ReactNode | – | The close glyph, decorative. Defaults to the internal |
labels | Partial<AlertDismissLabels> | – | |
onDismiss | () => void | – | Called with no arguments, so a Server Component can pass a Server Action. The Alert does not hide itself: the caller stops rendering it. |
render | RenderProp<Record<string, never>> | – | Your element in place of the default IconButton; it must render a |
- Also takes every attribute of
<button>exceptchildren. (Omit<ComponentPropsWithRef<"button">, "children">)
render takes an element, or, in client code, a function of the props and no state.
Other exports
AlertDismissLabelstypeimport type { AlertDismissLabels } from '@nizivo/react/alert'Strings this part renders (§16.4).
Name Type Default Description dismissrequiredstring'Dismiss'The button's accessible name.
AlertDismissPropstypeimport type { AlertDismissProps } from '@nizivo/react/alert'The props of
AlertDismiss, listed above.AlertPropstypeimport type { AlertProps } from '@nizivo/react/alert'The props of
Alert, listed above.AlertStatetypeimport type { AlertState } from '@nizivo/react/alert'The render state of
Alert, listed above.AlertTonetypeimport type { AlertTone } from '@nizivo/react/alert'Figma "Tone".
type AlertTone = "info" | "success" | "warning" | "critical"
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 |
|---|---|---|
alert.nz-alert | Alertroot (takes render) |
|
alert-action.nz-alert-action | Alertinner element (CSS only) | none |
alert-content.nz-alert-content | Alertinner element (CSS only) | none |
alert-description.nz-alert-description | Alertinner element (CSS only) | none |
alert-dismiss.nz-alert-dismiss | AlertDismissroot (takes render); interactive, focus: self | none |
alert-icon.nz-alert-icon | Alertinner element (CSS only) | none |
alert-title.nz-alert-title | Alertinner element (CSS only) | none |
icon-button-icon.nz-icon-button-icon | AlertDismissinner 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-alert-bg |
|
|
--nz-alert-description-font | --nz-font-body-m |
|
--nz-alert-dismiss-fg | --nz-icon-secondary |
|
--nz-alert-gap | --nz-space-3 |
|
--nz-alert-icon-fg |
|
|
--nz-alert-padding-block | --nz-space-3 |
|
--nz-alert-padding-inline | --nz-space-4 |
|
--nz-alert-radius | --nz-radius-lg |
|
--nz-alert-title-font | --nz-font-label-m-strong |
|
Layers: nz.components. Classes: .nz-alert, .nz-alert-action, .nz-alert-content, .nz-alert-description, .nz-alert-dismiss, .nz-alert-icon, .nz-alert-title, .nz-icon-button.
Tokens this stylesheet reads (21)
--nz-bg-critical-subtle, --nz-bg-info-subtle, --nz-bg-success-subtle, --nz-bg-warning-subtle, --nz-font-body-m, --nz-font-label-m-strong, --nz-icon-critical, --nz-icon-info, --nz-icon-secondary, --nz-icon-success, --nz-icon-warning, --nz-radius-lg, --nz-size-control-sm, --nz-size-icon-md, --nz-size-icon-sm, --nz-space-0-5, --nz-space-2, --nz-space-3, --nz-space-4, --nz-text-primary, --nz-text-secondary
Accessibility
These parts are interactive. Each gets the focus outline and touch-action rule from @nizivo/react/css/base.css (the nz.base layer), so the floor survives a restyle:
alert-dismiss: draws the focus outline itself on keyboard focus.
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves focus to the action, then to the dismiss button, in that order. The action is whatever you pass (the examples pass a Button); the dismiss control is a native button. |
| Enter, Space | Activates the focused button. The dismiss button calls onDismiss; the caller stops rendering the alert. |
Source: The Alert shell (alert.tsx) renders the action before the dismiss slot; AlertDismiss is a native <button type="button"> (alert-dismiss.client.tsx), and the Next fixture checks that it takes a click.
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
7275:15091 - Ghost masters: Figma node
756:868
Accordion
Sections that open and close under their headings, such as FAQs or a checkout's order summary. Each item is a native details element, so it works with no JavaScript, and items that share a name open one at a time.
AppShell
The page's frame. The Sidebar and the TopBar on screens 640 px and wider, the MobileTopBar and the MobileTabBar below that, around the page's main content, switched by CSS with no script.