@lateralus-ai/shipping-ui 2.0.0-dev.20 → 2.0.0-dev.4

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 (38) hide show
  1. package/dist/components/Entry.d.ts +7 -27
  2. package/dist/components/Tabs.d.ts +5 -5
  3. package/dist/components/index.d.ts +2 -4
  4. package/dist/index.cjs +25 -25
  5. package/dist/index.d.ts +2 -2
  6. package/dist/index.esm.js +3374 -3584
  7. package/dist/patterns/Search/ResultRow.d.ts +5 -11
  8. package/dist/patterns/Sidebar/sidebar-styles.d.ts +1 -2
  9. package/dist/primitives/Badge.d.ts +4 -7
  10. package/dist/primitives/index.d.ts +1 -1
  11. package/dist/tailwind-theme.d.ts +0 -4
  12. package/dist/{theme-entry-tLBc6zGT.mjs → theme-entry-BUK3MJUJ.mjs} +4 -8
  13. package/dist/theme-entry-ygTpGaNC.js +1 -0
  14. package/dist/theme.cjs +1 -1
  15. package/dist/theme.esm.js +1 -1
  16. package/package.json +128 -128
  17. package/src/components/Entry.tsx +45 -119
  18. package/src/components/Tabs.tsx +27 -33
  19. package/src/components/index.ts +1 -15
  20. package/src/index.ts +0 -11
  21. package/src/patterns/Search/ResultRow.tsx +38 -24
  22. package/src/patterns/Search/SearchModal.tsx +1 -7
  23. package/src/patterns/Sidebar/CollapsibleNavGroup.tsx +1 -1
  24. package/src/patterns/Sidebar/SidebarAction.tsx +17 -26
  25. package/src/patterns/Sidebar/SidebarEntry.tsx +39 -54
  26. package/src/patterns/Sidebar/SidebarLink.tsx +20 -30
  27. package/src/patterns/Sidebar/sidebar-styles.ts +1 -2
  28. package/src/primitives/Badge.tsx +10 -20
  29. package/src/primitives/Button.tsx +11 -16
  30. package/src/primitives/index.ts +1 -1
  31. package/src/stories/canvases/ContentCanvas.tsx +14 -253
  32. package/src/tailwind-theme.ts +182 -186
  33. package/src/utils/cn.ts +1 -28
  34. package/dist/components/PageHeader.d.ts +0 -41
  35. package/dist/components/ScrollableList.d.ts +0 -22
  36. package/dist/theme-entry-Dwr2mV7_.js +0 -1
  37. package/src/components/PageHeader.tsx +0 -132
  38. package/src/components/ScrollableList.tsx +0 -61
