@starci/grammar 0.12.0 → 0.12.1

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 (60) hide show
  1. package/README.md +18 -7
  2. package/dist/.build-stamp.json +4 -4
  3. package/dist/common/components-navigation.css +8 -6
  4. package/dist/common/components-overlays.css +0 -10
  5. package/dist/common/registry.d.ts +4 -4
  6. package/dist/common/renderers-forms.d.ts +1 -1
  7. package/dist/common/renderers-navigation.d.ts +2 -2
  8. package/dist/common/rule-catalog.generated.d.ts +1 -0
  9. package/dist/common/rule-catalog.generated.d.ts.map +1 -1
  10. package/dist/common/rule-catalog.generated.js +10 -1
  11. package/dist/common/rule-catalog.generated.js.map +1 -1
  12. package/dist/common/styles.css +104 -50
  13. package/dist/core/branch/DropdownMenu/index.d.ts +3 -8
  14. package/dist/core/branch/DropdownMenu/index.d.ts.map +1 -1
  15. package/dist/core/branch/DropdownMenu/index.js +3 -5
  16. package/dist/core/branch/DropdownMenu/index.js.map +1 -1
  17. package/dist/core/branch/Tooltip/index.d.ts +13 -0
  18. package/dist/core/branch/Tooltip/index.d.ts.map +1 -1
  19. package/dist/core/branch/Tooltip/index.js +40 -1
  20. package/dist/core/branch/Tooltip/index.js.map +1 -1
  21. package/dist/core/composite/AvatarButton/index.d.ts.map +1 -1
  22. package/dist/core/composite/AvatarButton/index.js +1 -1
  23. package/dist/core/composite/AvatarButton/index.js.map +1 -1
  24. package/dist/core/composite/IdentityLockup/index.d.ts +4 -2
  25. package/dist/core/composite/IdentityLockup/index.d.ts.map +1 -1
  26. package/dist/core/composite/IdentityLockup/index.js +1 -1
  27. package/dist/core/composite/IdentityLockup/index.js.map +1 -1
  28. package/dist/core/composition/Sidebar/index.d.ts +8 -1
  29. package/dist/core/composition/Sidebar/index.d.ts.map +1 -1
  30. package/dist/core/composition/Sidebar/index.js +45 -27
  31. package/dist/core/composition/Sidebar/index.js.map +1 -1
  32. package/dist/core/composition/WorkspaceShell/index.d.ts.map +1 -1
  33. package/dist/core/composition/WorkspaceShell/index.js +4 -3
  34. package/dist/core/composition/WorkspaceShell/index.js.map +1 -1
  35. package/dist/core/primitive/Button/index.d.ts +1 -1
  36. package/dist/core/primitive/Button/index.d.ts.map +1 -1
  37. package/dist/core/primitive/Button/index.js +3 -3
  38. package/dist/core/primitive/Button/index.js.map +1 -1
  39. package/dist/core/primitive/IconButton/index.d.ts +2 -2
  40. package/dist/core/primitive/IconButton/index.d.ts.map +1 -1
  41. package/dist/core/primitive/IconButton/index.js +1 -1
  42. package/dist/core/primitive/IconButton/index.js.map +1 -1
  43. package/dist/core/primitive/Input/index.d.ts +3 -1
  44. package/dist/core/primitive/Input/index.d.ts.map +1 -1
  45. package/dist/core/primitive/Input/index.js +3 -3
  46. package/dist/core/primitive/Input/index.js.map +1 -1
  47. package/dist/core/primitive/PlainPressable/index.d.ts +3 -1
  48. package/dist/core/primitive/PlainPressable/index.d.ts.map +1 -1
  49. package/dist/core/primitive/PlainPressable/index.js +1 -1
  50. package/dist/core/primitive/PlainPressable/index.js.map +1 -1
  51. package/dist/core/primitive/SearchField/index.d.ts +3 -1
  52. package/dist/core/primitive/SearchField/index.d.ts.map +1 -1
  53. package/dist/core/primitive/SearchField/index.js +2 -2
  54. package/dist/core/primitive/SearchField/index.js.map +1 -1
  55. package/dist/core/primitive/TextAction/index.d.ts.map +1 -1
  56. package/dist/core/primitive/TextAction/index.js +3 -1
  57. package/dist/core/primitive/TextAction/index.js.map +1 -1
  58. package/dist/core/primitive/actionStyles.d.ts +1 -1
  59. package/dist/core/primitive/actionStyles.d.ts.map +1 -1
  60. package/package.json +1 -1
package/README.md CHANGED
@@ -17,7 +17,7 @@ npm install @starci/grammar @heroui/react react react-dom
17
17
  npm install ./.claude/packages/grammar
18
18
  ```
19
19
 
20
- The package needs Node.js 20 or newer. Its peer dependencies are React 18+, `@xyflow/react` 12 (for `FlowGraph`) and `@heroui/react`
20
+ The package needs Node.js 22 or newer. Its peer dependencies are React 18+, `@xyflow/react` 12 (for `FlowGraph`) and `@heroui/react`
21
21
  3.2+. Load the HeroUI stylesheet once in the app, as HeroUI's own setup describes. Then import
22
22
  exactly one Grammar family stylesheet. Each family sheet already imports Common anatomy first.
23
23
 
@@ -36,6 +36,18 @@ its root from one place. Heritage does not re-export Common. It exports `heritag
36
36
 
37
37
  ## Usage
38
38
 
39
+ ### App shell
40
+
41
+ The [app-shell canon](../../knowledge/ui/composition/app-shell.yaml) owns `FE-APP-SHELL-1` through `FE-APP-SHELL-7`.
42
+ The `Compositions/App shell` stories show the fixed shell, grouped sidebar, icon rail and mobile drawer.
43
+
44
+ - `size="control"` is available on `Button`, `IconButton`, `TextAction`, `PlainPressable`, `IdentityLockup`, `Input` and `SearchField`, alongside `Switch`, `Avatar` and `AvatarButton`.
45
+ - `SidebarItem.badge`, `badgeLabel` and `badgeMax` show and announce unread counts in both sidebar presentations. `SidebarGroup.placement="end"` places settings groups after the main groups and pushes them to the bottom.
46
+ - The collapsed Sidebar uses Grammar's internal `AnchoredTooltip` on hover and focus. Its native popover reaches the top layer without leaving the family DOM scope or changing HeroUI's collection anatomy. `onAction` runs for every activated destination, including the selected item, so a drawer can close consistently.
47
+ - A fixed `WorkspaceShell` frames its `compactHeader` slot as the mobile opener band; pass a client `Drawer` with an ellipsis `IconButton` trigger. The `navigationDrawer` form owns the same band when it supplies the opener.
48
+ - `AvatarButton seed` passes the stable identity id to Grammar's shared `Avatar`, which draws the deterministic local DiceBear image; an uploaded `src` takes precedence.
49
+ - `DropdownMenuItem.mark` accepts a decorative identity mark and is mutually exclusive with `iconSource`. A destructive item uses `tone="danger"`; the existing `negative` tone has the same vendor presentation.
50
+
39
51
  ### Common (neutral structure only)
40
52
 
