@ponti-studios/ui 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +14 -0
  2. package/package.json +45 -24
  3. package/src/animations.css +92 -15
  4. package/src/components/data-display/accordion.tsx +15 -6
  5. package/src/components/data-display/filter-chip.stories.tsx +38 -0
  6. package/src/components/data-display/filter-chip.tsx +9 -3
  7. package/src/components/data-display/sort-controls.tsx +1 -1
  8. package/src/components/data-display/table.tsx +3 -7
  9. package/src/components/feedback/empty-state.tsx +16 -6
  10. package/src/components/feedback/file-upload-status-badge.tsx +1 -1
  11. package/src/components/feedback/progress.tsx +2 -2
  12. package/src/components/feedback/update-guard.tsx +1 -1
  13. package/src/components/forms/calendar.tsx +6 -3
  14. package/src/components/forms/field.tsx +3 -3
  15. package/src/components/forms/input.tsx +1 -1
  16. package/src/components/forms/passkey-management.tsx +2 -2
  17. package/src/components/forms/radio-group.tsx +1 -1
  18. package/src/components/forms/select.tsx +11 -4
  19. package/src/components/forms/slider.tsx +16 -4
  20. package/src/components/forms/stepper.tsx +1 -1
  21. package/src/components/forms/textarea.tsx +1 -1
  22. package/src/components/layout/section-intro.tsx +1 -1
  23. package/src/components/navigation/app-navigation.tsx +4 -4
  24. package/src/components/navigation/pagination-controls.tsx +2 -2
  25. package/src/components/navigation/tabs.tsx +1 -1
  26. package/src/components/overlays/alert-dialog.tsx +30 -8
  27. package/src/components/overlays/command.tsx +123 -20
  28. package/src/components/overlays/dialog.tsx +4 -4
  29. package/src/components/overlays/dropdown-menu.tsx +137 -21
  30. package/src/components/overlays/popover.tsx +14 -3
  31. package/src/components/overlays/sheet.tsx +24 -8
  32. package/src/components/primitives/avatar.tsx +6 -2
  33. package/src/components/primitives/badge.tsx +5 -2
  34. package/src/components/primitives/button.tsx +16 -18
  35. package/src/components/primitives/card.stories.tsx +2 -2
  36. package/src/components/primitives/card.tsx +2 -5
  37. package/src/constants/chart-colors.ts +2 -2
  38. package/src/index.ts +1 -1
  39. package/src/native/index.ts +11 -0
  40. package/src/native/make-styles.ts +32 -0
  41. package/src/native/shadows.ts +38 -0
  42. package/src/native/use-theme-colors.ts +19 -0
  43. package/src/styles.css +154 -66
  44. package/src/tokens/chart-colors.stories.tsx +189 -0
  45. package/src/tokens/color-systems.stories.tsx +21 -3
  46. package/src/tokens/css-vars.ts +15 -0
  47. package/src/tokens/foundations.stories.tsx +66 -16
  48. package/src/tokens/generated/dark.colors.generated.ts +24 -50
  49. package/src/tokens/generated/dark.css +24 -48
  50. package/src/tokens/generated/foundations.css +2 -2
  51. package/src/tokens/generated/foundations.generated.ts +14 -6
  52. package/src/tokens/generated/light.colors.generated.ts +24 -50
  53. package/src/tokens/generated/light.css +24 -48
  54. package/src/tokens/index.ts +12 -15
  55. package/src/tokens/layout.stories.tsx +40 -3
  56. package/src/tokens.css +3 -0
  57. package/dist/index.js +0 -2508
  58. package/dist/index.js.map +0 -1