@@ -1,186 +1,182 @@
1
- import { colorScales } from "./tokens/colors";
2
- import { elevation, borderRadius } from "./tokens/elevation";
3
-
4
- const toTailwindFontSize = (
5
- size: string,
6
- opts: { lineHeight: string; letterSpacing: string; fontWeight?: number },
7
- ) =>
8
- [
9
- size,
10
- {
11
- lineHeight: opts.lineHeight,
12
- letterSpacing: opts.letterSpacing,
13
- ...(opts.fontWeight ? { fontWeight: String(opts.fontWeight) } : {}),
14
- },
15
- ] as const;
16
-
17
- export const theme = {
18
- fontFamily: {
19
- heading: ['"TRY Vesterbro"', "Libre Baskerville", "Georgia", "serif"],
20
- sans: ['"Matter-TRIAL"', "DM Sans", "system-ui", "sans-serif"],
21
- mono: ["Roboto Mono", "monospace"],
22
- },
23
- fontSize: {
24
- title: toTailwindFontSize("28px", { lineHeight: "34px", letterSpacing: "-0.02em" }),
25
- "title-em": toTailwindFontSize("28px", {
26
- lineHeight: "34px",
27
- letterSpacing: "-0.02em",
28
- fontWeight: 500,
29
- }),
30
- heading: toTailwindFontSize("22px", {
31
- lineHeight: "28px",
32
- letterSpacing: "0",
33
- fontWeight: 500,
34
- }),
35
- subheader: toTailwindFontSize("18px", { lineHeight: "28px", letterSpacing: "-0.01em" }),
36
- "subheader-em": toTailwindFontSize("18px", {
37
- lineHeight: "28px",
38
- letterSpacing: "-0.01em",
39
- fontWeight: 500,
40
- }),
41
- body: toTailwindFontSize("16px", { lineHeight: "24px", letterSpacing: "-0.01em" }),
42
- "body-em": toTailwindFontSize("16px", {
43
- lineHeight: "24px",
44
- letterSpacing: "-0.01em",
45
- fontWeight: 500,
46
- }),
47
- "caption-1": toTailwindFontSize("16px", { lineHeight: "22px", letterSpacing: "0.02em" }),
48
- "caption-1-em": toTailwindFontSize("16px", {
49
- lineHeight: "22px",
50
- letterSpacing: "0.02em",
51
- fontWeight: 500,
52
- }),
53
- "caption-2": toTailwindFontSize("14px", { lineHeight: "20px", letterSpacing: "0.01em" }),
54
- "caption-2-em": toTailwindFontSize("14px", {
55
- lineHeight: "20px",
56
- letterSpacing: "0.01em",
57
- fontWeight: 500,
58
- }),
59
- footnote: toTailwindFontSize("13px", { lineHeight: "17px", letterSpacing: "0" }),
60
- "footnote-em": toTailwindFontSize("13px", {
61
- lineHeight: "17px",
62
- letterSpacing: "0",
63
- fontWeight: 500,
64
- }),
65
- },
66
- boxShadow: {
67
- raise1: elevation.raise1,
68
- raise2: elevation.raise2,
69
- raise3: elevation.raise3,
70
- },
71
- borderRadius: {
72
- control: borderRadius.control,
73
- lg: borderRadius.lg,
74
- md: borderRadius.md,
75
- sm: borderRadius.sm,
76
- },
77
- /** Extends Tailwind’s max-width scale (7xl = 1280px). */
78
- maxWidth: {
79
- "8xl": "1640px",
80
- },
81
- colors: {
82
- grey: colorScales.grey,
83
- gray: colorScales.grey,
84
- green: colorScales.green,
85
- blue: colorScales.blue,
86
- red: colorScales.red,
87
- orange: colorScales.orange,
88
- purple: colorScales.purple,
89
- white: "#ffffff",
90
- action: {
91
- primary: {
92
- idle: "var(--action-primary-idle)",
93
- "on-idle": "var(--action-primary-on-idle)",
94
- hover: "var(--action-primary-hover)",
95
- "on-hover": "var(--action-primary-on-hover)",
96
- disabled: "var(--action-primary-disabled)",
97
- "on-disabled": "var(--action-primary-on-disabled)",
98
- },
99
- secondary: {
100
- idle: "var(--action-secondary-idle)",
101
- "on-idle": "var(--action-secondary-on-idle)",
102
- hover: "var(--action-secondary-hover)",
103
- "on-hover": "var(--action-secondary-on-hover)",
104
- disabled: "var(--action-secondary-disabled)",
105
- "on-disabled": "var(--action-secondary-on-disabled)",
106
- },
107
- tertiary: {
108
- idle: "var(--action-tertiary-idle)",
109
- "on-idle": "var(--action-tertiary-on-idle)",
110
- hover: "var(--action-tertiary-hover)",
111
- "on-hover": "var(--action-tertiary-on-hover)",
112
- disabled: "var(--action-tertiary-disabled)",
113
- "on-disabled": "var(--action-tertiary-on-disabled)",
114
- },
115
- quaternary: {
116
- idle: "var(--action-quaternary-idle)",
117
- "on-idle": "var(--action-quaternary-on-idle)",
118
- hover: "var(--action-quaternary-hover)",
119
- "on-hover": "var(--action-quaternary-on-hover)",
120
- disabled: "var(--action-quaternary-disabled)",
121
- "on-disabled": "var(--action-quaternary-on-disabled)",
122
- },
123
- destructive: {
124
- idle: "var(--action-destructive-idle)",
125
- "on-idle": "var(--action-destructive-on-idle)",
126
- hover: "var(--action-destructive-hover)",
127
- "on-hover": "var(--action-destructive-on-hover)",
128
- disabled: "var(--action-destructive-disabled)",
129
- "on-disabled": "var(--action-destructive-on-disabled)",
130
- },
131
- },
132
- background: {
133
- primary: "var(--background-primary)",
134
- secondary: "var(--background-secondary)",
135
- tertiary: "var(--background-tertiary)",
136
- hover: "var(--background-hover)",
137
- selected: "var(--background-selected)",
138
- overlay: "var(--background-overlay)",
139
- },
140
- display: {
141
- "on-light": {
142
- primary: "var(--display-on-light-primary)",
143
- secondary: "var(--display-on-light-secondary)",
144
- tertiary: "var(--display-on-light-tertiary)",
145
- quaternary: "var(--display-on-light-quaternary)",
146
- },
147
- "on-dark": {
148
- primary: "var(--display-on-dark-primary)",
149
- secondary: "var(--display-on-dark-secondary)",
150
- tertiary: "var(--display-on-dark-tertiary)",
151
- quaternary: "var(--display-on-dark-quaternary)",
152
- },
153
- },
154
- accent: {
155
- "on-light": "var(--accent-on-light)",
156
- "on-dark": "var(--accent-on-dark)",
157
- "bg-light": "var(--accent-bg-light)",
158
- "bg-lighter": "var(--accent-bg-lighter)",
159
- },
160
- divider: {
161
- primary: "var(--divider-primary)",
162
- secondary: "var(--divider-secondary)",
163
- },
164
- meta: {
165
- green: "var(--meta-green)",
166
- onGreen: "var(--meta-on-green)",
167
- orange: "var(--meta-orange)",
168
- onOrange: "var(--meta-on-orange)",
169
- red: "var(--meta-red)",
170
- onRed: "var(--meta-on-red)",
171
- blue: "var(--meta-blue)",
172
- onBlue: "var(--meta-on-blue)",
173
- purple: "var(--meta-purple)",
174
- onPurple: "var(--meta-on-purple)",
175
- },
176
- /* Legacy aliases */
177
- "text-primary": "var(--display-on-light-primary)",
178
- "text-secondary": "var(--display-on-light-secondary)",
179
- "text-tertiary": "var(--display-on-light-tertiary)",
180
- "surface-primary": "var(--background-primary)",
181
- "surface-secondary": "var(--background-secondary)",
182
- "surface-hover": "var(--background-secondary)",
183
- "border-light": "var(--divider-primary)",
184
- "border-medium": "var(--divider-secondary)",
185
- },
186
- };
1
+ import { colorScales } from "./tokens/colors";
2
+ import { elevation, borderRadius } from "./tokens/elevation";
3
+
4
+ const toTailwindFontSize = (
5
+ size: string,
6
+ opts: { lineHeight: string; letterSpacing: string; fontWeight?: number },
7
+ ) =>
8
+ [
9
+ size,
10
+ {
11
+ lineHeight: opts.lineHeight,
12
+ letterSpacing: opts.letterSpacing,
13
+ ...(opts.fontWeight ? { fontWeight: String(opts.fontWeight) } : {}),
14
+ },
15
+ ] as const;
16
+
17
+ export const theme = {
18
+ fontFamily: {
19
+ heading: ['"TRY Vesterbro"', "Libre Baskerville", "Georgia", "serif"],
20
+ sans: ['"Matter-TRIAL"', "DM Sans", "system-ui", "sans-serif"],
21
+ mono: ["Roboto Mono", "monospace"],
22
+ },
23
+ fontSize: {
24
+ title: toTailwindFontSize("28px", { lineHeight: "34px", letterSpacing: "-0.02em" }),
25
+ "title-em": toTailwindFontSize("28px", {
26
+ lineHeight: "34px",
27
+ letterSpacing: "-0.02em",
28
+ fontWeight: 500,
29
+ }),
30
+ heading: toTailwindFontSize("22px", {
31
+ lineHeight: "28px",
32
+ letterSpacing: "0",
33
+ fontWeight: 500,
34
+ }),
35
+ subheader: toTailwindFontSize("18px", { lineHeight: "28px", letterSpacing: "-0.01em" }),
36
+ "subheader-em": toTailwindFontSize("18px", {
37
+ lineHeight: "28px",
38
+ letterSpacing: "-0.01em",
39
+ fontWeight: 500,
40
+ }),
41
+ body: toTailwindFontSize("16px", { lineHeight: "24px", letterSpacing: "-0.01em" }),
42
+ "body-em": toTailwindFontSize("16px", {
43
+ lineHeight: "24px",
44
+ letterSpacing: "-0.01em",
45
+ fontWeight: 500,
46
+ }),
47
+ "caption-1": toTailwindFontSize("16px", { lineHeight: "22px", letterSpacing: "0.02em" }),
48
+ "caption-1-em": toTailwindFontSize("16px", {
49
+ lineHeight: "22px",
50
+ letterSpacing: "0.02em",
51
+ fontWeight: 500,
52
+ }),
53
+ "caption-2": toTailwindFontSize("14px", { lineHeight: "20px", letterSpacing: "0.01em" }),
54
+ "caption-2-em": toTailwindFontSize("14px", {
55
+ lineHeight: "20px",
56
+ letterSpacing: "0.01em",
57
+ fontWeight: 500,
58
+ }),
59
+ footnote: toTailwindFontSize("13px", { lineHeight: "17px", letterSpacing: "0" }),
60
+ "footnote-em": toTailwindFontSize("13px", {
61
+ lineHeight: "17px",
62
+ letterSpacing: "0",
63
+ fontWeight: 500,
64
+ }),
65
+ },
66
+ boxShadow: {
67
+ raise1: elevation.raise1,
68
+ raise2: elevation.raise2,
69
+ raise3: elevation.raise3,
70
+ },
71
+ borderRadius: {
72
+ control: borderRadius.control,
73
+ lg: borderRadius.lg,
74
+ md: borderRadius.md,
75
+ sm: borderRadius.sm,
76
+ },
77
+ colors: {
78
+ grey: colorScales.grey,
79
+ gray: colorScales.grey,
80
+ green: colorScales.green,
81
+ blue: colorScales.blue,
82
+ red: colorScales.red,
83
+ orange: colorScales.orange,
84
+ purple: colorScales.purple,
85
+ white: "#ffffff",
86
+ action: {
87
+ primary: {
88
+ idle: "var(--action-primary-idle)",
89
+ "on-idle": "var(--action-primary-on-idle)",
90
+ hover: "var(--action-primary-hover)",
91
+ "on-hover": "var(--action-primary-on-hover)",
92
+ disabled: "var(--action-primary-disabled)",
93
+ "on-disabled": "var(--action-primary-on-disabled)",
94
+ },
95
+ secondary: {
96
+ idle: "var(--action-secondary-idle)",
97
+ "on-idle": "var(--action-secondary-on-idle)",
98
+ hover: "var(--action-secondary-hover)",
99
+ "on-hover": "var(--action-secondary-on-hover)",
100
+ disabled: "var(--action-secondary-disabled)",
101
+ "on-disabled": "var(--action-secondary-on-disabled)",
102
+ },
103
+ tertiary: {
104
+ idle: "var(--action-tertiary-idle)",
105
+ "on-idle": "var(--action-tertiary-on-idle)",
106
+ hover: "var(--action-tertiary-hover)",
107
+ "on-hover": "var(--action-tertiary-on-hover)",
108
+ disabled: "var(--action-tertiary-disabled)",
109
+ "on-disabled": "var(--action-tertiary-on-disabled)",
110
+ },
111
+ quaternary: {
112
+ idle: "var(--action-quaternary-idle)",
113
+ "on-idle": "var(--action-quaternary-on-idle)",
114
+ hover: "var(--action-quaternary-hover)",
115
+ "on-hover": "var(--action-quaternary-on-hover)",
116
+ disabled: "var(--action-quaternary-disabled)",
117
+ "on-disabled": "var(--action-quaternary-on-disabled)",
118
+ },
119
+ destructive: {
120
+ idle: "var(--action-destructive-idle)",
121
+ "on-idle": "var(--action-destructive-on-idle)",
122
+ hover: "var(--action-destructive-hover)",
123
+ "on-hover": "var(--action-destructive-on-hover)",
124
+ disabled: "var(--action-destructive-disabled)",
125
+ "on-disabled": "var(--action-destructive-on-disabled)",
126
+ },
127
+ },
128
+ background: {
129
+ primary: "var(--background-primary)",
130
+ secondary: "var(--background-secondary)",
131
+ tertiary: "var(--background-tertiary)",
132
+ hover: "var(--background-hover)",
133
+ selected: "var(--background-selected)",
134
+ overlay: "var(--background-overlay)",
135
+ },
136
+ display: {
137
+ "on-light": {
138
+ primary: "var(--display-on-light-primary)",
139
+ secondary: "var(--display-on-light-secondary)",
140
+ tertiary: "var(--display-on-light-tertiary)",
141
+ quaternary: "var(--display-on-light-quaternary)",
142
+ },
143
+ "on-dark": {
144
+ primary: "var(--display-on-dark-primary)",
145
+ secondary: "var(--display-on-dark-secondary)",
146
+ tertiary: "var(--display-on-dark-tertiary)",
147
+ quaternary: "var(--display-on-dark-quaternary)",
148
+ },
149
+ },
150
+ accent: {
151
+ "on-light": "var(--accent-on-light)",
152
+ "on-dark": "var(--accent-on-dark)",
153
+ "bg-light": "var(--accent-bg-light)",
154
+ "bg-lighter": "var(--accent-bg-lighter)",
155
+ },
156
+ divider: {
157
+ primary: "var(--divider-primary)",
158
+ secondary: "var(--divider-secondary)",
159
+ },
160
+ meta: {
161
+ green: "var(--meta-green)",
162
+ onGreen: "var(--meta-on-green)",
163
+ orange: "var(--meta-orange)",
164
+ onOrange: "var(--meta-on-orange)",
165
+ red: "var(--meta-red)",
166
+ onRed: "var(--meta-on-red)",
167
+ blue: "var(--meta-blue)",
168
+ onBlue: "var(--meta-on-blue)",
169
+ purple: "var(--meta-purple)",
170
+ onPurple: "var(--meta-on-purple)",
171
+ },
172
+ /* Legacy aliases */
173
+ "text-primary": "var(--display-on-light-primary)",
174
+ "text-secondary": "var(--display-on-light-secondary)",
175
+ "text-tertiary": "var(--display-on-light-tertiary)",
176
+ "surface-primary": "var(--background-primary)",
177
+ "surface-secondary": "var(--background-secondary)",
178
+ "surface-hover": "var(--background-secondary)",
179
+ "border-light": "var(--divider-primary)",
180
+ "border-medium": "var(--divider-secondary)",
181
+ },
182
+ };
package/src/utils/cn.ts CHANGED
@@ -1,33 +1,6 @@
1
- import { extendTailwindMerge } from "tailwind-merge";
1
+ import { twMerge } from "tailwind-merge";
2
2
  import { type ClassValue, clsx } from "clsx";
