组件 · 反馈
Banner
A soft-tinted notice inside a dialog or form that people read before they act, and, as PanelNotice, a full-width strip under a panel header when something in that panel failed.
import { Banner } from "@botiverse/raft-ui";A banner is a short notice that people need to read before they act: who can see a shared channel, what a delete removes, a limit they are about to reach, or that something saved. It sits inside the content of a dialog or a form, on a soft tint that says its intent. When something in one panel goes wrong, the same notice runs as a strip under the panel header instead; see Inside a panel.
When to use
The wider the scope of a message, the further out it goes; the full table is in Feedback.
| Situation | Use |
|---|---|
| One input is invalid | The input's error (Field), not a banner |
| Something to know before acting in a dialog or a form | Banner, in the content |
| Something in one panel failed: an agent won't start, a setting didn't save | PanelNotice, under the panel header (Panel) |
| The state of the whole server: a computer offline, a quota nearly full | NotificationCenter, not a banner at the top of the page |
| The result of something the person just did | Toast |
| The person must decide now | Dialog or AlertDialog |
Anatomy
Banner: the tinted container. Required. It fills the width it is given and lays out its parts by that width, so give it a width (or let it fill its parent); neverw-fit, which collapses it.- An icon: a Lucide icon as a direct child, before the text, or a
Statuslight in its place. Banner sizes the icon 20px with 10px before the text (16px and 8px in asmbanner), keeps a light at 9px, and centers either one on the first line (A mark that leads text). BannerTitle: an optional bold first line.BannerDescription: the message. Required. An inline text action goes inside it as aTextLink variant="strong", because it sits in a sentence (TextLink).BannerAction: the banner's button, and Dismiss before it when the banner has one. It sits at the bottom right: at the end of the last line of text, centered on that line, while the text fits beside it on one line. With a title and a description, that line is the description's. When the text would wrap beside it, or the banner is narrower than 480px, it takes a line of its own under the text, aligned to the end.BannerActiondecides this itself; don't place it. The width is a container query on the banner's content: 452px, which is a 480px banner atmd(476px atsm, 484px atlg).BannerClose: the × of a banner that has no button. A frameless icon button at the end of the first line, centered on it, whose icon box ends on the banner's padding, like a frameless icon button at the end of a header (Alignment). Its label defaults to "Dismiss". Don't use it withBannerAction: a banner with a button closes with Dismiss. If both are there, raft-ui warns in development and puts the actions on a line of their own, so they never share the ×'s place.
Variants
The status prop sets the tint. Each intent has one icon.
| Variant | Use for | Icon |
|---|---|---|
status="info" | Information and limits | Info |
status="warning" | Something to watch that can be recovered from, including errors | TriangleAlert |
status="destructive" | A consequence that cannot be undone, usually in a delete confirmation | OctagonAlert |
status="success" | Something finished or saved | CircleCheck |
Under 480px, as on every phone, the buttons go under the text, at the end:
A banner with no button closes with BannerClose:
- Use
status="warning"when something goes wrong;destructiveis only for consequences that cannot be undone (Color). - raft-ui also has a neutral
status="default"onfill-muted. The system's banners always state an intent, so prefer one of the four above.
Content
- Say what is happening now and what to do next (Writing, Feedback).
- Put the subject in
BannerTitleand the consequence inBannerDescription: "This channel is shared with Acme" / "People and agents from Acme will see what you post here." - Label the button with what it does, in Title Case: See Who, Retry, View Logs.
Accessibility
Bannerrenders adivwithrole="alert"forstatus="destructive"androle="status"for the other intents, so a notice that isn't urgent doesn't interrupt a screen reader.- The icon repeats the intent and is decorative. The title and description must say the intent in words.
BannerCloseis labelled "Dismiss"; pass anaria-labelthat names the notice when a page has more than one thing to dismiss.BannerClosedoesn't move focus. When the banner goes, the app moves focus to the next element after where the banner was, or to the page's heading when there is none; never leave it on the document.- Keep the parts in reading order: the icon, the title, the description with its link, then
BannerAction(Dismiss, then the button) orBannerClose. Tab reaches them in that order.
Rules
- Show at most one banner in one place.
- Give at most one button, plus Dismiss before it when the banner can be dismissed, and only when there is a way out: a 32px ink-bordered button (
variant="default" size="sm"). Never a pink button: a banner is not the screen's primary action. - Put the button in
BannerAction, at the bottom right, so it comes after what it acts on and ends where the eye ends, as a dialog's commit button does. A banner that can be dismissed and has a button puts Dismiss (variant="ghost" size="sm") just before the button, in the sameBannerAction. - Use
BannerCloseonly on a banner with no button, and never put a × inBannerAction, where it reads as one of the actions. - Don't add an ink border. A banner is a soft tint, not a sticker (Color); its edge is the container radius and a hairline.
Inside a panel
When something in one panel goes wrong (an agent won't start, the channel's settings didn't save), use PanelNotice from Panel, not a Banner. It is a region of the panel, not a card inside its content:
- Place it directly under the panel header, across the full width of the panel.
- Give it no radius and no hairline. It is closed by seams (
line-seam) above and below; the one above is the panel header's. - Line its sides up with the panel's margins (Spacing).
- Lead the text with a status pixel instead of an icon.
PanelNoticekeeps it at 9px and centers it on the first line, as it does an icon (A mark that leads text). - Write one message of at most 2 lines, in
PanelNoticeContent(semiboldtext-callout). - Put the actions in
PanelNoticeActions, on the right and centered on the first line of text: a small icon button (Copy Details) or a text button (View Logs). A 32px button doesn't make the strip taller. - Keep the default
status="warning"for something to fix; usedestructiveonly for what cannot be undone.
API
Banner
| Prop | 类型 | 默认值 |
|---|---|---|
| "sm" | "md" | "lg" | "md" | |
| "warning" | "default" | "success" | "info" | "destructive" | ||
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
BannerAction
| Prop | 类型 | 默认值 |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
BannerClose
| Prop | 类型 | 默认值 |
|---|---|---|
| boolean | ||
| string | ||
| Whether the button should be focusable when disabled. | boolean | false |
| Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (for example, `<div>`). | boolean | true |
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
BannerDescription, BannerTitle
| Prop | 类型 | 默认值 |
|---|---|---|
| Allows you to replace the component's HTML element with a different tag, or compose it with another component. | ReactElement | ((props, state) => ReactElement) |
Also takes the attributes of its element.
相关组件
改动
- 0.19.0 · Breaking ChangesBannerAction: the buttons sit at the bottom right, at the end of the last line of text and centered on it, while the text fits beside them on one line. When the text would wrap beside them, or the banner is narrower than 480px, they take a line of their own under the text, aligned to the end.
BannerActionplaces itself; it setsdata-wrapwhen it takes its own line. - 0.7.0 · Changed
Bannerrendersrole="status", androle="alert"only forstatus="destructive", so a notice that isn't urgent no longer interrupts a screen reader. Passroleto override. - 0.5.35 · Changed
Banner's action spans two rows only when it comes after both the title and the description; an action placed before them no longer spans. The status column now always spans two rows.