chore(web): sync cadence ui sources
This commit is contained in:
@@ -3,7 +3,7 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
|
|
||||||
export const alertVariants = cva(
|
export const alertVariants = cva(
|
||||||
[
|
[
|
||||||
"relative grid gap-x-3 gap-y-1 rounded-[var(--radius-lg)] border p-4 shadow-[var(--shadow-xs)]",
|
"relative grid gap-x-3 gap-y-1 rounded-[var(--ui-card-radius)] border p-4 shadow-[var(--ui-card-subtle-shadow)] [border-width:var(--ui-card-border-width)]",
|
||||||
"text-[var(--color-foreground)]",
|
"text-[var(--color-foreground)]",
|
||||||
getMotionRecipeClassNames("transition", "ring")
|
getMotionRecipeClassNames("transition", "ring")
|
||||||
],
|
],
|
||||||
@@ -11,13 +11,13 @@ export const alertVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default:
|
default:
|
||||||
"border-[var(--color-border)] bg-[var(--color-card)]",
|
"border-[var(--ui-card-default-border)] bg-[var(--ui-card-default-bg)]",
|
||||||
success:
|
success:
|
||||||
"border-[color-mix(in_oklch,var(--color-success)_34%,var(--color-border))] bg-[color-mix(in_oklch,var(--color-success)_10%,var(--color-card))]",
|
"border-[color-mix(in_oklch,var(--color-success)_34%,var(--ui-card-default-border))] bg-[color-mix(in_oklch,var(--color-success)_10%,var(--ui-card-default-bg))]",
|
||||||
warning:
|
warning:
|
||||||
"border-[color-mix(in_oklch,var(--color-warning)_34%,var(--color-border))] bg-[color-mix(in_oklch,var(--color-warning)_12%,var(--color-card))]",
|
"border-[color-mix(in_oklch,var(--color-warning)_34%,var(--ui-card-default-border))] bg-[color-mix(in_oklch,var(--color-warning)_12%,var(--ui-card-default-bg))]",
|
||||||
destructive:
|
destructive:
|
||||||
"border-[color-mix(in_oklch,var(--color-destructive)_38%,var(--color-border))] bg-[color-mix(in_oklch,var(--color-destructive)_10%,var(--color-card))]"
|
"border-[color-mix(in_oklch,var(--color-destructive)_38%,var(--ui-card-default-border))] bg-[color-mix(in_oklch,var(--color-destructive)_10%,var(--ui-card-default-bg))]"
|
||||||
},
|
},
|
||||||
hasIcon: {
|
hasIcon: {
|
||||||
false: "",
|
false: "",
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
|
|
||||||
export const badgeVariants = cva(
|
export const badgeVariants = cva(
|
||||||
[
|
[
|
||||||
"inline-flex shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-[var(--radius-full)] border font-medium",
|
"inline-flex shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-[var(--ui-control-radius)] border font-medium [border-width:var(--ui-input-border-width)]",
|
||||||
"outline-none select-none",
|
"outline-none select-none",
|
||||||
getMotionRecipeClassNames("transition", "ring")
|
getMotionRecipeClassNames("transition", "ring")
|
||||||
],
|
],
|
||||||
@@ -15,11 +15,11 @@ export const badgeVariants = cva(
|
|||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
subtle:
|
subtle:
|
||||||
"border-[var(--color-border)] bg-[var(--color-card)] text-[var(--color-foreground)]",
|
"border-[var(--ui-control-border)] bg-[var(--ui-control-bg)] text-[var(--color-foreground)] shadow-[var(--ui-control-shadow)]",
|
||||||
solid:
|
solid:
|
||||||
"border-transparent bg-[var(--color-foreground)] text-[var(--color-background)]",
|
"border-transparent bg-[var(--color-foreground)] text-[var(--color-background)]",
|
||||||
outline:
|
outline:
|
||||||
"border-[var(--color-border-strong)] bg-transparent text-[var(--color-foreground)]"
|
"border-[var(--ui-control-border)] bg-transparent text-[var(--color-foreground)]"
|
||||||
},
|
},
|
||||||
tone: {
|
tone: {
|
||||||
neutral: "",
|
neutral: "",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function Spinner() {
|
|||||||
{...createSlot("icon")}
|
{...createSlot("icon")}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
animate={{ opacity: 1, rotate: 0, scale: 1 }}
|
animate={{ opacity: 1, rotate: 0, scale: 1 }}
|
||||||
className="size-4 rounded-full border-2 border-current border-r-transparent animate-spin"
|
className="size-4 rounded-[var(--ui-spinner-radius)] [border-width:var(--ui-spinner-border-width)] border-current border-r-transparent animate-spin"
|
||||||
exit={{ opacity: 0, rotate: 90, scale: 0.7 }}
|
exit={{ opacity: 0, rotate: 90, scale: 0.7 }}
|
||||||
initial={{ opacity: 0, rotate: -90, scale: 0.7 }}
|
initial={{ opacity: 0, rotate: -90, scale: 0.7 }}
|
||||||
transition={{
|
transition={{
|
||||||
@@ -74,14 +74,14 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(function Button
|
|||||||
<motion.span
|
<motion.span
|
||||||
animate={
|
animate={
|
||||||
prefersReducedMotion || isDisabled
|
prefersReducedMotion || isDisabled
|
||||||
? { opacity: 0, x: "-120%" }
|
? { x: "-120%" }
|
||||||
: isHovered
|
: isHovered
|
||||||
? { opacity: 0.75, x: "115%" }
|
? { x: "115%" }
|
||||||
: { opacity: 0, x: "-120%" }
|
: { x: "-120%" }
|
||||||
}
|
}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
className="pointer-events-none absolute inset-y-0 left-0 w-1/2 rounded-[inherit] bg-[linear-gradient(120deg,transparent_0%,rgba(255,255,255,0.32)_45%,transparent_100%)] mix-blend-screen"
|
className="pointer-events-none absolute inset-y-0 left-0 w-1/2 rounded-[inherit] bg-[var(--ui-button-sheen-gradient)] opacity-[var(--ui-button-sheen-opacity)] [mix-blend-mode:var(--ui-button-sheen-mix)]"
|
||||||
initial={false}
|
initial={{ x: "-120%" }}
|
||||||
transition={{
|
transition={{
|
||||||
duration: prefersReducedMotion ? 0.01 : 0.55,
|
duration: prefersReducedMotion ? 0.01 : 0.55,
|
||||||
ease: [0.16, 1, 0.3, 1]
|
ease: [0.16, 1, 0.3, 1]
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
export const buttonVariants = cva(
|
export const buttonVariants = cva(
|
||||||
[
|
[
|
||||||
"relative isolate inline-flex shrink-0 items-center justify-center gap-2 overflow-hidden whitespace-nowrap",
|
"relative isolate inline-flex shrink-0 items-center justify-center gap-2 overflow-hidden whitespace-nowrap",
|
||||||
"rounded-[var(--radius-sm)] border font-medium select-none",
|
"rounded-[var(--ui-button-radius)] [border-width:var(--ui-button-border-width)] font-medium select-none",
|
||||||
|
"[transition-duration:var(--ui-button-transition-duration,var(--dur-fast))]",
|
||||||
"outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-ring)]",
|
"outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-ring)]",
|
||||||
"focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
"focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
||||||
"disabled:pointer-events-none disabled:opacity-55",
|
"disabled:pointer-events-none disabled:opacity-55",
|
||||||
@@ -20,15 +21,15 @@ export const buttonVariants = cva(
|
|||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
primary:
|
primary:
|
||||||
"border-transparent bg-[var(--color-primary)] text-[var(--color-primary-foreground)] shadow-[var(--shadow-xs)]",
|
"border-[var(--ui-button-primary-border)] bg-[var(--ui-button-primary-bg)] text-[var(--ui-button-primary-fg)] shadow-[var(--ui-button-primary-shadow)] hover:bg-[var(--ui-button-primary-hover-bg)]",
|
||||||
secondary:
|
secondary:
|
||||||
"border-[var(--color-border-strong)] bg-[var(--color-secondary)] text-[var(--color-secondary-foreground)]",
|
"border-[var(--ui-button-secondary-border)] bg-[var(--ui-button-secondary-bg)] text-[var(--ui-button-secondary-fg)] shadow-[var(--ui-button-secondary-shadow)] hover:bg-[var(--ui-button-secondary-hover-bg)]",
|
||||||
ghost:
|
ghost:
|
||||||
"border-transparent bg-transparent text-[var(--color-foreground)] hover:bg-[var(--color-surface)]",
|
"border-[var(--ui-button-ghost-border)] bg-[var(--ui-button-ghost-bg)] text-[var(--ui-button-ghost-fg)] shadow-[var(--ui-button-ghost-shadow)] hover:bg-[var(--ui-button-ghost-hover-bg)]",
|
||||||
subtle:
|
subtle:
|
||||||
"border-[var(--color-border)] bg-[var(--color-card)] text-[var(--color-foreground)] shadow-[var(--shadow-xs)]",
|
"border-[var(--ui-button-subtle-border)] bg-[var(--ui-button-subtle-bg)] text-[var(--ui-button-subtle-fg)] shadow-[var(--ui-button-subtle-shadow)] hover:bg-[var(--ui-button-subtle-hover-bg)]",
|
||||||
destructive:
|
destructive:
|
||||||
"border-transparent bg-[var(--color-destructive)] text-[var(--color-destructive-foreground)] shadow-[var(--shadow-xs)]"
|
"border-[var(--ui-button-destructive-border)] bg-[var(--ui-button-destructive-bg)] text-[var(--ui-button-destructive-fg)] shadow-[var(--ui-button-destructive-shadow)] hover:bg-[var(--ui-button-destructive-hover-bg)]"
|
||||||
},
|
},
|
||||||
loading: {
|
loading: {
|
||||||
false: "",
|
false: "",
|
||||||
|
|||||||
@@ -3,22 +3,23 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
|
|
||||||
export const cardVariants = cva(
|
export const cardVariants = cva(
|
||||||
[
|
[
|
||||||
"rounded-[var(--radius-lg)] border text-[var(--color-card-foreground)]",
|
"rounded-[var(--ui-card-radius)] border text-[var(--color-card-foreground)]",
|
||||||
"bg-[var(--color-card)] shadow-[var(--shadow-sm)]",
|
"bg-[var(--ui-card-bg)] shadow-[var(--ui-card-shadow)] [border-width:var(--ui-card-border-width)]",
|
||||||
getMotionRecipeClassNames("transition", "ring")
|
getMotionRecipeClassNames("transition", "ring")
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
tone: {
|
tone: {
|
||||||
default: "border-[var(--color-border)]",
|
default:
|
||||||
|
"border-[var(--ui-card-default-border)] bg-[var(--ui-card-default-bg)] shadow-[var(--ui-card-default-shadow)]",
|
||||||
subtle:
|
subtle:
|
||||||
"border-[color-mix(in_oklch,var(--color-border)_86%,transparent)] bg-[var(--color-surface)] shadow-[var(--shadow-xs)]",
|
"border-[var(--ui-card-subtle-border)] bg-[var(--ui-card-subtle-bg)] shadow-[var(--ui-card-subtle-shadow)]",
|
||||||
accent:
|
accent:
|
||||||
"border-[color-mix(in_oklch,var(--color-primary)_26%,var(--color-border))] bg-[color-mix(in_oklch,var(--color-primary)_8%,var(--color-card))]"
|
"border-[var(--ui-card-accent-border)] bg-[var(--ui-card-accent-bg)] shadow-[var(--ui-card-accent-shadow)]"
|
||||||
},
|
},
|
||||||
interactive: {
|
interactive: {
|
||||||
false: "",
|
false: "",
|
||||||
true: "hover:-translate-y-[2px] hover:shadow-[var(--shadow-md)]"
|
true: "hover:translate-y-[var(--ui-card-hover-translate)] hover:shadow-[var(--ui-card-hover-shadow)]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { dialogContentVariants, dialogFooterVariants, dialogHeaderVariants, dial
|
|||||||
import { cn } from "../lib/cn";
|
import { cn } from "../lib/cn";
|
||||||
import type { VariantProps } from "../lib/cva";
|
import type { VariantProps } from "../lib/cva";
|
||||||
import { createDataAttributes, createSlot } from "../lib/contracts";
|
import { createDataAttributes, createSlot } from "../lib/contracts";
|
||||||
|
import { CloseIcon } from "../lib/icons";
|
||||||
|
|
||||||
export const Dialog = DialogPrimitive.Root;
|
export const Dialog = DialogPrimitive.Root;
|
||||||
export const DialogTrigger = DialogPrimitive.Trigger;
|
export const DialogTrigger = DialogPrimitive.Trigger;
|
||||||
@@ -45,11 +46,9 @@ export const DialogContent = forwardRef<
|
|||||||
{children}
|
{children}
|
||||||
<DialogPrimitive.Close
|
<DialogPrimitive.Close
|
||||||
aria-label="Close dialog"
|
aria-label="Close dialog"
|
||||||
className="absolute right-4 top-4 inline-flex size-9 items-center justify-center rounded-[var(--radius-full)] text-[var(--color-muted-foreground)] outline-none transition-colors duration-[var(--dur-fast)] ease-[var(--ease-standard)] hover:bg-[var(--color-surface)] hover:text-[var(--color-foreground)] focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-card)]"
|
className="absolute right-4 top-4 inline-flex size-9 items-center justify-center rounded-[var(--ui-control-radius)] border border-transparent text-[var(--color-muted-foreground)] outline-none transition-colors duration-[var(--dur-fast)] ease-[var(--ease-standard)] hover:border-[var(--ui-control-border)] hover:bg-[var(--ui-control-bg)] hover:text-[var(--color-foreground)] hover:shadow-[var(--ui-control-shadow)] focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--ui-panel-bg)]"
|
||||||
>
|
>
|
||||||
<span aria-hidden="true" className="text-lg leading-none">
|
<CloseIcon className="size-4" />
|
||||||
×
|
|
||||||
</span>
|
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</DialogPortal>
|
</DialogPortal>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { cva } from "../lib/cva";
|
import { cva } from "../lib/cva";
|
||||||
|
|
||||||
export const dialogOverlayVariants = cva([
|
export const dialogOverlayVariants = cva([
|
||||||
"fixed inset-0 z-50 bg-[var(--color-overlay)] backdrop-blur-[2px]",
|
"fixed inset-0 z-50 bg-[var(--ui-panel-overlay-bg)] backdrop-blur-[var(--ui-panel-overlay-blur)]",
|
||||||
"data-[state=open]:motion-overlay-enter data-[state=closed]:motion-overlay-exit"
|
"data-[state=open]:motion-overlay-enter data-[state=closed]:motion-overlay-exit"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -9,7 +9,8 @@ export const dialogContentVariants = cva(
|
|||||||
[
|
[
|
||||||
"fixed left-1/2 top-1/2 z-50 grid -translate-x-1/2 -translate-y-1/2 gap-5",
|
"fixed left-1/2 top-1/2 z-50 grid -translate-x-1/2 -translate-y-1/2 gap-5",
|
||||||
"w-[min(calc(100vw-2rem),40rem)] max-h-[calc(100vh-2rem)] overflow-y-auto",
|
"w-[min(calc(100vw-2rem),40rem)] max-h-[calc(100vh-2rem)] overflow-y-auto",
|
||||||
"rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-card)] p-6 text-[var(--color-card-foreground)] shadow-[var(--shadow-md)] outline-none",
|
"rounded-[var(--ui-panel-radius)] border border-[var(--ui-panel-border)] bg-[var(--ui-panel-bg)] p-6 text-[var(--color-card-foreground)] shadow-[var(--ui-panel-shadow)] outline-none",
|
||||||
|
"[border-width:var(--ui-panel-border-width)] backdrop-blur-[var(--ui-panel-backdrop-blur)]",
|
||||||
"data-[state=open]:motion-enter-rise data-[state=closed]:motion-exit-drop"
|
"data-[state=open]:motion-enter-rise data-[state=closed]:motion-exit-drop"
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
|
|
||||||
export const inputVariants = cva(
|
export const inputVariants = cva(
|
||||||
[
|
[
|
||||||
"flex w-full min-w-0 rounded-[var(--radius-md)] border border-[var(--color-input)] bg-[var(--color-card)]",
|
"flex w-full min-w-0 rounded-[var(--ui-input-radius)] border bg-[var(--ui-input-bg)]",
|
||||||
"text-[var(--color-foreground)] shadow-[var(--shadow-xs)] outline-none",
|
"text-[var(--ui-input-fg)] shadow-[var(--ui-input-shadow)] outline-none",
|
||||||
|
"[border-width:var(--ui-input-border-width)] border-[var(--ui-input-border)] backdrop-blur-[var(--ui-input-backdrop-blur)]",
|
||||||
"placeholder:text-[var(--color-muted-foreground)]",
|
"placeholder:text-[var(--color-muted-foreground)]",
|
||||||
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
||||||
"disabled:cursor-not-allowed disabled:bg-[var(--color-surface)] disabled:text-[var(--color-muted-foreground)] disabled:opacity-100",
|
"disabled:cursor-not-allowed disabled:bg-[var(--ui-input-disabled-bg)] disabled:text-[var(--color-muted-foreground)] disabled:opacity-100",
|
||||||
"read-only:bg-[var(--color-surface)] read-only:text-[var(--color-muted-foreground)]",
|
"read-only:bg-[var(--ui-input-readonly-bg)] read-only:text-[var(--color-muted-foreground)]",
|
||||||
"aria-[invalid=true]:border-[color-mix(in_oklch,var(--color-destructive)_42%,var(--color-border-strong))]",
|
"aria-[invalid=true]:border-[color-mix(in_oklch,var(--color-destructive)_42%,var(--color-border-strong))]",
|
||||||
"aria-[invalid=true]:shadow-[0_0_0_1px_color-mix(in_oklch,var(--color-destructive)_28%,transparent)]",
|
"aria-[invalid=true]:shadow-[0_0_0_1px_color-mix(in_oklch,var(--color-destructive)_28%,transparent)]",
|
||||||
getMotionRecipeClassNames("ring")
|
getMotionRecipeClassNames("ring")
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ import { cva } from "../lib/cva";
|
|||||||
import { getMotionRecipeClassNames } from "../lib/motion";
|
import { getMotionRecipeClassNames } from "../lib/motion";
|
||||||
|
|
||||||
export const tabsListVariants = cva([
|
export const tabsListVariants = cva([
|
||||||
"inline-flex h-12 items-center gap-1 rounded-[var(--radius-full)] border border-[var(--color-border)] bg-[var(--color-surface)] p-1 shadow-[var(--shadow-xs)]"
|
"inline-flex h-12 items-center gap-1 rounded-[var(--ui-control-radius)] border border-[var(--ui-control-border)] bg-[var(--ui-control-bg)] p-1 shadow-[var(--ui-control-shadow)] [border-width:var(--ui-input-border-width)]"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const tabsTriggerVariants = cva([
|
export const tabsTriggerVariants = cva([
|
||||||
"inline-flex min-w-[7rem] items-center justify-center rounded-[var(--radius-full)] px-4 py-2.5 text-sm font-medium outline-none",
|
"inline-flex min-w-[7rem] items-center justify-center rounded-[var(--ui-control-radius)] px-4 py-2.5 text-sm font-medium outline-none",
|
||||||
"text-[var(--color-muted-foreground)] transition-[color,background-color,box-shadow,transform] duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
|
"text-[var(--color-muted-foreground)] transition-[color,background-color,box-shadow,transform] duration-[var(--dur-fast)] ease-[var(--ease-standard)]",
|
||||||
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
||||||
"data-[disabled]:pointer-events-none data-[disabled]:opacity-45",
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-45",
|
||||||
"data-[state=active]:bg-[var(--color-card)] data-[state=active]:text-[var(--color-foreground)] data-[state=active]:shadow-[var(--shadow-xs)]",
|
"data-[state=active]:bg-[var(--ui-panel-bg)] data-[state=active]:text-[var(--color-foreground)] data-[state=active]:shadow-[var(--ui-control-shadow)]",
|
||||||
getMotionRecipeClassNames("ring")
|
getMotionRecipeClassNames("ring")
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const tabsContentVariants = cva([
|
export const tabsContentVariants = cva([
|
||||||
"mt-4 rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-card)] p-6 text-[var(--color-card-foreground)] shadow-[var(--shadow-sm)] outline-none",
|
"mt-4 rounded-[var(--ui-card-radius)] border border-[var(--ui-card-default-border)] bg-[var(--ui-card-default-bg)] p-6 text-[var(--color-card-foreground)] shadow-[var(--ui-card-default-shadow)] outline-none [border-width:var(--ui-card-border-width)]",
|
||||||
"data-[state=active]:motion-enter-rise"
|
"data-[state=active]:motion-enter-rise"
|
||||||
]);
|
]);
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { getMotionRecipeClassNames } from "../lib/motion";
|
|||||||
|
|
||||||
export const textareaVariants = cva(
|
export const textareaVariants = cva(
|
||||||
[
|
[
|
||||||
"flex min-h-[8.75rem] w-full min-w-0 resize-y rounded-[var(--radius-md)] border border-[var(--color-input)] bg-[var(--color-card)] px-4 py-3",
|
"flex min-h-[8.75rem] w-full min-w-0 resize-y rounded-[var(--ui-input-radius)] border bg-[var(--ui-input-bg)] px-4 py-3",
|
||||||
"text-[var(--color-foreground)] shadow-[var(--shadow-xs)] outline-none",
|
"text-[var(--ui-input-fg)] shadow-[var(--ui-input-shadow)] outline-none",
|
||||||
|
"[border-width:var(--ui-input-border-width)] border-[var(--ui-input-border)] backdrop-blur-[var(--ui-input-backdrop-blur)]",
|
||||||
"placeholder:text-[var(--color-muted-foreground)]",
|
"placeholder:text-[var(--color-muted-foreground)]",
|
||||||
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
"focus-visible:ring-2 focus-visible:ring-[var(--color-ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--color-background)]",
|
||||||
"disabled:cursor-not-allowed disabled:bg-[var(--color-surface)] disabled:text-[var(--color-muted-foreground)] disabled:opacity-100",
|
"disabled:cursor-not-allowed disabled:bg-[var(--ui-input-disabled-bg)] disabled:text-[var(--color-muted-foreground)] disabled:opacity-100",
|
||||||
"read-only:bg-[var(--color-surface)] read-only:text-[var(--color-muted-foreground)]",
|
"read-only:bg-[var(--ui-input-readonly-bg)] read-only:text-[var(--color-muted-foreground)]",
|
||||||
"aria-[invalid=true]:border-[color-mix(in_oklch,var(--color-destructive)_42%,var(--color-border-strong))]",
|
"aria-[invalid=true]:border-[color-mix(in_oklch,var(--color-destructive)_42%,var(--color-border-strong))]",
|
||||||
"aria-[invalid=true]:shadow-[0_0_0_1px_color-mix(in_oklch,var(--color-destructive)_28%,transparent)]",
|
"aria-[invalid=true]:shadow-[0_0_0_1px_color-mix(in_oklch,var(--color-destructive)_28%,transparent)]",
|
||||||
getMotionRecipeClassNames("ring")
|
getMotionRecipeClassNames("ring")
|
||||||
|
|||||||
@@ -0,0 +1,133 @@
|
|||||||
|
import type { ComponentPropsWithoutRef, ReactNode } from "react";
|
||||||
|
|
||||||
|
import { cn } from "./cn";
|
||||||
|
|
||||||
|
type IconProps = ComponentPropsWithoutRef<"svg">;
|
||||||
|
|
||||||
|
function IconFrame({
|
||||||
|
children,
|
||||||
|
className,
|
||||||
|
viewBox = "0 0 16 16",
|
||||||
|
...props
|
||||||
|
}: IconProps & {
|
||||||
|
children: ReactNode;
|
||||||
|
viewBox?: string;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className={cn("size-4 shrink-0", className)}
|
||||||
|
fill="none"
|
||||||
|
viewBox={viewBox}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CheckIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="M3.5 8.5 6.5 11.5 12.5 5.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.75"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ChevronDownIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="m4.5 6.5 3.5 3 3.5-3"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.75"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ChevronRightIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="m6 4.5 3.5 3.5L6 11.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.75"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CloseIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="m4.5 4.5 7 7m0-7-7 7"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.75"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DotIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} viewBox="0 0 8 8" {...props}>
|
||||||
|
<circle cx="4" cy="4" fill="currentColor" r="2.25" />
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SortAscendingIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="M8 12.5v-9m0 0L5.5 6m2.5-2.5L10.5 6"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SortDescendingIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="M8 3.5v9m0 0-2.5-2.5M8 12.5l2.5-2.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SortUnsortedIcon({ className, ...props }: IconProps) {
|
||||||
|
return (
|
||||||
|
<IconFrame className={className} {...props}>
|
||||||
|
<path
|
||||||
|
d="m5 6 3-3 3 3M11 10l-3 3-3-3"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
/>
|
||||||
|
</IconFrame>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -18,10 +18,50 @@ export const themeDetails = {
|
|||||||
}
|
}
|
||||||
} as const satisfies Record<ThemeName, { label: string; note: string }>;
|
} as const satisfies Record<ThemeName, { label: string; note: string }>;
|
||||||
|
|
||||||
export const motionModeNames = ["system", "reduced"] as const;
|
export const motionPackNames = ["calm", "snappy", "spring"] as const;
|
||||||
export type MotionModeName = (typeof motionModeNames)[number];
|
export type MotionPackName = (typeof motionPackNames)[number];
|
||||||
|
|
||||||
export const defaultMotionMode: MotionModeName = "system";
|
export const defaultMotionPack: MotionPackName = "calm";
|
||||||
|
|
||||||
|
export const motionPackDetails = {
|
||||||
|
calm: {
|
||||||
|
label: "Calm",
|
||||||
|
note: "Editorial default with restrained lift and steady transitions"
|
||||||
|
},
|
||||||
|
snappy: {
|
||||||
|
label: "Snappy",
|
||||||
|
note: "Shorter durations, tighter distances, and more direct response"
|
||||||
|
},
|
||||||
|
spring: {
|
||||||
|
label: "Spring",
|
||||||
|
note: "More elastic easing, wider movement, and livelier feedback"
|
||||||
|
}
|
||||||
|
} as const satisfies Record<MotionPackName, { label: string; note: string }>;
|
||||||
|
|
||||||
|
export const motionAccessibilityNames = ["system", "full", "reduced"] as const;
|
||||||
|
export type MotionAccessibilityName = (typeof motionAccessibilityNames)[number];
|
||||||
|
|
||||||
|
export const defaultMotionAccessibility: MotionAccessibilityName = "system";
|
||||||
|
|
||||||
|
export const motionAccessibilityDetails = {
|
||||||
|
system: {
|
||||||
|
label: "System",
|
||||||
|
note: "Follow the operating system reduced-motion preference"
|
||||||
|
},
|
||||||
|
full: {
|
||||||
|
label: "Full",
|
||||||
|
note: "Always show the selected motion pack, even if the OS prefers reduced motion"
|
||||||
|
},
|
||||||
|
reduced: {
|
||||||
|
label: "Reduced",
|
||||||
|
note: "Always collapse durations, distances, and animated feedback"
|
||||||
|
}
|
||||||
|
} as const satisfies Record<MotionAccessibilityName, { label: string; note: string }>;
|
||||||
|
|
||||||
|
export const motionModeNames = motionAccessibilityNames;
|
||||||
|
export type MotionModeName = MotionAccessibilityName;
|
||||||
|
|
||||||
|
export const defaultMotionMode: MotionModeName = defaultMotionAccessibility;
|
||||||
|
|
||||||
export const motionScale = {
|
export const motionScale = {
|
||||||
instant: "var(--dur-instant)",
|
instant: "var(--dur-instant)",
|
||||||
@@ -150,6 +190,16 @@ function getTargetElement(root?: HTMLElement) {
|
|||||||
return document.documentElement;
|
return document.documentElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setMotionPack(pack: MotionPackName, root?: HTMLElement) {
|
||||||
|
const target = getTargetElement(root);
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
target.dataset.motionPack = pack;
|
||||||
|
}
|
||||||
|
|
||||||
export function setTheme(theme: ThemeName, root?: HTMLElement) {
|
export function setTheme(theme: ThemeName, root?: HTMLElement) {
|
||||||
const target = getTargetElement(root);
|
const target = getTargetElement(root);
|
||||||
|
|
||||||
@@ -160,7 +210,10 @@ export function setTheme(theme: ThemeName, root?: HTMLElement) {
|
|||||||
target.dataset.theme = theme;
|
target.dataset.theme = theme;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
|
export function setMotionAccessibility(
|
||||||
|
mode: MotionAccessibilityName,
|
||||||
|
root?: HTMLElement
|
||||||
|
) {
|
||||||
const target = getTargetElement(root);
|
const target = getTargetElement(root);
|
||||||
|
|
||||||
if (!target) {
|
if (!target) {
|
||||||
@@ -174,3 +227,7 @@ export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
|
|||||||
|
|
||||||
target.dataset.motion = mode;
|
target.dataset.motion = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setMotionMode(mode: MotionModeName, root?: HTMLElement) {
|
||||||
|
setMotionAccessibility(mode, root);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
:root {
|
:root,
|
||||||
|
[data-motion-pack="calm"] {
|
||||||
--dur-instant: 1ms;
|
--dur-instant: 1ms;
|
||||||
--dur-fast: 120ms;
|
--dur-fast: 120ms;
|
||||||
--dur-base: 200ms;
|
--dur-base: 200ms;
|
||||||
@@ -19,7 +20,52 @@
|
|||||||
--scale-pop: 1.02;
|
--scale-pop: 1.02;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root[data-motion="reduced"] {
|
:root[data-motion-pack="snappy"],
|
||||||
|
[data-motion-pack="snappy"] {
|
||||||
|
--dur-instant: 1ms;
|
||||||
|
--dur-fast: 90ms;
|
||||||
|
--dur-base: 150ms;
|
||||||
|
--dur-slow: 220ms;
|
||||||
|
--dur-deliberate: 300ms;
|
||||||
|
|
||||||
|
--ease-standard: cubic-bezier(0.18, 1, 0.32, 1);
|
||||||
|
--ease-emphasized: cubic-bezier(0.2, 1.08, 0.28, 1);
|
||||||
|
--ease-exit: cubic-bezier(0.4, 0, 1, 1);
|
||||||
|
|
||||||
|
--distance-xs: 2px;
|
||||||
|
--distance-sm: 4px;
|
||||||
|
--distance-md: 10px;
|
||||||
|
--distance-lg: 16px;
|
||||||
|
|
||||||
|
--scale-press: 0.985;
|
||||||
|
--scale-hover: 1.006;
|
||||||
|
--scale-pop: 1.012;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-motion-pack="spring"],
|
||||||
|
[data-motion-pack="spring"] {
|
||||||
|
--dur-instant: 1ms;
|
||||||
|
--dur-fast: 140ms;
|
||||||
|
--dur-base: 220ms;
|
||||||
|
--dur-slow: 360ms;
|
||||||
|
--dur-deliberate: 520ms;
|
||||||
|
|
||||||
|
--ease-standard: cubic-bezier(0.2, 1.08, 0.28, 1);
|
||||||
|
--ease-emphasized: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||||
|
--ease-exit: cubic-bezier(0.42, 0, 1, 1);
|
||||||
|
|
||||||
|
--distance-xs: 6px;
|
||||||
|
--distance-sm: 12px;
|
||||||
|
--distance-md: 20px;
|
||||||
|
--distance-lg: 32px;
|
||||||
|
|
||||||
|
--scale-press: 0.96;
|
||||||
|
--scale-hover: 1.018;
|
||||||
|
--scale-pop: 1.035;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-motion="reduced"],
|
||||||
|
[data-motion="reduced"] {
|
||||||
--dur-instant: 1ms;
|
--dur-instant: 1ms;
|
||||||
--dur-fast: 1ms;
|
--dur-fast: 1ms;
|
||||||
--dur-base: 1ms;
|
--dur-base: 1ms;
|
||||||
@@ -32,6 +78,19 @@
|
|||||||
--scale-press: 1;
|
--scale-press: 1;
|
||||||
--scale-hover: 1;
|
--scale-hover: 1;
|
||||||
--scale-pop: 1;
|
--scale-pop: 1;
|
||||||
|
scroll-behavior: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root[data-motion="reduced"] *,
|
||||||
|
:root[data-motion="reduced"] *::before,
|
||||||
|
:root[data-motion="reduced"] *::after,
|
||||||
|
[data-motion="reduced"] *,
|
||||||
|
[data-motion="reduced"] *::before,
|
||||||
|
[data-motion="reduced"] *::after {
|
||||||
|
animation-duration: 1ms !important;
|
||||||
|
animation-iteration-count: 1 !important;
|
||||||
|
scroll-behavior: auto !important;
|
||||||
|
transition-duration: 1ms !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
|||||||
Reference in New Issue
Block a user