@crewlethq/ui 0.84.2 → 0.86.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.
Files changed (103) hide show
  1. package/README.md +53 -5
  2. package/dist/Accordion/index.js +1 -1
  3. package/dist/AgentHandoffPanel/index.js +2 -2
  4. package/dist/ArtifactBar/index.js +1 -1
  5. package/dist/AttentionList/AttentionList.d.ts +82 -0
  6. package/dist/AttentionList/index.d.ts +3 -0
  7. package/dist/AttentionList/index.js +9 -0
  8. package/dist/AttentionList-LVX7KRET.css +212 -0
  9. package/dist/AvatarPicker/index.js +2 -2
  10. package/dist/ChangeList/index.js +2 -2
  11. package/dist/ChoiceCards/ChoiceCards.d.ts +35 -6
  12. package/dist/ChoiceCards/index.d.ts +1 -1
  13. package/dist/ChoiceCards/index.js +1 -1
  14. package/dist/{ChoiceCards-TVMBO3HZ.css → ChoiceCards-KHJW2FKO.css} +49 -0
  15. package/dist/ChoiceList/ChoiceList.d.ts +2 -2
  16. package/dist/ChoiceList/index.js +1 -1
  17. package/dist/{ChoiceList-JN4PPNFW.css → ChoiceList-ZQMZTEZX.css} +33 -17
  18. package/dist/CodeBlock/index.js +2 -2
  19. package/dist/ColorSwatch/index.js +2 -2
  20. package/dist/ContrastBadge/index.js +2 -2
  21. package/dist/ContrastHelp/index.js +3 -3
  22. package/dist/Copyable/index.js +1 -1
  23. package/dist/{Copyable-IS3MHMPL.css → Copyable-P5AMRHFX.css} +18 -4
  24. package/dist/DataGrid/index.js +1 -1
  25. package/dist/{DataGrid-Q26F2V5Q.css → DataGrid-SAHEL4SN.css} +57 -0
  26. package/dist/DataView/index.js +2 -2
  27. package/dist/DeepWorkCard/index.js +3 -3
  28. package/dist/Disclosure/Disclosure.d.ts +10 -1
  29. package/dist/Disclosure/index.js +1 -1
  30. package/dist/{Disclosure-D727FN5X.css → Disclosure-RJSKKO7Z.css} +20 -0
  31. package/dist/KeyValueRows/KeyValueRows.d.ts +125 -0
  32. package/dist/KeyValueRows/index.d.ts +3 -0
  33. package/dist/KeyValueRows/index.js +12 -0
  34. package/dist/KeyValueRows-US5KW7JK.css +44 -0
  35. package/dist/LogoSlot/index.js +3 -3
  36. package/dist/MarkdownEditor/index.js +1 -1
  37. package/dist/MemberPicker/MemberPicker.d.ts +86 -0
  38. package/dist/MemberPicker/index.d.ts +3 -0
  39. package/dist/MemberPicker/index.js +11 -0
  40. package/dist/MemberPicker-ZD35VEK6.css +162 -0
  41. package/dist/MergeConflicts/index.js +1 -1
  42. package/dist/PresenterView/index.js +2 -2
  43. package/dist/ProposalCard/index.js +3 -3
  44. package/dist/RailList/RailList.d.ts +74 -0
  45. package/dist/RailList/index.d.ts +3 -0
  46. package/dist/RailList/index.js +17 -0
  47. package/dist/RailList-N2ZBPRM2.css +97 -0
  48. package/dist/RelatedRow/index.js +2 -2
  49. package/dist/RichEditor/index.js +1 -1
  50. package/dist/RunChip/index.js +3 -3
  51. package/dist/SegmentedControl/index.js +1 -1
  52. package/dist/{SegmentedControl-B7XCUOML.css → SegmentedControl-7GY2KM44.css} +11 -0
  53. package/dist/SetupWizard/index.js +3 -3
  54. package/dist/ShareDialog/index.js +3 -3
  55. package/dist/{StepList-A4YVU4JI.css → StepList-OAJ45IBX.css} +12 -1
  56. package/dist/Stepper/StepList.d.ts +7 -4
  57. package/dist/Stepper/index.js +1 -1
  58. package/dist/TableCells/TableCells.d.ts +60 -0
  59. package/dist/TableCells/index.d.ts +2 -2
  60. package/dist/TableCells/index.js +2 -1
  61. package/dist/{TableCells-TKSNLRK3.css → TableCells-ZALZLLEF.css} +28 -0
  62. package/dist/Text/Text.d.ts +25 -3
  63. package/dist/Text/index.js +1 -1
  64. package/dist/ThemeSwitcher/index.js +1 -1
  65. package/dist/TimeRangePicker/index.js +1 -1
  66. package/dist/VersionCompare/index.js +1 -1
  67. package/dist/{chunk-CV2LU2T2.js → chunk-35CKF77R.js} +2 -2
  68. package/dist/{chunk-AUSFKGKL.js → chunk-3AMWXJQX.js} +1 -1
  69. package/dist/{chunk-AFLS26AC.js → chunk-3CALM534.js} +36 -2
  70. package/dist/{chunk-AOJ6ZA77.js → chunk-3MFRTZH6.js} +1 -1
  71. package/dist/{chunk-QSWQJX27.js → chunk-4ME4J3YY.js} +1 -1
  72. package/dist/{chunk-6FBPFG3C.js → chunk-6EZX26BD.js} +1 -1
  73. package/dist/chunk-AELKT34H.js +121 -0
  74. package/dist/{chunk-X7VZQKIW.js → chunk-AQ7ZV3CH.js} +1 -1
  75. package/dist/{chunk-EAHEJNVJ.js → chunk-CL3FWLDO.js} +1 -1
  76. package/dist/{chunk-XNC3M4IN.js → chunk-E2QPZGLG.js} +1 -1
  77. package/dist/{chunk-T5GBTXNC.js → chunk-ETNQYT5O.js} +1 -1
  78. package/dist/{chunk-36WK24AI.js → chunk-EVM6GYZ2.js} +1 -1
  79. package/dist/{chunk-B7NX425Z.js → chunk-JDMJVVVQ.js} +12 -4
  80. package/dist/chunk-KA4RBKQV.js +148 -0
  81. package/dist/{chunk-ABRWL5FJ.js → chunk-L2QRKIL4.js} +3 -2
  82. package/dist/{chunk-P7HMY3BQ.js → chunk-M33DABTW.js} +2 -2
  83. package/dist/{chunk-LVJGN5II.js → chunk-NAHA62WD.js} +3 -1
  84. package/dist/{chunk-QP2P6GDQ.js → chunk-O5CEG7TQ.js} +14 -0
  85. package/dist/{chunk-6SFDL4QH.js → chunk-P3LNA6G4.js} +1 -1
  86. package/dist/chunk-REWKR3S4.js +73 -0
  87. package/dist/{chunk-WMO722J2.js → chunk-TBQFZV4H.js} +1 -1
  88. package/dist/{chunk-RJWO2PC5.js → chunk-TMML7BHT.js} +14 -5
  89. package/dist/chunk-TRZS7DLB.js +159 -0
  90. package/dist/{chunk-K6RWEQ6P.js → chunk-WRZPO4YL.js} +2 -2
  91. package/dist/{chunk-DD7RBNT4.js → chunk-XH55NRHO.js} +1 -1
  92. package/dist/{chunk-6RW2MUTY.js → chunk-XU7RQNT6.js} +1 -1
  93. package/dist/{chunk-AQNP3KQU.js → chunk-Y7PPKQFQ.js} +1 -1
  94. package/dist/generated/index.d.ts +4 -0
  95. package/dist/generated/index.js +92 -88
  96. package/dist/index.js +92 -88
  97. package/dist/styles.css +763 -30
  98. package/package.json +3 -3
  99. package/dist/{Editor-5D5Z3LBQ.js → Editor-VGNB35NJ.js} +1 -1
  100. package/dist/{chunk-22CU7V4J.js → chunk-K2HEYQJL.js} +1 -1
  101. package/dist/{chunk-REEZQCML.js → chunk-PAGITACP.js} +0 -0
  102. package/dist/{chunk-LMEMH6DO.js → chunk-WCJTOKTY.js} +1 -1
  103. package/dist/{chunk-2ZSCHQOA.js → chunk-WMSXPF7T.js} +1 -1