package/README.md CHANGED
@@ -25,3 +25,17 @@ pnpm config set --location=user //registry.npmjs.org/:_authToken "$NODE_AUTH_TOK
25
25
  ```
26
26
 
27
27
  CI consumers should use a secret-backed npm token with read access.
28
+
29
+ ### Ships TypeScript source, not a bundle
30
+
31
+ This package has no build output — every `exports` entry resolves to a file under `src/`. Consumers are expected to transpile the package themselves (Vite, Metro, Next, etc. all do this for workspace/npm packages by default). This is deliberate: Tailwind v4 class detection for consumers of `./styles.css` or `./tokens.css` requires an `@source` directive pointing at the installed package's `src/`, e.g.
32
+
33
+ ```css
34
+ @source "../../../node_modules/@ponti-studios/ui/src";
35
+ ```
36
+
37
+ Bundling the package would break that detection, since Tailwind can't scan generated/minified output for class names. `pnpm run build` only type-checks; it does not emit JS.
38
+
39
+ ### `./native` subpath
40
+
41
+ `@ponti-studios/ui/native` is the only part of the package that imports `react-native`. Web consumers never pull it in; native consumers get `createMakeStyles`, `nativeShadows`, `useColorMode`, and `useThemeColors`. `react-native` is an optional peer dependency — only declare it in your own `package.json` if you actually import from this subpath.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ponti-studios/ui",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "private": false,
5
5
  "description": "Shared UI component library for ponti-studios labs",
6
6
  "license": "MIT",
@@ -14,13 +14,13 @@
14
14
  "access": "public"
15
15
  },
16
16
  "files": [
17
- "dist",
18
17
  "src",
19
18
  "THIRD_PARTY_NOTICES.md"
20
19
  ],
21
20
  "type": "module",
22
21
  "sideEffects": [
23
22
  "./src/styles.css",
23
+ "./src/tokens.css",
24
24
  "./src/animations.css"
25
25
  ],
26
26
  "exports": {
@@ -64,19 +64,41 @@
64
64
  "types": "./src/tokens/index.ts",
65
65
  "import": "./src/tokens/index.ts"
66
66
  },
67
+ "./tokens/css-vars": {
68
+ "types": "./src/tokens/css-vars.ts",
69
+ "import": "./src/tokens/css-vars.ts"
70
+ },
71
+ "./native": {
72
+ "types": "./src/native/index.ts",
73
+ "import": "./src/native/index.ts"
74
+ },
67
75
  "./hooks": {
68
76
  "types": "./src/hooks/index.ts",
69
77
  "import": "./src/hooks/index.ts"
70
78
  },
71
79
  "./styles.css": "./src/styles.css",
80
+ "./tokens.css": "./src/tokens.css",
72
81
  "./animations.css": "./src/animations.css"
73
82
  },
83
+ "scripts": {
84
+ "build": "tsc --noEmit",
85
+ "dev": "vite",
86
+ "storybook": "style-dictionary build --config style-dictionary.dark-storybook.json && storybook dev -p 6006",
87
+ "check:source": "node tokens/check-source.mjs",
88
+ "test:a11y": "vitest --run --config vitest.config.ts",
89
+ "tokens:build": "style-dictionary build --config style-dictionary.foundations.json && style-dictionary build --config style-dictionary.light.json && style-dictionary build --config style-dictionary.dark.json && style-dictionary build --config style-dictionary.dark-storybook.json",
90
+ "tokens:check": "pnpm run tokens:build && node tokens/check-foundations.mjs && git diff --exit-code -- src/tokens/generated",
91
+ "typecheck": "tsc --noEmit",
92
+ "lint": "oxlint src --fix",
93
+ "format": "oxfmt src --write",
94
+ "prepack": "pnpm run tokens:check && pnpm run check:source && pnpm run typecheck"
95
+ },
74
96
  "dependencies": {
75
97
  "@base-ui/react": "^1.6.0",
98
+ "@radix-ui/colors": "^3.0.0",
76
99
  "class-variance-authority": "^0.7.1",
77
100
  "clsx": "^2.1.1",
78
101
  "date-fns": "^4.1.0",
79
- "framer-motion": "^12.42.2",
80
102
  "lucide-react": "^1.24.0",
81
103
  "react-day-picker": "^10.0.1",
82
104
  "tailwind-merge": "^3.6.0"
@@ -90,39 +112,38 @@
90
112
  "@storybook/addon-themes": "10.5.3",
91
113
  "@storybook/addon-vitest": "10.5.3",
92
114
  "@storybook/react-vite": "^10.5.3",
93
- "@tailwindcss/vite": "^4.3.3",
94
- "@types/node": "^26.1.1",
115
+ "@tailwindcss/vite": "catalog:",
116
+ "@types/node": "catalog:",
95
117
  "@types/react": "^19.2.17",
96
118
  "@types/react-dom": "^19.2.3",
97
119
  "@vitejs/plugin-react": "^6.0.3",
98
120
  "@vitest/browser": "4.1.10",
99
121
  "@vitest/browser-playwright": "4.1.10",
100
- "oxfmt": "0.59.0",
101
- "oxlint": "^1.74.0",
102
- "playwright": "^1.61.1",
122
+ "oxfmt": "catalog:shared",
123
+ "oxlint": "catalog:shared",
124
+ "playwright": "catalog:",
103
125
  "react": "^19.2.7",
104
126
  "react-dom": "^19.2.7",
127
+ "react-native": "0.86.0",
105
128
  "storybook": "^10.5.3",
106
129
  "style-dictionary": "5.5.0",
107
- "tailwindcss": "^4.3.3",
130
+ "tailwindcss": "catalog:",
108
131
  "typescript": "6.0.3",
109
- "vite": "^8.1.5",
110
- "vitest": "^4.1.10"
132
+ "vite": "catalog:",
133
+ "vitest": "catalog:"
111
134
  },
112
135
  "peerDependencies": {
113
136
  "react": "^18.2.0 || ^19.0.0",
114
- "react-dom": "^18.2.0 || ^19.0.0"
137
+ "react-dom": "^18.2.0 || ^19.0.0",
138
+ "react-native": ">=0.74"
115
139
  },
116
- "scripts": {
117
- "build": "vite build",
118
- "dev": "vite",
119
- "storybook": "storybook dev -p 6006",
120
- "check:source": "node tokens/check-source.mjs",
121
- "test:a11y": "vitest --run --config vitest.config.ts",
122
- "tokens:build": "style-dictionary build --config style-dictionary.foundations.json && style-dictionary build --config style-dictionary.light.json && style-dictionary build --config style-dictionary.dark.json",
123
- "tokens:check": "pnpm run tokens:build && node tokens/check-foundations.mjs && git diff --exit-code -- src/tokens/generated",
124
- "typecheck": "tsc --noEmit",
125
- "lint": "oxlint src --fix",
126
- "format": "oxfmt src --write"
140
+ "packageManager": "pnpm@10.30.3",
141
+ "peerDependenciesMeta": {
142
+ "react-dom": {
143
+ "optional": true
144
+ },
145
+ "react-native": {
146
+ "optional": true
147
+ }
127
148
  }
128
- }
149
+ }
@@ -1,19 +1,96 @@
1
- @keyframes accordion-down { from { height: 0; } to { height: var(--accordion-content-height); } }
2
- @keyframes accordion-up { from { height: var(--accordion-content-height); } to { height: 0; } }
3
- @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
4
- @keyframes fade-out { from { opacity: 1; } to { opacity: 0; } }
5
- @keyframes zoom-in { from { opacity: 0; transform: scale(0.95); } to { opacity: 1; transform: scale(1); } }
6
- @keyframes zoom-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(0.95); } }
1
+ @keyframes accordion-down {
2
+ from {
3
+ height: 0;
4
+ }
5
+ to {
6
+ height: var(--accordion-content-height);
7
+ }
8
+ }
9
+ @keyframes accordion-up {
10
+ from {
11
+ height: var(--accordion-content-height);
12
+ }
13
+ to {
14
+ height: 0;
15
+ }
16
+ }
17
+ @keyframes fade-in {
18
+ from {
19
+ opacity: 0;
20
+ }
21
+ to {
22
+ opacity: 1;
23
+ }
24
+ }
25
+ @keyframes fade-out {
26
+ from {
27
+ opacity: 1;
28
+ }
29
+ to {
30
+ opacity: 0;
31
+ }
32
+ }
33
+ @keyframes zoom-in {
34
+ from {
35
+ opacity: 0;
36
+ transform: scale(0.95);
37
+ }
38
+ to {
39
+ opacity: 1;
40
+ transform: scale(1);
41
+ }
42
+ }
43
+ @keyframes zoom-out {
44
+ from {
45
+ opacity: 1;
46
+ transform: scale(1);
47
+ }
48
+ to {
49
+ opacity: 0;
50
+ transform: scale(0.95);
51
+ }
52
+ }
7
53
 
8
- .animate-in { animation: fade-in 150ms ease-out, zoom-in 150ms ease-out; }
9
- .animate-out { animation: fade-out 120ms ease-in, zoom-out 120ms ease-in; }
10
- .fade-in-0 { animation-name: fade-in; }
11
- .fade-out-0 { animation-name: fade-out; }
12
- .zoom-in-95 { animation-name: zoom-in; }
13
- .zoom-out-95 { animation-name: zoom-out; }
14
- .data-open\:animate-in[data-open], .data-open\:animate-in[data-state="open"] { animation: fade-in 150ms ease-out, zoom-in 150ms ease-out; }
15
- .data-closed\:animate-out[data-closed], .data-closed\:animate-out[data-state="closed"] { animation: fade-out 120ms ease-in, zoom-out 120ms ease-in; }
54
+ .animate-in {
55
+ animation:
56
+ fade-in 150ms ease-out,
57
+ zoom-in 150ms ease-out;
58
+ }
59
+ .animate-out {
60
+ animation:
61
+ fade-out 120ms ease-in,
62
+ zoom-out 120ms ease-in;
63
+ }
64
+ .fade-in-0 {
65
+ animation-name: fade-in;
66
+ }
67
+ .fade-out-0 {
68
+ animation-name: fade-out;
69
+ }
70
+ .zoom-in-95 {
71
+ animation-name: zoom-in;
72
+ }
73
+ .zoom-out-95 {
74
+ animation-name: zoom-out;
75
+ }
76
+ .data-open\:animate-in[data-open],
77
+ .data-open\:animate-in[data-state="open"] {
78
+ animation:
79
+ fade-in 150ms ease-out,
80
+ zoom-in 150ms ease-out;
81
+ }
82
+ .data-closed\:animate-out[data-closed],
83
+ .data-closed\:animate-out[data-state="closed"] {
84
+ animation:
85
+ fade-out 120ms ease-in,
86
+ zoom-out 120ms ease-in;
87
+ }
16
88
 
17
89
  @media (prefers-reduced-motion: reduce) {
18
- .animate-in, .animate-out, [data-open], [data-closed] { animation: none !important; }
90
+ .animate-in,
91
+ .animate-out,
92
+ [data-open],
93
+ [data-closed] {
94
+ animation: none !important;
95
+ }
19
96
  }
@@ -4,11 +4,23 @@ import * as React from "react";
4
4
 
5
5
  import { cn } from "../../lib/utils";
6
6
 
7
- function Accordion({ type, collapsible: _collapsible, ...props }: React.ComponentProps<typeof AccordionPrimitive.Root> & {
7
+ function Accordion({
8
+ type,
9
+ collapsible: _collapsible,
10
+ className,
11
+ ...props
12
+ }: React.ComponentProps<typeof AccordionPrimitive.Root> & {
8
13
  type?: "single" | "multiple";
9
14
  collapsible?: boolean;
10
15
  }) {
11
- return <AccordionPrimitive.Root data-slot="accordion" multiple={type === "multiple"} {...props} className="w-full" />;
16
+ return (
17
+ <AccordionPrimitive.Root
18
+ data-slot="accordion"
19
+ multiple={type === "multiple"}
20
+ {...props}
21
+ className={cn("w-full", className)}
22
+ />
23
+ );
12
24
  }
13
25
 
14
26
  function AccordionItem({
@@ -18,10 +30,7 @@ function AccordionItem({
18
30
  return (
19
31
  <AccordionPrimitive.Item
20
32
  data-slot="accordion-item"
21
- className={cn(
22
- "mb-2 overflow-hidden rounded-md border last:mb-0",
23
- className,
24
- )}
33
+ className={cn("mb-2 overflow-hidden rounded-md border last:mb-0", className)}
25
34
  {...props}
26
35
  />
27
36
  );
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+
3
+ import { FilterChip } from "./filter-chip";
4
+
5
+ const meta = {
6
+ title: "DataDisplay/FilterChip",
7
+ component: FilterChip,
8
+ tags: ["autodocs"],
9
+ args: {
10
+ onRemove: () => {},
11
+ },
12
+ } satisfies Meta<typeof FilterChip>;
13
+
14
+ export default meta;
15
+ type Story = StoryObj<typeof meta>;
16
+
17
+ export const Default: Story = {
18
+ args: { label: "Status: Active" },
19
+ };
20
+
21
+ export const Editable: Story = {
22
+ args: { label: "Status: Active", onClick: () => {} },
23
+ };
24
+
25
+ export const LongLabel: Story = {
26
+ args: { label: "Created between Jan 1, 2026 and Jul 24, 2026" },
27
+ };
28
+
29
+ export const Group: Story = {
30
+ args: { label: "Filters" },
31
+ render: () => (
32
+ <div className="flex flex-wrap gap-2">
33
+ <FilterChip label="Status: Active" onRemove={() => {}} onClick={() => {}} />
34
+ <FilterChip label="Team: Design" onRemove={() => {}} onClick={() => {}} />
35
+ <FilterChip label="Archived" onRemove={() => {}} />
36
+ </div>
37
+ ),
38
+ };
@@ -13,15 +13,21 @@ export interface FilterChipProps {
13
13
  /** An applied filter with an optional edit action and an explicit remove action. */
14
14
  export function FilterChip({ label, onRemove, onClick, className }: FilterChipProps) {
15
15
  const labelContent = onClick ? (
16
- <button type="button" className="min-h-11 px-3 text-left" onClick={onClick}>
16
+ <button
17
+ type="button"
18
+ className="focus-visible:ring-ring min-h-9 rounded-full px-3 text-left transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
19
+ onClick={onClick}
20
+ >
17
21
  {label}
18
22
  </button>
19
23
  ) : (
20
- <span className="flex min-h-11 items-center px-3">{label}</span>
24
+ <span className="flex min-h-9 items-center px-3">{label}</span>
21
25
  );
22
26
 
23
27
  return (
24
28
  <span
29
+ role="group"
30
+ aria-label={typeof label === "string" ? `${label} filter` : "filter"}
25
31
  className={cn(
26
32
  "border-border bg-secondary text-secondary-foreground inline-flex items-center rounded-full border text-sm font-medium",
27
33
  className,
@@ -30,7 +36,7 @@ export function FilterChip({ label, onRemove, onClick, className }: FilterChipPr
30
36
  {labelContent}
31
37
  <button
32
38
  type="button"
33
- className="text-muted-foreground hover:text-foreground mr-1 flex size-10 items-center justify-center rounded-full"
39
+ className="text-muted-foreground hover:text-foreground focus-visible:ring-ring mr-1 flex size-9 items-center justify-center rounded-full transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
34
40
  onClick={onRemove}
35
41
  aria-label={`Remove filter: ${typeof label === "string" ? label : "selected filter"}`}
36
42
  >
@@ -60,7 +60,7 @@ export function SortControls({
60
60
  <DropdownMenuItem
61
61
  key={sort.field}
62
62
  onSelect={(e) => e.preventDefault()}
63
- className={`p-0 focus:bg-transparent ${index === focusedSortIndex ? "bg-accent" : ""}`}
63
+ className={`p-0 focus:bg-transparent ${index === focusedSortIndex ? "bg-muted" : ""}`}
64
64
  >
65
65
  <SortRow
66
66
  sortOption={sort}
@@ -37,11 +37,7 @@ TableFooter.displayName = "TableFooter";
37
37
 
38
38
  const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(
39
39
  ({ className, ...props }, ref) => (
40
- <tr
41
- ref={ref}
42
- className={cn("data-[state=selected]:bg-muted border-b", className)}
43
- {...props}
44
- />
40
+ <tr ref={ref} className={cn("data-[state=selected]:bg-muted border-b", className)} {...props} />
45
41
  ),
46
42
  );
47
43
  TableRow.displayName = "TableRow";
@@ -53,7 +49,7 @@ const TableHead = React.forwardRef<
53
49
  <th
54
50
  ref={ref}
55
51
  className={cn(
56
- "h-9 px-3 text-left align-middle text-xs font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
52
+ "text-muted-foreground h-9 px-3 text-left align-middle text-xs font-medium [&:has([role=checkbox])]:pr-0",
57
53
  className,
58
54
  )}
59
55
  {...props}
@@ -77,7 +73,7 @@ const TableCaption = React.forwardRef<
77
73
  HTMLTableCaptionElement,
78
74
  React.HTMLAttributes<HTMLTableCaptionElement>
79
75
  >(({ className, ...props }, ref) => (
80
- <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />
76
+ <caption ref={ref} className={cn("text-muted-foreground mt-4 text-sm", className)} {...props} />
81
77
  ));
82
78
  TableCaption.displayName = "TableCaption";
83
79
 
@@ -37,9 +37,9 @@ export function EmptyState({
37
37
  <section
38
38
  className={cn(
39
39
  "rounded-lg px-5 py-8",
40
- variant === "default" && "border bg-card",
41
- variant === "dashed" && "border bg-card border-dashed",
42
- variant === "search" && "border bg-muted border-dashed",
40
+ variant === "default" && "bg-card border",
41
+ variant === "dashed" && "bg-card border border-dashed",
42
+ variant === "search" && "bg-muted border border-dashed",
43
43
  variant === "quiet" && "bg-surface",
44
44
  centered
45
45
  ? cn(
@@ -51,13 +51,23 @@ export function EmptyState({
51
51
  )}
52
52
  >
53
53
  {icon ? (
54
- <div className="text-muted-foreground mb-3 flex size-11 items-center justify-center" aria-hidden>
54
+ <div
55
+ className="text-muted-foreground mb-3 flex size-11 items-center justify-center"
56
+ aria-hidden
57
+ >
55
58
  {icon}
56
59
  </div>
57
60
  ) : null}
58
61
  <div className={cn("space-y-2", centered && "max-w-[34ch]")}>
59
- <h2 className={cn("text-foreground font-semibold tracking-tight", large ? "text-lg" : "text-base")}>{title}</h2>
60
- {description ? <p className="text-sm text-muted-foreground">{description}</p> : null}
62
+ <h2
63
+ className={cn(
64
+ "text-foreground font-semibold tracking-tight",
65
+ large ? "text-lg" : "text-base",
66
+ )}
67
+ >
68
+ {title}
69
+ </h2>
70
+ {description ? <p className="text-muted-foreground text-sm">{description}</p> : null}
61
71
  </div>
62
72
  {children ? <div className="mt-3">{children}</div> : null}
63
73
  {action ? <div className="mt-4">{action}</div> : null}
@@ -8,7 +8,7 @@ const STATUS_CONFIG: Record<FileUploadStatusValue, { bg: string; text: string; l
8
8
  uploading: { bg: "bg-muted", text: "text-foreground", label: "Uploading" },
9
9
  processing: { bg: "bg-muted", text: "text-foreground", label: "Processing" },
10
10
  queued: { bg: "bg-secondary", text: "text-secondary-foreground", label: "Queued" },
11
- done: { bg: "bg-accent", text: "text-accent-foreground", label: "Complete" },
11
+ done: { bg: "bg-muted", text: "text-muted-foreground", label: "Complete" },
12
12
  error: { bg: "bg-destructive/10", text: "text-destructive", label: "Error" },
13
13
  };
14
14
 
@@ -14,13 +14,13 @@ function Progress({
14
14
  return (
15
15
  <ProgressPrimitive.Root
16
16
  data-slot="progress"
17
- className={cn("bg-accent/20 relative h-2 w-full overflow-hidden rounded-full", className)}
17
+ className={cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className)}
18
18
  value={value}
19
19
  {...props}
20
20
  >
21
21
  <ProgressPrimitive.Indicator
22
22
  data-slot="progress-indicator"
23
- className={cn("bg-accent h-full w-full flex-1 transition-all", indicatorClassName)}
23
+ className={cn("bg-primary h-full w-full flex-1 transition-all", indicatorClassName)}
24
24
  style={{ transform: `translateX(-${100 - (value ?? 0)}%)` }}
25
25
  />
26
26
  </ProgressPrimitive.Root>
@@ -240,7 +240,7 @@ function UpdateGuardClient({
240
240
  {copy?.refreshButton ?? "Refresh"}
241
241
  </button>
242
242
  ) : null}
243
- <button type="button" onClick={closePrompt} className="text-muted-foreground text-sm">
243
+ <button type="button" onClick={closePrompt} className="text-muted-foreground text-sm">
244
244
  {copy?.closeButton ?? "Close"}
245
245
  </button>
246
246
  </div>
@@ -24,7 +24,8 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
24
24
  "inline-flex size-8 p-2 items-center justify-center rounded-full border bg-background text-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50",
25
25
  month_grid: "w-full border-collapse",
26
26
  weekdays: "flex",
27
- weekday: "flex size-8 items-center justify-center text-[0.8rem] font-normal text-muted-foreground",
27
+ weekday:
28
+ "flex size-8 items-center justify-center text-[0.8rem] font-normal text-muted-foreground",
28
29
  week: "mt-1 flex w-full",
29
30
  day: "relative size-8 p-0 text-center text-lg focus-within:z-20",
30
31
  day_button:
@@ -34,9 +35,11 @@ function Calendar({ className, classNames, showOutsideDays = true, ...props }: C
34
35
  today: "[&>button]:bg-primary [&>button]:text-primary-foreground",
35
36
  outside: "text-muted-foreground [&>button]:text-muted-foreground",
36
37
  disabled: "text-muted-foreground opacity-50",
37
- range_start: "rounded-l-md bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground",
38
+ range_start:
39
+ "rounded-l-md bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground",
38
40
  range_middle: "bg-primary [&>button]:rounded-none [&>button]:text-primary-foreground",
39
- range_end: "rounded-r-md bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground",
41
+ range_end:
42
+ "rounded-r-md bg-primary [&>button]:bg-primary [&>button]:text-primary-foreground",
40
43
  hidden: "invisible",
41
44
  ...classNames,
42
45
  }}
@@ -29,7 +29,7 @@ function Field({ label, helpText, error, required, children, id: externalId }: F
29
29
  <label
30
30
  htmlFor={id}
31
31
  className={cn(
32
- "text-sm text-foreground font-medium",
32
+ "text-foreground text-sm font-medium",
33
33
  required && "after:text-destructive after:ml-0.5 after:content-['*']",
34
34
  )}
35
35
  >
@@ -50,11 +50,11 @@ function Field({ label, helpText, error, required, children, id: externalId }: F
50
50
  : children}
51
51
 
52
52
  {error ? (
53
- <p id={errorId} role="alert" className="text-sm text-destructive">
53
+ <p id={errorId} role="alert" className="text-destructive text-sm">
54
54
  {error}
55
55
  </p>
56
56
  ) : helpText ? (
57
- <p id={descId} className="text-sm text-muted-foreground">
57
+ <p id={descId} className="text-muted-foreground text-sm">
58
58
  {helpText}
59
59
  </p>
60
60
  ) : null}
@@ -8,7 +8,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
8
8
  type={type}
9
9
  data-slot="input"
10
10
  className={cn(
11
- "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground bg-background focus-visible:ring-ring h-9 w-full min-w-0 rounded-md border border-input px-3 py-1 text-base transition-colors file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
11
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground bg-background focus-visible:ring-ring border-input h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base transition-colors file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
12
  "aria-invalid:ring-destructive/20 aria-invalid:border-destructive",
13
13
  className,
14
14
  )}
@@ -69,10 +69,10 @@ export function PasskeyManagement({
69
69
  <section aria-labelledby="passkey-heading" className="space-y-4">
70
70
  <div className="flex items-center justify-between">
71
71
  <div>
72
- <h2 id="passkey-heading" className="text-sm font-medium text-foreground">
72
+ <h2 id="passkey-heading" className="text-foreground text-sm font-medium">
73
73
  Passkeys
74
74
  </h2>
75
- <p className="text-sm text-muted-foreground">
75
+ <p className="text-muted-foreground text-sm">
76
76
  Sign in without a password using biometrics or a security key.
77
77
  </p>
78
78
  </div>
@@ -23,7 +23,7 @@ const RadioGroupItem = React.forwardRef<
23
23
  <RadioPrimitive.Root
24
24
  ref={ref}
25
25
  className={cn(
26
- "border-primary bg-background text-foreground focus-visible:border-ring focus-visible:bg-accent/25 focus-visible:ring-ring aspect-square h-6 w-6 rounded-full border focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
26
+ "border-primary bg-background text-foreground focus-visible:border-ring focus-visible:bg-muted/25 focus-visible:ring-ring aspect-square h-6 w-6 rounded-full border focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
27
27
  className,
28
28
  )}
29
29
  {...props}
@@ -4,7 +4,10 @@ import * as React from "react";
4
4
 
5
5
  import { cn } from "../../lib/utils";
6
6
 
7
- type SelectProps = Omit<React.ComponentProps<typeof SelectPrimitive.Root<string>>, "onValueChange" | "value" | "defaultValue"> & {
7
+ type SelectProps = Omit<
8
+ React.ComponentProps<typeof SelectPrimitive.Root<string>>,
9
+ "onValueChange" | "value" | "defaultValue"
10
+ > & {
8
11
  value?: string;
9
12
  defaultValue?: string;
10
13
  onValueChange?: (value: string) => void;
@@ -41,7 +44,7 @@ function SelectTrigger({
41
44
  data-slot="select-trigger"
42
45
  data-size={size}
43
46
  className={cn(
44
- "data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
47
+ "data-placeholder:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 aria-invalid:border-destructive border-input flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-inset disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
45
48
  className,
46
49
  )}
47
50
  {...props}
@@ -92,12 +95,16 @@ function SelectLabel({ className, ...props }: React.ComponentProps<typeof Select
92
95
  );
93
96
  }
94
97
 
95
- function SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {
98
+ function SelectItem({
99
+ className,
100
+ children,
101
+ ...props
102
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
96
103
  return (
97
104
  <SelectPrimitive.Item
98
105
  data-slot="select-item"
99
106
  className={cn(
100
- "data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50",
107
+ "data-highlighted:bg-muted data-highlighted:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50",
101
108
  className,
102
109
  )}
103
110
  {...props}