3
3
 
4
- /**
5
- * Custom fontSize keys from tailwind-theme.ts (tailwind-merge@1.x API).
6
- * Without this, twMerge treats e.g. text-caption-2-em as the same group as
7
- * text-display-on-light-primary and drops the font-size class.
8
- */
9
- const fontSizeTokens = [
10
- "title",
11
- "title-em",
12
- "heading",
13
- "subheader",
14
- "subheader-em",
15
- "body",
16
- "body-em",
17
- "caption-1",
18
- "caption-1-em",
19
- "caption-2",
20
- "caption-2-em",
21
- "footnote",
22
- "footnote-em",
23
- ] as const;
24
-
25
- const twMerge = extendTailwindMerge({
26
- classGroups: {
27
- "font-size": [{ text: [...fontSizeTokens] }],
28
- },
29
- });
30
-
31
4
  /**
32
5
  * Merges the tailwind clases (using twMerge). Conditionally removes false values
33
6
  * @param inputs The tailwind classes to merge
@@ -1,41 +0,0 @@
1
- import { ComponentPropsWithoutRef, MouseEvent, ReactNode } from 'react';
2
- export type PageHeaderCrumb = {
3
- label: string;
4
- /** Renders a real `<a href>` so native browser controls work. */
5
- href: string;
6
- /**
7
- * Optional SPA handler. Callers should `preventDefault` only for unmodified
8
- * primary clicks; modifier / middle-click keep native anchor behavior.
9
- */
10
- onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
11
- };
12
- export type PageHeaderProps = {
13
- /** Leading icon (Figma 24×24). */
14
- icon?: ReactNode;
15
- /** Standard title, or current (last) segment when `crumbs` is set. */
16
- title: ReactNode;
17
- /**
18
- * Parent breadcrumb links. When present, renders Nested: icon + parents + `/`
19
- * + current `title` (non-link).
20
- */
21
- crumbs?: PageHeaderCrumb[];
22
- /** Right-hand actions slot (buttons, menus, etc.). */
23
- actions?: ReactNode;
24
- className?: string;
25
- };
26
- export type PageHeaderShellProps = ComponentPropsWithoutRef<"div">;
27
- export type PageHeaderBodyProps = ComponentPropsWithoutRef<"div">;
28
- /**
29
- * Page title row — Figma `Header` (389:8850).
30
- * Variants: Standard (icon + title) | Nested (icon + crumb trail).
31
- */
32
- declare function PageHeaderRoot({ icon, title, crumbs, actions, className, }: PageHeaderProps): import("react/jsx-runtime").JSX.Element;
33
- /** Flex column shell — pin header, scroll body (avoids brittle CSS sticky). */
34
- declare function PageHeaderShell({ className, ...props }: PageHeaderShellProps): import("react/jsx-runtime").JSX.Element;
35
- /** Scrollable page content under a pinned PageHeader. */
36
- declare function PageHeaderBody({ className, ...props }: PageHeaderBodyProps): import("react/jsx-runtime").JSX.Element;
37
- export declare const PageHeader: typeof PageHeaderRoot & {
38
- Shell: typeof PageHeaderShell;
39
- Body: typeof PageHeaderBody;
40
- };
41
- export {};
@@ -1,22 +0,0 @@
1
- import { ComponentPropsWithoutRef } from 'react';
2
- export type ScrollableListProps = ComponentPropsWithoutRef<"div">;
3
- export type ScrollableListHeaderProps = ComponentPropsWithoutRef<"div">;
4
- export type ScrollableListBodyProps = ComponentPropsWithoutRef<"div">;
5
- /**
6
- * Fill-height list chrome — Figma `Table` (6154:152285).
7
- * Outer grey-100 frame + header slot + internally scrolling grey-50 body.
8
- * Column layout and rows are caller-owned children.
9
- */
10
- declare function ScrollableListRoot({ className, ...props }: ScrollableListProps): import("react/jsx-runtime").JSX.Element;
11
- /**
12
- * Column title bar. Default left padding aligns with a 24px leading icon +
13
- * 8px gap + 8px row padding (Figma). Override `className` when rows have no icon.
14
- */
15
- declare function ScrollableListHeader({ className, ...props }: ScrollableListHeaderProps): import("react/jsx-runtime").JSX.Element;
16
- /** Internally scrolling row region. */
17
- declare function ScrollableListBody({ className, ...props }: ScrollableListBodyProps): import("react/jsx-runtime").JSX.Element;
18
- export declare const ScrollableList: typeof ScrollableListRoot & {
19
- Header: typeof ScrollableListHeader;
20
- Body: typeof ScrollableListBody;
21
- };
22
- export {};
@@ -1 +0,0 @@
1
- "use strict";const n={50:"#fdfdfc",100:"#f4f2ea",200:"#e1ddce",300:"#bfb9a5",400:"#969080",500:"#6e6960",600:"#524e47",700:"#3a3733",800:"#312e2a",900:"#262420"},o={50:"#f5f8f2",100:"#dde6d2",200:"#c5d4b3",300:"#a8bf8f",400:"#7a9a5e",500:"#5a7a42",600:"#456332",700:"#304624",800:"#223018",900:"#141c0e"},d={50:"#eef1f8",100:"#dae0ef",200:"#b8c4e0",300:"#8fa3cc",400:"#5274ae",500:"#3a5d96",600:"#154199",700:"#103480",800:"#0c2860",900:"#081c42"},c={50:"#faf3f1",100:"#f0d3cc",200:"#e4b0a5",300:"#c97a6b",400:"#b85a48",500:"#a0392a",600:"#802c20",700:"#621f16",800:"#45150f",900:"#2a0c08"},l={50:"#faf1de",100:"#f5e4c0",200:"#efd49a",300:"#e4bc6a",400:"#d9a03e",500:"#c48820",600:"#8f6318",700:"#5a3d0d",800:"#3d2a09",900:"#261a05"},s={50:"#f6f2f8",100:"#e2d9e8",200:"#cbbad6",300:"#b09bc3",400:"#957cb0",500:"#7a5d9d",600:"#5e4680",700:"#3d2e4a",800:"#2a2033",900:"#18121c"},p="#ffffff",a={grey:n,green:o,blue:d,red:c,orange:l,purple:s},t={raise1:"0 1px 2px rgba(38, 36, 32, 0.06), 0 1px 3px rgba(38, 36, 32, 0.04)",raise2:"0 2px 8px rgba(38, 36, 32, 0.08), 0 1px 2px rgba(38, 36, 32, 0.04)",raise3:"0 8px 24px rgba(38, 36, 32, 0.12), 0 2px 8px rgba(38, 36, 32, 0.06)"},r={control:"8px",lg:"8px",md:"6px",sm:"4px"},e=(v,i)=>[v,{lineHeight:i.lineHeight,letterSpacing:i.letterSpacing,...i.fontWeight?{fontWeight:String(i.fontWeight)}:{}}],g={fontFamily:{heading:['"TRY Vesterbro"',"Libre Baskerville","Georgia","serif"],sans:['"Matter-TRIAL"',"DM Sans","system-ui","sans-serif"],mono:["Roboto Mono","monospace"]},fontSize:{title:e("28px",{lineHeight:"34px",letterSpacing:"-0.02em"}),"title-em":e("28px",{lineHeight:"34px",letterSpacing:"-0.02em",fontWeight:500}),heading:e("22px",{lineHeight:"28px",letterSpacing:"0",fontWeight:500}),subheader:e("18px",{lineHeight:"28px",letterSpacing:"-0.01em"}),"subheader-em":e("18px",{lineHeight:"28px",letterSpacing:"-0.01em",fontWeight:500}),body:e("16px",{lineHeight:"24px",letterSpacing:"-0.01em"}),"body-em":e("16px",{lineHeight:"24px",letterSpacing:"-0.01em",fontWeight:500}),"caption-1":e("16px",{lineHeight:"22px",letterSpacing:"0.02em"}),"caption-1-em":e("16px",{lineHeight:"22px",letterSpacing:"0.02em",fontWeight:500}),"caption-2":e("14px",{lineHeight:"20px",letterSpacing:"0.01em"}),"caption-2-em":e("14px",{lineHeight:"20px",letterSpacing:"0.01em",fontWeight:500}),footnote:e("13px",{lineHeight:"17px",letterSpacing:"0"}),"footnote-em":e("13px",{lineHeight:"17px",letterSpacing:"0",fontWeight:500})},boxShadow:{raise1:t.raise1,raise2:t.raise2,raise3:t.raise3},borderRadius:{control:r.control,lg:r.lg,md:r.md,sm:r.sm},maxWidth:{"8xl":"1640px"},colors:{grey:a.grey,gray:a.grey,green:a.green,blue:a.blue,red:a.red,orange:a.orange,purple:a.purple,white:"#ffffff",action:{primary:{idle:"var(--action-primary-idle)","on-idle":"var(--action-primary-on-idle)",hover:"var(--action-primary-hover)","on-hover":"var(--action-primary-on-hover)",disabled:"var(--action-primary-disabled)","on-disabled":"var(--action-primary-on-disabled)"},secondary:{idle:"var(--action-secondary-idle)","on-idle":"var(--action-secondary-on-idle)",hover:"var(--action-secondary-hover)","on-hover":"var(--action-secondary-on-hover)",disabled:"var(--action-secondary-disabled)","on-disabled":"var(--action-secondary-on-disabled)"},tertiary:{idle:"var(--action-tertiary-idle)","on-idle":"var(--action-tertiary-on-idle)",hover:"var(--action-tertiary-hover)","on-hover":"var(--action-tertiary-on-hover)",disabled:"var(--action-tertiary-disabled)","on-disabled":"var(--action-tertiary-on-disabled)"},quaternary:{idle:"var(--action-quaternary-idle)","on-idle":"var(--action-quaternary-on-idle)",hover:"var(--action-quaternary-hover)","on-hover":"var(--action-quaternary-on-hover)",disabled:"var(--action-quaternary-disabled)","on-disabled":"var(--action-quaternary-on-disabled)"},destructive:{idle:"var(--action-destructive-idle)","on-idle":"var(--action-destructive-on-idle)",hover:"var(--action-destructive-hover)","on-hover":"var(--action-destructive-on-hover)",disabled:"var(--action-destructive-disabled)","on-disabled":"var(--action-destructive-on-disabled)"}},background:{primary:"var(--background-primary)",secondary:"var(--background-secondary)",tertiary:"var(--background-tertiary)",hover:"var(--background-hover)",selected:"var(--background-selected)",overlay:"var(--background-overlay)"},display:{"on-light":{primary:"var(--display-on-light-primary)",secondary:"var(--display-on-light-secondary)",tertiary:"var(--display-on-light-tertiary)",quaternary:"var(--display-on-light-quaternary)"},"on-dark":{primary:"var(--display-on-dark-primary)",secondary:"var(--display-on-dark-secondary)",tertiary:"var(--display-on-dark-tertiary)",quaternary:"var(--display-on-dark-quaternary)"}},accent:{"on-light":"var(--accent-on-light)","on-dark":"var(--accent-on-dark)","bg-light":"var(--accent-bg-light)","bg-lighter":"var(--accent-bg-lighter)"},divider:{primary:"var(--divider-primary)",secondary:"var(--divider-secondary)"},meta:{green:"var(--meta-green)",onGreen:"var(--meta-on-green)",orange:"var(--meta-orange)",onOrange:"var(--meta-on-orange)",red:"var(--meta-red)",onRed:"var(--meta-on-red)",blue:"var(--meta-blue)",onBlue:"var(--meta-on-blue)",purple:"var(--meta-purple)",onPurple:"var(--meta-on-purple)"},"text-primary":"var(--display-on-light-primary)","text-secondary":"var(--display-on-light-secondary)","text-tertiary":"var(--display-on-light-tertiary)","surface-primary":"var(--background-primary)","surface-secondary":"var(--background-secondary)","surface-hover":"var(--background-secondary)","border-light":"var(--divider-primary)","border-medium":"var(--divider-secondary)"}};exports.blue=d;exports.borderRadius=r;exports.colorScales=a;exports.elevation=t;exports.green=o;exports.grey=n;exports.orange=l;exports.purple=s;exports.red=c;exports.theme=g;exports.white=p;
@@ -1,132 +0,0 @@
1
- import {
2
- type ComponentPropsWithoutRef,
3
- type MouseEvent,
4
- type ReactNode,
5
- } from "react";
6
- import { cn } from "../utils/cn";
7
-
8
- export type PageHeaderCrumb = {
9
- label: string;
10
- /** Renders a real `<a href>` so native browser controls work. */
11
- href: string;
12
- /**
13
- * Optional SPA handler. Callers should `preventDefault` only for unmodified
14
- * primary clicks; modifier / middle-click keep native anchor behavior.
15
- */
16
- onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
17
- };
18
-
19
- export type PageHeaderProps = {
20
- /** Leading icon (Figma 24×24). */
21
- icon?: ReactNode;
22
- /** Standard title, or current (last) segment when `crumbs` is set. */
23
- title: ReactNode;
24
- /**
25
- * Parent breadcrumb links. When present, renders Nested: icon + parents + `/`
26
- * + current `title` (non-link).
27
- */
28
- crumbs?: PageHeaderCrumb[];
29
- /** Right-hand actions slot (buttons, menus, etc.). */
30
- actions?: ReactNode;
31
- className?: string;
32
- };
33
-
34
- export type PageHeaderShellProps = ComponentPropsWithoutRef<"div">;
35
-
36
- export type PageHeaderBodyProps = ComponentPropsWithoutRef<"div">;
37
-
38
- /**
39
- * Page title row — Figma `Header` (389:8850).
40
- * Variants: Standard (icon + title) | Nested (icon + crumb trail).
41
- */
42
- function PageHeaderRoot({
43
- icon,
44
- title,
45
- crumbs,
46
- actions,
47
- className,
48
- }: PageHeaderProps) {
49
- const isNested = Boolean(crumbs?.length);
50
-
51
- return (
52
- <div
53
- data-variant={isNested ? "nested" : "standard"}
54
- className={cn(
55
- "flex w-full shrink-0 items-center justify-between gap-4",
56
- "min-h-10",
57
- className,
58
- )}
59
- >
60
- <div className="flex min-w-0 flex-1 items-center gap-2">
61
- {icon != null && (
62
- <span className="inline-flex size-6 shrink-0 items-center justify-center [&>svg]:size-6">
63
- {icon}
64
- </span>
65
- )}
66
-
67
- {isNested ? (
68
- <nav aria-label="Breadcrumb" className="min-w-0">
69
- <ol className="flex min-w-0 flex-wrap items-center gap-2">
70
- {crumbs!.map((crumb) => (
71
- <li key={`${crumb.href}-${crumb.label}`} className="contents">
72
- <a
73
- href={crumb.href}
74
- onClick={crumb.onClick}
75
- className="truncate text-caption-1-em text-display-on-light-secondary transition-colors hover:text-display-on-light-primary"
76
- >
77
- {crumb.label}
78
- </a>
79
- <span
80
- aria-hidden
81
- className="text-caption-1-em text-display-on-light-secondary"
82
- >
83
- /
84
- </span>
85
- </li>
86
- ))}
87
- <li
88
- aria-current="page"
89
- className="min-w-0 truncate text-caption-1-em text-display-on-light-primary"
90
- >
91
- {title}
92
- </li>
93
- </ol>
94
- </nav>
95
- ) : (
96
- <h1 className="min-w-0 truncate text-caption-1-em text-display-on-light-primary">
97
- {title}
98
- </h1>
99
- )}
100
- </div>
101
-
102
- {actions != null && (
103
- <div className="flex shrink-0 items-center gap-2">{actions}</div>
104
- )}
105
- </div>
106
- );
107
- }
108
-
109
- /** Flex column shell — pin header, scroll body (avoids brittle CSS sticky). */
110
- function PageHeaderShell({ className, ...props }: PageHeaderShellProps) {
111
- return (
112
- <div
113
- className={cn("flex h-full min-h-0 flex-col", className)}
114
- {...props}
115
- />
116
- );
117
- }
118
-
119
- /** Scrollable page content under a pinned PageHeader. */
120
- function PageHeaderBody({ className, ...props }: PageHeaderBodyProps) {
121
- return (
122
- <div
123
- className={cn("min-h-0 flex-1 overflow-y-auto", className)}
124
- {...props}
125
- />
126
- );
127
- }
128
-
129
- export const PageHeader = Object.assign(PageHeaderRoot, {
130
- Shell: PageHeaderShell,
131
- Body: PageHeaderBody,
132
- });