@ponti-studios/ui 0.3.0 → 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.
- package/dist/index.js +70 -112
- package/dist/index.js.map +1 -1
- package/package.json +25 -23
- package/src/animations.css +92 -15
- package/src/components/data-display/accordion.tsx +15 -6
- package/src/components/data-display/filter-chip.stories.tsx +38 -0
- package/src/components/data-display/filter-chip.tsx +9 -3
- package/src/components/data-display/sort-controls.tsx +1 -1
- package/src/components/data-display/table.tsx +3 -7
- package/src/components/feedback/empty-state.tsx +16 -6
- package/src/components/feedback/file-upload-status-badge.tsx +1 -1
- package/src/components/feedback/progress.tsx +2 -2
- package/src/components/feedback/update-guard.tsx +1 -1
- package/src/components/forms/calendar.tsx +6 -3
- package/src/components/forms/field.tsx +3 -3
- package/src/components/forms/input.tsx +1 -1
- package/src/components/forms/passkey-management.tsx +2 -2
- package/src/components/forms/radio-group.tsx +1 -1
- package/src/components/forms/select.tsx +11 -4
- package/src/components/forms/slider.tsx +16 -4
- package/src/components/forms/stepper.tsx +1 -1
- package/src/components/forms/textarea.tsx +1 -1
- package/src/components/layout/section-intro.tsx +1 -1
- package/src/components/navigation/app-navigation.tsx +4 -4
- package/src/components/navigation/pagination-controls.tsx +2 -2
- package/src/components/navigation/tabs.tsx +1 -1
- package/src/components/overlays/alert-dialog.tsx +30 -8
- package/src/components/overlays/command.tsx +123 -20
- package/src/components/overlays/dialog.tsx +4 -4
- package/src/components/overlays/dropdown-menu.tsx +137 -21
- package/src/components/overlays/popover.tsx +14 -3
- package/src/components/overlays/sheet.tsx +24 -8
- package/src/components/primitives/avatar.tsx +6 -2
- package/src/components/primitives/badge.tsx +5 -2
- package/src/components/primitives/button.tsx +16 -18
- package/src/components/primitives/card.stories.tsx +2 -2
- package/src/components/primitives/card.tsx +2 -5
- package/src/constants/chart-colors.ts +2 -2
- package/src/styles.css +153 -63
- package/src/tokens/chart-colors.stories.tsx +192 -0
- package/src/tokens/color-systems.stories.tsx +21 -3
- package/src/tokens/foundations.stories.tsx +66 -16
- package/src/tokens/generated/dark.colors.generated.ts +23 -50
- package/src/tokens/generated/dark.css +23 -48
- package/src/tokens/generated/foundations.css +2 -2
- package/src/tokens/generated/foundations.generated.ts +14 -6
- package/src/tokens/generated/light.colors.generated.ts +23 -50
- package/src/tokens/generated/light.css +23 -48
- package/src/tokens/index.ts +14 -9
- package/src/tokens/layout.stories.tsx +40 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ponti-studios/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Shared UI component library for ponti-studios labs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -71,12 +71,25 @@
|
|
|
71
71
|
"./styles.css": "./src/styles.css",
|
|
72
72
|
"./animations.css": "./src/animations.css"
|
|
73
73
|
},
|
|
74
|
+
"scripts": {
|
|
75
|
+
"build": "vite build",
|
|
76
|
+
"dev": "vite",
|
|
77
|
+
"storybook": "style-dictionary build --config style-dictionary.dark-storybook.json && storybook dev -p 6006",
|
|
78
|
+
"check:source": "node tokens/check-source.mjs",
|
|
79
|
+
"test:a11y": "vitest --run --config vitest.config.ts",
|
|
80
|
+
"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",
|
|
81
|
+
"tokens:check": "pnpm run tokens:build && node tokens/check-foundations.mjs && git diff --exit-code -- src/tokens/generated",
|
|
82
|
+
"typecheck": "tsc --noEmit",
|
|
83
|
+
"lint": "oxlint src --fix",
|
|
84
|
+
"format": "oxfmt src --write",
|
|
85
|
+
"prepack": "pnpm run tokens:check && pnpm run check:source && pnpm run typecheck && pnpm run build"
|
|
86
|
+
},
|
|
74
87
|
"dependencies": {
|
|
75
88
|
"@base-ui/react": "^1.6.0",
|
|
89
|
+
"@radix-ui/colors": "^3.0.0",
|
|
76
90
|
"class-variance-authority": "^0.7.1",
|
|
77
91
|
"clsx": "^2.1.1",
|
|
78
92
|
"date-fns": "^4.1.0",
|
|
79
|
-
"framer-motion": "^12.42.2",
|
|
80
93
|
"lucide-react": "^1.24.0",
|
|
81
94
|
"react-day-picker": "^10.0.1",
|
|
82
95
|
"tailwind-merge": "^3.6.0"
|
|
@@ -90,39 +103,28 @@
|
|
|
90
103
|
"@storybook/addon-themes": "10.5.3",
|
|
91
104
|
"@storybook/addon-vitest": "10.5.3",
|
|
92
105
|
"@storybook/react-vite": "^10.5.3",
|
|
93
|
-
"@tailwindcss/vite": "
|
|
94
|
-
"@types/node": "
|
|
106
|
+
"@tailwindcss/vite": "catalog:",
|
|
107
|
+
"@types/node": "catalog:",
|
|
95
108
|
"@types/react": "^19.2.17",
|
|
96
109
|
"@types/react-dom": "^19.2.3",
|
|
97
110
|
"@vitejs/plugin-react": "^6.0.3",
|
|
98
111
|
"@vitest/browser": "4.1.10",
|
|
99
112
|
"@vitest/browser-playwright": "4.1.10",
|
|
100
|
-
"oxfmt": "
|
|
101
|
-
"oxlint": "
|
|
102
|
-
"playwright": "
|
|
113
|
+
"oxfmt": "catalog:shared",
|
|
114
|
+
"oxlint": "catalog:shared",
|
|
115
|
+
"playwright": "catalog:",
|
|
103
116
|
"react": "^19.2.7",
|
|
104
117
|
"react-dom": "^19.2.7",
|
|
105
118
|
"storybook": "^10.5.3",
|
|
106
119
|
"style-dictionary": "5.5.0",
|
|
107
|
-
"tailwindcss": "
|
|
120
|
+
"tailwindcss": "catalog:",
|
|
108
121
|
"typescript": "6.0.3",
|
|
109
|
-
"vite": "
|
|
110
|
-
"vitest": "
|
|
122
|
+
"vite": "catalog:",
|
|
123
|
+
"vitest": "catalog:"
|
|
111
124
|
},
|
|
112
125
|
"peerDependencies": {
|
|
113
126
|
"react": "^18.2.0 || ^19.0.0",
|
|
114
127
|
"react-dom": "^18.2.0 || ^19.0.0"
|
|
115
128
|
},
|
|
116
|
-
"
|
|
117
|
-
|
|
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"
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
+
"packageManager": "pnpm@10.30.3"
|
|
130
|
+
}
|
package/src/animations.css
CHANGED
|
@@ -1,19 +1,96 @@
|
|
|
1
|
-
@keyframes accordion-down {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.
|
|
14
|
-
|
|
15
|
-
|
|
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,
|
|
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({
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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" && "
|
|
41
|
-
variant === "dashed" && "
|
|
42
|
-
variant === "search" && "
|
|
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
|
|
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
|
|
60
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
72
|
+
<h2 id="passkey-heading" className="text-foreground text-sm font-medium">
|
|
73
73
|
Passkeys
|
|
74
74
|
</h2>
|
|
75
|
-
<p className="text-
|
|
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-
|
|
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<
|
|
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
|
|
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({
|
|
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-
|
|
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}
|
|
@@ -5,14 +5,26 @@ import * as React from "react";
|
|
|
5
5
|
|
|
6
6
|
import { cn } from "../../lib/utils";
|
|
7
7
|
|
|
8
|
-
type SliderProps = Omit<
|
|
8
|
+
type SliderProps = Omit<
|
|
9
|
+
React.ComponentProps<typeof SliderPrimitive.Root>,
|
|
10
|
+
"onValueChange" | "value" | "defaultValue"
|
|
11
|
+
> & {
|
|
9
12
|
value?: number[];
|
|
10
13
|
defaultValue?: number[];
|
|
11
14
|
onValueChange?: (value: number[]) => void;
|
|
12
15
|
};
|
|
13
16
|
|
|
14
17
|
const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
|
15
|
-
(
|
|
18
|
+
(
|
|
19
|
+
{
|
|
20
|
+
className,
|
|
21
|
+
onValueChange,
|
|
22
|
+
"aria-label": ariaLabel,
|
|
23
|
+
"aria-labelledby": ariaLabelledby,
|
|
24
|
+
...props
|
|
25
|
+
},
|
|
26
|
+
ref,
|
|
27
|
+
) => (
|
|
16
28
|
<SliderPrimitive.Root
|
|
17
29
|
ref={ref}
|
|
18
30
|
className={cn("relative flex w-full touch-none items-center select-none", className)}
|
|
@@ -20,12 +32,12 @@ const Slider = React.forwardRef<HTMLDivElement, SliderProps>(
|
|
|
20
32
|
onValueChange={(value) => onValueChange?.(Array.isArray(value) ? [...value] : [value])}
|
|
21
33
|
>
|
|
22
34
|
<SliderPrimitive.Track className="bg-muted relative h-2 w-full grow overflow-hidden rounded-full">
|
|
23
|
-
<SliderPrimitive.Indicator className="bg-
|
|
35
|
+
<SliderPrimitive.Indicator className="bg-primary absolute h-full" />
|
|
24
36
|
</SliderPrimitive.Track>
|
|
25
37
|
<SliderPrimitive.Thumb
|
|
26
38
|
aria-label={ariaLabel ?? "Slider"}
|
|
27
39
|
aria-labelledby={ariaLabelledby}
|
|
28
|
-
className="border-border focus-visible:border-ring focus-visible:bg-
|
|
40
|
+
className="border-border focus-visible:border-ring focus-visible:bg-primary focus-visible:ring-ring bg-background block h-6 w-6 rounded-full border shadow-sm ring-1 ring-black/5 transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50"
|
|
29
41
|
/>
|
|
30
42
|
</SliderPrimitive.Root>
|
|
31
43
|
),
|
|
@@ -32,7 +32,7 @@ function Stepper({
|
|
|
32
32
|
const atMax = value >= max;
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<div className={cn("flex items-center rounded-lg border
|
|
35
|
+
<div className={cn("border-input bg-muted flex items-center rounded-lg border", className)}>
|
|
36
36
|
<Button
|
|
37
37
|
type="button"
|
|
38
38
|
variant="ghost"
|
|
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
|
7
7
|
<textarea
|
|
8
8
|
data-slot="textarea"
|
|
9
9
|
className={cn(
|
|
10
|
-
"placeholder:text-muted-foreground aria-invalid:ring-destructive/20 aria-invalid:border-destructive focus-visible:ring-ring flex field-sizing-content min-h-16 w-full rounded-md border
|
|
10
|
+
"placeholder:text-muted-foreground aria-invalid:ring-destructive/20 aria-invalid:border-destructive focus-visible:ring-ring border-input flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
11
11
|
className,
|
|
12
12
|
)}
|
|
13
13
|
{...props}
|
|
@@ -22,7 +22,7 @@ export function SectionIntro({ eyebrow, title, description, actions }: SectionIn
|
|
|
22
22
|
) : null}
|
|
23
23
|
<div className="space-y-3">
|
|
24
24
|
<h1 className="text-title-2 text-foreground font-semibold tracking-tight">{title}</h1>
|
|
25
|
-
{description ? <p className="text-
|
|
25
|
+
{description ? <p className="text-muted-foreground text-sm">{description}</p> : null}
|
|
26
26
|
</div>
|
|
27
27
|
</div>
|
|
28
28
|
{actions ? <div className="shrink-0">{actions}</div> : null}
|