@ponti-studios/ui 0.1.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -7
  3. package/THIRD_PARTY_NOTICES.md +17 -0
  4. package/dist/index.js +988 -640
  5. package/dist/index.js.map +1 -1
  6. package/package.json +41 -41
  7. package/src/animations.css +42 -383
  8. package/src/components/data-display/accordion.tsx +22 -10
  9. package/src/components/data-display/filter-chip.stories.tsx +38 -0
  10. package/src/components/data-display/filter-chip.tsx +10 -4
  11. package/src/components/data-display/index.ts +5 -0
  12. package/src/components/data-display/metric-card.stories.tsx +48 -0
  13. package/src/components/data-display/metric-card.tsx +20 -0
  14. package/src/components/data-display/sort-controls.stories.tsx +45 -0
  15. package/src/components/data-display/sort-controls.tsx +99 -0
  16. package/src/components/data-display/sort-row.tsx +74 -0
  17. package/src/components/data-display/table.tsx +5 -9
  18. package/src/components/feedback/alert.tsx +4 -4
  19. package/src/components/feedback/empty-state.tsx +16 -6
  20. package/src/components/feedback/file-upload-status-badge.stories.tsx +28 -0
  21. package/src/components/feedback/file-upload-status-badge.tsx +33 -0
  22. package/src/components/feedback/file-upload-status.stories.tsx +57 -0
  23. package/src/components/feedback/file-upload-status.tsx +152 -0
  24. package/src/components/feedback/index.ts +9 -0
  25. package/src/components/feedback/progress-bar.stories.tsx +39 -0
  26. package/src/components/feedback/progress-bar.tsx +21 -0
  27. package/src/components/feedback/progress.stories.tsx +8 -6
  28. package/src/components/feedback/progress.tsx +3 -3
  29. package/src/components/feedback/skeleton.stories.tsx +36 -0
  30. package/src/components/feedback/skeleton.tsx +7 -0
  31. package/src/components/feedback/spinner.tsx +2 -2
  32. package/src/components/feedback/update-guard.stories.tsx +32 -0
  33. package/src/components/feedback/update-guard.tsx +280 -0
  34. package/src/components/forms/calendar.tsx +14 -11
  35. package/src/components/forms/date-month-select.stories.tsx +26 -0
  36. package/src/components/forms/date-month-select.tsx +70 -0
  37. package/src/components/forms/date-picker.tsx +3 -3
  38. package/src/components/forms/drop-zone.stories.tsx +56 -0
  39. package/src/components/forms/drop-zone.tsx +146 -0
  40. package/src/components/forms/entity-select.stories.tsx +65 -0
  41. package/src/components/forms/entity-select.tsx +79 -0
  42. package/src/components/forms/field.tsx +3 -3
  43. package/src/components/forms/group-by-select.stories.tsx +26 -0
  44. package/src/components/forms/group-by-select.tsx +47 -0
  45. package/src/components/forms/index.ts +10 -0
  46. package/src/components/forms/input.stories.tsx +4 -4
  47. package/src/components/forms/input.tsx +1 -1
  48. package/src/components/forms/passkey-management.stories.tsx +81 -0
  49. package/src/components/forms/passkey-management.tsx +138 -0
  50. package/src/components/forms/radio-group.tsx +14 -13
  51. package/src/components/forms/select.stories.tsx +4 -4
  52. package/src/components/forms/select.tsx +47 -48
  53. package/src/components/forms/slider.stories.tsx +5 -2
  54. package/src/components/forms/slider.tsx +39 -17
  55. package/src/components/forms/stepper.tsx +4 -4
  56. package/src/components/forms/switch.stories.tsx +1 -1
  57. package/src/components/forms/switch.tsx +2 -2
  58. package/src/components/forms/textarea.stories.tsx +2 -2
  59. package/src/components/forms/textarea.tsx +1 -1
  60. package/src/components/layout/index.ts +3 -0
  61. package/src/components/layout/scroll-area.stories.tsx +4 -4
  62. package/src/components/layout/scroll-area.tsx +23 -21
  63. package/src/components/layout/section-intro.stories.tsx +29 -0
  64. package/src/components/layout/section-intro.tsx +31 -0
  65. package/src/components/layout/surface-panel.stories.tsx +32 -0
  66. package/src/components/layout/surface-panel.tsx +15 -0
  67. package/src/components/navigation/app-navigation.stories.tsx +2 -2
  68. package/src/components/navigation/app-navigation.tsx +13 -13
  69. package/src/components/navigation/index.ts +4 -0
  70. package/src/components/navigation/pagination-controls.stories.tsx +41 -0
  71. package/src/components/navigation/pagination-controls.tsx +50 -0
  72. package/src/components/navigation/route-link.stories.tsx +30 -0
  73. package/src/components/navigation/route-link.tsx +42 -0
  74. package/src/components/navigation/tabs.stories.tsx +5 -5
  75. package/src/components/navigation/tabs.tsx +8 -8
  76. package/src/components/overlays/alert-dialog.tsx +22 -25
  77. package/src/components/overlays/command.tsx +98 -26
  78. package/src/components/overlays/dialog.tsx +5 -5
  79. package/src/components/overlays/dropdown-menu.stories.tsx +0 -5
  80. package/src/components/overlays/dropdown-menu.tsx +49 -31
  81. package/src/components/overlays/popover.stories.tsx +2 -2
  82. package/src/components/overlays/popover.tsx +43 -14
  83. package/src/components/overlays/sheet.stories.tsx +2 -2
  84. package/src/components/overlays/sheet.tsx +51 -17
  85. package/src/components/primitives/avatar.tsx +9 -5
  86. package/src/components/primitives/badge.tsx +11 -12
  87. package/src/components/primitives/button.tsx +49 -23
  88. package/src/components/primitives/card.stories.tsx +2 -2
  89. package/src/components/primitives/card.tsx +2 -5
  90. package/src/components/primitives/index.ts +2 -0
  91. package/src/components/primitives/label.stories.tsx +1 -1
  92. package/src/components/primitives/label.tsx +5 -6
  93. package/src/components/primitives/status-badge.stories.tsx +52 -0
  94. package/src/components/primitives/status-badge.tsx +33 -0
  95. package/src/constants/chart-colors.ts +7 -7
  96. package/src/hooks/index.ts +1 -0
  97. package/src/hooks/use-sort.ts +20 -0
  98. package/src/index.ts +30 -11
  99. package/src/styles.css +100 -974
  100. package/src/tokens/chart-colors.stories.tsx +192 -0
  101. package/src/tokens/color-systems.stories.tsx +20 -112
  102. package/src/tokens/foundations.stories.tsx +58 -100
  103. package/src/tokens/generated/dark.colors.generated.ts +29 -0
  104. package/src/tokens/generated/dark.css +29 -0
  105. package/src/tokens/generated/foundations.css +148 -0
  106. package/src/tokens/generated/foundations.generated.ts +451 -0
  107. package/src/tokens/generated/light.colors.generated.ts +29 -0
  108. package/src/tokens/generated/light.css +29 -0
  109. package/src/tokens/index.ts +79 -16
  110. package/src/tokens/layout.stories.tsx +23 -91
  111. package/src/tokens/colors.ts +0 -156
  112. package/src/tokens/motion.ts +0 -51
  113. package/src/tokens/radii.ts +0 -10
  114. package/src/tokens/shadows.ts +0 -34
  115. package/src/tokens/spacing.ts +0 -30
  116. package/src/tokens/typography.ts +0 -42
