@stackone/malachite 2.14.0 → 2.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +20 -18
- package/dist/{CodeBlockHighlighter-BAu9-VdW.js → CodeBlockHighlighter-FRBmWthe.js} +673 -668
- package/dist/{CodeBlockHighlighter-BAu9-VdW.js.map → CodeBlockHighlighter-FRBmWthe.js.map} +1 -1
- package/dist/{index-9t717dmi.js → index-DB8AAfU8.js} +6293 -4938
- package/dist/index-DB8AAfU8.js.map +1 -0
- package/dist/index.d.ts +477 -4
- package/dist/index.js +91 -89
- package/package.json +1 -1
- package/dist/index-9t717dmi.js.map +0 -1
package/COMPONENTS.md
CHANGED
|
@@ -6,6 +6,7 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
6
6
|
|
|
7
7
|
## Layout & containers
|
|
8
8
|
|
|
9
|
+
- **`Chat`** — A chat column: `Chat.Thread` scrolls and pins itself to the newest message, `Chat.Composer` keeps its own height and owns the Enter/Shift+Enter convention, and `Chat.Message`, `Chat.ToolCall` and `Chat.Thinking` render one turn each. A user turn sits right and hugs its text; an assistant turn runs full width, and `variant="card"` frames it with its state, copy and rating controls, and a token/model line. `variant="bubble"` is a third treatment, not a repaint of either: tinted bubbles whose flattened corner points at whoever spoke, so authorship reads before the words do. `Chat.Context` lists what the conversation can see — a removable chip per source, and an add affordance only when a handler is given. `Chat.Thinking` and a loading turn draw bars in the shape of the answer rather than a spinner. The row under a composer is `ComposerChip`, `ContextMeter` and `ModelPicker` — PillButton tabs, so it reads as attached to the field; `ModelPicker` opens a portalled menu with a submenu per model. The transcript is a live `log` region, so a streamed reply is announced, and it shows a centred empty state until the first turn. _Key props:_ `Chat`: `children`, `className`. `Thread`: `aria-label`, `emptyTitle`, `emptyDescription`, `emptyIcon`. `Message`: `role`, `variant` (`plain` | `card`), `content`, `children`, `name`, `avatarSrc`, `status` (`streaming` | `completed` | `error`), `loading`, `onCopy`, `onFeedback`, `usage`. `ToolCall`: `name`, `status` (`running` | `completed` | `error`), `callId`, `input`, `output`, `defaultExpanded`. `Thinking`: `label`. `Composer`: `value`, `onChange`, `onSend`, `onStop`, `busy`, `disabled`, `placeholder`, `maxLength`, `rows`, `children`. `ComposerChip`: `label`, `icon`, `trailingIcon`, `onClick`, `disabled`. `ContextMeter`: `used`, `limit`, `cached`, `label`. `ModelPicker`: `models`, `value`, `optionValue`, `onChange`, `openUp`, `disabled`. `Context`: `label`, `items` (`{id, label, onRemove?}`), `onAdd`, `className`.
|
|
9
10
|
- **`Surface`** — Rounded, bordered card container with the standard elevation shadow. Use `overflow="clip"` to keep the rounded clipping while letting a `position: sticky` descendant still pin (`hidden` would trap it); `visible` disables clipping. _Key props:_ `children`, `padding`, `overflow`, `className`, `style`.
|
|
10
11
|
- **`SurfaceRow`** — A full-bleed row inside a Surface (used as `Surface.Row`). Owns hover highlight, colour transition and an optional bottom divider. Pass `onClick`/`href` to make the whole row clickable (renders as a real button/anchor, so keyboard nav works). For a selectable row use `role="radio"` + `selected` and put a presentational `<Radio>` inside as the indicator; `selected` then paints the same treatment `Table` gives `selectedRowKey`. Under `role="checkbox"` it only announces — a multi-select row carries its own checkbox, and a highlight marking one of many says nothing when most rows are checked. `selection` overrides that either way (`highlight` / `announce`). Use `trailing` for a control that must stay interactive — it renders outside the row button, which a nested control could not be. `tone="muted"` tints a row whose subject is inactive, which `disabled` does not: a muted row stays clickable. _Key props:_ `divider`, `disabled`, `tone` (`default` | `muted`), `onClick`, `href`, `selected`, `selection` (`highlight` | `announce`), `trailing`, `role`, `className`, `style`.
|
|
11
12
|
- **`Card`** — Generic content card.
|
|
@@ -26,6 +27,23 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
26
27
|
- **`SidePanel`** — Right-hand slide-in overlay panel (drawer) with header slots (back/icon/title/subtitle/extra), scrollable body and optional footer. Locks background scroll and dismisses on ESC, an overlay click or close. ESC and the Tab focus trap apply to the topmost overlay only, so a `Modal` may be stacked over it.
|
|
27
28
|
- **`SidePanelNavFooter`** — Keyboard-hint footer for SidePanel: up/down keycaps to step between records and an esc-to-close hint, with an optional right-aligned actions slot.
|
|
28
29
|
|
|
30
|
+
## Feedback & status
|
|
31
|
+
|
|
32
|
+
- **`ChangeReview`** — Reviewing changes a machine made. `ChangeReview.Item` attaches to one changed thing: it names what changed with an `assistant` Tag, shows the value it displaced struck through, and offers approve and deny as two equally reachable icon buttons — a review affordance that made keeping easier than rejecting would not be one. Given `children`, it wraps the field the change is annotating: the tag/label/actions become a header band above it and the before/after line moves below, so "Was …" reads next to the value it describes instead of stacked with the header; without children it renders as the standalone card it always has. `ChangeReview.Summary` counts what is still undecided across the whole form, which is what a per-item control cannot do and what a caller gates a save on; at zero it either says so or collapses to nothing. `ChangeReview.Removed` is for something the assistant took out: a dashed, tinted card listing what would be lost, because a removal that simply vanished would leave nothing to reject. `ChangeReview.Jump` is a chip an assistant turn carries to point at a field it touched. _Key props:_ `Item`: `label`, `before`, `after`, `kind` (`changed` | `added` | `removed`), `origin`, `children`, `onApprove`, `onDeny`, `disabled`, `className`. `Summary`: `count`, `origin`, `onApproveAll`, `onDenyAll`, `disabled`, `settledMessage`, `className`. `Removed`: `title`, `details` (`{label, value}[]`), `onRestore`, `onDiscard`, `restoreLabel`, `discardLabel`, `origin`, `disabled`, `className`. `Jump`: `label`, `onClick`, `disabled`, `className`. `Item` also takes `onPreviewRevert(previewing)`, fired on hover and on focus.
|
|
33
|
+
- **`Alert`** — Inline alert/callout (info, success, warning, error).
|
|
34
|
+
- **`StatusBadge`** — Large status indicator (e.g. success checkmark) for terminal/confirmation screens. _Key props:_ `type`.
|
|
35
|
+
- **`StatBadge`** — Pill showing a numeric value with a label (e.g. "3 accounts selected"). _Key props:_ `count`, `label`.
|
|
36
|
+
- **`Tag`** — Small status/label tag. Types: success, error, warning, default. _Key props:_ `value`, `type`, `paddingSize`, `textTransform`, `WidthSize`.
|
|
37
|
+
- **`NumberTag`** — Compact numeric badge/counter.
|
|
38
|
+
- **`Progress`** — Progress bar.
|
|
39
|
+
- **`LoadingBar`** — Indeterminate full-width loading line; the variant colour sweeps across a pale track for work of unknown duration. Toggle `active` rather than unmounting, so the reserved height prevents layout shift. _Key props:_ `active`, `LoadingBarVariant` (`default` | `warning` | `error`), `LoadingBarSize` (`small` | `medium` | `large`), `aria-label`, `aria-labelledby`, `className`, `style`.
|
|
40
|
+
- **`Spinner`** — Loading spinner.
|
|
41
|
+
- **`Skeleton`** — Loading placeholders. Includes `Skeleton.Avatar` and `Skeleton.Input`.
|
|
42
|
+
- **`Tooltip`** — Hover/focus tooltip; also works on disabled controls (see CLAUDE.md). It describes its trigger once shown, so `describesTrigger={false}` where the same sentence is already on screen and referenced — otherwise a screen reader reads it twice. _Key props:_ `text`, `placement`, `delay`, `maxWidth`, `shouldShow`, `triggerAs`, `describesTrigger`, `isShrinkable`, `fill`, `wrapChildren`.
|
|
43
|
+
- **`TruncatedTooltip`** — Shows a tooltip only when its text is truncated.
|
|
44
|
+
- **`Confetti`** — Celebratory confetti burst for success moments. _Key props:_ `pieces`.
|
|
45
|
+
- **`ConfirmationDialog`** — Asks the customer to confirm one consequential action — a preset over `Modal`, not a second dialog implementation. `variant` picks a whole coherent set at once (badge fill, tray tint, caption colour, badge icon and confirm-button variant), so `destructive` cannot end up with a non-destructive confirm button; `destructive` also renders as `role="alertdialog"`, and `description` is wired to the dialog through `aria-describedby`, so the consequence is announced and not just the title. `confirmPhrase` gates the confirm action on typing that exact phrase, for a consequence severe enough that one click should not be able to cause it — the typed value is trimmed, since copying a name picks up a trailing space, but stays case-sensitive, and the field clears each time the dialog opens, being a per-decision gate rather than a value. Neither a destructive dialog nor one carrying a `confirmPhrase` dismisses on a scrim click, and `loading` suppresses the pointer routes — the scrim and the close button — as well as disabling the buttons. It never suppresses ESC: that is the only guaranteed keyboard exit from a focus trap, so it always reaches `onClose` and whether to abort is left to the caller. ESC reaches it whenever it is the topmost overlay, so it can be opened over a panel. `callout` renders an `Alert` in a full-width band at the top of the body — it scrolls with the body rather than being pinned under the header — and its `type` is chosen independently of `variant` — the frames pair a green badge with an amber callout. `titleAdornment` names the entity beside the title, `badgeIcon` overrides the variant’s glyph for an action-specific one, and `tip` is the `{ label?, message }` caption on the tray beneath the card, which `Modal` renders and describes. `children` is where extra body content goes. `onConfirm` does not close the dialog, so the caller can hold it open on `loading` while the request is in flight. `confirmPhraseLabel` also takes `{ prefix, suffix }`, which renders the phrase itself as a copyable token between the two — the gate is case-sensitive and space-exact, so a customer who has identified the right entity should not be locked out by a glyph they cannot tell apart. The copy control sits outside the element that names the field, so “Copy…” never lands in the field’s accessible name; `confirmPhraseCopyLabel` names it and `onPhraseCopied` reports a completed write with the phrase it copied. A rejected write says so in the field rather than failing silently, and the control is disabled where the Clipboard API is unavailable. A near miss is named rather than left to a disabled button: typing the phrase with the wrong case or the wrong spacing says which, once the whole phrase is there, and that message is the field’s `aria-describedby`. _Key props:_ `open`, `onClose`, `onConfirm`, `title`, `description`, `titleAdornment`, `badgeIcon`, `variant` (`default` | `warning` | `destructive` | `success`), `callout`, `confirmPhrase`, `confirmPhraseLabel`, `confirmPhraseCopyLabel`, `confirmPhrasePlaceholder`, `onPhraseCopied`, `confirmLabel`, `cancelLabel`, `loading`, `tip`, `size`, `aria-label`, `aria-labelledby`.
|
|
46
|
+
|
|
29
47
|
## Lists, rows & navigation
|
|
30
48
|
|
|
31
49
|
- **`ButtonList`** — Vertical list of pill-style button/link rows with built-in hover/focus/active states. _Key props:_ `buttons[]` (`key`, `children`, `onClick`, `href`), `compact`.
|
|
@@ -57,34 +75,18 @@ The catalog of components exported from `@stackone/malachite`. **Reach for one o
|
|
|
57
75
|
- **`Radio`** — Single radio control with hover state; parent manages the group. Pass `presentational` to render a visual-only, non-focusable indicator for use inside a clickable row/card. _Key props:_ `checked`, `onChange`, `disabled`, `size`, `presentational`.
|
|
58
76
|
- **`SegmentedControl`** — A rounded track of mutually-exclusive options — the segmented “one of these” control. Owns the track background, the selected-thumb chrome and the `radiogroup` semantics, so consumers never hand-roll a track around `PillButton` (whose `default` variant tokens are tuned for standalone filter pills, not a sunken track). Single tab stop with arrow-key move-and-select; selection is conveyed via `aria-checked` and a foreground change, not background colour alone. Restyle via the `segmentedControl` theme tokens. _Key props:_ `options` (`value`, `label`, `icon`, `disabled`), `value`, `onChange`, `SegmentedControlSize` (`small` | `medium` | `large`), `fullWidth`, `disabled`, `aria-label`, `aria-labelledby`, `className`.
|
|
59
77
|
- **`Toggle`** — On/off switch. Add `label` for a visible caption, and `variant` to give it standalone toolbar-filter chrome — pick the family it sits beside: `pill` matches the filter-bar inputs (`Search`, `MultiSelect`), `button` renders the whole control as an outline `Button` with the switch as its trailing icon. `bordered` is shorthand for `variant="pill"`. `tone="pending"` paints the checked track amber, for a switch whose change has not been written yet — pair it with a `SelectionBar` reporting the same diff. The unchecked track never changes: nothing is pending about a switch that is off. Forwards a ref to its root element, so it can anchor an `InlineConfirm`. _Key props:_ `checked`, `onChange`, `disabled`, `ToggleSize` (`small` | `medium`), `ToggleTone` (`default` | `pending`), `label`, `ToggleVariant` (`pill` | `button`), `bordered`, `aria-label`, `aria-labelledby`, `aria-describedby`, `id`.
|
|
60
|
-
- **`Dropdown`** — Single-select dropdown. `DropdownSize` is `small` (28px) | `medium` (32px) | `large` (42px), matching Button; `small` is the chip that sits beside a page title and rounds tighter (10px) than the taller sizes. These names each moved up a tier in 0.71 — the old `xsmall`/`small`/`medium` are now `small`/`medium`/`large`. Pass `value` for a controlled selection whose source of truth lives elsewhere (URL or app state): the trigger follows it without the consumer remounting via `key`, which used to discard focus mid-interaction. `defaultValue` keeps the uncontrolled behaviour. `clearable` adds a clear control to the trigger once something is selected and reports it as `onItemSelected(undefined)` — without it a selection cannot be undone, so filter bars had to invent a sentinel "any" item to carry that meaning. `requiredIndicator` switches the label between the library default of naming the optional fields, an `asterisk` on the required ones for designs drawn that way, and `none` for a field whose value is supplied rather than asked for — a locked control is still required, but a marker only sends the reader looking for something to fill in. Visual only: `aria-required` is set from `required` whichever is chosen. `showSubtitleInTrigger` promotes the selected item's `subtitle` into the closed trigger, on one line under the value, so the consequence of a choice stays on screen once the menu shuts — the trigger trades its fixed height for a floor and grows by that line, and either line too long for it ellipsises, with a single tooltip carrying whichever lines are cut off, value first. It does not combine with `search`, whose trigger is a single-line text input with nowhere to put a second line, so the type rejects the pair rather than letting a consumer ask for a subtitle and get none. `subtitleLayout` decides how a subtitle sits in the open menu: the default `inline` keeps it on the label's row after a divider, which suits a short qualifier, while `stacked` gives it its own line beneath the label, clamped to two — inline, a sentence-length subtitle is ellipsised away to a few words. Passing `formControl` is enough to show validation on the same terms as `Input`, though only validation: the trigger still paints `value` or `defaultValue`, never the value the form holds. The resolver's message renders on its own line beneath the field in the destructive colour, politely announced, with `aria-invalid` and `aria-describedby` wired, while an explicit `helperText` keeps its own line above it and stays dimmed, and `error={false}` suppresses the resolver outright. _Key props:_ `DropdownItem[]`, `DropdownSize`, `value`, `defaultValue`, `label`, `search`, `showSubtitleInTrigger`, `subtitleLayout`, `clearable`, `required`, `requiredIndicator`, `error`, `helperText`, `loading`, `formControl`, `aria-label`, `aria-labelledby`, `id`.
|
|
78
|
+
- **`Dropdown`** — Single-select dropdown. `DropdownSize` is `small` (28px) | `medium` (32px) | `large` (42px), matching Button; `fullWidth` fills the container instead of sizing to content and matches the panel to the trigger, which is what a table cell or a toolbar slot needs — without it the field column sizes to its content, so a consumer has to compute a width; `small` is the chip that sits beside a page title and rounds tighter (10px) than the taller sizes. These names each moved up a tier in 0.71 — the old `xsmall`/`small`/`medium` are now `small`/`medium`/`large`. Pass `value` for a controlled selection whose source of truth lives elsewhere (URL or app state): the trigger follows it without the consumer remounting via `key`, which used to discard focus mid-interaction. `defaultValue` keeps the uncontrolled behaviour. `clearable` adds a clear control to the trigger once something is selected and reports it as `onItemSelected(undefined)` — without it a selection cannot be undone, so filter bars had to invent a sentinel "any" item to carry that meaning. `requiredIndicator` switches the label between the library default of naming the optional fields, an `asterisk` on the required ones for designs drawn that way, and `none` for a field whose value is supplied rather than asked for — a locked control is still required, but a marker only sends the reader looking for something to fill in. Visual only: `aria-required` is set from `required` whichever is chosen. `showSubtitleInTrigger` promotes the selected item's `subtitle` into the closed trigger, on one line under the value, so the consequence of a choice stays on screen once the menu shuts — the trigger trades its fixed height for a floor and grows by that line, and either line too long for it ellipsises, with a single tooltip carrying whichever lines are cut off, value first. It does not combine with `search`, whose trigger is a single-line text input with nowhere to put a second line, so the type rejects the pair rather than letting a consumer ask for a subtitle and get none. `subtitleLayout` decides how a subtitle sits in the open menu: the default `inline` keeps it on the label's row after a divider, which suits a short qualifier, while `stacked` gives it its own line beneath the label, clamped to two — inline, a sentence-length subtitle is ellipsised away to a few words. Passing `formControl` is enough to show validation on the same terms as `Input`, though only validation: the trigger still paints `value` or `defaultValue`, never the value the form holds. The resolver's message renders on its own line beneath the field in the destructive colour, politely announced, with `aria-invalid` and `aria-describedby` wired, while an explicit `helperText` keeps its own line above it and stays dimmed, and `error={false}` suppresses the resolver outright. _Key props:_ `DropdownItem[]`, `DropdownSize`, `fullWidth`, `value`, `defaultValue`, `label`, `search`, `showSubtitleInTrigger`, `subtitleLayout`, `clearable`, `required`, `requiredIndicator`, `error`, `helperText`, `loading`, `formControl`, `aria-label`, `aria-labelledby`, `id`.
|
|
61
79
|
- **`MultiSelect`** — Multi-select dropdown. `requiredIndicator` follows the same three-way convention the single-select controls do, so a form choosing asterisks does not get "(Optional)" on one of its fields. _Key props:_ `MultiSelectOption[]`, `MultiSelectSize`, `label`, `searchable`, `inlineSearch`, `chips`, `chipsRemovable`, `required`, `requiredIndicator`, `aria-label`, `aria-labelledby`, `id`.
|
|
62
80
|
- **`SettingRow`** — One setting: a labelled row with its control on the trailing edge, and the sentence that explains it underneath. `control` may be a render prop receiving the label’s id, so a control that no `<label htmlFor>` can reach — `Toggle` renders a `<button role="switch">` — still names itself via `aria-labelledby`. _Key props:_ `label`, `badge`, `description`, `control`, `className`.
|
|
63
81
|
|
|
64
82
|
## Buttons & actions
|
|
65
83
|
|
|
66
84
|
- **`Button`** — Primary button. Variants: `filled`, `outline`, `destructive`, `success`, `warning`, `error`, `ghost`, `no-style`. Supports `iconOnly`, `loading`, `tooltip`. _Key props:_ `variant`, `size`, `icon`, `iconOnly`, `loading`, `disabled`, `fill`, `tooltip`.
|
|
67
|
-
- **`PillButton`** — Pill-shaped button, often used for filters/toggleable chips.
|
|
85
|
+
- **`PillButton`** — Pill-shaped button, often used for filters/toggleable chips. `shape="tab"` squares the top corners so a row of them reads as attached to whatever sits above — the controls under a chat composer. _Key props:_ `label`, `icon`, `trailingIcon`, `selected`, `disabled`, `interactive`, `size`, `variant`, `shape` (`pill` | `tab`), `onClick`.
|
|
68
86
|
- **`Link`** — Styled anchor/link text. _Key props:_ `LinkProps`.
|
|
69
87
|
- **`InlineConfirm`** — A confirmation asked on the control that triggered it rather than in a modal, for a reversible bulk edit where a dialog would be heavier than the change it guards. Drawn to the design's chip: 33px tall, 12px radius, its confirm cell running to the pill's own edge between two rules. Reads its own `inlineConfirm` theme tokens — a shade off the `SelectionBar` it appears beside, by design. Carries a spinning glyph by default — its own, so it takes the pill's colour rather than the sheet's dimmed grey — standing for a change waiting on an answer; pass `icon={null}` to drop it or a node to replace it. Anchored placement is in viewport coordinates, so the chip must not sit inside an ancestor carrying `transform`, `filter` or `contain`. It takes focus on open so `Enter` confirms, dismisses on `Escape` (through the shared escape-layer stack, so the topmost overlay answers) or a click outside, and returns focus to whatever opened it. `role="alertdialog"` named by the message itself, so the confirm button is never announced bare. Only one can be open at a time: opening a second dismisses the first, so it is never ambiguous what Yes answers. Pass `anchorTo` (a ref to the control it answers for) and it pins itself to that control's left, follows it while the page or a sticky header scrolls, dismisses once it scrolls out of view, and treats clicks on it as inside — without which the same click would dismiss and reopen. Left unanchored it renders in flow for the consumer to place, and must then not sit in a container that clips overflow (`Table` header cells among them). Nothing renders while `open` is false, and its listeners are attached only while it is open. _Key props:_ `open`, `message`, `confirmLabel`, `onConfirm`, `onDismiss`, `anchorTo`, `icon`, `className`, `style`.
|
|
70
88
|
- **`SelectionBar`** — A bar reporting a pending selection and the actions that resolve it, for flows where changes accumulate and save once rather than writing on every toggle. Paints its own inverted surface from the `selectionBar` theme tokens, so its buttons are its own rather than `Button`. A count renders as one phrase (`3 Added`), not a number styled apart from its label, and an empty `value` carries a bare message instead; the separators between counts and before an action are glyphs (`•`, `|`) in the muted colour, not drawn rules. `emphasis` runs `primary` (a light filled button with its own edge, for the action that commits) → `secondary`, the default (a filled chip) → `quiet` (unfilled, taking a wash on hover). The pill is edgeless in light mode and keeps a hairline `border` token in dark, where a shadow alone would not separate it from the sheet. Defaults to `placement="sticky"` — render it as the last child of the scrolling content and it holds its place over a long list. Counts are announced through a live region that outlives the bar, so the first change is not lost; `open` drives an animated mount so it can appear and leave as the selection goes dirty and clean. Every action closes the bar, so the caller must move focus deliberately in `onClick`. _Key props:_ `open`, `counts` (`value`, `label`), `actions` (`label`, `onClick`, `emphasis`, `icon`, `iconPosition`, `disabled`, `dividerBefore`), `placement`, `aria-label`, `className`.
|
|
71
89
|
|
|
72
|
-
## Feedback & status
|
|
73
|
-
|
|
74
|
-
- **`Alert`** — Inline alert/callout (info, success, warning, error).
|
|
75
|
-
- **`StatusBadge`** — Large status indicator (e.g. success checkmark) for terminal/confirmation screens. _Key props:_ `type`.
|
|
76
|
-
- **`StatBadge`** — Pill showing a numeric value with a label (e.g. "3 accounts selected"). _Key props:_ `count`, `label`.
|
|
77
|
-
- **`Tag`** — Small status/label tag. Types: success, error, warning, default. _Key props:_ `value`, `type`, `paddingSize`, `textTransform`, `WidthSize`.
|
|
78
|
-
- **`NumberTag`** — Compact numeric badge/counter.
|
|
79
|
-
- **`Progress`** — Progress bar.
|
|
80
|
-
- **`LoadingBar`** — Indeterminate full-width loading line; the variant colour sweeps across a pale track for work of unknown duration. Toggle `active` rather than unmounting, so the reserved height prevents layout shift. _Key props:_ `active`, `LoadingBarVariant` (`default` | `warning` | `error`), `LoadingBarSize` (`small` | `medium` | `large`), `aria-label`, `aria-labelledby`, `className`, `style`.
|
|
81
|
-
- **`Spinner`** — Loading spinner.
|
|
82
|
-
- **`Skeleton`** — Loading placeholders. Includes `Skeleton.Avatar` and `Skeleton.Input`.
|
|
83
|
-
- **`Tooltip`** — Hover/focus tooltip; also works on disabled controls (see CLAUDE.md). It describes its trigger once shown, so `describesTrigger={false}` where the same sentence is already on screen and referenced — otherwise a screen reader reads it twice. _Key props:_ `text`, `placement`, `delay`, `maxWidth`, `shouldShow`, `triggerAs`, `describesTrigger`, `isShrinkable`, `fill`, `wrapChildren`.
|
|
84
|
-
- **`TruncatedTooltip`** — Shows a tooltip only when its text is truncated.
|
|
85
|
-
- **`Confetti`** — Celebratory confetti burst for success moments. _Key props:_ `pieces`.
|
|
86
|
-
- **`ConfirmationDialog`** — Asks the customer to confirm one consequential action — a preset over `Modal`, not a second dialog implementation. `variant` picks a whole coherent set at once (badge fill, tray tint, caption colour, badge icon and confirm-button variant), so `destructive` cannot end up with a non-destructive confirm button; `destructive` also renders as `role="alertdialog"`, and `description` is wired to the dialog through `aria-describedby`, so the consequence is announced and not just the title. `confirmPhrase` gates the confirm action on typing that exact phrase, for a consequence severe enough that one click should not be able to cause it — the typed value is trimmed, since copying a name picks up a trailing space, but stays case-sensitive, and the field clears each time the dialog opens, being a per-decision gate rather than a value. Neither a destructive dialog nor one carrying a `confirmPhrase` dismisses on a scrim click, and `loading` suppresses the pointer routes — the scrim and the close button — as well as disabling the buttons. It never suppresses ESC: that is the only guaranteed keyboard exit from a focus trap, so it always reaches `onClose` and whether to abort is left to the caller. ESC reaches it whenever it is the topmost overlay, so it can be opened over a panel. `callout` renders an `Alert` in a full-width band at the top of the body — it scrolls with the body rather than being pinned under the header — and its `type` is chosen independently of `variant` — the frames pair a green badge with an amber callout. `titleAdornment` names the entity beside the title, `badgeIcon` overrides the variant’s glyph for an action-specific one, and `tip` is the `{ label?, message }` caption on the tray beneath the card, which `Modal` renders and describes. `children` is where extra body content goes. `onConfirm` does not close the dialog, so the caller can hold it open on `loading` while the request is in flight. `confirmPhraseLabel` also takes `{ prefix, suffix }`, which renders the phrase itself as a copyable token between the two — the gate is case-sensitive and space-exact, so a customer who has identified the right entity should not be locked out by a glyph they cannot tell apart. The copy control sits outside the element that names the field, so “Copy…” never lands in the field’s accessible name; `confirmPhraseCopyLabel` names it and `onPhraseCopied` reports a completed write with the phrase it copied. A rejected write says so in the field rather than failing silently, and the control is disabled where the Clipboard API is unavailable. A near miss is named rather than left to a disabled button: typing the phrase with the wrong case or the wrong spacing says which, once the whole phrase is there, and that message is the field’s `aria-describedby`. _Key props:_ `open`, `onClose`, `onConfirm`, `title`, `description`, `titleAdornment`, `badgeIcon`, `variant` (`default` | `warning` | `destructive` | `success`), `callout`, `confirmPhrase`, `confirmPhraseLabel`, `confirmPhraseCopyLabel`, `confirmPhrasePlaceholder`, `onPhraseCopied`, `confirmLabel`, `cancelLabel`, `loading`, `tip`, `size`, `aria-label`, `aria-labelledby`.
|
|
87
|
-
|
|
88
90
|
## Typography
|
|
89
91
|
|
|
90
92
|
- **`ClampText`** — Clamps text to N lines; expands to full text on hover/focus with a height animation. Wrapping markdown? Pass `variant="flow"` to the `Typography.MarkdownBlock` inside it, or the clamp counts blocks instead of lines.
|