{"slug":"banner","name":"Banner","packageName":"@liquidify/react","category":"presentational","maturity":"stable","summary":"A persistent, in-flow bar that surfaces a short status or notification without blocking the page: a status glyph, a title, an optional secondary message, an optional row of trailing actions, and an optional dismiss control.","importPath":"@liquidify/react/banner","sourcePath":"packages/@liquidify/react/src/components/banner/banner.tsx","specPath":"packages/@liquidify/react/src/components/banner/spec.md","docsPath":"../liquidify-page/content/component-source/banner.md","documentationStatus":"stable","storyIds":["presentational-banner--default"],"additionalExports":["BannerAction","BannerActionRole","BannerStatus","PresentationalProps"],"anatomy":[{"name":"Status glyph (leading, .lq-banner-glyph)","description":"Status glyph (leading, .lq-banner-glyph) — an rendering the"},{"name":"Text stack (.lq-banner-text)","description":"Text stack (.lq-banner-text) — title (primary, semibold) over an"},{"name":"Actions (trailing, optional, .lq-banner-actions)","description":"Actions (trailing, optional, .lq-banner-actions) — an inline row of"},{"name":"Dismiss (trailing-most, optional, .lq-banner-dismiss)","description":"Dismiss (trailing-most, optional, .lq-banner-dismiss) — an xmark"}],"props":[{"name":"actions","type":"readonly BannerAction[] | undefined","required":false,"description":"Trailing action row, keyed by each action's stable `id`.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"className","type":"string | undefined","required":false,"description":"Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"defaultOpen","type":"boolean | undefined","required":false,"description":"Uncontrolled seed for the open state — a banner passed no `open` renders visible.","defaultValue":"`true`","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"dismissible","type":"boolean | undefined","required":false,"description":"Renders the trailing `xmark` dismiss control when `true`.","defaultValue":"`true`","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"dismissIcon","type":"ReactNode","required":false,"description":"Custom dismiss glyph — an SF-Symbol-style name string or a node (the `Image(systemName:)` analogue, mirroring {@link BannerProps.icon}); when omitted the default self-drawn `xmark` cross renders. Purely visual: the control keeps its `aria-label` ({@link BannerProps.dismissLabel}) either way.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"dismissLabel","type":"string | undefined","required":false,"description":"Accessible name override for the dismiss control.","defaultValue":"`\"Dismiss\"`","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"icon","type":"ReactNode","required":false,"description":"Leading status glyph. An SF-Symbol-style name string or a node; when omitted a status-default glyph is derived from {@link BannerProps.status}.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"id","type":"string | undefined","required":false,"description":"Native `id` forwarded to the bar root (charter §8: no silently-discarded inherited props).","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"items","type":"readonly ReactNode[] | undefined","required":false,"description":"Optional bulleted supporting points. Each item receives the same native Banner message typography configured through `messageProps`.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"labelProps","type":"LabelProps | undefined","required":false,"description":"Per-instance typography override for the title, forwarded to the internal `Text` (ADR-0028). Spread last over the computed default.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"live","type":"boolean | undefined","required":false,"description":"When `false`, the banner is a static, labelled `role=\"region\"` (not a live region) — for banners present at page load rather than dynamically raised.","defaultValue":"`true`","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"material","type":"\"frosted\" | \"regular\" | \"clear\" | undefined","required":false,"description":"Material of the glass surface — `frosted · regular · clear` (§06). Forwarded to the engine, which resolves the chain `prop ?? <Material default> ?? \"regular\"`, so a bare surface inherits the enclosing provider default.","defaultValue":"enclosing `<Material default>`, else `\"regular\"`","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"message","type":"ReactNode","required":false,"description":"Optional secondary copy; the `aria-describedby` target.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"messageProps","type":"LabelProps | undefined","required":false,"description":"Per-instance typography override for the message, forwarded to the internal `Text` (ADR-0028). Spread last over the `footnote`/`secondary` default.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"onOpenChange","type":"((open: boolean) => void) | undefined","required":false,"description":"Fires with the next boolean on every close path (dismiss, or `closesOnPress` action).","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"open","type":"boolean | undefined","required":false,"description":"Controlled open state. Passing it switches Banner to controlled mode.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"perf","type":"\"low\" | \"high\" | undefined","required":false,"description":"Perf budget of the glass surface (ADR-0006/0007). Forwarded to the engine as `data-glass-perf`; `\"high\"` opts this surface into the edge-lensing filter. When omitted, derives from the enclosing `<Backdrop type>` (§04).","defaultValue":"derived from `<Backdrop type>`, else `\"low\"`","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"ref","type":"Ref<HTMLDivElement> | undefined","required":false,"description":"Forwarded ref to the rendered element — the bar `<div>` carrying the a11y role; attached while `open` and `null` while dismissed.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"status","type":"BannerStatus | undefined","required":false,"description":"Severity axis — selects the default glyph + accent colour (glyph/edge only, never a full-surface wash, ADR-0019) and the derived a11y `role`.","defaultValue":"`\"info\"`","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"},{"name":"title","type":"ReactNode","required":true,"description":"The bar's primary content — required, the `aria-labelledby` target.","declaredIn":"packages/@liquidify/react/src/components/banner/banner.tsx"}],"swiftUIMap":[{"swiftUI":"`Label(_ title:, systemImage:)`","react":"`title: string` (+ `icon?`)","notes":"the icon+title pairing; `title` is required and is the accessible name","relationship":"direct"},{"swiftUI":"`Image(systemName:)` status glyph","react":"`icon?: string | ReactNode`","notes":"SF-Symbol-style name string or a node; when omitted a **status-default glyph** is derived from `status`","relationship":"direct"},{"swiftUI":"`Text(_:)` (secondary line)","react":"`message?: string | ReactNode`","notes":"optional secondary copy; the `aria-describedby` target","relationship":"direct"},{"swiftUI":"`Image(systemName:)` severity family","react":"`status?: \"info\" | \"success\" | \"warning\" | \"error\" | \"neutral\"`","notes":"severity axis; drives default glyph + accent colour (glyph/edge only), and the a11y role (see Accessibility)","relationship":"direct"},{"swiftUI":"`Button(_:action:)` in a trailing slot","react":"`actions?: BannerAction[]`","notes":"`{ id, label, role?, onPress?, disabled?, closesOnPress? }`; each carries a stable, consumer-supplied `id` — rows key by `id` (never `role+label`), duplicate labels are supported, a duplicate `id` is a dev-time error","relationship":"direct"},{"swiftUI":"`Button.id` (collection identity)","react":"`BannerAction.id: string`","notes":"required; the React key + collection identity (audit §16)","relationship":"direct"},{"swiftUI":"`Button(role: .destructive)`","react":"`BannerAction.role: \"destructive\"`","notes":"red label (`--lq-color-action-destructive`); reuses Alert's role palette","relationship":"direct"},{"swiftUI":"`Button(role: .cancel)`","react":"`BannerAction.role: \"cancel\"`","notes":"neutral bold label","relationship":"direct"},{"swiftUI":"`Button(…).disabled(_:)`","react":"`BannerAction.disabled?: boolean`","notes":"Shape N — native `disabled` on `<Button>`, no `aria-disabled`; hard-suppressed (no `onPress`)","relationship":"direct"},{"swiftUI":"(undo-style coupling)","react":"`BannerAction.closesOnPress?: boolean`","notes":"opt-in per-action close; default `false` — banner actions do **not** auto-close (unlike Alert; resolved Q5 — iOS-faithful: an inline status bar's action does not implicitly dismiss it)","relationship":"direct"},{"swiftUI":"dismiss gesture (analogue only)","react":"`dismissible?: boolean`","notes":"renders the trailing `xmark` control; default `true` (resolved Q4 — orchestrator decision, 2026-07-16)","relationship":"direct"},{"swiftUI":"`isPresented: Binding<Bool>` (analogue)","react":"`open` / `defaultOpen` / `onOpenChange`","notes":"presentation (open) triad (ADR-0015); **not** a value triad — Banner holds no `value`","relationship":"direct"},{"swiftUI":"`.font(_:)` / `.foregroundStyle(_:)` on the title","react":"`labelProps?: LabelProps`","notes":"shared `Pick<TextProps,…>`; spread **last** into the title `TextLabel` (ADR-0028)","relationship":"direct"},{"swiftUI":"`.font(_:)` / `.foregroundStyle(_:)` on the message","react":"`messageProps?: LabelProps`","notes":"spread **last** into the message `TextLabel`","relationship":"direct"},{"swiftUI":"(presentation chrome)","react":"`material?` / `perf?`","notes":"`PresentationalProps` — the bar's glass surface; the base is tint-free (status carried by glyph + edge, not a surface wash)","relationship":"direct"},{"swiftUI":"(no SwiftUI analogue)","react":"`ref?: Ref<HTMLDivElement>`","notes":"forwarded to the semantic root (the bar `<div>` carrying the a11y role); attached while `open`, `null` while dismissed","relationship":"web-only"}],"tokens":["--lq-alert-control-fill","--lq-banner-gap","--lq-banner-pad","--lq-color-action-destructive","--lq-color-label-primary","--lq-color-label-secondary","--lq-color-separator","--lq-color-system-blue-default","--lq-color-system-green-default","--lq-color-system-orange-default","--lq-color-system-red-default","--lq-duration-","--lq-easing-","--lq-glass-","--lq-opacity-muted","--lq-radius-","--lq-radius-pill","--lq-shadow-presentational","--lq-space-"],"keyboard":[],"variants":[],"variantPages":[]}