@@ -1,16 +1,79 @@
1
- export { colors } from "./colors";
2
- export {
3
- COLOR_MODE_ATTRIBUTE,
4
- COLOR_SYSTEM_ATTRIBUTE,
5
- colorSystems,
6
- colorTokenNames,
7
- } from "./colors";
8
- export type { ColorMode, ColorSystem, ColorToken } from "./colors";
9
- export { durations, easingWeb, translateDistances } from "./motion";
10
- export { radii } from "./radii";
11
- export { shadowsNative, shadowsWeb } from "./shadows";
12
- export { contentWidths, spacing } from "./spacing";
13
- export { fontFamilies, fontSizes, fontWeights, letterSpacing, lineHeights } from "./typography";
14
- export type { RadiusToken } from "./radii";
15
- export type { ContentWidthToken, SpacingToken } from "./spacing";
16
- export type { FontSizeToken, FontWeightToken } from "./typography";
1
+ import darkTokens from "./generated/dark.colors.generated";
2
+ import foundations from "./generated/foundations.generated";
3
+ import lightTokens from "./generated/light.colors.generated";
4
+
5
+ const toPixels = (value: string) => {
6
+ if (value.endsWith("rem")) return Number.parseFloat(value) * 16;
7
+ if (value.endsWith("px")) return Number.parseFloat(value);
8
+ throw new Error(`Unsupported foundation dimension: ${value}`);
9
+ };
10
+
11
+ const toMilliseconds = (value: string) => Number.parseFloat(value);
12
+ const toBezier = (value: number[]) => `cubic-bezier(${value.join(", ")})`;
13
+ type NormalizedSpacingKey<Key extends string> = Key extends `${infer Whole}-${infer Fraction}`
14
+ ? `${Whole}.${Fraction}`
15
+ : Key;
16
+ export type SpacingToken = NormalizedSpacingKey<
17
+ keyof (typeof foundations)["spacing-scale"] & string
18
+ >;
19
+
20
+ export const colorTokenNames = Object.keys(lightTokens) as Array<keyof typeof lightTokens>;
21
+ export type ColorToken = keyof typeof lightTokens;
22
+ export type ColorMode = "light" | "dark";
23
+ export type ColorTheme = Readonly<Record<ColorToken, string>>;
24
+
25
+ export const colorThemes = {
26
+ light: lightTokens,
27
+ dark: darkTokens,
28
+ } as const satisfies Record<ColorMode, ColorTheme>;
29
+
30
+ export const colors = colorTokenNames.reduce(
31
+ (accumulator, token) => {
32
+ accumulator[token] = `var(--${token})`;
33
+ return accumulator;
34
+ },
35
+ {} as Record<ColorToken, `var(--${string})`>,
36
+ );
37
+
38
+ export const spacing = Object.fromEntries(
39
+ Object.entries(foundations["spacing-scale"]).map(([key, value]) => [
40
+ key.replace("-", "."),
41
+ toPixels(value),
42
+ ]),
43
+ ) as Record<SpacingToken, number>;
44
+
45
+ export const fontFamilies = Object.fromEntries(
46
+ Object.entries(foundations.font).map(([key, value]) => [key, value.join(", ")]),
47
+ ) as Record<keyof typeof foundations.font, string>;
48
+
49
+ export const fontFamiliesNative = { sans: "System", serif: "serif", mono: "monospace" } as const;
50
+ export const textSizes = Object.fromEntries(
51
+ Object.entries(foundations.text).map(([key, value]) => [key, toPixels(value)]),
52
+ ) as Record<keyof typeof foundations.text, number>;
53
+ export const textLineHeights = foundations["text-line-height"];
54
+ export const fontWeights = Object.fromEntries(
55
+ Object.entries(foundations["font-weight"]).map(([key, value]) => [key, String(value)]),
56
+ ) as Record<keyof (typeof foundations)["font-weight"], string>;
57
+ export const tracking = foundations.tracking;
58
+ export const leading = foundations.leading;
59
+ export const radii = Object.fromEntries(
60
+ Object.entries(foundations.radius).map(([key, value]) => [key, toPixels(value)]),
61
+ ) as Record<keyof typeof foundations.radius, number>;
62
+ export const shadows = foundations.shadow;
63
+ export const breakpoints = foundations.breakpoint;
64
+ export const containers = foundations.container;
65
+ export const zIndices = foundations["z-index"];
66
+ export const easing = Object.fromEntries(
67
+ Object.entries(foundations.ease).map(([key, value]) => [key, toBezier(value)]),
68
+ ) as Record<keyof typeof foundations.ease, string>;
69
+ export const transitionDurations = Object.fromEntries(
70
+ Object.entries(foundations.duration).map(([key, value]) => [key, toMilliseconds(value)]),
71
+ ) as Record<keyof typeof foundations.duration, number>;
72
+ export const animations = foundations.animate;
73
+
74
+ export type RadiusToken = keyof typeof radii;
75
+ export type TextSizeToken = keyof typeof textSizes;
76
+ export type FontWeightToken = keyof typeof fontWeights;
77
+ export type TrackingToken = keyof typeof tracking;
78
+ export type LeadingToken = keyof typeof leading;
79
+ export type ShadowToken = keyof typeof shadows;
@@ -2,26 +2,24 @@ import type { Meta, StoryObj } from "@storybook/react-vite";
2
2
 