41
53
  ```tsx
@@ -184,7 +196,7 @@ className and no size. An item takes `id`, `label`, `description`, `shortcut`, `
184
196
  - `iconSource`: a glyph component (the app's Heroicons). Grammar draws it in HeroUI's leading position at the canon icon size,
185
197
  20px (`size-5`, `Icon` `leading`; the Heroicons rule R93 / FE-ICON). HeroUI's own docs example draws its sample glyph at
186
198
  `size-4`, which is example content and not a component default, so 20px is StarCi's icon rule and not a vendor override.
187
- - `leading`: a node instead of a glyph, e.g. an identity mark (`<Avatar size="sm" shape="rounded" isDecorative />`).
199
+ - `mark`: a decorative node instead of `iconSource`, e.g. an identity mark (`<Avatar size="sm" shape="rounded" isDecorative />`). The public type rejects both props together.
188
200
  - `tone: "danger"`: HeroUI's `danger` variant, which colours the label and the glyph. Sign out, delete, remove, leave workspace
189
201
  and revoke are destructive; the lint rule `starci-fe/destructive-menu-entry-needs-danger-tone` refuses such an entry without it.
190
202
 
@@ -199,7 +211,7 @@ an item with a submenu).
199
211
  placement="bottom end"
200
212
  entries={[
201
213
  { kind: "section", id: "workspace", label: "Workspace", selection: { mode: "single", selectedIds, onChange },
202
- items: [{ id: "hakuen", label: "Hakuen", description: "Owner", leading: <Avatar name="Hakuen" size="sm" shape="rounded" isDecorative /> }] },
214
+ items: [{ id: "hakuen", label: "Hakuen", description: "Owner", mark: <Avatar name="Hakuen" size="sm" shape="rounded" isDecorative /> }] },
203
215
  { kind: "section", id: "account", items: [{ id: "profile", label: "Profile", description: "Name and photo", iconSource: UserIcon }] },
204
216
  { kind: "section", id: "session", items: [{ id: "sign-out", label: "Sign out", tone: "danger", iconSource: ArrowRightStartOnRectangleIcon }] },
205
217
  ]}
@@ -264,7 +276,7 @@ dismissal and focus return.
264
276
  shape in any state, no hover effect, a zoom-out on press, a focus ring, and no zoom under
265
277
  `prefers-reduced-motion`. `AvatarButton` is a circle-only avatar built on it (an account-menu
266
278
  trigger) and `IdentityLockup` a mark beside a title and a muted subtitle with no caret (a workspace
267
- switcher trigger). All three work as the `trigger` of `DropdownMenu` and `Popover`. `IdentityLockup`'s mark is a transparent, uncropped square by default (`markShape="rounded"` opts in to a
279
+ switcher trigger). All three work as the `trigger` of `DropdownMenu` and `Popover`. `IdentityLockup`'s mark and monogram fallback are transparent, with foreground-colored initials; the mark is an uncropped square by default (`markShape="rounded"` opts in to a
268
280
  corner) and `Avatar` takes `shape="square" | "rounded"`.
269
281
 
270
282
  Personal avatars are circles. Pass the user or identity id as `seed` on `Avatar`, `AvatarButton`
@@ -288,9 +300,8 @@ MarkdownTableFrame, MediaFrame, Rail, SectionHeader, StaticStateRow, SurfaceAcco
288
300
  SurfaceCard, SurfaceCopyGroup, SurfaceListCard, VerticalScrollRegion.
289
301
 
290
302
  **Compositions (9).** BottomNav, ChatWorkspace, Footer, NavigationFeatureNav, PageContainer,
291
- PrimaryRailLayout, Sidebar, TopBar, WorkspaceShell. Storybook also pins three page recipes to
292
- each family: a settings form, a data list with a filter drawer and pagination, and a mobile home
293
- with TopBar, BottomNav and a Toast.
303
+ PrimaryRailLayout, Sidebar, TopBar, WorkspaceShell. Storybook pins settings and data-list content
304
+ recipes to each family; the mobile app recipes reuse the fixed App shell with its left navigation drawer.
294
305
 
295
306
  `COMMON_GRAMMAR_COMPONENTS` is the frozen registry of the published renderers.
296
307
  `COMMON_FORMS_COMPONENTS`, `COMMON_OVERLAYS_COMPONENTS` and `COMMON_NAVIGATION_COMPONENTS` are the
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "schema": "starci/grammar-build-stamp@1",
3
3
  "package": "@starci/grammar",
4
- "version": "0.12.0",
4
+ "version": "0.12.1",
5
5
  "algorithm": "starci/grammar-source-digest@1",
6
- "sourceDigest": "sha256:fd2b712405d87230cd1736101068d562483cd3c0b8b4ef4d629bb9944354842f",
7
- "distDigest": "sha256:1a7c5eb6dcb25a1ef5bfba338d3c374fce07a3d1f534fe8f830b66e2ca1893b3",
8
- "builtAt": "2026-10-25T11:48:36.769Z"
6
+ "sourceDigest": "sha256:f6fce286c3f714d14372fa19725d4d9b92b8ed98d49342f022224250b09a1e14",
7
+ "distDigest": "sha256:53e4a14158e106244c9d13a98bdde5ad226f689c070e7170ecd71d58bb7a0120",
8
+ "builtAt": "2026-10-25T12:13:44.249Z"
9
9
  }
@@ -341,9 +341,11 @@
341
341
 
342
342
  /* ---------- TopBar ---------- */
343
343
  .starci-core-top-bar {
344
+ box-sizing: border-box;
344
345
  display: flex;
345
346
  min-width: 0;
346
- min-block-size: 3.5rem;
347
+ block-size: 4rem;
348
+ min-block-size: 4rem;
347
349
  align-items: center;
348
350
  gap: var(--grammar-row-gap, 0.75rem);
349
351
  padding-block: 0.5rem;
@@ -351,7 +353,7 @@
351
353
  padding-inline-start: max(var(--grammar-page-inset, 1rem), env(safe-area-inset-left));
352
354
  padding-inline-end: max(var(--grammar-page-inset, 1rem), env(safe-area-inset-right));
353
355
  border-block-end: 1px solid var(--separator, var(--border, CanvasText));
354
- background: var(--background, Canvas);
356
+ background: var(--surface, Canvas);
355
357
  color: var(--foreground, CanvasText);
356
358
  }
357
359
 
@@ -673,7 +675,7 @@
673
675
 
674
676
  /*
675
677
  * A square brand mark (Avatar shape="square"): a transparent box with no corner and no clipping; the image is contained, so a round,
676
- * square or wide logo shows whole in its own shape. The monogram fallback keeps its tint (see the lockup) so initials stay legible.
678
+ * square or wide logo shows whole in its own shape.
677
679
  */
678
680
  .starci-core-avatar[data-grammar-avatar-shape="square"] {
679
681
  overflow: visible !important;
@@ -794,10 +796,10 @@
794
796
  white-space: nowrap;
795
797
  }
796
798
 