package/README.md CHANGED
@@ -41,17 +41,17 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
41
41
  | Area | Components |
42
42
  | ---- | ---------- |
43
43
  | Actions | `Button` and `ButtonLink` (variants `primary`, `secondary`, `outline`, `ghost`, `accent`, `danger`; sizes `small`, `medium`, `large`; shapes `square`, `pill`), `IconButton`, `Menu`, `Link`, `Copyable`, `CopyButton`, `DownloadButton`, `Kbd` |
44
- | Content and text | `Text` (the eight registers and `inherit`), `Prose`, `Statement`, `Document`, `DocumentTitle` and `DocumentTitleField`, the Markdown grammar (`parseMarkdown`, `parseMarkdownSpans`, `markdownInline`, `safeHref` and the line readers, with no React in it), `Highlight`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime`, `Note`, `Divider` |
45
- | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `CheckboxGroup`, `ConfirmField`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `TimeRangePicker`, `ImageUpload`, `CharacterPicker`, `HuePicker`, `AvatarPicker`, `FactList`, `ChoiceList`, `ChoiceCards`, `ChipField` (chosen items as chips inside the field), `PersonRow` (a person or an agent as one row of a list), `Composer`, `MarkdownEditor`, `RichEditor` (with `preloadRichEditor`, and the round trip `roundTripMarkdown` and `canonicalMarkdown` from `@crewlethq/ui/RichEditorMarkdown`) |
46
- | Data display | `DataGrid` (with `useDataGridDriving`, `useAnyDataGridDriving` and `countDataGridRows`), `DataTable`, `CopyableCell`, `Table`, the read-only table cells (`TableKeyCell`, `TableNumberCell`, `TableDateCell`, `TableEntityCell`, `TableStatusCell`, `TableTagsCell`, `TableTextCell`), `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow`, `StatGroup`, `PinTile`, `IconTile`, `SettingsTable` (with `SettingsTable.Row`), `CatalogTile` |
44
+ | Content and text | `Text` (the eight registers and `inherit`; a line cut by `truncate` or `clamp` shows its whole words on hover), `Prose`, `Statement`, `Document`, `DocumentTitle` and `DocumentTitleField`, the Markdown grammar (`parseMarkdown`, `parseMarkdownSpans`, `markdownInline`, `safeHref` and the line readers, with no React in it), `Highlight`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime`, `Note`, `Divider` |
45
+ | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `CheckboxGroup`, `ConfirmField`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `TimeRangePicker`, `ImageUpload`, `CharacterPicker`, `HuePicker`, `AvatarPicker`, `FactList`, `ChoiceList`, `ChoiceCards`, `MemberPicker` (groups granted whole, with members left out or chosen on their own, and `chosenMembers`), `KeyValueRows` (keys and their values as rows under one column head, with `keyValueRowsLabels`), `ChipField` (chosen items as chips inside the field), `PersonRow` (a person or an agent as one row of a list), `Composer`, `MarkdownEditor`, `RichEditor` (with `preloadRichEditor`, and the round trip `roundTripMarkdown` and `canonicalMarkdown` from `@crewlethq/ui/RichEditorMarkdown`) |
46
+ | Data display | `DataGrid` (with `useDataGridDriving`, `useAnyDataGridDriving` and `countDataGridRows`), `DataTable`, `CopyableCell`, `Table`, the read-only table cells (`TableKeyCell`, `TableNumberCell`, `TableDateCell`, `TableEntityCell`, `TableStatusCell`, `TableTagsCell`, `TableTextCell`, `TableTwoLineCell`), `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `QrCode`, `ObjectHeader`, `FactLine`, `SetByLine`, `Skeleton`, `Eyebrow`, `StatGroup`, `PinTile`, `IconTile`, `SettingsTable` (with `SettingsTable.Row`), `CatalogTile` |
47
47
  | List screens | `DataView`, and its parts on their own: `DataViewToolbar`, `FilterAxisBar`, `FilterAxisChip`, `FilterPill`, plus the filter model (`filterDefsFromColumns`, `applyColumnFilters`, `filterPredicate`, `blankFilterValue`) |
48
- | Feedback and overlays | `Callout`, `ConflictNote`, `EditingStatus`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
48
+ | Feedback and overlays | `Callout`, `AttentionList` (what needs a person, as rows in one card), `ConflictNote`, `EditingStatus`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
49
49
  | Documents and review | `DiffView` and `DiffSummary` with the line diff they draw (`diffLines`, `diffStat`, `collapseDiff`, `firstChangedLines`, `splitLines`, `MAX_DIFF_LINES`, with no React in it), `DiffList`, `VersionCompare`, `CommentThread` |
50
50
  | Conversations and the assistant | `ChatThread` (with `ChatThreadHandle`), `ChatMessage` and `ChatMessageFailure`, `MessageActions` (with `MessageAction`, `QuickReaction` and `ActionDivider`), `ReactionBar` and `AddReaction` (with `reactionWho`), `EmojiPicker` (with `EMOJI_GROUPS`, `emojiName` and `searchEmoji`), `ThreadSummary`, `ActivityLine`, `MentionChip`, `MessageBubble`, `RunChip`, `StepList` and `StepStateMark`, `ProposalCard`, `ChangeList` (with `shortenUnchanged`), `StatusCard`, `ReceiptStrip`, `RefusalStrip`, `ResultTableCard`, `OpenInAppCard`, `BriefCard` (with `points`, what was said, each citing its message), `EntityList`, `RecordChip` and `RecordChipList` (a record named in a sentence, opening a peek, and the Also read line), `RefusalCard`, `SuggestionRow` and `SuggestionList`, `SendButton`, a transcript's timeline (`ChatDay` with `ChatDayPill`, `ChatDivider`), `LinkCard` (a link unfurled under its message), `MentionMenu` (with `mentionQuery`), `ActionCard` and `ActionCardRow` |
51
51
  | Charts | `Legend`, `BarList`, `StackedBar`, `StackedColumns`, `ActivityStrip`, `TimeSeries`, `Sparkline`, the reading layer they share (`ChartTooltip`, `useChartHover`), and the ramp (`DATA_COLORS`, `DATA_COLOR_OTHER`, `dataColor`) |
52
52
  | Marks | `Count` (with `tone="attention"`), `StatusDot`, `Spinner`, `EmptyValue`, `VisuallyHidden` |
53
53
  | Hooks and seams | `useModalLayer`, `usePopupLayer`, `LayerHost`, `useListbox`, `useOptionKeys`, `useHighlightRest` and `HIGHLIGHT_REST_MS`, `useClipboard`, `useDownload`, `downloadText`, `downloadBlob`, `safeFilename`, `toCsv`, `elementToPng` and `ElementToPngError`, `useOutcome`, `useAnnouncer`, `useNow`, `formatRelative`, `HeadingLevelProvider`, `cx`, the node hues (`NODE_HUES`, `NODE_HUE_NAMES`, `isNodeHue`) |
54
- | Layout | `Container`, `Section`, `Card`, `TileGrid`, `ListDetail`, `AsideLayout`, `Tabs`, `Accordion`, `Disclosure`, `Outline` (with `useActiveHeading` and `scrollToHeading`), `TreeGrid` |
54
+ | Layout | `Container`, `Section`, `Card`, `TileGrid`, `ListDetail`, `RailList` (a directory's groups as a rail beside its list, folding into a picker), `AsideLayout`, `Tabs`, `Accordion`, `Disclosure`, `Outline` (with `useActiveHeading` and `scrollToHeading`), `TreeGrid` |
55
55
  | Arranging a page | `ArrangeBoard`, `ArrangeGrid`, `ArrangeFrame` (with `useGridResize`), `ArrangeGroup`, `ArrangeList`, and the reorder hooks under them (`useReorder`, `useReorderLists`, `moveKey`) |
56
56
  | Application shell | `AppShell` with `AppShell.Rail`, the compact rail (`rail="compact"`, the one fold control from `onRailChange`, and `useAppShell().rail` to pick the shape) and `fill="flush"`, the `aside` track and the `peek` slot (`useAppShellAside`, `useAppShellPeek`), `AppShell.ResizeHandle` (also `ResizeHandle`) and `useStoredWidth`, `SidePanel` and `SidePanelFrame`, `PeekRail` and `PeekHost` (with `PeekNeighbours`, `usePeekNeighbours`, `usePeekStep`, `peekClickHandler`, `peekRowActivation`), `SectionFrame` (with `SectionFrame.Nav` and `SectionFrame.Body`), `DockColumn` and `usePresence`, `LockedLabel`, `AppShell.Topbar`, `AppShell.AccountRow` and `useAppShell`, `AuthLayout`, `SidebarNav` and `NavItem` (with `dense` lists, `unread` and `muted` rows and `collapsible` groups), `CompactNav` with `CompactNavItem`, `CompactNavGroup` and `CompactNavSeparator` (the rail folded to its marks, fed from the same places), `DirectoryList`, `BrandLockup`, `SearchTrigger`, `PageHeader`, `Toolbar`, `Stack`, `Inline`, `Spacer`, `AutoGrid`, `ErrorBoundary`, `useShortcut`, `useFullscreen`, `useIdle`, `useMediaMatch` |
57
57
  | Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `ThemeGallery`, `ThemeSwatch`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences`, and the framework-free `applyTheme`, `applyPalette`, `applyDensity` with `THEME_PREFERENCES`, `DENSITY_PREFERENCES` and their guards |