3
3
  const meta = {
4
4
  title: "Foundations/Layout Rhythm",
5
- parameters: {
6
- layout: "fullscreen",
7
- },
5
+ parameters: { layout: "fullscreen" },
8
6
  } satisfies Meta;
9
-
10
7
  export default meta;
11
8
  type Story = StoryObj<typeof meta>;
12
9
 
13
10
  export const PageShell: Story = {
14
11
  render: () => (
15
- <main className="page-shell bg-canvas text-primary">
16
- <header className="layout-stack">
17
- <p className="body-4 text-secondary">Page shell</p>
18
- <h1 className="display-1">A consistent starting point for content pages</h1>
12
+ <main className="page-shell bg-background text-foreground">
13
+ <header className="flex flex-col gap-4">
14
+ <p className="text-muted-foreground text-sm">Page shell</p>
15
+ <h1 className="text-4xl font-semibold tracking-tight">
16
+ A consistent starting point for content pages.
17
+ </h1>
19
18
  </header>
20
- <section className="layout-stack">
21
- <h2 className="heading-2">Section rhythm</h2>
22
- <p className="body-1 text-secondary max-w-2xl">
23
- Page-level breathing room and internal section spacing remain consistent across indexes,
24
- feeds, and editorial surfaces.
19
+ <section className="flex flex-col gap-4">
20
+ <h2 className="text-2xl font-semibold">Section rhythm</h2>
21
+ <p className="text-muted-foreground max-w-2xl text-base">
22
+ Layout helpers compose standard Tailwind spacing and semantic colors.
25
23
  </p>
26
24
  </section>
27
25
  </main>
@@ -30,20 +28,18 @@ export const PageShell: Story = {
30
28
 
31
29
  export const ListRows: Story = {
32
30
  render: () => (
33
- <main className="page-shell bg-canvas text-primary">
34
- <div className="layout-stack">
35
- <h1 className="display-1">List row rhythm</h1>
36
- <div className="border-subtle divide-border-subtle divide-y border-b">
37
- {[
38
- ["01", "A compact row", "For projects, search results, or activity."],
39
- ["02", "A readable row", "Consistent padding keeps scanning calm."],
40
- ["03", "A responsive row", "The same rhythm holds on mobile and desktop."],
41
- ].map(([index, title, description]) => (
42
- <div key={index} className="list-row items-start justify-between">
43
- <span className="body-3 text-secondary tabular-nums">{index}</span>
44
- <div className="layout-stack min-w-0 flex-1 gap-1">
45
- <h2 className="heading-3">{title}</h2>
46
- <p className="body-3 text-secondary">{description}</p>
31
+ <main className="page-shell bg-background text-foreground">
32
+ <div className="flex flex-col gap-4">
33
+ <h1 className="text-4xl font-semibold tracking-tight">List row rhythm</h1>
34
+ <div className="divide-border border-border divide-y border-b">
35
+ {["A compact row", "A readable row", "A responsive row"].map((title, index) => (
36
+ <div key={title} className="flex gap-4 py-6">
37
+ <span className="text-muted-foreground font-mono text-sm">0{index + 1}</span>
38
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
39
+ <h2 className="text-lg font-semibold">{title}</h2>
40
+ <p className="text-muted-foreground text-sm">
41
+ Consistent padding keeps scanning calm.
42
+ </p>
47
43
  </div>
48
44
  </div>
49
45
  ))}
@@ -52,67 +48,3 @@ export const ListRows: Story = {
52
48
  </main>
53
49
  ),
54
50
  };
55
-
56
- export const ListRowsWithMedia: Story = {
57
- render: () => (
58
- <main className="page-shell bg-canvas text-primary">
59
- <div className="layout-stack">
60
- <h1 className="display-1">List rows with media</h1>
61
- <div className="border-subtle divide-border-subtle divide-y border-b">
62
- <div className="list-row items-center">
63
- <div className="list-media list-media-wide bg-panel" aria-hidden="true">
64
- <span className="heading-3 text-secondary">WO</span>
65
- </div>
66
- <div className="layout-stack min-w-0 gap-1">
67
- <h2 className="heading-3">Wide media row</h2>
68
- <p className="body-3 text-secondary">For client or partner marks.</p>
69
- </div>
70
- </div>
71
- <div className="list-row items-center">
72
- <div className="list-media list-media-square bg-panel" aria-hidden="true">
73
- <span className="heading-3 text-secondary">PR</span>
74
- </div>
75
- <div className="layout-stack min-w-0 gap-1">
76
- <h2 className="heading-3">Square media row</h2>
77
- <p className="body-3 text-secondary">For product or project marks.</p>
78
- </div>
79
- </div>
80
- </div>
81
- </div>
82
- </main>
83
- ),
84
- };
85
-
86
- export const DetailSections: Story = {
87
- render: () => (
88
- <main className="bg-canvas text-primary">
89
- <section className="section section-hero">
90
- <p className="body-4 text-secondary">Detail hero</p>
91
- <h1 className="display-1">A detail page with a clear vertical rhythm</h1>
92
- </section>
93
- <section className="section">
94
- <h2 className="heading-2">Standard section</h2>
95
- <p className="body-1 text-secondary max-w-2xl">
96
- Sections share a border, gutter, and vertical breathing room without requiring a React
97
- component.
98
- </p>
99
- </section>
100
- <section className="section gap-8">
101
- <h2 className="heading-2">Dense section</h2>
102
- <ol className="layout-stack gap-8">
103
- <li className="body-1">01 — Start with the problem.</li>
104
- <li className="body-1">02 — Explain the approach.</li>
105
- <li className="body-1">03 — Close with the outcome.</li>
106
- </ol>
107
- </section>
108
- <div className="detail-navigation px-4 md:px-6">
109
- <a className="body-2 text-secondary hover:text-primary" href="#previous">
110
- ← Previous
111
- </a>
112
- <a className="body-2 text-secondary hover:text-primary" href="#next">
113
- Next →
114
- </a>
115
- </div>
116
- </main>
117
- ),
118
- };
@@ -1,156 +0,0 @@
1
- /**
2
- * Canonical semantic color contract for the Ponti Studios system.
3
- *
4
- * Components consume these roles. The runtime CSS provides the light and dark
5
- * values; this module exists for inspection, tooling, and typed consumers.
6
- */
7
-
8
- export const colorTokenNames = [
9
- "surface-canvas",
10
- "surface-panel",
11
- "surface-raised",
12
- "surface-inset",
13
- "surface-hover",
14
- "surface-pressed",
15
- "surface-selected",
16
- "surface-disabled",
17
- "overlay-scrim",
18
- "text-primary",
19
- "text-secondary",
20
- "text-tertiary",
21
- "text-disabled",
22
- "text-accent",
23
- "text-destructive",
24
- "text-success",
25
- "text-warning",
26
- "text-on-accent",
27
- "text-on-destructive",
28
- "text-on-success",
29
- "text-on-warning",
30
- "border-subtle",
31
- "border-default",
32
- "border-strong",
33
- "border-focus",
34
- "border-accent",
35
- "border-destructive",
36
- "accent",
37
- "accent-hover",
38
- "accent-pressed",
39
- "accent-subtle",
40
- "destructive",
41
- "destructive-hover",
42
- "destructive-pressed",
43
- "destructive-subtle",
44
- "success",
45
- "success-subtle",
46
- "warning",
47
- "warning-subtle",
48
- "ring-focus",
49
- ] as const;
50
-
51
- export type ColorToken = (typeof colorTokenNames)[number];
52
- export type ColorMode = "light" | "dark";
53
- export type ColorSystem = "ponti";
54
- export type ColorTheme = Record<ColorToken, string>;
55
- export type ColorSystemThemes = Record<ColorMode, ColorTheme>;
56
-
57
- const pontiLight: ColorTheme = {
58
- "surface-canvas": "#ffffff",
59
- "surface-panel": "#f6f8fa",
60
- "surface-raised": "#ffffff",
61
- "surface-inset": "#eff2f5",
62
- "surface-hover": "#e8ebef",
63
- "surface-pressed": "#dfe3e8",
64
- "surface-selected": "rgba(9, 105, 218, 0.1)",
65
- "surface-disabled": "#eff2f5",
66
- "overlay-scrim": "rgba(31, 35, 40, 0.42)",
67
- "text-primary": "#25292e",
68
- "text-secondary": "#59636e",
69
- "text-tertiary": "#818b98",
70
- "text-disabled": "#9ea7b3",
71
- "text-accent": "#0969da",
72
- "text-destructive": "#cf222e",
73
- "text-success": "#1f883d",
74
- "text-warning": "#9a6700",
75
- "text-on-accent": "#ffffff",
76
- "text-on-destructive": "#ffffff",
77
- "text-on-success": "#ffffff",
78
- "text-on-warning": "#1c1c1e",
79
- "border-subtle": "rgba(129, 139, 152, 0.2)",
80
- "border-default": "#d1d9e0",
81
- "border-strong": "#8c959f",
82
- "border-focus": "#0969da",
83
- "border-accent": "#0969da",
84
- "border-destructive": "#cf222e",
85
- accent: "#0969da",
86
- "accent-hover": "#0550ae",
87
- "accent-pressed": "#033d8b",
88
- "accent-subtle": "rgba(9, 105, 218, 0.1)",
89
- destructive: "#cf222e",
90
- "destructive-hover": "#a40e26",
91
- "destructive-pressed": "#82071e",
92
- "destructive-subtle": "rgba(207, 34, 46, 0.12)",
93
- success: "#1f883d",
94
- "success-subtle": "rgba(31, 136, 61, 0.12)",
95
- warning: "#9a6700",
96
- "warning-subtle": "rgba(154, 103, 0, 0.12)",
97
- "ring-focus": "#0969da",
98
- };
99
-
100
- const pontiDark: ColorTheme = {
101
- "surface-canvas": "#0d1117",
102
- "surface-panel": "#161b22",
103
- "surface-raised": "#21262d",
104
- "surface-inset": "#1a2029",
105
- "surface-hover": "#242a33",
106
- "surface-pressed": "#30363d",
107
- "surface-selected": "rgba(47, 129, 247, 0.18)",
108
- "surface-disabled": "#1a2029",
109
- "overlay-scrim": "rgba(1, 4, 9, 0.78)",
110
- "text-primary": "#f0f6fc",
111
- "text-secondary": "#8b949e",
112
- "text-tertiary": "#6e7681",
113
- "text-disabled": "#484f58",
114
- "text-accent": "#58a6ff",
115
- "text-destructive": "#ff7b72",
116
- "text-success": "#3fb950",
117
- "text-warning": "#d29922",
118
- "text-on-accent": "#ffffff",
119
- "text-on-destructive": "#ffffff",
120
- "text-on-success": "#ffffff",
121
- "text-on-warning": "#0d1117",
122
- "border-subtle": "rgba(240, 246, 252, 0.14)",
123
- "border-default": "#30363d",
124
- "border-strong": "#6e7681",
125
- "border-focus": "#2f81f7",
126
- "border-accent": "#2f81f7",
127
- "border-destructive": "#da3633",
128
- accent: "#2f81f7",
129
- "accent-hover": "#58a6ff",
130
- "accent-pressed": "#1f6feb",
131
- "accent-subtle": "rgba(47, 129, 247, 0.18)",
132
- destructive: "#da3633",
133
- "destructive-hover": "#f85149",
134
- "destructive-pressed": "#b62324",
135
- "destructive-subtle": "rgba(218, 54, 51, 0.18)",
136
- success: "#238636",
137
- "success-subtle": "rgba(35, 134, 54, 0.18)",
138
- warning: "#9e6a03",
139
- "warning-subtle": "rgba(158, 106, 3, 0.18)",
140
- "ring-focus": "#2f81f7",
141
- };
142
-
143
- export const colorSystems = {
144
- ponti: { light: pontiLight, dark: pontiDark },
145
- } as const satisfies Record<ColorSystem, ColorSystemThemes>;
146
-
147
- export const colors = colorTokenNames.reduce(
148
- (accumulator, token) => {
149
- accumulator[token] = `var(--color-${token})`;
150
- return accumulator;
151
- },
152
- {} as Record<ColorToken, `var(--color-${string})`>,
153
- );
154
-
155
- export const COLOR_SYSTEM_ATTRIBUTE = "data-color-system" as const;
156
- export const COLOR_MODE_ATTRIBUTE = "data-color-mode" as const;
@@ -1,51 +0,0 @@
1
- /**
2
- * Motion tokens — durations and translate distances.
3
- *
4
- * Durations are in milliseconds. Must match animations.css and
5
- * apps/omiro/theme/motion.ts (which imports from here).
6
- *
7
- * CSS easing strings are web-only. Mobile uses react-native-reanimated
8
- * Easing.* functions which cannot be expressed as strings — the mobile
9
- * motion.ts keeps those local and imports only the numeric constants here.
10
- *
11
- * ## Animation mandate
12
- *
13
- * Web interactive animations MUST use the shared GSAP helpers exposed by the
14
- * consuming app.
15
- * The canonical sequences (playFocusExpand, playFocusCollapse,
16
- * playContextSwitch, playSubmitPulse, playEnterRow, playExitRow,
17
- * playShimmer) read the numeric constants from this file so all motion
18
- * stays in sync.
19
- *
20
- * CSS `motion-anim-*` classes (animations.css) are reserved for Radix UI
21
- * component enter/exit only — do not add new CSS keyframe animations for
22
- * interactive product surfaces.
23
- */
24
-
25
- export const durations = {
26
- /** Element arrives and settles (decelerate). */
27
- enter: 150,
28
- /** Element leaves without lingering (accelerate). */
29
- exit: 120,
30
- /** Content animations: loading states, thinking indicators. */
31
- standard: 120,
32
- /** Loop / breezy animations. */
33
- breezy: 1800,
34
- spin: 1200,
35
- } as const;
36
-
37
- export const translateDistances = {
38
- /** Enter lift (px). */
39
- enterY: 6,
40
- /** Exit settle (px). */
41
- exitY: 4,
42
- enterX: 6,
43
- exitX: 4,
44
- } as const;
45
-
46
- /** CSS cubic-bezier strings — web only. */
47
- export const easingWeb = {
48
- enter: "cubic-bezier(0.0, 0.0, 0.2, 1)",
49
- exit: "cubic-bezier(0.4, 0.0, 1, 1)",
50
- standard: "cubic-bezier(0.4, 0, 0.2, 1)",
51
- } as const;
@@ -1,10 +0,0 @@
1
- export const radii = {
2
- sm: 6,
3
- md: 10,
4
- lg: 14,
5
- xl: 18,
6
- full: 9999,
7
- icon: 20,
8
- } as const;
9
-
10
- export type RadiusToken = keyof typeof radii;
@@ -1,34 +0,0 @@
1
- /**
2
- * Shadow tokens.
3
- *
4
- * `shadowsWeb` values must match --shadow-* in globals.css.
5
- * `shadowsNative` are React Native shadow object equivalents.
6
- */
7
-
8
- export const shadowsWeb = {
9
- low: "0 2px 8px rgba(0, 0, 0, 0.35)",
10
- medium: "0 8px 24px rgba(0, 0, 0, 0.45)",
11
- high: "0 20px 60px rgba(0, 0, 0, 0.55)",
12
- } as const;
13
-
14
- /** React Native shadow objects. Pass these into StyleSheet styles. */
15
- export const shadowsNative = {
16
- low: {
17
- shadowColor: "#0f1113",
18
- shadowOffset: { width: 0, height: 2 },
19
- shadowOpacity: 0.35,
20
- shadowRadius: 8,
21
- },
22
- medium: {
23
- shadowColor: "#0f1113",
24
- shadowOffset: { width: 0, height: 8 },
25
- shadowOpacity: 0.45,
26
- shadowRadius: 24,
27
- },
28
- high: {
29
- shadowColor: "#0f1113",
30
- shadowOffset: { width: 0, height: 20 },
31
- shadowOpacity: 0.55,
32
- shadowRadius: 60,
33
- },
34
- } as const;
@@ -1,30 +0,0 @@
1
- /**
2
- * Spacing tokens — 8px primary grid, 4px secondary.
3
- *
4
- * Values are unitless numbers (px on web via CSS vars, logical pixels on
5
- * mobile). Must match --spacing-* in packages/ui/src/styles.css.
6
- */
7
-
8
- export const spacing = {
9
- 1: 4,
10
- 2: 8,
11
- 3: 12,
12
- 4: 16,
13
- 5: 24,
14
- 6: 32,
15
- 7: 48,
16
- 8: 64,
17
- } as const;
18
-
19
- /**
20
- * Content width tokens for constraining max-width of content.
21
- * Used for message bubbles, transcript areas, and other content containers.
22
- */
23
- export const contentWidths = {
24
- bubble: "36rem", // Compact message bubble width (576px)
25
- transcript: "44rem", // Standard transcript/content width (704px)
26
- notePreview: "32ch", // Empty-state note preview width
27
- } as const;
28
-
29
- export type SpacingToken = keyof typeof spacing;
30
- export type ContentWidthToken = keyof typeof contentWidths;
@@ -1,42 +0,0 @@
1
- export const fontFamilies = {
2
- primary: "-apple-system, BlinkMacSystemFont, system-ui, sans-serif",
3
- mono: "ui-monospace, monospace",
4
- } as const;
5
-
6
- export const fontSizes = {
7
- micro: 10,
8
- caption2: 11,
9
- caption1: 12,
10
- footnote: 13,
11
- xs: 12,
12
- sm: 14,
13
- subhead: 15,
14
- md: 16,
15
- body: 17,
16
- lg: 18,
17
- xl: 20,
18
- headline: 17,
19
- display: 28,
20
- } as const;
21
-
22
- export const fontWeights = {
23
- regular: "400",
24
- medium: "500",
25
- semibold: "600",
26
- bold: "700",
27
- } as const;
28
-
29
- export const lineHeights = {
30
- tight: 1.2,
31
- normal: 1.4,
32
- relaxed: 1.6,
33
- } as const;
34
-
35
- export const letterSpacing = {
36
- tight: -0.05,
37
- normal: 0,
38
- relaxed: 0.01,
39
- } as const;
40
-
41
- export type FontSizeToken = keyof typeof fontSizes;
42
- export type FontWeightToken = keyof typeof fontWeights;