prime-ui-kit 0.9.1 → 0.9.3

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 (169) hide show
  1. package/README.md +30 -12
  2. package/dist/chunks/{chunk-NHOWNIAR.js → chunk-6JTZOA5I.js} +1472 -671
  3. package/dist/chunks/{chunk-DB2Y3XXA.js → chunk-OAE4IQX2.js} +2845 -1732
  4. package/dist/chunks/{chunk-KCQFOORX.js → chunk-U5SR2LZR.js} +17 -4
  5. package/dist/color-picker.js +2 -2
  6. package/dist/components/button/Button.d.ts +19 -2
  7. package/dist/components/card/Card.d.ts +1 -1
  8. package/dist/components/code-block/CodeBlock.d.ts +1 -1
  9. package/dist/components/color-picker/ColorPicker.d.ts +1 -1
  10. package/dist/components/data-table/DataTable.d.ts +6 -1
  11. package/dist/components/data-table/Row.d.ts +3 -1
  12. package/dist/components/data-table/rows.d.ts +4 -0
  13. package/dist/components/data-table/types.d.ts +5 -0
  14. package/dist/components/digit-input/DigitInput.d.ts +6 -1
  15. package/dist/components/dnd/Dnd.d.ts +1 -1
  16. package/dist/components/dnd/dragSession.d.ts +9 -0
  17. package/dist/components/dnd/useDropTarget.d.ts +5 -0
  18. package/dist/components/dnd/useFlipList.d.ts +3 -3
  19. package/dist/components/drawer/Drawer.d.ts +8 -5
  20. package/dist/components/dropdown/Dropdown.d.ts +17 -0
  21. package/dist/components/index.d.ts +9 -2
  22. package/dist/components/input/Input.d.ts +16 -1
  23. package/dist/components/input/passwordStrength.d.ts +9 -0
  24. package/dist/components/kanban/Kanban.d.ts +129 -0
  25. package/dist/components/modal/Modal.d.ts +5 -2
  26. package/dist/components/page-toolbar/PageToolbar.d.ts +53 -0
  27. package/dist/components/progress-bar/ProgressBar.d.ts +16 -1
  28. package/dist/components/segmented-control/SegmentedControl.d.ts +5 -2
  29. package/dist/components/sparkline/Sparkline.d.ts +26 -0
  30. package/dist/components/tabs/Tabs.d.ts +5 -2
  31. package/dist/hooks/useEdgeOverflow.d.ts +16 -0
  32. package/dist/hooks/useMediaQuery.d.ts +7 -0
  33. package/dist/hooks/useSwipeDismiss.d.ts +34 -0
  34. package/dist/icons/registry.d.ts +2 -0
  35. package/dist/index.css +2977 -1306
  36. package/dist/index.d.ts +1 -0
  37. package/dist/index.js +17 -3
  38. package/dist/internal/CheckMark.d.ts +12 -0
  39. package/dist/internal/MorphText.d.ts +12 -0
  40. package/dist/internal/RollingNumber.d.ts +14 -0
  41. package/dist/internal/overlay/FloatingPanel.d.ts +3 -1
  42. package/dist/internal/overlay/useFloatingLayer.d.ts +11 -1
  43. package/dist/internal/surfaceDepth.d.ts +25 -0
  44. package/dist/internal/swatch.d.ts +4 -1
  45. package/dist/internal/touchTarget.d.ts +4 -0
  46. package/dist/layout/app-header/AppHeader.d.ts +110 -0
  47. package/dist/layout/app-shell/AppShell.d.ts +16 -11
  48. package/dist/layout/bottom-nav/BottomNav.d.ts +80 -0
  49. package/dist/layout/index.d.ts +5 -1
  50. package/dist/motion/celebrate.d.ts +18 -0
  51. package/dist/tokens/layers.d.ts +37 -0
  52. package/dist/tokens/naming.d.ts +1 -1
  53. package/dist/tokens/primitives.d.ts +4 -0
  54. package/dist/tokens/semantic.d.ts +122 -56
  55. package/dist/tokens/themes/dark.d.ts +10 -14
  56. package/package.json +3 -2
  57. package/src/components/accordion/COMPONENT.md +5 -5
  58. package/src/components/avatar/COMPONENT.md +1 -1
  59. package/src/components/badge/COMPONENT.md +2 -2
  60. package/src/components/banner/COMPONENT.md +1 -1
  61. package/src/components/button/COMPONENT.md +26 -5
  62. package/src/components/button/examples/download.tsx +45 -0
  63. package/src/components/button/examples/hold-to-confirm.tsx +23 -0
  64. package/src/components/button/examples/label-morph.tsx +33 -0
  65. package/src/components/card/COMPONENT.md +4 -2
  66. package/src/components/card/examples/narrow.tsx +2 -2
  67. package/src/components/card/examples/panel-chart.tsx +1 -1
  68. package/src/components/card/examples/variants.tsx +1 -1
  69. package/src/components/checkbox/examples/examples.module.css +5 -3
  70. package/src/components/code-block/COMPONENT.md +6 -6
  71. package/src/components/code-block/examples/overview.tsx +1 -1
  72. package/src/components/code-block/examples/variants.tsx +1 -1
  73. package/src/components/color-picker/COMPONENT.md +1 -1
  74. package/src/components/color-swatches/COMPONENT.md +5 -5
  75. package/src/components/command-menu/COMPONENT.md +1 -1
  76. package/src/components/crossfade/COMPONENT.md +1 -1
  77. package/src/components/crossfade/examples/overview.tsx +3 -3
  78. package/src/components/data-table/COMPONENT.md +24 -10
  79. package/src/components/data-table/examples/columns-visibility.tsx +167 -0
  80. package/src/components/digit-input/COMPONENT.md +15 -13
  81. package/src/components/digit-input/examples/examples.module.css +8 -0
  82. package/src/components/digit-input/examples/in-form.tsx +2 -5
  83. package/src/components/digit-input/examples/on-complete.tsx +7 -6
  84. package/src/components/digit-input/examples/sizes.tsx +1 -1
  85. package/src/components/divider/COMPONENT.md +1 -1
  86. package/src/components/dnd/COMPONENT.md +3 -3
  87. package/src/components/dnd/examples/examples.module.css +4 -4
  88. package/src/components/drawer/COMPONENT.md +17 -9
  89. package/src/components/drawer/examples/date-sheet.tsx +41 -0
  90. package/src/components/drawer/examples/examples.module.css +5 -0
  91. package/src/components/drawer/examples/placement.tsx +4 -2
  92. package/src/components/dropdown/COMPONENT.md +20 -6
  93. package/src/components/dropdown/examples/checkbox-items.tsx +48 -0
  94. package/src/components/dropdown/examples/examples.module.css +1 -1
  95. package/src/components/empty-page/COMPONENT.md +1 -1
  96. package/src/components/empty-page/examples/examples.module.css +1 -1
  97. package/src/components/example-frame/COMPONENT.md +1 -1
  98. package/src/components/input/COMPONENT.md +10 -1
  99. package/src/components/input/examples/password-strength.tsx +12 -0
  100. package/src/components/kanban/COMPONENT.md +181 -0
  101. package/src/components/kanban/examples/controlled.tsx +78 -0
  102. package/src/components/kanban/examples/examples.module.css +31 -0
  103. package/src/components/kanban/examples/limits.tsx +58 -0
  104. package/src/components/kanban/examples/narrow.tsx +76 -0
  105. package/src/components/kanban/examples/overview.tsx +130 -0
  106. package/src/components/kanban/examples/states.tsx +75 -0
  107. package/src/components/kanban/examples/structure.tsx +76 -0
  108. package/src/components/login-form/COMPONENT.md +5 -5
  109. package/src/components/login-form/examples/register.tsx +2 -2
  110. package/src/components/login-form/examples/reset-password.tsx +2 -2
  111. package/src/components/modal/COMPONENT.md +11 -8
  112. package/src/components/modal/examples/examples.module.css +2 -2
  113. package/src/components/notification/COMPONENT.md +2 -2
  114. package/src/components/page-content/COMPONENT.md +1 -1
  115. package/src/components/page-content/examples/examples.module.css +1 -1
  116. package/src/components/page-toolbar/COMPONENT.md +142 -0
  117. package/src/components/page-toolbar/examples/examples.module.css +16 -0
  118. package/src/components/page-toolbar/examples/narrow.tsx +103 -0
  119. package/src/components/page-toolbar/examples/overview.tsx +113 -0
  120. package/src/components/page-toolbar/examples/save-changes.tsx +40 -0
  121. package/src/components/page-toolbar/examples/without-search.tsx +60 -0
  122. package/src/components/popover/COMPONENT.md +5 -4
  123. package/src/components/progress-bar/COMPONENT.md +6 -2
  124. package/src/components/progress-bar/examples/examples.module.css +7 -0
  125. package/src/components/progress-bar/examples/milestone.tsx +43 -0
  126. package/src/components/progress-bar/examples/steps.tsx +35 -0
  127. package/src/components/progress-circle/COMPONENT.md +1 -1
  128. package/src/components/scroll-container/COMPONENT.md +1 -1
  129. package/src/components/segmented-control/COMPONENT.md +8 -8
  130. package/src/components/segmented-control/examples/full-width.tsx +1 -1
  131. package/src/components/select/COMPONENT.md +2 -1
  132. package/src/components/skeleton/COMPONENT.md +1 -1
  133. package/src/components/skeleton/examples/with-crossfade.tsx +3 -3
  134. package/src/components/smart-filter/COMPONENT.md +2 -0
  135. package/src/components/sparkline/COMPONENT.md +98 -0
  136. package/src/components/sparkline/examples/examples.module.css +13 -0
  137. package/src/components/sparkline/examples/overview.tsx +27 -0
  138. package/src/components/sparkline/examples/period.tsx +46 -0
  139. package/src/components/spinner/COMPONENT.md +1 -1
  140. package/src/components/tabs/COMPONENT.md +24 -22
  141. package/src/components/tabs/examples/closable.tsx +1 -1
  142. package/src/components/tabs/examples/examples.module.css +14 -0
  143. package/src/components/tabs/examples/orientation.tsx +87 -33
  144. package/src/components/tooltip/COMPONENT.md +8 -6
  145. package/src/components/tooltip/examples/examples.module.css +2 -2
  146. package/src/layout/app-header/COMPONENT.md +178 -0
  147. package/src/layout/app-header/examples/breadcrumbs.tsx +36 -0
  148. package/src/layout/app-header/examples/examples.module.css +47 -0
  149. package/src/layout/app-header/examples/in-app-shell.tsx +70 -0
  150. package/src/layout/app-header/examples/narrow.tsx +29 -0
  151. package/src/layout/app-header/examples/overview.tsx +36 -0
  152. package/src/layout/app-shell/COMPONENT.md +35 -29
  153. package/src/layout/app-shell/examples/examples.module.css +17 -2
  154. package/src/layout/app-shell/examples/footer.tsx +59 -0
  155. package/src/layout/app-shell/examples/overview.tsx +19 -8
  156. package/src/layout/bottom-nav/COMPONENT.md +153 -0
  157. package/src/layout/bottom-nav/examples/examples.module.css +39 -0
  158. package/src/layout/bottom-nav/examples/floating.tsx +89 -0
  159. package/src/layout/bottom-nav/examples/icon-only.tsx +41 -0
  160. package/src/layout/bottom-nav/examples/in-app-shell.tsx +64 -0
  161. package/src/layout/bottom-nav/examples/overview.tsx +44 -0
  162. package/src/layout/bottom-nav/examples/router.tsx +31 -0
  163. package/src/layout/bottom-nav/examples/structure.tsx +47 -0
  164. package/src/layout/sidebar/COMPONENT.md +14 -13
  165. package/src/layout/sidebar/examples/examples.module.css +5 -5
  166. package/src/styles/globals.css +125 -2
  167. package/src/styles/theme-dark.css +39 -13
  168. package/src/styles/theme-light.css +84 -16
  169. package/src/styles/tokens.css +2 -0
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./components";
2
2
  export * from "./icons";