@@ -205,6 +205,54 @@ places:
205
205
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
206
206
  when the content beneath it moves, and every panel anchored inside follows.
207
207
 
208
+ ## Changes in 0.86.0
209
+
210
+ ### Forms, tables and directories
211
+
212
+ **`KeyValueRows` is new**: keys and their values edited as rows under one column head, for request headers, environment variables and any list of names and what each is set to. The key and value columns are named once (`keyLabel`, `valueLabel`), and each field is named on its own for a screen reader ("Header 2", "Value for Authorization"), so every row is the same row. Every row stands on its fields' top edge, so a refused key or value (`keyError`, `valueError`) is said under its own field, linked to it, and the controls beside it stay level. The remove button is a square the fields' height, and Add is a flush quiet action under the rows. Add puts the focus in the new row's key; Remove moves it to the row that took that row's place, else the one before, else Add, and says what went. Keys take the `reference` appearance and are never spell-checked; `secret` hides each value and marks it `new-password`, so no browser offers a saved password into it. `keyReadOnly` holds a row's key, and `valuePlaceholder` may differ per row. Controlled: every edit hands back a new list with each untouched row as it was. Rows may carry fields of their own (`KeyValueRows<T extends KeyValueRow>`), and then `createRow` makes a blank one, which the type requires. The group is a fieldset named by `label` (`hideLabel` keeps it for assistive technology only); `empty` is what an empty list says; `helper`, `error` and `disabled` are as on a field. Every word is the caller's (`labels`), with English defaults made from the column names by `keyValueRowsLabels(keyLabel, valueLabel)`. Types: `KeyValueRow`, `KeyValueRowsLabels`, `KeyValueRowsProps`. Stories: `KeyValueRows`.
213
+
214
+ **`TableTwoLineCell` is new**: a value over a quieter line, each cut on one line, among the read-only table cells. The `value` is set in the cell's own register and the `detail` under it is a caption in the secondary ink, so a row of these is exactly two lines tall whatever they hold. `mono` (`TableTwoLineCellMono`: `value`, `detail` or `both`) sets a literal in the mono face. A mark stands centred against both lines, as a column's hidden `icon` or a row's read `mark`, and in a grid's stacked rows the lines give the row its baseline. A cut line shows its whole words on hover; `title` speaks for the whole cell instead, and `titleWhenCut={false}` leaves the words to a `Tooltip` around the cell. Types: `TableTwoLineCellProps`, `TableTwoLineCellMono`. Stories: `TableCells` Two Line Cells, and its right to left, stacked and both themes variants.
215
+
216
+ **`RailList` is new**: a directory in a card, the groups its items are filed in as a rail beside the chosen group's list, so a long catalogue reads as a few short lists. The rail is a dense `SidebarNav`, each group (`RailListItem`) a row with its `count`, read as part of its name with `labels.counted` ("Chat, 6 apps"), the chosen one (`value`) raised and `aria-current`, with an optional quiet `note` under the rows. A group with an `href` is a link a reader can open in a new tab, and a plain click chooses it in place (`onChange`); without one it is a button. The chosen group's `description` stands over the list on a hairline, and a grid at the top of the list draws no second rule. Under 44rem of the card's own width the rail goes and a `Select` of the same groups, named by the same `label`, joins the bar across the top, so the same directory in a page and in a sheet needs nothing set. `toolbar` is the bar's content: given as a function, it is handed the picker to place among its own controls; given as content, the picker leads it. `renderLink` draws each row's link for a router. Every word is the caller's (`labels`, with `RAIL_LIST_LABELS` as the defaults). Types: `RailListItem`, `RailListLabels`, `RailListProps`. Stories: `RailList`.
217
+
218
+ ### Text
219
+
220
+ **A `Text` cut by `truncate` or `clamp` shows its whole words on hover.** While the words are cut, the element's title carries them whole, read from the element as it is shown; while they fit, it carries none. The cut is measured when the pointer arrives, so the title never goes stale after a resize or a new value, and nothing is measured until then. A `title` the caller passes always wins, and `titleWhenCut={false}` leaves the title to whatever already shows the words, such as a `Tooltip`. Story: `Text` Whole Words When Cut.
221
+
222
+ ## Changes in 0.85.0
223
+
224
+ ### What needs a person, and who gets something
225
+
226
+ **`AttentionList` is new**: what needs a person, as rows in one card like the page's others rather than a tinted banner each. A row is the tone's glyph in its feedback ink, the subject's picture (`media`, decorative), a one-line `title` over a quieter `meta` line, a Details control that opens `details` under the row, and the one fix (`action`) at the row's end in the page's own button. Problems come first, then warnings, then notes (`AttentionTone`: `danger`, `warning`, `info`), each in the order given. The card's header counts each tone with its glyph and says the counts in words to a screen reader; no strip, frame or ground takes the worst row's tone. Past `collapseAfter` rows (3) the rest fold behind "Show N more", and one row past the limit is shown rather than folded. Every row is a subgrid of the list's columns, so each Details and each fix stand in one column whatever their widths, and every title starts on one line whether or not its row has a picture; under the phone breakpoint the picture goes and Details and the fix take a line of their own. Each tone is said in words before its title. Every word is the caller's (`labels`, with `ATTENTION_LIST_LABELS` as the defaults), and so is the heading's level (`headingLevel`). Nothing is drawn when nothing needs attention. Types: `AttentionItem`, `AttentionListLabels`, `AttentionListProps`, `AttentionTone`. Stories: `AttentionList`.
227
+
228
+ **`MemberPicker` is new**: who gets something, as one list of groups with a three-state box and a member count, each opening to its members (a face, a name and one quiet line), under a live count of everyone reached. A group's grant reaches whoever joins it later, so a group is chosen whole and its members are overrides: a member a chosen group reaches says so ("Through Product"), unticking it leaves it out of that grant (`except`), and a member of an unchosen group is chosen on its own (`members`). Choosing or unchoosing a group clears the overrides inside it. A group's box is ticked only when the group is chosen and reaches every member, and mixed when it is chosen with members left out or when its members are chosen on their own, so a box never says a newcomer is covered when they are not. A member listed under two groups is a row in each, and either row's box answers for the member. A member's name and line are its box's target, as a group's name is. Members in no group (`ungrouped`) follow the groups. The boxes are native checkboxes in the compact step, the open control is a small ghost `IconButton` with `aria-expanded`, and every word is the caller's (`labels`, with `MEMBER_PICKER_LABELS` speaking of agents by default). `chosenMembers(groups, ungrouped, value)` is the set a value reaches. Types: `MemberPickerGroup`, `MemberPickerLabels`, `MemberPickerMember`, `MemberPickerProps`, `MemberPickerValue`. Stories: `MemberPicker`.
229
+
230
+ ### Choices
231
+
232
+ **A chosen `ChoiceCards` card opens its `detail` under its own row.** An option's `detail` (a narrower choice that belongs to it, such as which client a sign-in uses) is drawn while the card is chosen, as an item of the grid straight after its card and across every column; the grid packs densely, so the cards after it on that row fill the row back in and the rest follow the detail. It draws no frame of its own, since what it holds is usually a framed list, and it is a group named by its card, controlled by the card's radio. Stories: `ChoiceCards` Detail Under The Chosen Card, Detail Under Its Own Row.
233
+
234
+ **A `ChoiceCards` tag can say a state.** `tagTone` (`ChoiceCardTagTone`: `success`, `warning`, `danger`, `info`) draws the tag in that tone's feedback ink and line, in the card's own pill; without it the pill stays neutral. Pass words as the `tag`, not a `Tag`, which drew a pill inside the pill. Story: `ChoiceCards` Tag Tones.
235
+
236
+ **`ChoiceCards` takes `minCardWidth="xs"`** (8rem), for four short cards with a picture and one line across a form's column. Story: `ChoiceCards` Four Across.
237
+
238
+ **`ChoiceList` sets its tag, radio and reason as a card does**, so a list nested in a chosen card's detail reads as part of it. Its `tag` is the pill a `ChoiceCards` card draws its tag in, in the secondary ink, with the strong edge on the chosen row (it was an 11px capital label). Its radio is the compact control step, 14px (was 13px), the compact `Checkbox`'s box, centred on the label's first line. A disabled choice's `disabledReason` takes a line of its own under its detail, where it ran on after the detail as the detail's next clause. Props are unchanged.
239
+
240
+ ### Tables, chips, values and steps
241
+
242
+ **A stacked `DataGrid` row keeps its labels and its actions on the right lines.** In the card rows a grid stacks into, a value that led with a picture (a mark beside a name and its host) was labelled on its picture's line, the bottom of the mark, and the row's `action` cells stood alone on a line after every value. The words after a leading picture with no words of its own (an `svg`, an `img`, or a box holding nothing but one) now give the row its baseline, so the label stands on the name's line; a monogram avatar or an avatar stack, whose initials already gave it, keeps the words beside it centred on it. The actions stand on the row's first line at its end, and only that line gives up its width to them: every line after it spans the row. The compact phone row (`phoneRows="compact"`) is unchanged. Action cells carry `crewlet-data-grid__cell--action`. Story: `DataGrid` Stacked Rows Led By A Mark.
243
+
244
+ **A `SegmentedControl` chip's count is a figure in the chip's own ink.** In the chips layout a count kept a tab's inset pill, so on the chosen chip its figure lay on the accent fill at 1.4:1. It now draws no pill and takes the chip's ink: on-accent on the chosen chip, secondary on the others. Story: `SegmentedControl` Chips With Counts.
245
+
246
+ **A block `Copyable` shows its value whole**, wrapped at any character with every space kept, where it held the value to one line and scrolled it out of a narrow column behind an ellipsis. **An inline `Copyable` takes the size and ink of the row it stands in** (in the mono face, if asked), where it was a fixed 12px in the secondary ink. A caller that relied on the smaller inline value sets the size on the element around it. Stories: `Copyable` Inline In A Detail List, Block Long Address Narrow.
247
+
248
+ **`Disclosure` takes `flush`**: its chevron and its panel start on the line its box starts on, for a section opened under a sentence (a request's arguments under the sentence that asks for it). Only the trigger's hover ground and focus ring reach into the gutter, as a flush `Button`'s do. Story: `Disclosure` Flush Under A Question.
249
+
250
+ **`StepList` takes a `pending` state** for a step not yet started: the steps a check never reached, or the ones still to come. It draws a dashed circle (`CircleDashedGlyph`) in the tertiary ink, says "Not started" after the step's words (`labels.pending` changes it, to "Not reached" for example), and sets the step's words in the same quiet ink. `StepState` and `STEP_STATES` include it, so a `Record<StepState, ...>` of a caller's own needs a `pending` entry. Stories: `StepList` Not Reached, Under Way.
251
+
252
+ ### Icons
253
+
254
+ **`@crewlethq/icons` adds the Cloudflare, Linear, PostgreSQL, Sentry and Stripe marks** to `VendorMark` (`cloudflare`, `linear`, `postgresql`, `sentry`, `stripe`), each Simple Icons' drawing from simple-icons 16.35.0 (CC0 1.0) in its brand's hex. Sentry's violet falls under 2:1 on the dark ground, so the dark themes draw it in the text colour, as Sentry publishes its glyph for a dark ground and as Mattermost's already is. The trademark notes name the new owners.
255
+
208
256
  ## Changes in 0.84.2
209
257
 
210
258
  **A directory's lines run to the hairline.** In a `ListDetail` the list pane kept its end inset (`--crewlet-list-detail-gutter`, 32px) before the hairline, and a `DirectoryList` inside it kept its own step and its scrollbar's gutter as well, so a line's state ("In use", "Connected") ended 60px before the line beside it. A list pane holding a `DirectoryList` now gives its end inset back: the lines end at the groups' own step before the scrollbar, as the rail's rows end at its edge. Every other list keeps the inset, and folded to one pane the list takes the screen's inset as before. Props are unchanged.
@@ -1,4 +1,4 @@
1
- export { Accordion, AccordionItem } from '../chunk-XNC3M4IN.js';
1
+ export { Accordion, AccordionItem } from '../chunk-E2QPZGLG.js';
2
2
  import '../chunk-ULYHDP7U.js';
3
3
  import '../chunk-D2GT3CR4.js';
4
4
  import '../chunk-PQADV6P6.js';
@@ -1,8 +1,8 @@
1
- export { AGENT_HANDOFF_LABELS, AgentHandoffPanel } from '../chunk-DD7RBNT4.js';
1
+ export { AGENT_HANDOFF_LABELS, AgentHandoffPanel } from '../chunk-XH55NRHO.js';
2
2
  import '../chunk-4MJN2KN6.js';
3
3
  import '../chunk-WFCWPXJN.js';
4
4
  import '../chunk-EBVZHVPD.js';
5
- import '../chunk-LVJGN5II.js';
5
+ import '../chunk-NAHA62WD.js';
6
6
  import '../chunk-5ILRWUE7.js';
7
7
  import '../chunk-SKGOKLJD.js';
8
8
  import '../chunk-PIYJNCN7.js';
@@ -1,5 +1,5 @@
1
1
  export { ARTIFACT_BAR_LABELS, ArtifactBar, ArtifactVersionChip } from '../chunk-HKUZ2GYX.js';
2
- import '../chunk-36WK24AI.js';
2
+ import '../chunk-EVM6GYZ2.js';
3
3
  import '../chunk-AZYE7NR4.js';
4
4
  import '../chunk-MVKUE4FI.js';
5
5
  import '../chunk-EGMQURBR.js';
@@ -0,0 +1,82 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type HeadingLevel } from '../utils/headingLevel.js';
3
+ /** How much an item matters: something broken, something owed, or news. */
4
+ export type AttentionTone = 'danger' | 'warning' | 'info';
5
+ /** One thing that needs a person. */
6
+ export interface AttentionItem {
7
+ key: string;
8
+ tone: AttentionTone;
9
+ /** What it is about, as a picture beside the title: a vendor's mark. Decorative. */
10
+ media?: ReactNode;
11
+ /** One line: what is wrong. */
12
+ title: ReactNode;
13
+ /** One quieter line: who it stops, since when. */
14
+ meta?: ReactNode;
15
+ /** Its one fix, at the row's end: a small secondary button or link. */
16
+ action?: ReactNode;
17
+ /** What else there is to read, behind Details: the recorded sentence, the remedy at length. */
18
+ details?: ReactNode;
19
+ }
20
+ export interface AttentionListLabels {
21
+ /** The panel's heading. */
22
+ title: string;
23
+ /** What each tone is called to a screen reader, before the title. */
24
+ tones: Record<AttentionTone, string>;
25
+ details: string;
26
+ /** The control that shows the rows past the first few: "Show 3 more". */
27
+ more: (hidden: number) => string;
28
+ less: string;
29
+ /** The heading's counts in words, for a screen reader: "1 problem, 2 warnings". */
30
+ summary: (counts: Record<AttentionTone, number>) => string;
31
+ }
32
+ export declare const ATTENTION_LIST_LABELS: AttentionListLabels;
33
+ export interface AttentionListProps {
34
+ items: readonly AttentionItem[];
35
+ /** Rows shown before the rest fold behind "Show N more". */
36
+ collapseAfter?: number | undefined;
37
+ /** Any of the words, each tone's on its own: the rest keep their defaults. */
38
+ labels?: (Partial<Omit<AttentionListLabels, 'tones'>> & {
39
+ tones?: Partial<Record<AttentionTone, string>> | undefined;
40
+ }) | undefined;
41
+ /** The heading's level, where the surrounding outline does not decide it. */
42
+ headingLevel?: HeadingLevel | undefined;
43
+ className?: string | undefined;
44
+ }
45
+ /**
46
+ * What needs a person, as one quiet panel of rows instead of a banner each:
47
+ * the tone's glyph in its ink, the subject's mark, a one-line title over a
48
+ * quieter line, and the one fix at the row's end in the page's own button,
49
+ * so the colour of a warning never fights the colour of its action. What
50
+ * there is to read at length opens under the row, behind Details. Problems
51
+ * first, then warnings, then notes, each in the order given.
52
+ *
53
+ * THE PANEL IS A CARD LIKE ITS NEIGHBOURS: the page's own surface, hairline
54
+ * and corner, and a header in the card's own type with the counts at its end.
55
+ * No strip, border or ground takes the worst row's tone. A tinted frame made
56
+ * the panel the loudest thing on the page whatever it held, and said the
57
+ * same thing as the glyphs inside it a second time; severity is each row's
58
+ * glyph, and the header's counts are those glyphs again, small, in the
59
+ * tertiary type.
60
+ *
61
+ * MANY ROWS FOLD TO A SUMMARY: the header counts them by tone, the first few
62
+ * stay, and the rest open on request, so a bad day does not push the page's
63
+ * own content off the screen.
64
+ *
65
+ * ONE SET OF COLUMNS FOR EVERY ROW: glyph, mark, words, Details, the fix. The
66
+ * rows are subgrids of the list, so each Details and each fix stands in one
67
+ * column whatever the width of the button beside it, every title starts on
68
+ * one line whether or not its row has a mark, and what opens under a row
69
+ * starts on the title's own line. Were each row to size its own end slot,
70
+ * four fixes of four widths would put four Details at four places. Details
71
+ * and the fold are the kit's small ghost Button, the step of the fix beside
72
+ * them.
73
+ *
74
+ * The tone is said in words before each title ("Problem: ..."), for a reader
75
+ * who cannot tell the glyphs apart, and each Details names the body it opens
76
+ * by an id taken from the row's position, never its key, since a key may hold
77
+ * a space and an id reference list splits on whitespace.
78
+ *
79
+ * Nothing when there is nothing: a panel that says all is well is noise
80
+ * beside a page that shows it.
81
+ */
82
+ export declare function AttentionList({ items, collapseAfter, labels: overrides, headingLevel, className }: AttentionListProps): import("react").JSX.Element | null;
@@ -0,0 +1,3 @@
1
+ import './AttentionList.css';
2
+ export { AttentionList, ATTENTION_LIST_LABELS } from './AttentionList.js';
3
+ export type { AttentionItem, AttentionListLabels, AttentionListProps, AttentionTone } from './AttentionList.js';
@@ -0,0 +1,9 @@
1
+ export { ATTENTION_LIST_LABELS, AttentionList } from '../chunk-AELKT34H.js';
2
+ import '../chunk-U2IQNDDR.js';
3
+ import '../chunk-AV2DXAEL.js';
4
+ import '../chunk-DGXZ635L.js';
5
+ import '../chunk-XSPCITPN.js';
6
+ import '../chunk-D2GT3CR4.js';
7
+ import '../chunk-PQADV6P6.js';
8
+ import '../chunk-UT6CW3C7.js';
9
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,212 @@
1
+ /*
2
+ * What needs a person: a card like the page's other panels (Card supplies the
3
+ * surface, the hairline, the corner and the header), rows a line or two high,
4
+ * and the tone in each row's glyph alone. Nothing here tints the frame: the
5
+ * row's action is the page's own button, and the panel sits as calmly as the
6
+ * cards beside it.
7
+ */
8
+
9
+ /* The header's counts: each tone's glyph in its ink beside a figure in the
10
+ header's quiet type, so the summary reads as the rows' glyphs, small. */
11
+ .crewlet-attention-list__counts {
12
+ display: inline-flex;
13
+ align-items: center;
14
+ gap: var(--spacing-3);
15
+ }
16
+
17
+ .crewlet-attention-list__count {
18
+ display: inline-flex;
19
+ align-items: center;
20
+ gap: var(--spacing-1);
21
+ color: var(--color-text-secondary);
22
+ font-size: var(--font-size-xs);
23
+ font-variant-numeric: tabular-nums;
24
+ }
25
+
26
+ .crewlet-attention-list__count.is-danger svg {
27
+ color: var(--color-feedback-danger-ink);
28
+ }
29
+
30
+ .crewlet-attention-list__count.is-warning svg {
31
+ color: var(--color-feedback-warning-ink);
32
+ }
33
+
34
+ .crewlet-attention-list__count.is-info svg {
35
+ color: var(--color-feedback-info-ink);
36
+ }
37
+
38
+ /*
39
+ * ONE SET OF COLUMNS FOR EVERY ROW. The list holds the tracks and each row is
40
+ * a subgrid of them, so a Details and a fix stand in one column down the
41
+ * panel whatever the width of each fix, every title starts on one line
42
+ * whether or not its row has a mark, and the body that opens under a row
43
+ * starts on that line too. The mark's track is there only when a row has a
44
+ * mark (`--media`), since an empty track still takes a gap each side.
45
+ */
46
+ .crewlet-attention-list__rows {
47
+ --crewlet-attention-list-line: calc(var(--font-size-sm) * var(--font-line-height-normal));
48
+
49
+ display: grid;
50
+ grid-template-columns: [glyph] auto [text] minmax(0, 1fr) [details] auto [action] auto [end];
51
+ column-gap: var(--spacing-2);
52
+ margin: 0;
53
+ padding: 0;
54
+ list-style: none;
55
+ }
56
+
57
+ .crewlet-attention-list__rows--media {
58
+ grid-template-columns: [glyph] auto [media] auto [text] minmax(0, 1fr) [details] auto [action] auto [end];
59
+ }
60
+
61
+ .crewlet-attention-list__item {
62
+ display: grid;
63
+ grid-column: 1 / -1;
64
+ grid-template-columns: subgrid;
65
+ }
66
+
67
+ .crewlet-attention-list__item + .crewlet-attention-list__item {
68
+ border-top: 1px solid var(--color-border-default);
69
+ }
70
+
71
+ /* A ghost Details takes no gutter back here: it stands in a column of its
72
+ own, and pulled out it would reach into the words before it. */
73
+ .crewlet-attention-list__row {
74
+ --crewlet-btn-flush-outdent: 0px;
75
+
76
+ display: grid;
77
+ grid-column: 1 / -1;
78
+ grid-template-columns: subgrid;
79
+ align-items: center;
80
+ min-height: var(--size-row-lg);
81
+ padding: var(--spacing-2) var(--spacing-4);
82
+ }
83
+
84
+ /* THE GLYPH STANDS ON THE TITLE'S LINE, as a Callout's does: a box one title
85
+ line tall at the row's top, the glyph centred in it. Centred on the row, it
86
+ would sit beside the second line of a title that wraps (a phone's width
87
+ wraps them). A row of one line is centred whole, since its line is the
88
+ row's middle. */
89
+ .crewlet-attention-list__glyph {
90
+ display: inline-flex;
91
+ grid-column: glyph;
92
+ align-self: start;
93
+ align-items: center;
94
+ block-size: var(--crewlet-attention-list-line);
95
+ }
96
+
97
+ .crewlet-attention-list__row:not(:has(.crewlet-attention-list__meta)) .crewlet-attention-list__glyph {
98
+ align-self: center;
99
+ }
100
+
101
+ .crewlet-attention-list__glyph.is-danger {
102
+ color: var(--color-feedback-danger-ink);
103
+ }
104
+
105
+ .crewlet-attention-list__glyph.is-warning {
106
+ color: var(--color-feedback-warning-ink);
107
+ }
108
+
109
+ .crewlet-attention-list__glyph.is-info {
110
+ color: var(--color-feedback-info-ink);
111
+ }
112
+
113
+ /* A MARK IS CENTRED ON THE TWO LINES, as a table row centres its mark: it is
114
+ the height of the pair, not of a title's line. */
115
+ .crewlet-attention-list__media {
116
+ display: inline-flex;
117
+ grid-column: media;
118
+ }
119
+
120
+ .crewlet-attention-list__text {
121
+ display: flex;
122
+ grid-column: text;
123
+ flex-direction: column;
124
+ min-width: 0;
125
+ }
126
+
127
+ .crewlet-attention-list__line {
128
+ overflow: hidden;
129
+ color: var(--color-text-primary);
130
+ font-size: var(--font-size-sm);
131
+ font-weight: var(--font-weight-medium);
132
+ line-height: var(--font-line-height-normal);
133
+ text-overflow: ellipsis;
134
+ white-space: nowrap;
135
+ }
136
+
137
+ .crewlet-attention-list__meta {
138
+ overflow: hidden;
139
+ color: var(--color-text-secondary);
140
+ font-size: var(--font-size-xs);
141
+ text-overflow: ellipsis;
142
+ white-space: nowrap;
143
+ }
144
+
145
+ /* Details and the fix are each a column of their own (see the rows). */
146
+ .crewlet-attention-list__end {
147
+ display: contents;
148
+ }
149
+
150
+ .crewlet-attention-list__details {
151
+ grid-column: details;
152
+ }
153
+
154
+ .crewlet-attention-list__action {
155
+ display: inline-flex;
156
+ grid-column: action;
157
+ justify-self: end;
158
+ }
159
+
160
+ .crewlet-attention-list__details[aria-expanded='true'] svg {
161
+ transform: rotate(180deg);
162
+ }
163
+
164
+ /* What opens under a row starts on its title's line and keeps the card's edge. */
165
+ .crewlet-attention-list__body {
166
+ grid-column: text / end;
167
+ padding: 0 var(--spacing-4) var(--spacing-3) 0;
168
+ color: var(--color-text-secondary);
169
+ font-size: var(--font-size-xs);
170
+ overflow-wrap: anywhere;
171
+ }
172
+
173
+ /* The fold's control on a row of its own, its words on the card's text edge,
174
+ where every glyph stands. */
175
+ .crewlet-attention-list__foot {
176
+ padding: var(--spacing-1) var(--spacing-4);
177
+ border-top: 1px solid var(--color-border-default);
178
+ }
179
+
180
+ @media (width < 640px) {
181
+ /* No mark, and Details and the fix wrap onto a line of their own under the
182
+ words, Details first on the title's line. */
183
+ .crewlet-attention-list__rows,
184
+ .crewlet-attention-list__rows--media {
185
+ grid-template-columns: [glyph] auto [text] minmax(0, 1fr) [end];
186
+ }
187
+
188
+ .crewlet-attention-list__row {
189
+ --crewlet-btn-flush-outdent: initial;
190
+ }
191
+
192
+ .crewlet-attention-list__media {
193
+ display: none;
194
+ }
195
+
196
+ .crewlet-attention-list__line,
197
+ .crewlet-attention-list__meta {
198
+ white-space: normal;
199
+ }
200
+
201
+ .crewlet-attention-list__row:not(:has(.crewlet-attention-list__meta)) .crewlet-attention-list__glyph {
202
+ align-self: start;
203
+ }
204
+
205
+ .crewlet-attention-list__end {
206
+ display: flex;
207
+ grid-column: text / end;
208
+ flex-wrap: wrap;
209
+ align-items: center;
210
+ gap: var(--spacing-2);
211
+ }
212
+ }
@@ -1,8 +1,8 @@
1
- export { AvatarPicker } from '../chunk-22CU7V4J.js';
1
+ export { AvatarPicker } from '../chunk-K2HEYQJL.js';
2
2
  import '../chunk-SHH7UD5U.js';