797
- /* A monogram sits on an accent tint. */
799
+ /* The workspace monogram shares the mark's transparent box and uses the foreground text color. */
798
800
  .starci-core-identity-lockup [data-grammar-avatar-fallback] {
799
- background-color: var(--accent-soft, Canvas) !important;
800
- color: var(--accent-soft-foreground, CanvasText);
801
+ background-color: transparent !important;
802
+ color: var(--foreground, CanvasText) !important;
801
803
  font-weight: 600;
802
804
  }
803
805
 
@@ -415,16 +415,6 @@
415
415
  justify-content: center;
416
416
  }
417
417
 
418
- /* A leading node (an identity mark) sits in a box at least as big as the 20px a glyph gets (the canon icon rule, `Icon` `leading`), centred. */
419
- [data-grammar-menu-leading] {
420
- display: inline-flex;
421
- flex: none;
422
- min-inline-size: 1.25rem;
423
- min-block-size: 1.25rem;
424
- align-items: center;
425
- justify-content: center;
426
- }
427
-
428
418
  [data-grammar-menu-mark] > * {
429
419
  width: 100%;
430
420
  height: 100%;
@@ -21,12 +21,12 @@ export declare const COMMON_GRAMMAR_COMPONENTS: Readonly<{
21
21
  readonly DragItem: ({ children, isDisabled, onDragStart, onDragEnd, isSelected, isInvalid, isDashed, leadingColor }: import("./renderers-navigation.js").DragItemProps) => import("react").JSX.Element;
22
22
  readonly FlowGraph: ({ label, nodes, edges, selectedId, onSelect, height, isInteractive, showControls, layout, emptyLabel, isLoading, className, }: import("./renderers-navigation.js").FlowGraphProps) => import("react").JSX.Element;
23
23
  readonly Footer: ({ label, brand, groups, legal, externalHint, children, className }: import("./renderers-navigation.js").FooterProps) => import("react").JSX.Element;
24
- readonly IdentityLockup: ({ title, subtitle, logoSrc, markShape, onPress, isDisabled }: import("./renderers-navigation.js").IdentityLockupProps) => import("react").JSX.Element;
24
+ readonly IdentityLockup: ({ title, subtitle, logoSrc, markShape, size, onPress, isDisabled }: import("./renderers-navigation.js").IdentityLockupProps) => import("react").JSX.Element;
25
25
  readonly Image: ({ src, alt, aspect, fit, fallback, loading, srcSet, sizes, width, height, onLoadStateChange, plate, className, ...assetSlot }: import("./renderers-navigation.js").ImageProps) => import("react").JSX.Element;
26
26
  readonly Link: ({ children, href, kind, isCurrent, visited, externalHint, externalIcon, isDisabled, onFollow, className, }: import("./renderers-navigation.js").LinkProps) => import("react").JSX.Element;
27
27
  readonly ListBox: ({ label, items, sections, inset, selectionMode, selectedIds, defaultSelectedIds, onSelectionChange, onAction, emptyContent, isLoading, loadingRows, className, }: import("./renderers-navigation.js").ListBoxProps) => import("react").JSX.Element;
28
28
  readonly Pagination: ({ label, page, pageCount, onPageChange, siblingCount, previousLabel, nextLabel, pageLabel, summary, className, }: import("./renderers-navigation.js").PaginationProps) => import("react").JSX.Element;
29
- readonly PlainPressable: ({ children, "aria-label": ariaLabel, onPress, isDisabled, shape, className }: import("./renderers-navigation.js").PlainPressableProps) => import("react").JSX.Element;
29
+ readonly PlainPressable: ({ children, "aria-label": ariaLabel, onPress, isDisabled, shape, size, className }: import("./renderers-navigation.js").PlainPressableProps) => import("react").JSX.Element;
30
30
  readonly Rating: ({ label, value, defaultValue, onChange, max, isReadOnly, isDisabled, valueLabel, icon, name, className, }: import("./renderers-navigation.js").RatingProps) => import("react").JSX.Element;
31
31
  readonly Stepper: ({ label, steps, currentStepId, orientation, onStepSelect, stateLabel, renderMarker, className, isLoading, }: import("./renderers-navigation.js").StepperProps) => import("react").JSX.Element;
32
32
  readonly TagGroup: ({ label, items, selectionMode, selectedIds, defaultSelectedIds, onSelectionChange, onRemove, removeLabel, emptyContent, size, className, }: import("./renderers-navigation.js").TagGroupProps) => import("react").JSX.Element;
@@ -60,7 +60,7 @@ export declare const COMMON_GRAMMAR_COMPONENTS: Readonly<{
60
60
  readonly Form: ({ children, label, id, onSubmit, onReset, action, method, validationErrors, validationBehavior, isPending, }: import("./renderers-forms.js").FormProps) => import("react").JSX.Element;
61
61
  readonly NumberField: ({ id, placeholder, value, defaultValue, onValueChange, minValue, maxValue, step, formatOptions, hideSteppers, variant: requestedVariant, isSkeleton, ...field }: import("./renderers-forms.js").NumberFieldProps) => import("react").JSX.Element;
62
62
  readonly RadioGroup: ({ options, value, defaultValue, onValueChange, orientation, variant: requestedVariant, ...field }: import("./renderers-forms.js").RadioGroupProps) => import("react").JSX.Element;
63
- readonly SearchField: ({ id, placeholder, value, defaultValue, onValueChange, onSubmit, onClear, isPending, clearLabel, variant: requestedVariant, isSkeleton, onBlur, onPaste, autoFocus, ...field }: import("./renderers-forms.js").SearchFieldProps) => import("react").JSX.Element;
63
+ readonly SearchField: ({ id, placeholder, value, defaultValue, onValueChange, onSubmit, onClear, isPending, clearLabel, variant: requestedVariant, size, isSkeleton, onBlur, onPaste, autoFocus, ...field }: import("./renderers-forms.js").SearchFieldProps) => import("react").JSX.Element;
64
64
  readonly SegmentedControl: ({ options, value, defaultValue, onValueChange, width, label, isLabelHidden, description, errorMessage, isInvalid, isRequired, isDisabled, isReadOnly, name, isSkeleton, }: import("./renderers-forms.js").SegmentedControlProps) => import("react").JSX.Element;
65
65
  readonly Select: ({ options, placeholder, value, defaultValue, onValueChange, isPending, isSkeleton, variant: requestedVariant, ...field }: import("./renderers-forms.js").SelectProps) => import("react").JSX.Element;
66
66
  readonly Slider: ({ value, defaultValue, onValueChange, onValueCommit, minValue, maxValue, step, formatOptions, thumbLabels, orientation, label, isLabelHidden, description, errorMessage, isInvalid, isRequired, isDisabled, isReadOnly, name, }: import("./renderers-forms.js").SliderProps) => import("react").JSX.Element;
@@ -82,7 +82,7 @@ export declare const COMMON_GRAMMAR_COMPONENTS: Readonly<{
82
82
  readonly IconButton: ({ source, label, variant, size, isFloating, isActive, isDisabled, isSkeleton, onPress, "aria-controls": controls, "aria-expanded": expanded, badge, badgeLabel, badgeMax, }: import("./renderers.js").IconButtonProps) => import("react").JSX.Element;
83
83
  readonly IconTile: ({ source, artwork, ariaLabel, tone, size, isSkeleton, }: import("./renderers.js").IconTileProps) => import("react").JSX.Element;
84
84
  readonly IncludedMark: ({ className, label, ...props }: import("./renderers.js").IncludedMarkProps) => import("react").JSX.Element;
85
- readonly Input: ({ id, name, label, isLabelHidden, kind: kindName, variant: requestedVariant, placeholder, defaultValue, value, hint, errorMessage, isError, isDisabled, isRequired, isSkeleton, isReadOnly, isCopyable, copyLabel, copiedLabel, copyIcon: CopyIcon, copiedIcon: CopiedIcon, onCopy, revealLabel, hideLabel, revealIcon: RevealIcon, hideIcon: HideIcon, onValueChange, onBlur, onPaste, autoFocus, }: import("./renderers.js").InputProps) => import("react").JSX.Element;
85
+ readonly Input: ({ id, name, label, isLabelHidden, kind: kindName, variant: requestedVariant, size, placeholder, defaultValue, value, hint, errorMessage, isError, isDisabled, isRequired, isSkeleton, isReadOnly, isCopyable, copyLabel, copiedLabel, copyIcon: CopyIcon, copiedIcon: CopiedIcon, onCopy, revealLabel, hideLabel, revealIcon: RevealIcon, hideIcon: HideIcon, onValueChange, onBlur, onPaste, autoFocus, }: import("./renderers.js").InputProps) => import("react").JSX.Element;
86
86
  readonly Label: ({ id, children, depth, as }: import("./renderers.js").LabelProps) => import("react").DetailedReactHTMLElement<{
87
87
  readonly id: string | undefined;
88
88
  readonly className: string;
@@ -33,7 +33,7 @@ export declare const COMMON_FORMS_COMPONENTS: Readonly<{
33
33
  readonly Form: ({ children, label, id, onSubmit, onReset, action, method, validationErrors, validationBehavior, isPending, }: import("./renderers-forms.js").FormProps) => import("react").JSX.Element;
34
34
  readonly NumberField: ({ id, placeholder, value, defaultValue, onValueChange, minValue, maxValue, step, formatOptions, hideSteppers, variant: requestedVariant, isSkeleton, ...field }: import("./renderers-forms.js").NumberFieldProps) => import("react").JSX.Element;
35
35
  readonly RadioGroup: ({ options, value, defaultValue, onValueChange, orientation, variant: requestedVariant, ...field }: import("./renderers-forms.js").RadioGroupProps) => import("react").JSX.Element;
36
- readonly SearchField: ({ id, placeholder, value, defaultValue, onValueChange, onSubmit, onClear, isPending, clearLabel, variant: requestedVariant, isSkeleton, onBlur, onPaste, autoFocus, ...field }: import("./renderers-forms.js").SearchFieldProps) => import("react").JSX.Element;
36
+ readonly SearchField: ({ id, placeholder, value, defaultValue, onValueChange, onSubmit, onClear, isPending, clearLabel, variant: requestedVariant, size, isSkeleton, onBlur, onPaste, autoFocus, ...field }: import("./renderers-forms.js").SearchFieldProps) => import("react").JSX.Element;
37
37
  readonly SegmentedControl: ({ options, value, defaultValue, onValueChange, width, label, isLabelHidden, description, errorMessage, isInvalid, isRequired, isDisabled, isReadOnly, name, isSkeleton, }: import("./renderers-forms.js").SegmentedControlProps) => import("react").JSX.Element;
38
38
  readonly Select: ({ options, placeholder, value, defaultValue, onValueChange, isPending, isSkeleton, variant: requestedVariant, ...field }: import("./renderers-forms.js").SelectProps) => import("react").JSX.Element;
39
39
  readonly Slider: ({ value, defaultValue, onValueChange, onValueCommit, minValue, maxValue, step, formatOptions, thumbLabels, orientation, label, isLabelHidden, description, errorMessage, isInvalid, isRequired, isDisabled, isReadOnly, name, }: import("./renderers-forms.js").SliderProps) => import("react").JSX.Element;
@@ -38,12 +38,12 @@ export declare const COMMON_NAVIGATION_COMPONENTS: Readonly<{
38
38
  readonly DragItem: ({ children, isDisabled, onDragStart, onDragEnd, isSelected, isInvalid, isDashed, leadingColor }: import("./renderers-navigation.js").DragItemProps) => import("react").JSX.Element;
39
39
  readonly FlowGraph: ({ label, nodes, edges, selectedId, onSelect, height, isInteractive, showControls, layout, emptyLabel, isLoading, className, }: import("./renderers-navigation.js").FlowGraphProps) => import("react").JSX.Element;
40
40
  readonly Footer: ({ label, brand, groups, legal, externalHint, children, className }: import("./renderers-navigation.js").FooterProps) => import("react").JSX.Element;
41
- readonly IdentityLockup: ({ title, subtitle, logoSrc, markShape, onPress, isDisabled }: import("./renderers-navigation.js").IdentityLockupProps) => import("react").JSX.Element;
41
+ readonly IdentityLockup: ({ title, subtitle, logoSrc, markShape, size, onPress, isDisabled }: import("./renderers-navigation.js").IdentityLockupProps) => import("react").JSX.Element;
42
42
  readonly Image: ({ src, alt, aspect, fit, fallback, loading, srcSet, sizes, width, height, onLoadStateChange, plate, className, ...assetSlot }: import("./renderers-navigation.js").ImageProps) => import("react").JSX.Element;
43
43
  readonly Link: ({ children, href, kind, isCurrent, visited, externalHint, externalIcon, isDisabled, onFollow, className, }: import("./renderers-navigation.js").LinkProps) => import("react").JSX.Element;
44
44
  readonly ListBox: ({ label, items, sections, inset, selectionMode, selectedIds, defaultSelectedIds, onSelectionChange, onAction, emptyContent, isLoading, loadingRows, className, }: import("./renderers-navigation.js").ListBoxProps) => import("react").JSX.Element;
45
45
  readonly Pagination: ({ label, page, pageCount, onPageChange, siblingCount, previousLabel, nextLabel, pageLabel, summary, className, }: import("./renderers-navigation.js").PaginationProps) => import("react").JSX.Element;
46
- readonly PlainPressable: ({ children, "aria-label": ariaLabel, onPress, isDisabled, shape, className }: import("./renderers-navigation.js").PlainPressableProps) => import("react").JSX.Element;
46
+ readonly PlainPressable: ({ children, "aria-label": ariaLabel, onPress, isDisabled, shape, size, className }: import("./renderers-navigation.js").PlainPressableProps) => import("react").JSX.Element;
47
47
  readonly Rating: ({ label, value, defaultValue, onChange, max, isReadOnly, isDisabled, valueLabel, icon, name, className, }: import("./renderers-navigation.js").RatingProps) => import("react").JSX.Element;
48
48
  readonly Stepper: ({ label, steps, currentStepId, orientation, onStepSelect, stateLabel, renderMarker, className, isLoading, }: import("./renderers-navigation.js").StepperProps) => import("react").JSX.Element;
49
49
  readonly TagGroup: ({ label, items, selectionMode, selectedIds, defaultSelectedIds, onSelectionChange, onRemove, removeLabel, emptyContent, size, className, }: import("./renderers-navigation.js").TagGroupProps) => import("react").JSX.Element;
@@ -12,6 +12,7 @@ export declare const RULE_FAMILY_COUNTS: Readonly<{
12
12
  readonly COVERAGE: 1;
13
13
  readonly CTA: 5;
14
14
  readonly DISCIPLINE: 3;
15
+ readonly "FE-APP-SHELL": 7;
15
16
  readonly FEEDBACK: 3;
16
17
  readonly FLOW: 5;
17
18
  readonly FOCUS: 6;
@@ -1 +1 @@
1
- {"version":3,"file":"rule-catalog.generated.d.ts","sourceRoot":"","sources":["../../src/common/rule-catalog.generated.ts"],"names":[],"mappings":"AAQA,qFAAqF;AACrF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiCpB,CAAA;AAEX,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,MAAM,CA4MnD,CAAA"}
1
+ {"version":3,"file":"rule-catalog.generated.d.ts","sourceRoot":"","sources":["../../src/common/rule-catalog.generated.ts"],"names":[],"mappings":"AAQA,qFAAqF;AACrF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkCpB,CAAA;AAEX,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,EAAE,aAAa,CAAC,MAAM,CAoNnD,CAAA"}
@@ -3,7 +3,7 @@
3
3
  * Regenerate with node packages/grammar/scripts/generate-rule-catalog.mjs [knowledgeDir].
4
4
  * Canonical declarations are rules[].id in the YAML knowledge topics.
5
5
  * References, scale rows, cases and closed addresses contribute no additional rules.
6
- * 32 families, 171 rules.
6
+ * 33 families, 178 rules.
7
7
  */
8
8
  /** The number of declared rule ids in each family, never expanded into addresses. */
9
9
  export const RULE_FAMILY_COUNTS = Object.freeze({
@@ -19,6 +19,7 @@ export const RULE_FAMILY_COUNTS = Object.freeze({
19
19
  "COVERAGE": 1, // ui/composition/coverage.yaml
20
20
  "CTA": 5, // ui/composition/cta.yaml
21
21
  "DISCIPLINE": 3, // ui/composition/taste.yaml
22
+ "FE-APP-SHELL": 7, // ui/composition/app-shell.yaml
22
23
  "FEEDBACK": 3, // ui/composition/feedback.yaml
23
24
  "FLOW": 5, // ui/presentation/text-flow.yaml
24
25
  "FOCUS": 6, // ui/proof/focus.yaml
@@ -97,6 +98,14 @@ export const CANONICAL_RULE_IDS = Object.freeze([
97
98
  "DISCIPLINE-1",
98
99
  "DISCIPLINE-2",
99
100
  "DISCIPLINE-3",
101
+ // FE-APP-SHELL
102
+ "FE-APP-SHELL-1",
103
+ "FE-APP-SHELL-2",
104
+ "FE-APP-SHELL-3",
105
+ "FE-APP-SHELL-4",
106
+ "FE-APP-SHELL-5",
107
+ "FE-APP-SHELL-6",
108
+ "FE-APP-SHELL-7",
100
109
  // FEEDBACK
101
110
  "FEEDBACK-1",
102
111
  "FEEDBACK-2",
@@ -1 +1 @@
1
- {"version":3,"file":"rule-catalog.generated.js","sourceRoot":"","sources":["../../src/common/rule-catalog.generated.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rule-catalog.generated.js","sourceRoot":"","sources":["../../src/common/rule-catalog.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,qFAAqF;AACrF,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC5C,MAAM,EAAE,CAAC,EAAE,8BAA8B;IACzC,QAAQ,EAAE,CAAC,EAAE,6BAA6B;IAC1C,QAAQ,EAAE,CAAC,EAAE,6BAA6B;IAC1C,SAAS,EAAE,CAAC,EAAE,+BAA+B;IAC7C,UAAU,EAAE,CAAC,EAAE,gCAAgC;IAC/C,OAAO,EAAE,CAAC,EAAE,sBAAsB;IAClC,YAAY,EAAE,CAAC,EAAE,iCAAiC;IAClD,OAAO,EAAE,CAAC,EAAE,yBAAyB;IACrC,UAAU,EAAE,CAAC,EAAE,yBAAyB;IACxC,UAAU,EAAE,CAAC,EAAE,+BAA+B;IAC9C,KAAK,EAAE,CAAC,EAAE,0BAA0B;IACpC,YAAY,EAAE,CAAC,EAAE,4BAA4B;IAC7C,cAAc,EAAE,CAAC,EAAE,gCAAgC;IACnD,UAAU,EAAE,CAAC,EAAE,+BAA+B;IAC9C,MAAM,EAAE,CAAC,EAAE,iCAAiC;IAC5C,OAAO,EAAE,CAAC,EAAE,sBAAsB;IAClC,MAAM,EAAE,CAAC,EAAE,4BAA4B;IACvC,KAAK,EAAE,CAAC,EAAE,2BAA2B;IACrC,WAAW,EAAE,CAAC,EAAE,gCAAgC;IAChD,QAAQ,EAAE,CAAC,EAAE,6BAA6B;IAC1C,QAAQ,EAAE,CAAC,EAAE,8BAA8B;IAC3C,SAAS,EAAE,CAAC,EAAE,+BAA+B;IAC7C,QAAQ,EAAE,CAAC,EAAE,uBAAuB;IACpC,UAAU,EAAE,CAAC,EAAE,gCAAgC;IAC/C,SAAS,EAAE,EAAE,EAAE,+BAA+B;IAC9C,QAAQ,EAAE,CAAC,EAAE,8BAA8B;IAC3C,YAAY,EAAE,CAAC,EAAE,iCAAiC;IAClD,OAAO,EAAE,CAAC,EAAE,4BAA4B;IACxC,SAAS,EAAE,CAAC,EAAE,+BAA+B;IAC7C,OAAO,EAAE,EAAE,EAAE,sBAAsB;IACnC,MAAM,EAAE,CAAC,EAAE,4BAA4B;IACvC,OAAO,EAAE,CAAC,EAAE,6BAA6B;IACzC,IAAI,EAAE,EAAE,EAAE,mBAAmB;CACvB,CAAC,CAAA;AAEX,gFAAgF;AAChF,MAAM,CAAC,MAAM,kBAAkB,GAA0B,MAAM,CAAC,MAAM,CAAC;IACnE,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,QAAQ;IACR,SAAS;IACT,SAAS;IACT,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,eAAe;IACf,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,gBAAgB;IAChB,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,OAAO;IACP,YAAY;IACZ,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,aAAa;IACb,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,aAAa;IACb,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,aAAa;IACb,cAAc;IACd,cAAc;IACd,cAAc;IACd,cAAc;IACd,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,UAAU;IACV,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,WAAW;IACX,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,UAAU;IACV,UAAU;IACV,UAAU;IACV,UAAU;IACV,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,KAAK;IACL,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,OAAO;IACP,OAAO;IACP,OAAO;CACV,CAAC,CAAA"}
@@ -752,6 +752,20 @@
752
752
  visibility: hidden;
753
753
  }
754
754
 
755
+ /* Collection annotations use the native top layer to escape scroll clipping without leaving Grammar scope. */
756
+ .starci-core-tooltip-content[data-grammar-tooltip-annotation="true"] {
757
+ position: fixed;
758
+ inset: auto;
759
+ box-sizing: border-box;
760
+ max-inline-size: calc(100dvw - 1rem);
761
+ margin: 0;
762
+ border: 0;
763
+ white-space: normal;
764
+ overflow-wrap: anywhere;
765
+ opacity: 1;
766
+ visibility: visible;
767
+ }
768
+
755
769
  .starci-core-tooltip:hover > .starci-core-tooltip-content,
756
770
  .starci-core-tooltip:focus-within > .starci-core-tooltip-content {
757
771
  opacity: 1;
@@ -1823,9 +1837,10 @@
1823
1837
  }
1824
1838
 
1825
1839
  .starci-core-navigation-feature-nav {
1840
+ box-sizing: border-box;
1826
1841
  width: 100%;
1827
1842
  border-bottom: 1px solid var(--separator, var(--starci-core-separator, GrayText));
1828
- background: var(--background, var(--starci-core-canvas, Canvas));
1843
+ background: var(--surface, Canvas);
1829
1844
  color: var(--foreground, var(--starci-core-foreground, CanvasText));
1830
1845
  }
1831
1846
 
@@ -1835,33 +1850,18 @@
1835
1850
  top: 0;
1836
1851
  }
1837
1852
 
1838
- /*
1839
- * THE BAND PUBLISHES ITS OWN HEIGHT.
1840
- *
1841
- * A page under a sticky band needs exactly one number - where the band stops - to pin a rail
1842
- * beneath it, and until now every consumer RESTATED that number: `calc(4rem + 1px)` for the
1843
- * primary row and its separator, `calc(4rem + 2rem + 1px)` once a feature layer is stacked.
1844
- * Restated geometry is wrong the moment the band changes, so the band publishes it instead.
1845
- *
1846
- * It is published with `:has()` on the Grammar root, not measured in JS, because presence and
1847
- * stacking are already spelled by the data attributes these compositions emit, and a custom
1848
- * property set on the root inherits to every page inside it. The root - not `:root` - keeps the
1849
- * package inside its own boundary, which is the same reason no rule here touches the document.
1850
- *
1851
- * NOTHING is defined when no sticky band is present, so `var(--starci-core-band-offset, X)`
1852
- * still resolves to a consumer's own X exactly as it did before this property existed.
1853
- */
1853
+ /* The Grammar root publishes the sticky band offset, including its separator and optional feature layer. */
1854
1854
  .grammar-common-root:has(.starci-core-navigation-feature-nav[data-grammar-navigation-feature-nav-position="sticky"]),
1855
1855
  .grammar-common-root:has(.starci-core-subnav[data-grammar-subnav-position="sticky"]) {
1856
1856
  --starci-core-band-offset: calc(var(--starci-core-band-height, 0rem) + var(--starci-core-band-subnav-height, 0rem));
1857
1857
  }
1858
1858
 
1859
1859
  .grammar-common-root:has(.starci-core-navigation-feature-nav[data-grammar-navigation-feature-nav-position="sticky"]) {
1860
- --starci-core-band-height: calc(4rem + 1px);
1860
+ --starci-core-band-height: 4rem;
1861
1861
  }
1862
1862
 
1863
1863
  .grammar-common-root:has(.starci-core-navigation-feature-nav[data-grammar-navigation-feature-nav-position="sticky"][data-grammar-navigation-feature-nav-layers="two"]) {
1864
- --starci-core-band-height: calc(4rem + 2rem + 1px);
1864
+ --starci-core-band-height: 6rem;
1865
1865
  }
1866
1866
 
1867
1867
  /* A sticky Subnav stacks under the band, so it adds its own height and separator to the offset. */
@@ -1871,7 +1871,9 @@
1871
1871
 
1872
1872
  .starci-core-navigation-feature-nav-primary {
1873
1873
  display: grid !important;
1874
- min-height: 4rem;
1874
+ box-sizing: border-box;
1875
+ block-size: calc(4rem - 1px);
1876
+ min-height: calc(4rem - 1px);
1875
1877
  grid-template-columns: minmax(0, 1fr) auto auto !important;
1876
1878
  align-items: center;
1877
1879
  gap: var(--grammar-row-gap, 0.75rem);
@@ -1882,6 +1884,15 @@
1882
1884
  padding-inline: 0.75rem;
1883
1885
  }
1884
1886
 
1887
+ .starci-core-navigation-feature-nav[data-grammar-navigation-feature-nav-layers="one"] {
1888
+ block-size: 4rem;
1889
+ }
1890
+
1891
+ .starci-core-navigation-feature-nav[data-grammar-navigation-feature-nav-layers="one"] .starci-core-navigation-feature-nav-primary {
1892
+ block-size: 100%;
1893
+ min-height: 0;
1894
+ }
1895
+
1885
1896
  .starci-core-navigation-feature-nav-identity,
1886
1897
  .starci-core-navigation-feature-nav-navigation,
1887
1898
  .starci-core-navigation-feature-nav-compact-navigation,
@@ -1913,34 +1924,12 @@
1913
1924
  gap: var(--grammar-inline-gap, 0.5rem);
1914
1925
  }
1915
1926
 
1916
- /*
1917
- * THE BAND'S OWN CONTROLS MEET THE 44px TOUCH FLOOR.
1918
- *
1919
- * Every pressable in the two action slots was the vendor button's own height - 2.25rem on
1920
- * desktop and 2.5rem compact - so the language menu, the cart, the account button, the compact
1921
- * drawer trigger and the field-shaped search trigger all sat under the floor, on the surface a
1922
- * reader is most likely to touch. It is a MINIMUM, not a size: `min-inline-size` and
1923
- * `min-block-size` are properties the vendor's rules never set, so the glyph, the label, the
1924
- * paint and the corner are all untouched and no `!important` is owed to the components layer.
1925
- *
1926
- * The band does NOT grow. The primary row is 4rem with a 0.5rem block inset on each side, so
1927
- * 44px is 4px short of the 3rem it already offers a control, and `--starci-core-band-height`
1928
- * stays `calc(4rem + 1px)`. The floor is spelled on the pressable, never on the slot: a slot
1929
- * with a min-height would pad a row that has nothing in it.
1930
- *
1931
- * The feature layer is deliberately out of scope - its tabs are a Tabs branch, and a tab's
1932
- * target is that branch's to answer.
1933
- *
1934
- * The primary destinations in the `navigation` slot carry the identical selector: a
1935
- * `route`-appearance TextAction already meets the floor on its own (below), but the slot rule
1936
- * is the family's general-purpose net for ANY pressable a consumer puts there, the same way the
1937
- * action slots protect a control regardless of which leaf renders it.
1938
- */
1927
+ /* Navbar controls share one exact height; the feature layer keeps its own tab geometry. */
1939
1928
  .starci-core-navigation-feature-nav-actions :where(button, [role="button"], a[href]),
1940
1929
  .starci-core-navigation-feature-nav-navigation :where(button, [role="button"], a[href]),
1941
1930
  .starci-core-navigation-feature-nav-compact-navigation :where(button, [role="button"], a[href]) {
1942
- min-inline-size: 44px;
1943
- min-block-size: 44px;
1931
+ min-inline-size: var(--starci-core-control-min-size, 2.75rem);
1932
+ min-block-size: var(--starci-core-control-min-size, 2.75rem);
1944
1933
  }
1945
1934
 
1946
1935
  /*
@@ -2284,6 +2273,17 @@
2284
2273
  margin-block-end: 0;
2285
2274
  }
2286
2275
 
2276
+ .starci-core-workspace-shell-header[data-grammar-workspace-header-landmark="shell"] {
2277
+ box-sizing: border-box;
2278
+ display: flex;
2279
+ block-size: 4rem;
2280
+ align-items: center;
2281
+ padding-block: 0.5rem;
2282
+ padding-inline: var(--grammar-page-inset, 1rem);
2283
+ border-block-end: 1px solid var(--separator, GrayText);
2284
+ background: var(--surface, Canvas);
2285
+ }
2286
+
2287
2287
  .starci-core-workspace-shell[data-grammar-workspace-viewport="fixed"] > .starci-core-workspace-shell-layout {
2288
2288
  min-block-size: 0;
2289
2289
  flex: 1 1 0%;
@@ -2300,15 +2300,33 @@
2300
2300
  overscroll-behavior: contain;
2301
2301
  }
2302
2302
 
2303
+ @media (min-width: 48rem) and (max-width: 56rem) {
2304
+ .starci-core-workspace-shell[data-grammar-workspace-viewport="fixed"] > .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"] {
2305
+ grid-template-areas: "navigation primary" "navigation rail";
2306
+ grid-template-columns: var(--starci-core-workspace-navigation-track) minmax(0, 1fr);
2307
+ }
2308
+
2309
+ .starci-core-workspace-shell[data-grammar-workspace-viewport="fixed"] > .starci-core-workspace-shell-layout[data-grammar-workspace-navigation="present"][data-grammar-workspace-rail="absent"] {
2310
+ grid-template-areas: "navigation primary";
2311
+ }
2312
+ }
2313
+
2303
2314
  /* The compact opener row: the bar's height, an edge-to-edge divider, the opener at the inline start. */
2304
2315
  .starci-core-workspace-shell-opener {
2316
+ box-sizing: border-box;
2305
2317
  display: flex;
2306
- min-block-size: var(--starci-core-band-height, 3.5rem);
2318
+ block-size: 4rem;
2319
+ min-block-size: 4rem;
2307
2320
  align-items: center;
2308
2321
  gap: var(--grammar-inline-gap, 0.5rem);
2309
2322
  padding-inline: var(--grammar-page-inset, 1rem);
2323
+ padding-block: 0.5rem;
2310
2324
  border-block-end: 1px solid var(--separator, var(--starci-core-separator, GrayText));
2311
- background: var(--background, var(--starci-core-canvas, Canvas));
2325
+ background: var(--surface, Canvas);
2326
+ }
2327
+
2328
+ .starci-core-workspace-shell-compact-header.starci-core-workspace-shell-opener {
2329
+ display: none;
2312
2330
  }
2313
2331
 
2314
2332
  .starci-core-workspace-shell-opener-title {
@@ -2349,7 +2367,7 @@
2349
2367
  min-width: 0;
2350
2368
  flex-direction: column;
2351
2369
  overflow: hidden;
2352
- background: var(--background, var(--starci-core-canvas, Canvas));
2370
+ background: var(--surface, Canvas);
2353
2371
  color: var(--foreground, var(--starci-core-foreground, CanvasText));
2354
2372
  }
2355
2373
 
@@ -2397,6 +2415,7 @@
2397
2415
 
2398
2416
  .starci-core-sidebar[data-collapsed="true"] .starci-core-sidebar-list {
2399
2417
  align-items: center;
2418
+ gap: 1rem;
2400
2419
  padding: 0.5rem !important;
2401
2420
  }
2402
2421
 
@@ -2407,6 +2426,10 @@
2407
2426
  gap: 0.25rem !important;
2408
2427
  }
2409
2428
 
2429
+ .starci-core-sidebar-section[data-grammar-sidebar-end-start="true"] {
2430
+ margin-block-start: auto;
2431
+ }
2432
+
2410
2433
  .starci-core-sidebar[data-collapsed="true"] .starci-core-sidebar-section {
2411
2434
  align-items: center !important;
2412
2435
  }
@@ -2433,6 +2456,7 @@
2433
2456
  }
2434
2457
 
2435
2458
  .starci-core-sidebar-item {
2459
+ position: relative;
2436
2460
  display: flex;
2437
2461
  min-width: 0;
2438
2462
  align-items: center;
@@ -2455,7 +2479,8 @@
2455
2479
  background: var(--default, var(--starci-core-surface-secondary, Canvas));
2456
2480
  }
2457
2481
 
2458
- .starci-core-sidebar-item[data-selected="true"] {
2482
+ .starci-core-sidebar-item[data-selected="true"],
2483
+ .starci-core-sidebar-item[data-grammar-current="true"] {
2459
2484
  background: var(--accent-soft, var(--starci-core-accent, Highlight)) !important;
2460
2485
  color: var(--accent-soft-foreground, var(--starci-core-accent, HighlightText));
2461
2486
  }
@@ -2483,6 +2508,12 @@
2483
2508
  flex-shrink: 0;
2484
2509
  }
2485
2510
 
2511
+ .starci-core-sidebar:not([data-collapsed="true"]) .starci-core-sidebar-item-badge {
2512
+ position: static;
2513
+ flex: none;
2514
+ box-shadow: none;
2515
+ }
2516
+
2486
2517
  .starci-core-sidebar-footer {
2487
2518
  min-width: 0;
2488
2519
  padding: 0.75rem;
@@ -2638,7 +2669,7 @@
2638
2669
  }
2639
2670
  }
2640
2671
 
2641
- @media (max-width: 69.999rem) {
2672
+ @media (max-width: 47.999rem) {
2642
2673
  .starci-core-workspace-shell-layout[data-grammar-workspace-navigation-visibility="wide"] .starci-core-workspace-shell-navigation {
2643
2674
  display: none;
2644
2675
  }
@@ -2669,6 +2700,10 @@
2669
2700
  display: block;
2670
2701
  }
2671
2702
 
2703
+ .starci-core-workspace-shell-compact-header.starci-core-workspace-shell-opener {
2704
+ display: flex;
2705
+ }
2706
+
2672
2707
  .starci-core-workspace-shell-compact-navigation {
2673
2708
  position: sticky;
2674
2709
  z-index: 40;
@@ -2906,6 +2941,25 @@
2906
2941
  }
2907
2942
 
2908
2943
  /* --- Icon button: a HeroUI `Button` worn as a circle. --- */
2944
+ [data-grammar-control-size="control"],
2945
+ .starci-core-control-size .starci-core-field-skeleton-control {
2946
+ box-sizing: border-box;
2947
+ block-size: var(--starci-core-control-min-size, 2.75rem) !important;
2948
+ min-block-size: var(--starci-core-control-min-size, 2.75rem) !important;
2949
+ max-block-size: var(--starci-core-control-min-size, 2.75rem) !important;
2950
+ }
2951
+
2952
+ .starci-core-icon-button[data-grammar-control-size="control"] {
2953
+ inline-size: var(--starci-core-control-min-size, 2.75rem) !important;
2954
+ min-inline-size: var(--starci-core-control-min-size, 2.75rem) !important;
2955
+ max-inline-size: var(--starci-core-control-min-size, 2.75rem) !important;
2956
+ }
2957
+
2958
+ .starci-core-text-action[data-size="control"] {
2959
+ font-size: 0.875rem;
2960
+ line-height: 1.25rem;
2961
+ }
2962
+
2909
2963
  .starci-core-icon-button {
2910
2964
  border-radius: var(--starci-core-pill-radius, 999px) !important;
2911
2965
  }
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from "react";
2
2
  import { type OverlayOpenState } from "../../overlayScope.js";
3
3
  import { type IconSource } from "../../primitive/Icon/index.js";
4
- export type DropdownMenuItemTone = "neutral" | "danger";
4
+ export type DropdownMenuItemTone = "neutral" | "negative" | "danger";
5
5
  /** One command, destination or (inside a selectable section) checkable choice. */
6
6
  export type DropdownMenuItem = {
7
7
  readonly kind?: "item";
@@ -10,12 +10,7 @@ export type DropdownMenuItem = {
10
10
  readonly description?: string;
11
11
  /** Shortcut chord drawn with `Kbd`, e.g. `["command", "K"]`. Display only: the app binds the keys. */
12
12
  readonly shortcut?: readonly string[];
13
- /**
14
- * A node in the leading position instead of a glyph, e.g. an identity mark. It sits in a 20px slot (the same box a glyph gets) and
15
- * wins over `iconSource` or `mark` when also given.
16
- */
17
- readonly leading?: ReactNode;
18
- /** `danger` marks a destructive command (sign out, delete, remove, revoke): HeroUI's danger variant colours its label and glyph. */
13
+ /** `danger` marks a destructive command; `negative` has the same presentation. */
19
14
  readonly tone?: DropdownMenuItemTone;
20
15
  readonly isDisabled?: boolean;
21
16
  /** A destination: the item renders a real link. */
@@ -32,7 +27,7 @@ export type DropdownMenuItem = {
32
27
  /** Decorative identity artwork in the same leading icon box. The item's label supplies its name. */
33
28
  readonly mark?: ReactNode;
34
29
  });
35
- /** Checkable items: `single` draws a dot (radio semantics), `multiple` a check (checkbox semantics). */
30
+ /** Checkable items use HeroUI's default checkmark in both selection modes. */
36
31
  export type DropdownMenuSelection = {
37
32
  readonly mode: "single" | "multiple";
38
33
  readonly selectedIds: readonly string[];
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/branch/DropdownMenu/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACpG,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAGrE,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEvD,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAA;IAC5B,oIAAoI;IACpI,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAA;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,0GAA0G;IAC1G,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAClD,GAAG,CACE;IACE,4GAA4G;IAC5G,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CACxB,GACC;IACE,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;IAC3B,oGAAoG;IACpG,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAC5B,CACJ,CAAA;AAED,wGAAwG;AACxG,MAAM,MAAM,qBAAqB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;IACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;CAC9D,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,mBAAmB,CAAA;AAEtE,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAA;AAE3F,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IAC/C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC7C,CAAA;AAeD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,yDAM1B,iBAAiB,gCAkInB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/branch/DropdownMenu/index.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAyC,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACpG,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,+BAA+B,CAAA;AAGrE,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,GAAG,QAAQ,CAAA;AAEpE,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;IAC7B,sGAAsG;IACtG,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACrC,kFAAkF;IAClF,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAA;IACpC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,mDAAmD;IACnD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;IAC9B,0GAA0G;IAC1G,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAClD,GAAG,CACE;IACE,4GAA4G;IAC5G,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAA;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CACxB,GACC;IACE,QAAQ,CAAC,UAAU,CAAC,EAAE,KAAK,CAAA;IAC3B,oGAAoG;IACpG,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAC5B,CACJ,CAAA;AAED,8EAA8E;AAC9E,MAAM,MAAM,qBAAqB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;IACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IACvC,QAAQ,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,KAAK,IAAI,CAAA;CAC9D,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,+DAA+D;IAC/D,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC3C,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC7C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG,mBAAmB,CAAA;AAEtE,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,SAAS,CAAA;AAE3F,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IAC/C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAA;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,iBAAiB,EAAE,CAAA;IAC9C,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAA;CAC7C,CAAA;AAeD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY,GAAI,yDAM1B,iBAAiB,gCAgInB,CAAA"}
@@ -35,11 +35,9 @@ export const DropdownMenu = ({ trigger, entries, onAction, placement = "bottom s
35
35
  onAction?.(id);
36
36
  };
37
37
  const renderItem = (item, selectionMode) => {
38
- const tone = item.tone ?? "neutral";
39
- const icon = item.leading !== undefined
40
- ? _jsx("span", { "aria-hidden": "true", "data-grammar-menu-leading": "true", children: item.leading })
41
- : item.iconSource !== undefined ? _jsx(Icon, { source: item.iconSource, usage: "leading" })
42
- : item.mark === undefined || item.mark === null ? null : (_jsx("span", { "aria-hidden": "true", className: "starci-core-icon", "data-usage": "leading", "data-grammar-menu-mark": "true", children: item.mark }));
38
+ const tone = item.tone === "negative" ? "danger" : item.tone ?? "neutral";
39
+ const icon = item.iconSource !== undefined ? _jsx(Icon, { source: item.iconSource, usage: "leading" })
40
+ : item.mark === undefined || item.mark === null ? null : (_jsx("span", { "aria-hidden": "true", className: "starci-core-icon", "data-usage": "leading", "data-grammar-menu-mark": "true", children: item.mark }));
43
41
  const content = (_jsxs(_Fragment, { children: [selectionMode === undefined ? null : _jsx(HeroDropdown.ItemIndicator, {}), item.description === undefined ? icon : icon === null ? null : _jsx("div", { "data-grammar-menu-icon-slot": "true", children: icon }), item.description === undefined ? _jsx(HeroLabel, { children: item.label }) : (_jsxs("div", { "data-grammar-menu-copy": "true", children: [_jsx(HeroLabel, { children: item.label }), _jsx(HeroDescription, { children: item.description })] })), item.shortcut === undefined ? null : (_jsx(HeroKbd, { "data-grammar-menu-shortcut": "true", slot: "keyboard", variant: "light", children: kbdChordContent(item.shortcut) })), item.submenu === undefined ? null : _jsx(HeroDropdown.SubmenuIndicator, {})] }));
44
42
  const itemElement = (_jsx(HeroDropdown.Item, { id: item.id, textValue: item.label, variant: tone === "danger" ? "danger" : "default", isDisabled: item.isDisabled ?? false, ...(item.href === undefined ? {} : { href: item.href }), "data-grammar-menu-item": "true", "data-contract": "FOCUS-1 CTA-2", "data-grammar-tone": tone, children: content }, item.id));
45
43
  if (item.submenu === undefined)