3
3
  export * from "./internal/states";
4
+ export * from "./motion/celebrate";
4
5
  export * from "./theme/applyTheme";
package/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import {
2
2
  Accordion,
3
+ AppHeader,
3
4
  AppShell,
4
5
  Avatar,
5
6
  Badge,
6
7
  Banner,
8
+ BottomNav,
7
9
  Breadcrumb,
8
10
  ButtonGroup,
9
11
  Card,
@@ -20,6 +22,7 @@ import {
20
22
  Dropdown,
21
23
  ExampleFrame,
22
24
  FileUpload,
25
+ Kanban,
23
26
  Kbd,
24
27
  LinkButton,
25
28
  LoginForm,
@@ -28,9 +31,9 @@ import {
28
31
  NotificationCard,
29
32
  NotificationProvider,
30
33
  PageContent,
34
+ PageToolbar,
31
35
  Pagination,
32
36
  Popover,
33
- ProgressBar,
34
37
  ProgressCircle,
35
38
  Radio,
36
39
  SegmentedControl,
@@ -38,6 +41,7 @@ import {
38
41
  Skeleton,
39
42
  Slider,
40
43
  SmartFilter,
44
+ Sparkline,
41
45
  Stepper,
42
46
  Switch,
43
47
  THEME_SWITCHING_ATTRIBUTE,
@@ -49,6 +53,7 @@ import {
49
53
  Typography,
50
54
  YEARLESS_YEAR,
51
55
  applyTheme,
56
+ celebrate,
52
57
  datepickerPresets,
53
58
  formatDatepickerValue,
54
59
  matchesSmartFilter,
@@ -57,7 +62,7 @@ import {
57
62
  suspendTransitions,
58
63
  useNotifications,
59
64
  useSidebar
60
- } from "./chunks/chunk-DB2Y3XXA.js";
65
+ } from "./chunks/chunk-OAE4IQX2.js";
61
66
  import {
62
67
  Button,
63
68
  COLOR_PRESETS,
@@ -70,6 +75,7 @@ import {
70
75
  Icon,
71
76
  Input,
72
77
  Label,
78
+ ProgressBar,
73
79
  ScrollContainer,
74
80
  Select,
75
81
  Spinner,
@@ -77,19 +83,22 @@ import {
77
83
  controlSizes,
78
84
  createIcon,
79
85
  dataStates,
86
+ getPasswordStrength,
80
87
  paletteColors,
81
88
  stepDown,
82
89
  textTones,
83
90
  tones,
84
91
  useOptionalControlSize,
85
92
  variants
86
- } from "./chunks/chunk-NHOWNIAR.js";
93
+ } from "./chunks/chunk-6JTZOA5I.js";
87
94
  export {
88
95
  Accordion,
96
+ AppHeader,
89
97
  AppShell,
90
98
  Avatar,
91
99
  Badge,
92
100
  Banner,
101
+ BottomNav,
93
102
  Breadcrumb,
94
103
  Button,
95
104
  ButtonGroup,
@@ -116,6 +125,7 @@ export {
116
125
  Hint,
117
126
  Icon,
118
127
  Input,
128
+ Kanban,
119
129
  Kbd,
120
130
  Label,
121
131
  LinkButton,
@@ -125,6 +135,7 @@ export {
125
135
  NotificationCard,
126
136
  NotificationProvider,
127
137
  PageContent,
138
+ PageToolbar,
128
139
  Pagination,
129
140
  Popover,
130
141
  ProgressBar,
@@ -137,6 +148,7 @@ export {
137
148
  Skeleton,
138
149
  Slider,
139
150
  SmartFilter,
151
+ Sparkline,
140
152
  Spinner,
141
153
  Stepper,
142
154
  Switch,
@@ -150,11 +162,13 @@ export {
150
162
  Typography,
151
163
  YEARLESS_YEAR,
152
164
  applyTheme,
165
+ celebrate,
153
166
  controlSizes,
154
167
  createIcon,
155
168
  dataStates,
156
169
  datepickerPresets,
157
170
  formatDatepickerValue,
171
+ getPasswordStrength,
158
172
  matchesSmartFilter,
159
173
  moveBefore,
160
174
  paletteColors,
@@ -0,0 +1,12 @@
1
+ export type CheckMarkState = "checked" | "unchecked" | "indeterminate";
2
+ /**
3
+ * The kit's check and indeterminate bar, drawn in with a stroke reveal (foundation §7 rule 8: a
4
+ * check draws in, it does not pop). Both paths stay in the DOM so the mark animates both ways;
5
+ * `state` picks the one that shows. Color is `currentColor`; size comes from the host box.
6
+ * Shared by Checkbox and the color swatches. Own SVG instead of `Icon`: the motion needs
7
+ * `pathLength` on the paths.
8
+ */
9
+ export declare function CheckMark({ state, className }: {
10
+ state: CheckMarkState;
11
+ className?: string;
12
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,12 @@
1
+ export type MorphTextProps = {
2
+ children: string;
3
+ className?: string;
4
+ };
5
+ /**
6
+ * A label that changes in place (foundation §7 rule 8): the old letters leave upward, the new ones
7
+ * come from below one short step apart, and the box glides between the two widths. At rest it is
8
+ * one plain text span; the letter layers exist only while a change plays. Still on the first
9
+ * render, under reduced motion, and when only digits change (a counter or a percentage in a label
10
+ * updates in place).
11
+ */
12
+ export declare function MorphText({ children: text, className }: MorphTextProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ export type RollingNumberProps = {
2
+ /** The formatted value («4 812 350 ₽», «12», «−3,4%»); digits roll, other characters stay put. */
3
+ children: string | number;
4
+ className?: string;
5
+ };
6
+ /**
7
+ * A number whose digits roll to their new values column by column, like an odometer (foundation §7
8
+ * rule 8: counters ease, they do not flip). The DOM holds the real digits (text, copy, assistive
9
+ * tech and a page without CSS read the value); each digit column draws the 0–9 strip in a
10
+ * pseudo-element. Columns are keyed from the right, so an unchanged digit stays still and a new
11
+ * leading digit appears without rolling. A value that changes by itself every frame (a running
12
+ * percentage) stays plain tabular text: rolling there is noise.
13
+ */
14
+ export declare function RollingNumber({ children, className }: RollingNumberProps): import("react/jsx-runtime").JSX.Element;
@@ -15,7 +15,9 @@ export type FloatingPanelProps = Omit<React.HTMLAttributes<HTMLElement>, "onAnim
15
15
  * The panel of a floating layer: portaled to `<body>` when it opens (so it stacks above every
16
16
  * layer opened before it, on the one overlay z-index), positioned, animated from `data-state` /
17
17
  * `data-side` (foundation §8), a size context for the controls inside, and a layer context so
18
- * layers opened inside stack above it in the layer stack. Renders nothing while closed.
18
+ * layers opened inside stack above it in the layer stack. Renders nothing while closed. A layer in
19
+ * sheet mode (`floating.sheet`) renders a scrim and a bottom sheet with a grab handle around the
20
+ * same panel element; the consumer ref stays on the panel.
19
21
  */
20
22
  export declare function FloatingPanel({ floating, size, scroll, surface, className, onKeyDown, children, ref, ...rest }: FloatingPanelProps): import("react/jsx-runtime").JSX.Element | null;
21
23
  export type FloatingTriggerProps = {
@@ -30,6 +30,12 @@ export type UseFloatingLayerOptions = PositionOptions & {
30
30
  exitDuration?: MotionDurationToken;
31
31
  /** Unmount at once on close, skipping the exit animation (a Tooltip replaced by its neighbour). */
32
32
  skipExit?: boolean;
33
+ /**
34
+ * Below 640px of viewport the panel is a bottom sheet instead of an anchored panel: a scrim,
35
+ * a grab handle, swipe down to close, page scroll locked. For panels the user works in (menus,
36
+ * listboxes, pickers); not for a panel driven by typing in its anchor.
37
+ */
38
+ sheet?: boolean;
33
39
  };
34
40
  export type FloatingLayer = {
35
41
  open: boolean;
@@ -38,6 +44,10 @@ export type FloatingLayer = {
38
44
  mounted: boolean;
39
45
  /** The side after flipping. */
40
46
  side: PositionSide;
47
+ /** Rendered as a bottom sheet (`sheet` on a narrow viewport). */
48
+ sheet: boolean;
49
+ /** Swipe-to-close of the sheet; part of the sheet's `onPointerDown`. */
50
+ onSheetPointerDown: (event: React.PointerEvent<HTMLElement>) => void;
41
51
  /** Attach to the panel element (merged with a consumer ref). */
42
52
  panelRef: React.RefCallback<HTMLElement>;
43
53
  /** The panel element while mounted. */
@@ -57,4 +67,4 @@ export type FloatingLayer = {
57
67
  * policy (foundation §8): focus returns to the trigger after Escape, a pick, Tab or a close — not
58
68
  * after a press outside, where focus follows the pointer. Render the panel with `FloatingPanel`.
59
69
  */
60
- export declare function useFloatingLayer({ open, onOpenChange, triggerRef, closeOnEscape, closeOnOutsideClick, dismiss, focusOnOpen, trap, tabExit, exitDuration, skipExit, ...positionOptions }: UseFloatingLayerOptions): FloatingLayer;
70
+ export declare function useFloatingLayer({ open, onOpenChange, triggerRef, closeOnEscape, closeOnOutsideClick, dismiss, focusOnOpen, trap, tabExit, exitDuration, skipExit, sheet: sheetOption, ...positionOptions }: UseFloatingLayerOptions): FloatingLayer;
@@ -0,0 +1,25 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Depth of a surface on the ladder (foundation §4): `0` the page … `4` the deepest nested layer,
4
+ * `floating` for menus, popovers, modals and drawers, `floating-1`/`floating-2` for layers nested in
5
+ * one, `tinted` for a host off the ladder (a tinted banner, an accent wash). A surface renders
6
+ * `data-depth` with it; `globals.css` maps each depth to the context variables
7
+ * (`--prime-color-layer-current`, `--prime-color-field-bg`…).
8
+ */
9
+ export type SurfaceDepth = 0 | 1 | 2 | 3 | 4 | "floating" | "floating-1" | "floating-2" | "tinted";
10
+ /**
11
+ * The depth of a surface nested in `depth`; the deepest layer and `floating-2` repeat, a card on a
12
+ * tinted host is a card on the page.
13
+ */
14
+ export declare function nextSurfaceDepth(depth: SurfaceDepth): SurfaceDepth;
15
+ /** Depth of the surface the caller renders: one above the nearest surface around it. */
16
+ export declare function useNestedSurfaceDepth(): SurfaceDepth;
17
+ /** Surfaces inside `children` count their depth from `value`. */
18
+ export declare const SurfaceDepthProvider: React.Provider<SurfaceDepth>;
19
+ /**
20
+ * The layer an ExampleFrame stage stands for (the docs' "preview background"). The stage element
21
+ * itself takes it as `data-depth`: no wrapper may sit between the stage and the example, because
22
+ * the stage lays out its children with child selectors (`> *`).
23
+ */
24
+ export declare const StageDepthProvider: React.Provider<SurfaceDepth>;
25
+ export declare function useStageDepth(): SurfaceDepth;
@@ -31,7 +31,10 @@ export declare const swatchTierClass: string;
31
31
  export declare function SwatchFill({ value }: {
32
32
  value: string | null;
33
33
  }): import("react/jsx-runtime").JSX.Element;
34
- /** Inside a selectable swatch: the color layer and, when selected, the contrasting check. */
34
+ /**
35
+ * Inside a selectable swatch: the color layer and the contrasting check, which draws in when the
36
+ * swatch is selected and retracts when it is not (`CheckMark`, the same mark as Checkbox).
37
+ */
35
38
  export declare function SwatchContent({ value, selected }: {
36
39
  value: string | null;
37
40
  selected: boolean;
@@ -0,0 +1,4 @@
1
+ /** A 44px hit area on coarse pointers, both axes, the visual size unchanged (`touchTarget.module.css`). */
2
+ export declare const touchTargetClass: string;
3
+ /** The same hit area grown in height only: a segment beside other content of its host. */
4
+ export declare const touchTargetBlockClass: string;
@@ -0,0 +1,110 @@
1
+ import * as React from "react";
2
+ import { type DividerProps } from "@/components/divider/Divider";
3
+ export type AppHeaderLabels = {
4
+ /** Name of the menu button that opens the off-canvas Sidebar. */
5
+ menu: string;
6
+ };
7
+ type HeaderProps = React.HTMLAttributes<HTMLElement> & {
8
+ ref?: React.Ref<HTMLElement>;
9
+ };
10
+ type DivProps = React.HTMLAttributes<HTMLDivElement> & {
11
+ ref?: React.Ref<HTMLDivElement>;
12
+ };
13
+ export type AppHeaderRootProps = HeaderProps & {
14
+ labels?: Partial<AppHeaderLabels>;
15
+ };
16
+ /**
17
+ * The bar at the very top of the content panel: where you are, global search, a few actions.
18
+ * One row as high as the Sidebar brand row, so the two read as one line; sticky; lays itself out
19
+ * from its own width (narrow: the search folds into an icon, the title truncates).
20
+ */
21
+ declare function AppHeaderRoot({ labels, className, children, ...rest }: AppHeaderRootProps): import("react/jsx-runtime").JSX.Element;
22
+ declare namespace AppHeaderRoot {
23
+ var displayName: string;
24
+ }
25
+ export type AppHeaderStartProps = DivProps;
26
+ /** The leading zone: the menu button, a back button, the title or breadcrumbs. Takes the free width. */
27
+ declare function AppHeaderStart({ className, ...rest }: AppHeaderStartProps): import("react/jsx-runtime").JSX.Element;
28
+ declare namespace AppHeaderStart {
29
+ var displayName: string;
30
+ }
31
+ export type AppHeaderTitleProps = DivProps;
32
+ /**
33
+ * Where you are: an optional `AppHeader.Icon`, the name and an optional `AppHeader.Description`
34
+ * under it — the same anatomy as the Sidebar brand. The name truncates.
35
+ */
36
+ declare function AppHeaderTitle({ className, children, ...rest }: AppHeaderTitleProps): import("react/jsx-runtime").JSX.Element;
37
+ declare namespace AppHeaderTitle {
38
+ var displayName: string;
39
+ }
40
+ export type AppHeaderIconProps = React.HTMLAttributes<HTMLSpanElement> & {
41
+ ref?: React.Ref<HTMLSpanElement>;
42
+ };
43
+ /**
44
+ * Decorative glyph before the title on a tile shaped like the bar's soft buttons (control m).
45
+ * Not a Thumbnail: its tiers (32 · 40) miss the control height the buttons beside it have.
46
+ */
47
+ declare function AppHeaderIcon({ className, ...rest }: AppHeaderIconProps): import("react/jsx-runtime").JSX.Element;
48
+ declare namespace AppHeaderIcon {
49
+ var displayName: string;
50
+ }
51
+ export type AppHeaderDescriptionProps = React.HTMLAttributes<HTMLSpanElement> & {
52
+ ref?: React.Ref<HTMLSpanElement>;
53
+ };
54
+ /** Muted second line under the title (a workspace, a period); hidden on a narrow header. */
55
+ declare function AppHeaderDescription({ className, ...rest }: AppHeaderDescriptionProps): import("react/jsx-runtime").JSX.Element;
56
+ declare namespace AppHeaderDescription {
57
+ var displayName: string;
58
+ }
59
+ export type AppHeaderSeparatorProps = Omit<DividerProps, "orientation" | "children">;
60
+ /** A short vertical line between groups in a zone (a back button | the path), with air on both sides. */
61
+ declare function AppHeaderSeparator({ className, ...rest }: AppHeaderSeparatorProps): import("react/jsx-runtime").JSX.Element;
62
+ declare namespace AppHeaderSeparator {
63
+ var displayName: string;
64
+ }
65
+ export type AppHeaderSearchProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" | "children"> & {
66
+ /** Placeholder text; also the button's name when the header is narrow and the field folds. */
67
+ children: React.ReactNode;
68
+ /** Key hint at the end. Default `⌘K`; `null` hides it. */
69
+ shortcut?: React.ReactNode;
70
+ ref?: React.Ref<HTMLButtonElement>;
71
+ };
72
+ /**
73
+ * Global search entry: looks like a field, works as a button that opens your CommandMenu (wire
74
+ * `onClick` and the shortcut). On a narrow header it folds into a square search button.
75
+ */
76
+ declare function AppHeaderSearch({ children, shortcut, className, ...rest }: AppHeaderSearchProps): import("react/jsx-runtime").JSX.Element;
77
+ declare namespace AppHeaderSearch {
78
+ var displayName: string;
79
+ }
80
+ export type AppHeaderActionsProps = DivProps;
81
+ /** Buttons at the end: one primary action, notifications, the account. Never wraps. */
82
+ declare function AppHeaderActions({ className, ...rest }: AppHeaderActionsProps): import("react/jsx-runtime").JSX.Element;
83
+ declare namespace AppHeaderActions {
84
+ var displayName: string;
85
+ }
86
+ export type AppHeaderMenuButtonProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type" | "children"> & {
87
+ /**
88
+ * `narrow` (default): shown below 768px, where an `offCanvas="auto"` Sidebar leaves the layout;
89
+ * `always`: on every width (`offCanvas="always"`).
90
+ */
91
+ show?: "narrow" | "always";
92
+ ref?: React.Ref<HTMLButtonElement>;
93
+ };
94
+ /** Opens the off-canvas Sidebar: an icon button named by `labels.menu`; wire `onClick` and `aria-expanded`. */
95
+ declare function AppHeaderMenuButton({ show, className, ...rest }: AppHeaderMenuButtonProps): import("react/jsx-runtime").JSX.Element;
96
+ declare namespace AppHeaderMenuButton {
97
+ var displayName: string;
98
+ }
99
+ export declare const AppHeader: {
100
+ Root: typeof AppHeaderRoot;
101
+ Start: typeof AppHeaderStart;
102
+ Title: typeof AppHeaderTitle;
103
+ Icon: typeof AppHeaderIcon;
104
+ Description: typeof AppHeaderDescription;
105
+ Separator: typeof AppHeaderSeparator;
106
+ Search: typeof AppHeaderSearch;
107
+ Actions: typeof AppHeaderActions;
108
+ MenuButton: typeof AppHeaderMenuButton;
109
+ };
110
+ export {};
@@ -7,25 +7,25 @@ export type AppShellRootProps = React.HTMLAttributes<HTMLDivElement> & {
7
7
  export type AppShellNavProps = React.HTMLAttributes<HTMLDivElement> & {
8
8
  ref?: React.Ref<HTMLDivElement>;
9
9
  };
10
- /** Navigation column (usually `Sidebar.Root`); sits on the canvas. */
10
+ /** Navigation column (usually `Sidebar.Root`, a surface one layer above the page). */
11
11
  declare function AppShellNav({ className, ...rest }: AppShellNavProps): import("react/jsx-runtime").JSX.Element;
12
12
  declare namespace AppShellNav {
13
13
  var displayName: string;
14
14
  }
15
15
  /**
16
16
  * Grid: navigation column | content panel. Everything that is not `AppShell.Nav` goes into the
17
- * content panel (`bg-surface`, inset from the window on wide screens).
17
+ * content panel, which is the page itself (the layer around the shell): cards on it are the next layer.
18
18
  */
19
19
  declare function AppShellRoot({ fillViewport, className, children, ...rest }: AppShellRootProps): import("react/jsx-runtime").JSX.Element;
20
20
  declare namespace AppShellRoot {
21
21
  var displayName: string;
22
22
  }
23
- export type AppShellHeaderProps = React.HTMLAttributes<HTMLElement> & {
24
- ref?: React.Ref<HTMLElement>;
23
+ export type AppShellFooterProps = React.HTMLAttributes<HTMLDivElement> & {
24
+ ref?: React.Ref<HTMLDivElement>;
25
25
  };
26
- /** Top bar of the content panel (breadcrumbs, page actions, mobile menu button). Sticky. */
27
- declare function AppShellHeader({ className, ...rest }: AppShellHeaderProps): import("react/jsx-runtime").JSX.Element;
28
- declare namespace AppShellHeader {
26
+ /** Bottom bar of the content panel (`BottomNav` on a narrow shell). Sticky. */
27
+ declare function AppShellFooter({ className, ...rest }: AppShellFooterProps): import("react/jsx-runtime").JSX.Element;
28
+ declare namespace AppShellFooter {
29
29
  var displayName: string;
30
30
  }
31
31
  /** `full` (default): the whole panel with responsive gutters; `contained`: centered, up to `--prime-layout-content-max-width` (long-read pages). */
@@ -44,23 +44,28 @@ export type AppShellTemplateProps = Omit<AppShellRootProps, "children" | "ref">
44
44
  ref?: React.Ref<HTMLElement>;
45
45
  /** Navigation column content, usually `Sidebar.Root`. */
46
46
  nav?: React.ReactNode;
47
- /** `AppShell.Header` content; no header row when omitted. */
47
+ /** The top bar of the content panel, an `AppHeader.Root`; no header when omitted. */
48
48
  header?: React.ReactNode;
49
+ /** `AppShell.Footer` content (`BottomNav`); no footer when omitted. */
50
+ footer?: React.ReactNode;
49
51
  children?: React.ReactNode;
50
52
  mainProps?: Omit<AppShellMainProps, "children" | "ref">;
51
53
  /** Main scrolls back to the top whenever this value changes (pass the router pathname). */
52
54
  scrollResetKey?: unknown;
53
55
  };
54
- /** Root + Nav + Header + Main in one; main scrolls to the top when `scrollResetKey` changes. */
55
- declare function AppShellTemplate({ ref, nav, header, children, mainProps, scrollResetKey, ...rootProps }: AppShellTemplateProps): import("react/jsx-runtime").JSX.Element;
56
+ /**
57
+ * Root + Nav + the header + Main + Footer in one; main scrolls to the top when `scrollResetKey`
58
+ * changes.
59
+ */
60
+ declare function AppShellTemplate({ ref, nav, header, footer, children, mainProps, scrollResetKey, ...rootProps }: AppShellTemplateProps): import("react/jsx-runtime").JSX.Element;
56
61
  declare namespace AppShellTemplate {
57
62
  var displayName: string;
58
63
  }
59
64
  export declare const AppShell: {
60
65
  Root: typeof AppShellRoot;
61
66
  Nav: typeof AppShellNav;
62
- Header: typeof AppShellHeader;
63
67
  Main: typeof AppShellMain;
68
+ Footer: typeof AppShellFooter;
64
69
  Template: typeof AppShellTemplate;
65
70
  };
66
71
  export {};
@@ -0,0 +1,80 @@
1
+ import * as React from "react";
2
+ import type { PaletteColor, Variant } from "@/internal/states";
3
+ export type BottomNavLabels = {
4
+ /** `aria-label` of the `<nav>` landmark. */
5
+ nav: string;
6
+ };
7
+ export type BottomNavRootProps = React.HTMLAttributes<HTMLElement> & {
8
+ /** Icons without visible labels; the labels still name the items for screen readers. */
9
+ iconOnly?: boolean;
10
+ /**
11
+ * A glass capsule floating over the content (backdrop blur, inset from the edges) instead of
12
+ * a flat bar at the edge. It places itself at the bottom of its positioned container
13
+ * (`AppShell.Footer`), so the page scrolls under it.
14
+ */
15
+ floating?: boolean;
16
+ labels?: Partial<BottomNavLabels>;
17
+ /** The `<nav>` bar. */
18
+ ref?: React.Ref<HTMLElement>;
19
+ };
20
+ /**
21
+ * Phone navigation: a bar of 3–5 sections at the bottom of the screen. Inside `AppShell.Footer`
22
+ * it shows only while the content panel is narrower than 640px; wider, Sidebar navigates.
23
+ */
24
+ declare function BottomNavRoot({ iconOnly, floating, labels, className, ...rest }: BottomNavRootProps): import("react/jsx-runtime").JSX.Element;
25
+ declare namespace BottomNavRoot {
26
+ var displayName: string;
27
+ }
28
+ export type BottomNavItemIconProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> & {
29
+ children: React.ReactNode;
30
+ ref?: React.Ref<HTMLSpanElement>;
31
+ };
32
+ /** The item glyph above the label. */
33
+ declare function BottomNavItemIcon({ className, ...rest }: BottomNavItemIconProps): import("react/jsx-runtime").JSX.Element;
34
+ declare namespace BottomNavItemIcon {
35
+ var displayName: string;
36
+ }
37
+ export type BottomNavItemCountProps = Omit<React.HTMLAttributes<HTMLSpanElement>, "children" | "color"> & {
38
+ /** The number (or a short status). */
39
+ children: React.ReactNode;
40
+ /** Badge hue. Default `red`: a count on a section asks for attention. */
41
+ color?: PaletteColor;
42
+ /** Badge treatment. Default `solid`. */
43
+ variant?: Exclude<Variant, "ghost">;
44
+ /** The Badge `<span>`. */
45
+ ref?: React.Ref<HTMLSpanElement>;
46
+ };
47
+ /** A count on the corner of the icon: a small Badge, read after the label. */
48
+ declare function BottomNavItemCount({ color, variant, className, ...rest }: BottomNavItemCountProps): import("react/jsx-runtime").JSX.Element;
49
+ declare namespace BottomNavItemCount {
50
+ var displayName: string;
51
+ }
52
+ type BottomNavItemOwnProps = {
53
+ /** Current section: `aria-current="page"`. Links rendered by a router may set it themselves. */
54
+ current?: boolean;
55
+ disabled?: boolean;
56
+ /** Render the single child element (a router link) as the item; its children are the content. */
57
+ asChild?: boolean;
58
+ /** `BottomNav.ItemIcon`, an optional `BottomNav.ItemCount` and the label. */
59
+ children?: React.ReactNode;
60
+ };
61
+ export type BottomNavItemProps = BottomNavItemOwnProps & Omit<React.ComponentPropsWithoutRef<"button">, keyof BottomNavItemOwnProps> & {
62
+ /** Renders an `<a>` instead of a `<button>`. */
63
+ href?: string;
64
+ target?: string;
65
+ rel?: string;
66
+ /** The `<a>`, `<button>` or the `asChild` element. */
67
+ ref?: React.Ref<HTMLElement>;
68
+ };
69
+ /** A section of the bar: the icon above a short label, both in the primary color while current. */
70
+ declare function BottomNavItem({ current, disabled, asChild, href, className, children, onClick, type, ref, ...rest }: BottomNavItemProps): import("react/jsx-runtime").JSX.Element;
71
+ declare namespace BottomNavItem {
72
+ var displayName: string;
73
+ }
74
+ export declare const BottomNav: {
75
+ Root: typeof BottomNavRoot;
76
+ Item: typeof BottomNavItem;
77
+ ItemIcon: typeof BottomNavItemIcon;
78
+ ItemCount: typeof BottomNavItemCount;
79
+ };
80
+ export {};
@@ -1,4 +1,8 @@
1
- export type { AppShellContentWidth, AppShellHeaderProps, AppShellMainProps, AppShellNavProps, AppShellRootProps, AppShellTemplateProps, } from "./app-shell/AppShell";
1
+ export type { AppHeaderActionsProps, AppHeaderDescriptionProps, AppHeaderIconProps, AppHeaderLabels, AppHeaderMenuButtonProps, AppHeaderRootProps, AppHeaderSearchProps, AppHeaderSeparatorProps, AppHeaderStartProps, AppHeaderTitleProps, } from "./app-header/AppHeader";
2
+ export { AppHeader } from "./app-header/AppHeader";
3
+ export type { AppShellContentWidth, AppShellFooterProps, AppShellMainProps, AppShellNavProps, AppShellRootProps, AppShellTemplateProps, } from "./app-shell/AppShell";
2
4
  export { AppShell } from "./app-shell/AppShell";
5
+ export type { BottomNavItemCountProps, BottomNavItemIconProps, BottomNavItemProps, BottomNavLabels, BottomNavRootProps, } from "./bottom-nav/BottomNav";
6
+ export { BottomNav } from "./bottom-nav/BottomNav";
3
7
  export type { SidebarAccountProps, SidebarBrandLogoProps, SidebarBrandProps, SidebarContentProps, SidebarFooterProps, SidebarGroupProps, SidebarHeaderProps, SidebarItemActionProps, SidebarItemCountProps, SidebarItemIconProps, SidebarItemProps, SidebarItemShortcutProps, SidebarLabels, SidebarMode, SidebarRootProps, SidebarSubContentProps, SidebarSubProps, SidebarSubTriggerProps, SidebarToggleProps, } from "./sidebar/Sidebar";
4
8
  export { Sidebar, useSidebar } from "./sidebar/Sidebar";
@@ -0,0 +1,18 @@
1
+ export type CelebrateOptions = {
2
+ /**
3
+ * Where the burst starts: an element (from its center) or a point in the viewport. Default: the
4
+ * middle of the screen, a third from the top.
5
+ */
6
+ origin?: Element | {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ };
11
+ /**
12
+ * A short confetti burst for a rare milestone: a quarter closed, the first invoice paid, an
13
+ * onboarding finished (foundation §7 rule 1 — only rare moments carry delight; never for routine
14
+ * success, that is a Notification). Draws on a canvas above every layer, ignores the pointer and
15
+ * assistive tech, and removes itself after 1.4 s. Under reduced motion it draws nothing. Say the
16
+ * achievement in words too: the burst is decoration. Resolves when the canvas is gone.
17
+ */
18
+ export declare function celebrate(options?: CelebrateOptions): Promise<void>;
@@ -0,0 +1,37 @@
1
+ /** ΔL in OKLab between neighbouring layers. */
2
+ export declare const LAYER_STEP = 0.03;
3
+ /** Layers 0…4: the page and four nested surfaces. */
4
+ export declare const LAYER_DEPTH = 4;
5
+ export type LayerTheme = {
6
+ /** The page color (layer 0). */
7
+ page: string;
8
+ /** Lightness window: no color goes outside it. */
9
+ lo: number;
10
+ hi: number;
11
+ /** Direction of control fills from their host: −1 darker, +1 lighter. */
12
+ control: 1 | -1;
13
+ };
14
+ export declare const LIGHT_LAYERS: LayerTheme;
15
+ export declare const DARK_LAYERS: LayerTheme;
16
+ export declare const lightnessOf: (hex: string) => number;
17
+ /**
18
+ * `steps` steps from L towards `dir`. Reflects when less than half a step of room is left (unless
19
+ * `reflect` is off), snaps to the edge when less than half a step would remain after the move.
20
+ */
21
+ export declare function move(theme: LayerTheme, L: number, dir: 1 | -1, steps?: number, reflect?: boolean): number;
22
+ export type LayerColors = {
23
+ /** The layer itself. */
24
+ bg: string;
25
+ /** Fields, chips, segmented tracks, neutral buttons on this layer. */
26
+ fill: string;
27
+ /** Hover of that fill. */
28
+ fillHover: string;
29
+ /** The selected segment (thumb) on a track of this layer. */
30
+ selected: string;
31
+ };
32
+ /** Layers 0…LAYER_DEPTH of a theme, each one step from its parent. */
33
+ export declare function layerLadder(theme: LayerTheme): LayerColors[];
34
+ /** Floating layers (popovers, menus, modals, drawers) sit one step above a card and never reflect. */
35
+ export declare function floatingLayer(theme: LayerTheme): LayerColors;
36
+ /** Token tree for `color.layer`: `0`…`4` plus `floating` and the two layers nested in it. */
37
+ export declare function layerTokens(theme: LayerTheme): Record<string, LayerColors>;
@@ -2,5 +2,5 @@
2
2
  export declare const REF_PREFIX = "--prime-ref";
3
3
  /** Semantic variables: `--prime-*`. */
4
4
  export declare const SYS_PREFIX = "--prime";
5
- /** Token path → CSS variable: `color.bg.canvas` → `--prime-color-bg-canvas`, camelCase → kebab-case. */
5
+ /** Token path → CSS variable: `color.text.primary` → `--prime-color-text-primary`, camelCase → kebab-case. */
6
6
  export declare function toVarName(path: string, prefix?: string): string;
@@ -134,6 +134,8 @@ export declare const primitiveTokens: {
134
134
  };
135
135
  /** Modular scale, ~1.2 in the body range, ~1.25 for headings. */
136
136
  readonly size: {
137
+ /** Only for tab-bar labels under an icon (BottomNav, iOS tab bar 10pt); text roles start at 12. */
138
+ readonly 10: "0.625rem";
137
139
  readonly 12: "0.75rem";
138
140
  readonly 13: "0.8125rem";
139
141
  readonly 14: "0.875rem";
@@ -147,6 +149,8 @@ export declare const primitiveTokens: {
147
149
  readonly 60: "3.75rem";
148
150
  };
149
151
  readonly lineHeight: {
152
+ /** Only for tab-bar labels (BottomNav). */
153
+ readonly 12: "0.75rem";
150
154
  readonly 16: "1rem";
151
155
  readonly 20: "1.25rem";
152
156
  readonly 24: "1.5rem";