3
3
  import '../chunk-EC6EUIAD.js';
4
- import '../chunk-AYKXMIOR.js';
5
4
  import '../chunk-LNQSNXGJ.js';
5
+ import '../chunk-AYKXMIOR.js';
6
6
  import '../chunk-XZY6S3UC.js';
7
7
  import '../chunk-AZYE7NR4.js';
8
8
  import '../chunk-MVKUE4FI.js';
@@ -1,8 +1,8 @@
1
- export { CHANGE_LIST_COLLAPSE_OVER, CHANGE_LIST_LABELS, ChangeList, ChangeListItems, shortenUnchanged } from '../chunk-AOJ6ZA77.js';
1
+ export { CHANGE_LIST_COLLAPSE_OVER, CHANGE_LIST_LABELS, ChangeList, ChangeListItems, shortenUnchanged } from '../chunk-3MFRTZH6.js';
2
2
  import '../chunk-LR4IWUWQ.js';
3
3
  import '../chunk-LBGKLYBY.js';
4
4
  import '../chunk-CYQBDZ6M.js';
5
- import '../chunk-LVJGN5II.js';
5
+ import '../chunk-NAHA62WD.js';
6
6
  import '../chunk-ULYHDP7U.js';
7
7
  import '../chunk-D2GT3CR4.js';
