Alert

Highlights information, warnings or errors inline, with context and a clear next action.

import { Alert } from "@usefragments/ui";Source

Preview

import { Alert } from '@usefragments/ui';

<Alert tone="info">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Content>

Usage

Use when

  • Flagging a risk before the user hits it
  • A failure the user must fix, said where it happened
  • Standing information that must stay on screen

Avoid when

  • A one-word status or a pass verdict (use Badge)
  • A confirmation that should fade away (use Toast)
  • An invalid field (use the Input error prop)
  • A decision the user must make first (use Dialog)
  • A neutral note with no state (use Text or Box)

Implementation notes

  • Match tone to real stakes; an error that is not an error trains people to ignore you
  • There is no success tone: a pass goes to a Badge verdict and a confirmation to Toast
  • Every danger alert says what to do next
  • Add Alert.Title only when the message needs two lines
  • At most two actions; Alert.Action is a small soft Button and they wrap under the copy
  • Only dismissible when losing the message costs nothing; use open and onOpenChange to bring it back
  • Alert.Action and Alert.Close default to type="button", so they are safe inside a form
  • Alert.Close runs your onClick and still respects preventDefault()

Installation

pnpm add @usefragments/ui

The npm package stays managed by your package manager. Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Anatomy

Import Alert once, then compose its parts with dot notation.

  • Alert.Icon
  • Alert.Body
  • Alert.Title
  • Alert.Content
  • Alert.Actions
  • Alert.Action
  • Alert.Close

Neutral context — nothing went wrong, nothing needs doing.

import { Alert } from '@usefragments/ui';

<Alert tone="info">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Content>
      Your session will expire in 15 minutes. Save your work to avoid losing changes.
    </Alert.Content>
  </Alert.Body>
</Alert>

Examples

Warning

Nothing is broken yet — act before it is.

import { Alert } from '@usefragments/ui';

<Alert tone="warning">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Title>Storage almost full</Alert.Title>

Error

Something failed; say what to do about it.

import { Alert } from '@usefragments/ui';

<Alert tone="danger">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Title>Upload failed</Alert.Title>

With Action

One small soft button; a second verb wraps beside it, never more.

import { Alert } from '@usefragments/ui';

<Alert tone="warning">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Title>Update available</Alert.Title>

Dismissible

A close button suits news the user can safely ignore.

import { Alert } from '@usefragments/ui';

<Alert tone="info">
  <Alert.Icon />
  <Alert.Body>
    <Alert.Content>

Controlled

open and onOpenChange let the page bring a dismissed alert back.

import { Alert } from '@usefragments/ui';

const [open, setOpen] = React.useState(true);

<Alert tone="info" open={open} onOpenChange={setOpen}>
  <Alert.Icon />

API reference

Component props
Prop
Type
Default
Description
Action.childrenReact.ReactNodeNot setThe label. Optional only so a Button can be the `render` element of a trigger (`<Dialog.Trigger render={<Button />}>Open</Dialog.Trigger>`), where the trigger's children become the label.
Action.focusableWhenDisabledboolean | undefinedNot setKeep a disabled button in the tab order (`aria-disabled` instead of `disabled`), so keyboard and screen reader users can still reach it and read why it is unavailable.
Action.fullWidthboolean | undefinedNot setFill the parent's width. Without it a button is as wide as its label in every parent, a column stack or a grid cell included.
Action.nativeButtonboolean | undefinedNot setWhether the rendered element is a native `<button>`. Inferred from an element passed to `render` (a `<button>`, or a component without `href`); pass it when `render` is a function or a component that renders an anchor without an `href` prop.
Action.pendingboolean | undefinedNot setWork started by this button is running. The button sets `aria-busy` and ignores further presses at once; after a second (`--fui-pending-delay`) its label fades and a spinner takes its place, and its width holds.
Action.renderuseRender.RenderProp<Record<string, unknown>> | undefinedNot setReplace the rendered element, e.g. `render={<a href="/docs" />}` or a router link. A rendered anchor keeps its link semantics (no button role); the button's look, pending and disabled behaviour move onto it.
Actions.childrenRequiredReact.ReactNodeNot set—
Body.childrenRequiredReact.ReactNodeNot set—
childrenRequiredReact.ReactNodeNot setAlert content - use Alert.Icon, Alert.Body, Alert.Title, Alert.Content, Alert.Actions, Alert.Close sub-components
Close.childrenReact.ReactNodeNot setA replacement glyph. Defaults to a cross.
Close.defaultPressedboolean | undefinedNot setInitial pressed state of an uncontrolled toggle.
Close.nativeButtonboolean | undefinedNot setWhether the rendered element is a native `<button>`. Inferred from an element passed to `render` (a `<button>`, or a component without `href`).
Close.onPressedChange((pressed: boolean) => void) | undefinedNot setCalled with the next pressed state when the toggle is pressed.
Close.pendingboolean | undefinedNot setWork started by this button is running: `aria-busy`, presses ignored, and after a second the icon gives way to a spinner.
Close.pressedboolean | undefinedNot setControlled pressed state. Passing `pressed`, `defaultPressed` or `onPressedChange` makes the button a toggle: it sets `aria-pressed` and paints the selection wash and ring while pressed.
Close.renderuseRender.RenderProp<Record<string, unknown>> | undefinedNot setReplace the rendered element, e.g. `render={<a href="/settings" />}` or a router link. A rendered anchor keeps its link semantics (no button role); the look, pending and disabled behaviour move onto it.
Close.valuestring | undefinedNot setForm value of the button, or the toggle's value inside a group.
Content.childrenRequiredReact.ReactNodeNot set—
Icon.childrenReact.ReactNodeNot setA replacement glyph. Defaults to the tone's icon.
onOpenChange((open: boolean) => void) | undefinedNot setCalled with false when Alert.Close is pressed
openboolean | undefinedNot setControlled visibility. Leave unset and the alert hides itself once Alert.Close is pressed.
Title.childrenRequiredReact.ReactNodeNot set—
toneAlertTone | undefinedinfowarningdangerinfoTone; sets the tint fill, the icon, the title ink and the live-region role

Accessibility

  • role="alert" (warning, danger) means assistive tech announces it on arrival; info uses role="status"
  • aria-labelledby and aria-describedby point only at a Title and Content that render
  • Alert.Close is labelled "Dismiss alert" unless you pass your own aria-label
  • Icon plus wording carry the tone, never colour alone
  • BadgealternativeUse Badge for compact, inline status labels
  • ToastalternativeUse Toast for transient notifications that auto-dismiss
  • DialogsiblingUse Dialog for blocking confirmations

Next steps