8
8
  import '../chunk-PQADV6P6.js';
@@ -17,8 +17,17 @@ export interface ChoiceCardOption {
17
17
  label: ReactNode;
18
18
  /** A picture of the choice before its name: a product's mark, a glyph. Decorative; the label names it. */
19
19
  media?: ReactNode;
20
- /** A short word beside the choice's name, read as part of its name: "Company default". */
20
+ /**
21
+ * A short word beside the choice's name, read as part of its name: "Company
22
+ * default". Words, drawn in the card's own pill: a Tag handed in here was a
23
+ * pill inside a pill. Give it a tone with `tagTone`.
24
+ */
21
25
  tag?: ReactNode;
26
+ /**
27
+ * The tag's state, where it says one ("Not reviewed" in the warning ink and
28
+ * line); left out, the neutral pill.
29
+ */
30
+ tagTone?: ChoiceCardTagTone | undefined;
22
31
  /** One plain line saying what choosing it means. */
23
32
  description?: ReactNode;
24
33
  /** A few short facts, one to a line under the description, each its name and its value. */
@@ -37,9 +46,19 @@ export interface ChoiceCardOption {
37
46
  * the same lines as the cards beside it rather than growing one.
38
47
  */
39
48
  disabledReasonAt?: number | undefined;
49
+ /**
50
+ * What the choice opens once chosen, drawn on a line of its own straight
51
+ * under the chosen card's row: a second, narrower choice that belongs to
52
+ * this one (which OAuth client a sign-in uses). Shown only while the card is
53
+ * chosen, so the cards stay one shape and the detail is never a dead
54
+ * control.
55
+ */
56
+ detail?: ReactNode;
40
57
  }
41
- /** The narrowest a card stands: `sm` 15rem, `md` 20rem, `lg` 24rem. */
42
- export type ChoiceCardsMinWidth = 'sm' | 'md' | 'lg';
58
+ /** The states a card's tag can say, each drawn in its feedback ink and line. */
59
+ export type ChoiceCardTagTone = Extract<Tone, 'success' | 'warning' | 'danger' | 'info'>;
60
+ /** The narrowest a card stands: `xs` 8rem, `sm` 15rem, `md` 20rem, `lg` 24rem. */
61
+ export type ChoiceCardsMinWidth = 'xs' | 'sm' | 'md' | 'lg';
43
62
  /**
44
63
  * How much room a card's lines take: `comfortable`, the default, or
45
64
  * `compact`, tighter padding and gaps and a smaller picture, for a set of
@@ -54,9 +73,11 @@ export interface ChoiceCardsProps {
54
73
  value: string | null;
55
74
  onChange: (value: string) => void;
56
75
  /**
57
- * The narrowest a card stands, which decides how many share a row: `sm`
58
- * (15rem) for three compact cards across a form's wide column, `md` (20rem)
59
- * for a short name and facts, `lg` (24rem) for choices with more to say. A
76
+ * The narrowest a card stands, which decides how many share a row: `xs`
77
+ * (8rem) for four short cards with a picture and one line, such as where a
78
+ * thing comes from, `sm` (15rem) for three compact cards across a form's
79
+ * wide column, `md` (20rem) for a short name and facts, `lg` (24rem) for
80
+ * choices with more to say. A
60
81
  * form's column holds one to a row; a wider surface two or three. Under any
61
82
  * of them a phone's width stacks the cards, one to a row.
62
83
  */
@@ -90,5 +111,13 @@ export interface ChoiceCardsProps {
90
111
  *
91
112
  * A FACT'S STATE IS NEVER ONLY A COLOUR: the dot sits beside words that say
92
113
  * it ("Docker 24.0.7 found", "E2B key not set").
114
+ *
115
+ * A CHOSEN CARD'S DETAIL OPENS UNDER ITS OWN ROW, not under the whole grid:
116
+ * it is an item of the grid, after its card, across every column, and the
117
+ * grid packs densely, so the cards after it on that row fill the row back in
118
+ * and the rest follow the detail. Under the grid, with a second row of cards
119
+ * between, the chosen card and its options read as two separate questions.
120
+ * It draws no frame of its own: what it holds is usually a framed list, and a
121
+ * frame round a frame is two boxes for one choice.
93
122
  */
94
123
  export declare function ChoiceCards({ label, options, value, onChange, minCardWidth, density, className, }: ChoiceCardsProps): import("react").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import './ChoiceCards.css';
2
2
  export { ChoiceCards } from './ChoiceCards.js';
3
- export type { ChoiceCardFact, ChoiceCardOption, ChoiceCardsDensity, ChoiceCardsMinWidth, ChoiceCardsProps } from './ChoiceCards.js';
3
+ export type { ChoiceCardFact, ChoiceCardOption, ChoiceCardsDensity, ChoiceCardsMinWidth, ChoiceCardsProps, ChoiceCardTagTone, } from './ChoiceCards.js';
@@ -1,3 +1,3 @@
1
- export { ChoiceCards } from '../chunk-B7NX425Z.js';
1
+ export { ChoiceCards } from '../chunk-JDMJVVVQ.js';
2
2
  import '../chunk-CYQBDZ6M.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -28,10 +28,17 @@
28
28
  minmax(min(100%, var(--crewlet-choice-cards-min)), 1fr)
29
29
  );
30
30
  grid-auto-rows: auto;
31
+ /* DENSE, for a chosen card's detail: it spans every column after its card,
32
+ and the cards after it on that row pack back in before it (see below). */
33
+ grid-auto-flow: row dense;
31
34
  column-gap: var(--spacing-3);
32
35
  row-gap: 0;
33
36
  }
34
37
 
38
+ .crewlet-choice-cards--xs {
39
+ --crewlet-choice-cards-min: 8rem;
40
+ }
41
+
35
42
  .crewlet-choice-cards--sm {
36
43
  --crewlet-choice-cards-min: 15rem;
37
44
  }
@@ -194,6 +201,32 @@
194
201
  border-color: var(--color-border-strong);
195
202
  }
196
203
 
204
+ /* A TAG THAT SAYS A STATE takes its feedback ink and line, in the card's own
205
+ pill: a kit Tag handed in drew a second pill inside this one. */
206
+ .crewlet-choice-cards__tag.is-success,
207
+ .crewlet-choice-cards__card.is-checked .crewlet-choice-cards__tag.is-success {
208
+ border-color: var(--color-feedback-success-line);
209
+ color: var(--color-feedback-success-ink);
210
+ }
211
+
212
+ .crewlet-choice-cards__tag.is-warning,
213
+ .crewlet-choice-cards__card.is-checked .crewlet-choice-cards__tag.is-warning {
214
+ border-color: var(--color-feedback-warning-line);
215
+ color: var(--color-feedback-warning-ink);
216
+ }
217
+
218
+ .crewlet-choice-cards__tag.is-danger,
219
+ .crewlet-choice-cards__card.is-checked .crewlet-choice-cards__tag.is-danger {
220
+ border-color: var(--color-feedback-danger-line);
221
+ color: var(--color-feedback-danger-ink);
222
+ }
223
+
224
+ .crewlet-choice-cards__tag.is-info,
225
+ .crewlet-choice-cards__card.is-checked .crewlet-choice-cards__tag.is-info {
226
+ border-color: var(--color-feedback-info-line);
227
+ color: var(--color-feedback-info-ink);
228
+ }
229
+
197
230
  /*
198
231
  * THE NAME IS THE TITLE LINE'S STRUT: at least the title step tall, its words
199
232
  * centred in it. The title wraps (a tag that does not fit takes a line of its
@@ -371,3 +404,19 @@
371
404
  transition: none;
372
405
  }
373
406
  }
407
+
408
+ /*
409
+ * A CHOSEN CARD'S DETAIL: the narrower choice it opens, on a line of its own
410
+ * straight under the chosen card's row (an item of the grid after its card,
411
+ * across every column, packed densely), so it reads as part of that choice and
412
+ * not as a second question. NO FRAME OF ITS OWN: what it holds is usually a
413
+ * framed list, and a tinted, bordered panel round it was a box in a box. It
414
+ * keeps the gap a row of cards keeps below it.
415
+ */
416
+ .crewlet-choice-cards__detail {
417
+ display: grid;
418
+ grid-column: 1 / -1;
419
+ gap: var(--spacing-2);
420
+ min-width: 0;
421
+ margin-block-end: var(--spacing-3);
422
+ }
@@ -53,8 +53,8 @@ export interface ChoiceListProps {
53
53
  * NATIVE RADIOS, so the arrow keys move the choice and Tab leaves the group as
54
54
  * the platform does, and every row is its radio's label, so the whole row
55
55
  * takes the pointer. A disabled choice is skipped by the arrows, keeps its
56
- * words at full contrast, and says why on its detail line. A choice's `panel` is drawn under it only while it is
57
- * selected, which is how a list ends in "Something else" with a field of its
56
+ * words at full contrast, and says why on a line of its own under its detail.
57
+ * A choice's `panel` is drawn under it only while it is selected, which is how a list ends in "Something else" with a field of its
58
58
  * own without a second control beside the list.
59
59
  */
60
60
  export declare function ChoiceList({ options, value, onChange, label, footer, disabled, className }: ChoiceListProps): import("react").JSX.Element;
@@ -1,3 +1,3 @@
1
- export { ChoiceList } from '../chunk-6RW2MUTY.js';
1
+ export { ChoiceList } from '../chunk-XU7RQNT6.js';
2
2
  import '../chunk-2YTOOH3A.js';
3
3
  import '../chunk-ODEQTPFM.js';