@waveso/ui 0.17.0 → 0.19.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/README.md CHANGED
@@ -47,11 +47,12 @@ Wave builds around an intuitive, intentional **3-tier hierarchy** — for almost
47
47
  - 3 offset amounts for transforms
48
48
  - …and more
49
49
 
50
- It also builds around 3 semantic intents:
50
+ It builds around semantic intents:
51
51
 
52
52
  - **Background** colors focus on elevation — how deep a surface sits
53
53
  - **Content** colors focus on emphasis — how strongly something reads
54
54
  - **Border** colors focus on structure — how functional a boundary is
55
+ - **Control** colors focus on state — whether a control is at rest, pointed at or chosen
55
56
 
56
57
  This is the right shape for a system centered on an emphasis ladder: clean and minimal, but flexible.
57
58
 
@@ -71,43 +72,53 @@ A pinned class always beats the OS — put `.paper`, `.graphite`, or `.ink` on y
71
72
 
72
73
  ## Taxonomy
73
74
 
74
- Wave pays close attention to token taxonomy. Surfaces encode elevation; borders act as _light interference rather than geometry_.
75
+ Wave pays close attention to token taxonomy. Surfaces encode elevation; borders act as _light interference rather than geometry_. Each of the five families below has three members, each with one job.
75
76
 
76
- ### Background
77
+ **Surfaces are solid: they contain. Borders and control fills are see-through:** `line`, `edge`, `contour`, `neutral` and `highlighted` are the theme's text colour made translucent, so they blend into whatever is underneath, for depth and integration. An input inside a primary-coloured banner, or on an accent card, only works if its fill is see-through; a solid control colour can't follow every background. And because controls don't borrow `secondary`, it's free to be a real brand colour.
78
+
79
+ ### Surfaces — solid, to contain
77
80
 
78
81
  - `--foundation` — the deepest layer, the base where elevation starts
79
82
  - `--surface` — the middle layer: cards, sidebars, content boxes
80
83
  - `--elevated` — the highest layer: floating windows, modals, dropdowns, dialogs
81
84
 
82
- ### Foreground
85
+ ### Text — contrast
83
86
 
84
87
  - `--contrast` — titles, primary text
85
88
  - `--muted` — body text, icons, any mark
86
- - `--soft` — placeholders, hints
89
+ - `--subtle` — placeholders, hints
87
90
 
88
- ### Form
91
+ ### Brand — colour
89
92
 
90
- The theme's foreground made translucent, at three strengths — the way a draughtsman renders a form. Each is translucent, so it reads the same on any surface, and each keeps one job on a border or a background.
93
+ - `--primary` — wired to the Wave ramp
94
+ - `--secondary` — the second brand colour, a quiet neutral by default
95
+ - `--accent` — alternative emphasis
91
96
 
92
- - `--contour` — where a shape ends: hairline borders, separators, dividers
93
- - `--highlight` — where attention lands: hovered, keyboard-highlighted and open items
94
- - `--shade` — what gives a control its body: field and track fills, and the intense border (control outlines, layout regions)
97
+ ### Borders — boundary
95
98
 
96
- ### Ring
99
+ The theme's text colour at three strengths, one job each:
97
100
 
98
- - `--focus` — active / focus states
101
+ - `--line` (5%) — what divides: separators, dividers, hairlines
102
+ - `--edge` (10%) — what bounds a surface: cards, dialogs, popups, toasts
103
+ - `--contour` (15%) — what outlines a control or a region: outline buttons, badges, toggles, layout regions
99
104
 
100
- ### Brand
105
+ ### Controls — depth
101
106
 
102
- - `--primary` — wired to the Wave ramp
103
- - `--secondary` — neutral fill
104
- - `--accent` — alternative emphasis
107
+ A control's state, from resting to chosen:
108
+
109
+ - `--neutral` (10%) — the look before anything is chosen or pointed at: field and track fills, unchecked boxes, table footers, muted items. Not Tailwind's `neutral-*` grey palette, which Wave doesn't use
110
+ - `--highlighted` (15%) — where attention lands: hovered, keyboard-highlighted and open items, a step stronger than `neutral`
111
+ - `--selected` — chosen, current or on: the current tab, a pressed toggle, a checked box, a selected row. `--primary` by default; set it to restyle every chosen state at once. Chosen items keep white text, so pick a colour it reads on, such as a darker shade of your brand colour
112
+
113
+ ### Ring
114
+
115
+ - `--focus` — active / focus states
105
116
 
106
117
  ### Border strategy
107
118
 
108
119
  This is the sophisticated move most libraries skip.
109
120
 
110
- Wave uses **transparent (alpha) borders only**: `contour` by default, and `shade` where a boundary has to be intense.
121
+ Wave uses **transparent (alpha) borders only**: `line` and `edge` by default, and `contour` where a boundary has to be intense. Rings are halos, kept for focus and invalid states, never a surface's edge: a ring is drawn outside the surface (past a menu's glass, so it flickers where it crosses text) and disappears in Windows high contrast mode, while a border is part of the surface.
111
122
 
112
123
  Wave's palette behaves like a layered _material system_, not a flat UI. Dark surfaces, a soft text hierarchy, and subtle elevation shifts (low-contrast steps) mean borders should not introduce a new "color layer" — that would break the illusion of depth — yet structure still needs an intense option.
113
124
 
@@ -115,13 +126,12 @@ Alpha borders **inherit the surface beneath them**, take the **content color as
115
126
 
116
127
  Intense borders compete with the surface ladder and create visual "grid noise" if overused, so use them sparingly. Overusing them flattens everything into "outlined boxes" with reduced perceived elevation — the "Bootstrap feel."
117
128
 
118
- The default **`contour`** borders are ideal for:
129
+ The default **`edge`** and **`line`** borders are ideal for:
119
130
 
120
- - Cards
121
- - Panels
122
- - Subtle separators
131
+ - Cards, panels and popups (`edge`)
132
+ - Subtle separators (`line`)
123
133
 
124
- The intense **`shade`** borders are ideal for:
134
+ The intense **`contour`** borders are ideal for:
125
135
 
126
136
  - Layout definition (sidebar vs. content)
127
137
  - Component grouping
@@ -130,8 +140,9 @@ The intense **`shade`** borders are ideal for:
130
140
 
131
141
  **Rule of thumb:**
132
142
 
133
- - If it separates **surface from surface** → `contour`
134
- - If it separates **layout regions** → `shade`
143
+ - If it bounds **a surface** → `edge`
144
+ - If it divides **content within a surface** → `line`
145
+ - If it separates **layout regions** or outlines a control → `contour`
135
146
  - If it indicates **interaction / state** → colored alpha border
136
147
 
137
148
  ---
package/dist/accordion.js CHANGED
@@ -14,7 +14,7 @@ function Accordion({ className, ...props }) {
14
14
  function AccordionItem({ className, ...props }) {
15
15
  return /* @__PURE__ */ jsx(Accordion$1.Item, {
16
16
  "data-slot": "accordion-item",
17
- className: cn("not-last:border-b border-shade", className),
17
+ className: cn("not-last:border-b border-contour", className),
18
18
  ...props
19
19
  });
20
20
  }
@@ -24,7 +24,7 @@ function AccordionTrigger({ className, children, ...props }) {
24
24
  className: "flex",
25
25
  children: /* @__PURE__ */ jsxs(Accordion$1.Trigger, {
26
26
  "data-slot": "accordion-trigger",
27
- className: cn("cursor-clickable focus-visible:ring-focus/50 focus-visible:border-focus focus-visible:after:border-focus **:data-[slot=accordion-trigger-icon]:text-muted group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-2.5 text-left text-sm font-medium motion-color outline-hidden hover:underline focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", className),
27
+ className: cn("cursor-clickable focus-visible:ring-focus/50 focus-visible:border-focus focus-visible:after:border-focus **:data-[slot=accordion-trigger-icon]:text-muted group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-2.5 text-left text-sm font-medium motion-color focus-visible:outline-hidden hover:underline focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4", className),
28
28
  ...props,
29
29
  children: [
30
30
  children,
@@ -209,7 +209,7 @@ function ActionBarProvider({ children, message = "You have unsaved changes", plu
209
209
  className: "fixed bottom-6 left-1/2 z-50",
210
210
  children: /* @__PURE__ */ jsxs("div", {
211
211
  "data-slot": "action-bar-content",
212
- className: cn("flex items-center gap-6 rounded-lg border border-contour/60 bg-surface px-5 py-2.5 shadow-lg ring-1 ring-contour", className),
212
+ className: cn("flex items-center gap-6 rounded-lg bg-surface px-5 py-2.5 shadow-lg border border-edge", className),
213
213
  children: [/* @__PURE__ */ jsx("span", {
214
214
  "data-slot": "action-bar-message",
215
215
  className: cn("whitespace-nowrap text-sm font-medium", saveError ? "text-danger" : "text-contrast"),
@@ -33,7 +33,7 @@ function AlertDialogContent({ className, size = "default", ...props }) {
33
33
  return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [/* @__PURE__ */ jsx(AlertDialogOverlay, {}), /* @__PURE__ */ jsx(AlertDialog$1.Popup, {
34
34
  "data-slot": "alert-dialog-content",
35
35
  "data-size": size,
36
- className: cn("motion-scale-lg bg-foundation ring-contrast/10 group/alert-dialog-content fixed top-1/2 start-1/2 z-50 grid w-[calc(100%-2rem)] -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 gap-6 rounded-lg p-6 ring-1 outline-hidden data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl shadow-lg", className),
36
+ className: cn("motion-scale-lg bg-foundation border-edge group/alert-dialog-content fixed top-1/2 start-1/2 z-50 grid w-[calc(100%-2rem)] -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 gap-6 rounded-lg p-6 border focus-visible:outline-hidden data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=lg]:max-w-lg data-[size=xl]:max-w-xl data-[size=default]:sm:max-w-sm data-[size=lg]:sm:max-w-lg data-[size=xl]:sm:max-w-xl shadow-lg", className),
37
37
  ...props
38
38
  })] });
39
39
  }
package/dist/alert.js CHANGED
@@ -2,7 +2,7 @@ import { cn } from "./lib/utils.js";
2
2
  import { jsx } from "react/jsx-runtime";
3
3
  import { cva } from "class-variance-authority";
4
4
  //#region src/alert.tsx
5
- const alertVariants = cva("grid gap-0.5 rounded-md border border-shade px-4 py-3 text-start text-sm has-data-[slot=alert-action]:pe-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2.5 *:data-[icon]:col-start-1 *:data-[icon]:row-span-2 *:data-[icon]:translate-y-0.5 *:data-[icon]:text-current *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert", {
5
+ const alertVariants = cva("grid gap-0.5 rounded-md border border-contour px-4 py-3 text-start text-sm has-data-[slot=alert-action]:pe-18 has-data-[icon]:grid-cols-[auto_1fr] has-data-[icon]:gap-x-2.5 *:data-[icon]:col-start-1 *:data-[icon]:row-span-2 *:data-[icon]:translate-y-0.5 *:data-[icon]:text-current *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 w-full relative group/alert", {
6
6
  variants: { variant: {
7
7
  default: "bg-surface text-contrast",
8
8
  info: "bg-surface text-contrast *:data-[icon]:text-info *:[svg]:text-info",
@@ -69,7 +69,7 @@ function AutocompletePositioner({ className, ...props }) {
69
69
  function AutocompletePopup({ className, ...props }) {
70
70
  return /* @__PURE__ */ jsx(Autocomplete$1.Popup, {
71
71
  "data-slot": "autocomplete-popup",
72
- className: cn("motion-pop-md bg-elevated text-contrast ring-contrast/10 group/autocomplete-content relative max-h-(--available-height) min-w-(--anchor-width) max-w-(--available-width) overflow-x-hidden overflow-y-auto rounded-md shadow-md ring-1", className),
72
+ className: cn("motion-pop-md bg-elevated text-contrast border-edge group/autocomplete-content relative flex max-h-(--available-height) min-w-(--anchor-width) max-w-(--available-width) flex-col overflow-hidden rounded-md shadow-md border", className),
73
73
  ...props
74
74
  });
75
75
  }
@@ -97,7 +97,7 @@ function AutocompleteEmpty({ className, ...props }) {
97
97
  function AutocompleteList({ className, ...props }) {
98
98
  return /* @__PURE__ */ jsx(Autocomplete$1.List, {
99
99
  "data-slot": "autocomplete-list",
100
- className: cn("scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0", className),
100
+ className: cn("scroll-fade supports-[animation-timeline:scroll()]:scrollbar-none min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain p-1 data-empty:p-0", className),
101
101
  ...props
102
102
  });
103
103
  }
@@ -111,14 +111,14 @@ function AutocompleteRow({ className, ...props }) {
111
111
  function AutocompleteItem({ className, ...props }) {
112
112
  return /* @__PURE__ */ jsx(Autocomplete$1.Item, {
113
113
  "data-slot": "autocomplete-item",
114
- className: cn("data-highlighted:bg-highlight relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pl-1.5 pr-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
114
+ className: cn("data-highlighted:bg-highlighted relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pl-1.5 pr-1.5 text-sm data-highlighted:outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
115
115
  ...props
116
116
  });
117
117
  }
118
118
  function AutocompleteSeparator({ className, ...props }) {
119
119
  return /* @__PURE__ */ jsx(Autocomplete$1.Separator, {
120
120
  "data-slot": "autocomplete-separator",
121
- className: cn("bg-contour -mx-1 my-1 h-px", className),
121
+ className: cn("bg-line -mx-1 my-1 h-px", className),
122
122
  ...props
123
123
  });
124
124
  }
package/dist/avatar.js CHANGED
@@ -7,42 +7,42 @@ function Avatar({ className, size = "default", ...props }) {
7
7
  return /* @__PURE__ */ jsx(Avatar$1.Root, {
8
8
  "data-slot": "avatar",
9
9
  "data-size": size,
10
- className: cn("after:border-contour group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border data-[size=lg]:size-10 data-[size=sm]:size-6 data-[size=xs]:size-5", className),
10
+ className: cn("after:border-line group/avatar relative flex size-(--avatar-size) shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border", "[--avatar-size:calc(var(--spacing)*8)] data-[size=lg]:[--avatar-size:calc(var(--spacing)*10)] data-[size=sm]:[--avatar-size:calc(var(--spacing)*6)] data-[size=xs]:[--avatar-size:calc(var(--spacing)*5)]", "[--avatar-badge-size:calc(var(--spacing)*2.5)] data-[size=lg]:[--avatar-badge-size:calc(var(--spacing)*3)] data-[size=sm]:[--avatar-badge-size:calc(var(--spacing)*2)] data-[size=xs]:[--avatar-badge-size:calc(var(--spacing)*1.5)]", "has-data-[slot=avatar-badge]:[--avatar-cutout:radial-gradient(circle_calc(var(--avatar-badge-size)/2_+_2px)_at_calc(100%_-_var(--avatar-badge-size)/2)_calc(100%_-_var(--avatar-badge-size)/2),transparent_calc(var(--avatar-badge-size)/2_+_1.5px),#000_calc(var(--avatar-badge-size)/2_+_2px))]", "rtl:has-data-[slot=avatar-badge]:[--avatar-cutout:radial-gradient(circle_calc(var(--avatar-badge-size)/2_+_2px)_at_calc(var(--avatar-badge-size)/2)_calc(100%_-_var(--avatar-badge-size)/2),transparent_calc(var(--avatar-badge-size)/2_+_1.5px),#000_calc(var(--avatar-badge-size)/2_+_2px))]", "after:[mask-image:var(--avatar-cutout,none)]", className),
11
11
  ...props
12
12
  });
13
13
  }
14
14
  function AvatarImage({ className, ...props }) {
15
15
  return /* @__PURE__ */ jsx(Avatar$1.Image, {
16
16
  "data-slot": "avatar-image",
17
- className: cn("aspect-square size-full rounded-full object-cover", className),
17
+ className: cn("aspect-square size-full rounded-full object-cover [mask-image:var(--avatar-cutout,none)]", className),
18
18
  ...props
19
19
  });
20
20
  }
21
21
  function AvatarFallback({ className, ...props }) {
22
22
  return /* @__PURE__ */ jsx(Avatar$1.Fallback, {
23
23
  "data-slot": "avatar-fallback",
24
- className: cn("bg-secondary text-contrast flex size-full items-center justify-center rounded-full text-sm group-data-[size=xs]/avatar:text-[10px] group-data-[size=sm]/avatar:text-xs group-data-[size=lg]/avatar:text-base", className),
24
+ className: cn("bg-secondary text-contrast flex size-full items-center justify-center rounded-full text-sm group-data-[size=xs]/avatar:text-[10px] group-data-[size=sm]/avatar:text-xs group-data-[size=lg]/avatar:text-base [mask-image:var(--avatar-cutout,none)]", className),
25
25
  ...props
26
26
  });
27
27
  }
28
28
  function AvatarBadge({ className, ...props }) {
29
29
  return /* @__PURE__ */ jsx("span", {
30
30
  "data-slot": "avatar-badge",
31
- className: cn("bg-primary text-white ring-foundation absolute end-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full ring-2 select-none", "group-data-[size=xs]/avatar:size-1.5 group-data-[size=xs]/avatar:[&>svg]:hidden", "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2", "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2", className),
31
+ className: cn("bg-primary text-white absolute end-0 bottom-0 z-10 inline-flex size-(--avatar-badge-size) items-center justify-center rounded-full select-none", "group-data-[size=xs]/avatar:[&>svg]:hidden group-data-[size=sm]/avatar:[&>svg]:hidden", "group-data-[size=default]/avatar:[&>svg]:size-2 group-data-[size=lg]/avatar:[&>svg]:size-2", className),
32
32
  ...props
33
33
  });
34
34
  }
35
35
  function AvatarGroup({ className, ...props }) {
36
36
  return /* @__PURE__ */ jsx("div", {
37
37
  "data-slot": "avatar-group",
38
- className: cn("*:data-[slot=avatar]:ring-foundation group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2", className),
38
+ className: cn("group/avatar-group flex -space-x-2", "*:data-[slot=avatar]:not-last:[mask-image:radial-gradient(circle_calc(var(--avatar-size)/2_+_2px)_at_calc(150%_-_var(--spacing)*2)_50%,transparent_calc(var(--avatar-size)/2_+_1.5px),#000_calc(var(--avatar-size)/2_+_2px))]", "rtl:*:data-[slot=avatar]:not-last:[mask-image:radial-gradient(circle_calc(var(--avatar-size)/2_+_2px)_at_calc(-50%_+_var(--spacing)*2)_50%,transparent_calc(var(--avatar-size)/2_+_1.5px),#000_calc(var(--avatar-size)/2_+_2px))]", className),
39
39
  ...props
40
40
  });
41
41
  }
42
42
  function AvatarGroupCount({ className, ...props }) {
43
43
  return /* @__PURE__ */ jsx("div", {
44
44
  "data-slot": "avatar-group-count",
45
- className: cn("bg-secondary text-contrast ring-foundation relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm ring-2 group-has-data-[size=xs]/avatar-group:size-5 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=xs]/avatar-group:[&>svg]:size-3 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className),
45
+ className: cn("bg-secondary text-contrast relative flex size-8 shrink-0 items-center justify-center rounded-full text-sm group-has-data-[size=xs]/avatar-group:size-5 group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=xs]/avatar-group:[&>svg]:size-3 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3", className),
46
46
  ...props
47
47
  });
48
48
  }
package/dist/badge.js CHANGED
@@ -11,8 +11,8 @@ const badgeVariants = cva("h-5 gap-1 rounded-full border border-transparent px-2
11
11
  danger: "bg-danger text-white [a]:hover:bg-danger/80 [a]:focus-visible:ring-danger/50",
12
12
  warning: "bg-warning text-white [a]:hover:bg-warning/80",
13
13
  secondary: "bg-secondary text-contrast [a]:hover:bg-secondary/80",
14
- outline: "border-shade bg-foundation [a]:hover:bg-highlight [a]:hover:text-contrast",
15
- ghost: "text-muted [a]:hover:bg-highlight",
14
+ outline: "border-contour bg-foundation [a]:hover:bg-highlighted [a]:hover:text-contrast",
15
+ ghost: "text-muted [a]:hover:bg-highlighted",
16
16
  link: "text-primary [a]:underline-offset-4 [a]:hover:underline"
17
17
  } },
18
18
  defaultVariants: { variant: "default" }
@@ -6,7 +6,7 @@ import { cva } from "class-variance-authority";
6
6
  import { mergeProps } from "@base-ui/react/merge-props";
7
7
  import { useRender } from "@base-ui/react/use-render";
8
8
  //#region src/button-group.tsx
9
- const buttonGroupVariants = cva("group/button-group has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md flex w-fit items-stretch *:focus-visible:z-10 *:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[>[data-variant=outline]]:*:data-[slot=input-group]:border-shade has-[>[data-variant=outline]]:*:data-[slot=select-trigger]:border-shade has-[>[data-variant=outline]]:[&>input]:border-shade has-[>[data-variant=outline]]:[&>[data-slot=input-group]:has(:focus-visible)]:border-focus has-[>[data-variant=outline]]:[&>[data-slot=select-trigger]:focus-visible]:border-focus has-[>[data-variant=outline]]:[&>input:focus-visible]:border-focus [&>[data-variant=default]]:border-primary [&>[data-variant=secondary]]:border-secondary [&>[data-variant=danger]]:border-danger", {
9
+ const buttonGroupVariants = cva("group/button-group has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md flex w-fit items-stretch *:focus-visible:z-10 *:focus-visible:relative [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1 has-[>[data-variant=outline]]:*:data-[slot=input-group]:border-contour has-[>[data-variant=outline]]:*:data-[slot=select-trigger]:border-contour has-[>[data-variant=outline]]:[&>input]:border-contour has-[>[data-variant=outline]]:[&>[data-slot=input-group]:has(:focus-visible)]:border-focus has-[>[data-variant=outline]]:[&>[data-slot=select-trigger]:focus-visible]:border-focus has-[>[data-variant=outline]]:[&>input:focus-visible]:border-focus [&>[data-variant=default]]:border-primary [&>[data-variant=secondary]]:border-secondary [&>[data-variant=danger]]:border-danger", {
10
10
  variants: { orientation: {
11
11
  horizontal: "[&>[data-slot]:has(~[data-slot])]:rounded-r-none [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0",
12
12
  vertical: "flex-col [&>[data-slot]:has(~[data-slot])]:rounded-b-none [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0"
@@ -26,7 +26,7 @@ function ButtonGroup({ className, orientation, size = "default", ...props }) {
26
26
  function ButtonGroupText({ className, render, ...props }) {
27
27
  return useRender({
28
28
  defaultTagName: "div",
29
- props: mergeProps({ className: cn("bg-secondary gap-2 rounded-md border border-shade px-3 text-base font-medium group-data-[size=xs]/button-group:px-2 group-data-[size=xs]/button-group:text-xs group-data-[size=sm]/button-group:text-sm group-data-[size=lg]/button-group:px-4 group-data-[size=lg]/button-group:text-lg [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none", className) }, props),
29
+ props: mergeProps({ className: cn("bg-secondary gap-2 rounded-md border border-contour px-3 text-base font-medium group-data-[size=xs]/button-group:px-2 group-data-[size=xs]/button-group:text-xs group-data-[size=sm]/button-group:text-sm group-data-[size=lg]/button-group:px-4 group-data-[size=lg]/button-group:text-lg [&_svg:not([class*='size-'])]:size-4 flex items-center [&_svg]:pointer-events-none", className) }, props),
30
30
  render,
31
31
  state: { slot: "button-group-text" }
32
32
  });
@@ -35,7 +35,7 @@ function ButtonGroupSeparator({ className, orientation = "vertical", ...props })
35
35
  return /* @__PURE__ */ jsx(Separator, {
36
36
  "data-slot": "button-group-separator",
37
37
  orientation,
38
- className: cn("bg-contour relative self-stretch data-[orientation=horizontal]:w-auto data-[orientation=vertical]:h-auto", className),
38
+ className: cn("bg-line relative self-stretch data-[orientation=horizontal]:w-auto data-[orientation=vertical]:h-auto", className),
39
39
  ...props
40
40
  });
41
41
  }
package/dist/button.js CHANGED
@@ -4,13 +4,13 @@ import { jsx } from "react/jsx-runtime";
4
4
  import { Button as Button$1 } from "@base-ui/react/button";
5
5
  import { cva } from "class-variance-authority";
6
6
  //#region src/button.tsx
7
- const buttonVariants = cva("cursor-clickable focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 aria-invalid:border-danger rounded-md border border-transparent bg-clip-padding font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap motion-color data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 outline-hidden group/button select-none active:not-aria-[haspopup]:scale-[0.97]", {
7
+ const buttonVariants = cva("cursor-clickable focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 aria-invalid:border-danger rounded-md border border-transparent bg-clip-padding font-medium focus-visible:ring-3 aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 inline-flex items-center justify-center whitespace-nowrap motion-color data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none shrink-0 [&_svg]:shrink-0 focus-visible:outline-hidden group/button select-none active:not-aria-[haspopup]:scale-[0.97]", {
8
8
  variants: {
9
9
  variant: {
10
10
  default: "bg-primary text-white hover:bg-primary/80 not-supports-backdrop-filter:hover:bg-primary/90 hover:backdrop-blur-xl hover:backdrop-saturate-150",
11
- outline: "border-shade bg-foundation hover:bg-highlight hover:text-contrast aria-expanded:bg-highlight aria-expanded:text-contrast",
11
+ outline: "border-contour bg-foundation hover:bg-highlighted hover:text-contrast aria-expanded:bg-highlighted aria-expanded:text-contrast",
12
12
  secondary: "bg-secondary text-contrast hover:bg-secondary/80 not-supports-backdrop-filter:hover:bg-secondary/90 hover:backdrop-blur-xl hover:backdrop-saturate-150 aria-expanded:bg-secondary aria-expanded:text-contrast",
13
- ghost: "text-contrast hover:bg-highlight aria-expanded:bg-highlight aria-expanded:text-contrast",
13
+ ghost: "text-contrast hover:bg-highlighted aria-expanded:bg-highlighted aria-expanded:text-contrast",
14
14
  danger: "bg-danger text-white hover:bg-danger/80 not-supports-backdrop-filter:hover:bg-danger/90 hover:backdrop-blur-xl hover:backdrop-saturate-150 focus-visible:ring-danger/50",
15
15
  link: "text-primary underline-offset-4 hover:underline"
16
16
  },
package/dist/card.js CHANGED
@@ -12,7 +12,7 @@ import { useRender } from "@base-ui/react/use-render";
12
12
  function Card({ className, size = "default", render, ...props }) {
13
13
  return useRender({
14
14
  defaultTagName: "div",
15
- props: mergeProps({ className: cn("ring-contrast/10 bg-surface text-contrast group/card flex flex-col gap-6 overflow-hidden rounded-lg py-6 text-sm ring-1 has-[>img:first-child]:pt-0 has-[>img:last-child]:pb-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg", "[a,button]:cursor-clickable [a,button]:hover:bg-elevated [button]:text-start motion-color outline-hidden focus-visible:ring-3 focus-visible:ring-focus/50 disabled:pointer-events-none disabled:opacity-30 aria-disabled:pointer-events-none aria-disabled:opacity-30", className) }, props),
15
+ props: mergeProps({ className: cn("border-edge bg-surface text-contrast group/card flex flex-col gap-6 overflow-hidden rounded-lg py-6 text-sm border has-[>img:first-child]:pt-0 has-[>img:last-child]:pb-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg", "[a,button]:cursor-clickable [a,button]:hover:bg-elevated [button]:text-start motion-color focus-visible:outline-hidden focus-visible:ring-3 focus-visible:ring-focus/50 disabled:pointer-events-none disabled:opacity-30 aria-disabled:pointer-events-none aria-disabled:opacity-30", className) }, props),
16
16
  render,
17
17
  state: {
18
18
  slot: "card",
package/dist/checkbox.js CHANGED
@@ -7,7 +7,7 @@ import { Checkbox as Checkbox$1 } from "@base-ui/react/checkbox";
7
7
  function Checkbox({ className, ...props }) {
8
8
  return /* @__PURE__ */ jsx(Checkbox$1.Root, {
9
9
  "data-slot": "checkbox",
10
- className: cn("cursor-clickable bg-shade border-transparent not-data-disabled:data-unchecked:hover:border-focus not-data-disabled:data-unchecked:group-hover/field:border-focus data-checked:bg-primary data-indeterminate:bg-primary data-checked:text-white data-indeterminate:text-white data-checked:border-primary data-indeterminate:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-danger focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 peer relative flex size-6 shrink-0 items-center justify-center rounded-sm border motion-color outline-hidden group-has-disabled/field:opacity-30 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 aria-invalid:ring-3", className),
10
+ className: cn("cursor-clickable bg-neutral border-transparent not-data-disabled:data-unchecked:hover:border-focus not-data-disabled:data-unchecked:group-hover/field:border-focus data-checked:bg-selected data-indeterminate:bg-selected data-checked:text-white data-indeterminate:text-white data-checked:border-selected data-indeterminate:border-selected aria-invalid:aria-checked:border-selected aria-invalid:border-danger focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 peer relative flex size-6 shrink-0 items-center justify-center rounded-sm border motion-color focus-visible:outline-hidden group-has-disabled/field:opacity-30 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 aria-invalid:ring-3", className),
11
11
  ...props,
12
12
  children: /* @__PURE__ */ jsxs(Checkbox$1.Indicator, {
13
13
  "data-slot": "checkbox-indicator",
package/dist/combobox.js CHANGED
@@ -94,7 +94,7 @@ function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "
94
94
  className: "isolate z-50",
95
95
  children: /* @__PURE__ */ jsx(Combobox$1.Popup, {
96
96
  "data-slot": "combobox-content",
97
- className: cn("motion-pop-md bg-elevated text-contrast ring-contrast/10 *:data-[slot=input-group]:bg-shade/30 *:data-[slot=input-group]:border-shade/30 group/combobox-content relative max-h-(--available-height) max-w-(--available-width) min-w-(--anchor-width) overflow-hidden rounded-md shadow-md ring-1 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:shadow-none", className),
97
+ className: cn("motion-pop-md bg-elevated text-contrast border-edge group/combobox-content relative max-h-(--available-height) max-w-(--available-width) min-w-(--anchor-width) overflow-hidden rounded-md border shadow-md", "*:data-[slot=input-group]:h-8 *:data-[slot=input-group]:rounded-none *:data-[slot=input-group]:bg-transparent *:data-[slot=input-group]:shadow-none", "*:data-[slot=input-group]:border-transparent *:data-[slot=input-group]:border-b-line", "*:data-[slot=input-group]:hover:border-transparent *:data-[slot=input-group]:hover:border-b-line", "*:data-[slot=input-group]:has-[[data-slot=input-group-control]:focus-visible]:border-transparent *:data-[slot=input-group]:has-[[data-slot=input-group-control]:focus-visible]:border-b-line *:data-[slot=input-group]:has-[[data-slot=input-group-control]:focus-visible]:ring-0", className),
98
98
  ...props
99
99
  })
100
100
  }) });
@@ -102,14 +102,14 @@ function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "
102
102
  function ComboboxList({ className, ...props }) {
103
103
  return /* @__PURE__ */ jsx(Combobox$1.List, {
104
104
  "data-slot": "combobox-list",
105
- className: cn("[scrollbar-width:none] [&::-webkit-scrollbar]:hidden max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto overscroll-contain p-1 data-empty:p-0", className),
105
+ className: cn("scroll-fade supports-[animation-timeline:scroll()]:scrollbar-none max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] overflow-x-hidden overflow-y-auto overscroll-contain p-1 data-empty:p-0", className),
106
106
  ...props
107
107
  });
108
108
  }
109
109
  function ComboboxItem({ className, children, ...props }) {
110
110
  return /* @__PURE__ */ jsxs(Combobox$1.Item, {
111
111
  "data-slot": "combobox-item",
112
- className: cn("data-highlighted:bg-highlight relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pr-8 pl-1.5 text-sm outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
112
+ className: cn("data-highlighted:bg-highlighted relative flex w-full cursor-clickable items-center gap-2 rounded-sm py-1 pr-8 pl-1.5 text-sm data-highlighted:outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
113
113
  ...props,
114
114
  children: [children, /* @__PURE__ */ jsx(Combobox$1.ItemIndicator, {
115
115
  render: /* @__PURE__ */ jsx("span", {
@@ -150,11 +150,11 @@ function ComboboxEmpty({ className, ...props }) {
150
150
  function ComboboxSeparator({ className, ...props }) {
151
151
  return /* @__PURE__ */ jsx(Combobox$1.Separator, {
152
152
  "data-slot": "combobox-separator",
153
- className: cn("bg-contour -mx-1 my-1 h-px", className),
153
+ className: cn("bg-line -mx-1 my-1 h-px", className),
154
154
  ...props
155
155
  });
156
156
  }
157
- const comboboxChipsVariants = cva("bg-shade hover:border-focus focus-within:border-focus focus-within:ring-focus/50 has-aria-invalid:ring-danger/30 has-aria-invalid:border-danger flex flex-wrap items-center gap-1 rounded-md border border-transparent motion-color focus-within:ring-3 has-aria-invalid:ring-3 has-data-[slot=combobox-chip]:px-1", {
157
+ const comboboxChipsVariants = cva("bg-neutral hover:border-focus focus-within:border-focus focus-within:ring-focus/50 has-aria-invalid:ring-danger/30 has-aria-invalid:border-danger flex flex-wrap items-center gap-1 rounded-md border border-transparent motion-color focus-within:ring-3 has-aria-invalid:ring-3 has-data-[slot=combobox-chip]:px-1", {
158
158
  variants: { size: {
159
159
  xs: "min-h-6 rounded-sm px-2 py-0.5 text-xs",
160
160
  sm: "min-h-8 px-3 py-1 text-sm",
@@ -191,7 +191,7 @@ function ComboboxChip({ className, children, showRemove = true, ...props }) {
191
191
  function ComboboxChipsInput({ className, ...props }) {
192
192
  return /* @__PURE__ */ jsx(Combobox$1.Input, {
193
193
  "data-slot": "combobox-chip-input",
194
- className: cn("min-w-16 flex-1 outline-hidden", className),
194
+ className: cn("min-w-16 flex-1 focus-visible:outline-hidden", className),
195
195
  ...props
196
196
  });
197
197
  }
@@ -40,7 +40,7 @@ type ContextMenuShortcutProps = React.ComponentProps<"span">;
40
40
  declare function ContextMenu(props: ContextMenuProps): React.JSX.Element;
41
41
  declare function ContextMenuPortal(props: ContextMenuPortalProps): React.JSX.Element;
42
42
  declare function ContextMenuTrigger({ className, ...props }: ContextMenuTriggerProps): React.JSX.Element;
43
- declare function ContextMenuContent({ className, align, alignOffset, side, sideOffset, restoreFocusOnClose, finalFocus, ...props }: ContextMenuContentProps): React.JSX.Element;
43
+ declare function ContextMenuContent({ className, align, alignOffset, side, sideOffset, restoreFocusOnClose, finalFocus, onKeyDown, children, ...props }: ContextMenuContentProps): React.JSX.Element;
44
44
  declare function ContextMenuGroup(props: ContextMenuGroupProps): React.JSX.Element;
45
45
  declare function ContextMenuLabel({ className, inset, ...props }: ContextMenuLabelProps): React.JSX.Element;
46
46
  declare function ContextMenuItem({ className, inset, variant, ...props }: ContextMenuItemProps): React.JSX.Element;
@@ -3,6 +3,7 @@ import { cn } from "./lib/utils.js";
3
3
  import { CheckIcon, ChevronRightIcon } from "./lib/internal-icons.js";
4
4
  import { resolveFinalFocus } from "./lib/focus.js";
5
5
  import { jsx, jsxs } from "react/jsx-runtime";
6
+ import * as React from "react";
6
7
  import { ContextMenu as ContextMenu$1 } from "@base-ui/react/context-menu";
7
8
  //#region src/context-menu.tsx
8
9
  function ContextMenu(props) {
@@ -24,19 +25,35 @@ function ContextMenuTrigger({ className, ...props }) {
24
25
  ...props
25
26
  });
26
27
  }
27
- function ContextMenuContent({ className, align = "start", alignOffset = 4, side = "inline-end", sideOffset = 0, restoreFocusOnClose, finalFocus, ...props }) {
28
+ function ContextMenuContent({ className, align = "start", alignOffset = 4, side = "inline-end", sideOffset = 0, restoreFocusOnClose, finalFocus, onKeyDown, children, ...props }) {
29
+ const listRef = React.useRef(null);
28
30
  return /* @__PURE__ */ jsx(ContextMenu$1.Portal, { children: /* @__PURE__ */ jsx(ContextMenu$1.Positioner, {
29
31
  "data-slot": "context-menu-positioner",
30
- className: "isolate z-50 outline-hidden",
32
+ className: "isolate z-50",
31
33
  align,
32
34
  alignOffset,
33
35
  side,
34
36
  sideOffset,
35
37
  children: /* @__PURE__ */ jsx(ContextMenu$1.Popup, {
36
38
  "data-slot": "context-menu-content",
37
- className: cn("motion-pop-md bg-elevated/80 not-supports-backdrop-filter:bg-elevated/90 text-contrast ring-contrast/10 z-50 max-h-(--available-height) min-w-48 overflow-x-hidden overflow-y-auto rounded-lg p-1.5 shadow-md ring-1 backdrop-blur-xl backdrop-saturate-150 outline-hidden", className),
39
+ className: cn("motion-pop-md bg-elevated/80 not-supports-backdrop-filter:bg-elevated/90 text-contrast border-edge z-50 flex max-h-(--available-height) min-w-48 flex-col overflow-hidden rounded-lg shadow-md border backdrop-blur-xl backdrop-saturate-150 focus-visible:outline-hidden", className),
38
40
  finalFocus: resolveFinalFocus(restoreFocusOnClose, finalFocus),
39
- ...props
41
+ onKeyDown: (event) => {
42
+ onKeyDown?.(event);
43
+ const list = listRef.current;
44
+ if (list && !event.defaultPrevented && event.target === event.currentTarget && (event.key === "PageDown" || event.key === "PageUp")) {
45
+ event.preventDefault();
46
+ const direction = event.key === "PageDown" ? 1 : -1;
47
+ list.scrollBy({ top: direction * list.clientHeight * .875 });
48
+ }
49
+ },
50
+ ...props,
51
+ children: /* @__PURE__ */ jsx("div", {
52
+ ref: listRef,
53
+ "data-slot": "context-menu-list",
54
+ className: "scroll-fade supports-[animation-timeline:scroll()]:scrollbar-none min-h-0 flex-1 overflow-x-hidden overflow-y-auto overscroll-contain p-1.5",
55
+ children
56
+ })
40
57
  })
41
58
  }) });
42
59
  }
@@ -59,7 +76,7 @@ function ContextMenuItem({ className, inset, variant = "default", ...props }) {
59
76
  "data-slot": "context-menu-item",
60
77
  "data-inset": inset,
61
78
  "data-variant": variant,
62
- className: cn("focus:bg-highlight data-[variant=danger]:text-danger data-[variant=danger]:*:[svg]:text-danger data-[variant=danger]:focus:bg-danger data-[variant=danger]:focus:text-white data-[variant=danger]:focus:**:text-white group/context-menu-item relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] px-3 py-2 text-sm font-medium outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
79
+ className: cn("focus:bg-highlighted data-[variant=danger]:text-danger data-[variant=danger]:*:[svg]:text-danger data-[variant=danger]:focus:bg-danger data-[variant=danger]:focus:text-white data-[variant=danger]:focus:**:text-white group/context-menu-item relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] px-3 py-2 text-sm font-medium focus:outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
63
80
  ...props
64
81
  });
65
82
  }
@@ -73,12 +90,12 @@ function ContextMenuSubTrigger({ className, inset, children, ...props }) {
73
90
  return /* @__PURE__ */ jsxs(ContextMenu$1.SubmenuTrigger, {
74
91
  "data-slot": "context-menu-sub-trigger",
75
92
  "data-inset": inset,
76
- className: cn("focus:bg-highlight data-popup-open:bg-highlight flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] px-3 py-2 text-sm font-medium outline-hidden select-none data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
93
+ className: cn("focus:bg-highlighted data-popup-open:bg-highlighted flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] px-3 py-2 text-sm font-medium focus:outline-hidden select-none data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
77
94
  ...props,
78
95
  children: [children, /* @__PURE__ */ jsx(ChevronRightIcon, { className: "ms-auto rtl:rotate-180" })]
79
96
  });
80
97
  }
81
- function ContextMenuSubContent({ align = "start", alignOffset = -6, side = "inline-end", sideOffset = 0, className, ...props }) {
98
+ function ContextMenuSubContent({ align = "start", alignOffset = -7, side = "inline-end", sideOffset = 0, className, ...props }) {
82
99
  return /* @__PURE__ */ jsx(ContextMenuContent, {
83
100
  "data-slot": "context-menu-sub-content",
84
101
  className: cn("w-auto min-w-24", className),
@@ -93,7 +110,7 @@ function ContextMenuCheckboxItem({ className, children, checked, inset, ...props
93
110
  return /* @__PURE__ */ jsxs(ContextMenu$1.CheckboxItem, {
94
111
  "data-slot": "context-menu-checkbox-item",
95
112
  "data-inset": inset,
96
- className: cn("focus:bg-highlight relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] py-2 pe-8 ps-3 text-sm font-medium outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
113
+ className: cn("focus:bg-highlighted relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] py-2 pe-8 ps-3 text-sm font-medium focus:outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
97
114
  checked,
98
115
  ...props,
99
116
  children: [/* @__PURE__ */ jsx("span", {
@@ -113,7 +130,7 @@ function ContextMenuRadioItem({ className, children, inset, ...props }) {
113
130
  return /* @__PURE__ */ jsxs(ContextMenu$1.RadioItem, {
114
131
  "data-slot": "context-menu-radio-item",
115
132
  "data-inset": inset,
116
- className: cn("focus:bg-highlight relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] py-2 pe-8 ps-3 text-sm font-medium outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
133
+ className: cn("focus:bg-highlighted relative flex cursor-clickable items-center gap-2.5 rounded-[calc(var(--radius)+var(--spacing)-var(--spacing)*1.5)] py-2 pe-8 ps-3 text-sm font-medium focus:outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-30 data-inset:ps-9.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className),
117
134
  ...props,
118
135
  children: [/* @__PURE__ */ jsx("span", {
119
136
  "data-slot": "context-menu-radio-item-indicator",
@@ -125,7 +142,7 @@ function ContextMenuRadioItem({ className, children, inset, ...props }) {
125
142
  function ContextMenuSeparator({ className, ...props }) {
126
143
  return /* @__PURE__ */ jsx(ContextMenu$1.Separator, {
127
144
  "data-slot": "context-menu-separator",
128
- className: cn("bg-contour -mx-1.5 my-1.5 h-px", className),
145
+ className: cn("bg-line -mx-1.5 my-1.5 h-px", className),
129
146
  ...props
130
147
  });
131
148
  }
package/dist/dialog.js CHANGED
@@ -40,7 +40,7 @@ function DialogOverlay({ className, ...props }) {
40
40
  function DialogContent({ className, children, showCloseButton = true, ...props }) {
41
41
  return /* @__PURE__ */ jsxs(DialogPortal, { children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(Dialog$1.Popup, {
42
42
  "data-slot": "dialog-content",
43
- className: cn("motion-scale-lg bg-foundation ring-contrast/10 fixed top-1/2 start-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 gap-6 rounded-lg p-6 text-sm ring-1 outline-hidden sm:max-w-sm shadow-lg", className),
43
+ className: cn("motion-scale-lg bg-foundation border-edge fixed top-1/2 start-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 rtl:translate-x-1/2 -translate-y-1/2 gap-6 rounded-lg p-6 text-sm border focus-visible:outline-hidden sm:max-w-sm shadow-lg", className),
44
44
  ...props,
45
45
  children: [children, showCloseButton && /* @__PURE__ */ jsxs(Dialog$1.Close, {
46
46
  "data-slot": "dialog-close",
package/dist/drawer.js CHANGED
@@ -39,14 +39,14 @@ function DrawerOverlay({ className, ...props }) {
39
39
  function DrawerViewport({ className, ...props }) {
40
40
  return /* @__PURE__ */ jsx(Drawer$1.Viewport, {
41
41
  "data-slot": "drawer-viewport",
42
- className: cn("fixed inset-0 z-50 outline-hidden", className),
42
+ className: cn("fixed inset-0 z-50 focus-visible:outline-hidden", className),
43
43
  ...props
44
44
  });
45
45
  }
46
46
  function DrawerContent({ className, children, showCloseButton = false, ...props }) {
47
47
  return /* @__PURE__ */ jsxs(DrawerPortal, { children: [/* @__PURE__ */ jsx(DrawerOverlay, {}), /* @__PURE__ */ jsx(DrawerViewport, { children: /* @__PURE__ */ jsxs(Drawer$1.Popup, {
48
48
  "data-slot": "drawer-content",
49
- className: cn("group/drawer-content bg-foundation fixed z-50 flex flex-col overflow-y-auto border-shade text-sm shadow-lg outline-hidden", "transition-[translate] duration-(--duration-lg) ease-(--ease) data-[swiping]:duration-0", "data-[swipe-direction=down]:inset-x-0 data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:mt-24 data-[swipe-direction=down]:max-h-[80vh] data-[swipe-direction=down]:rounded-t-lg data-[swipe-direction=down]:border-t", "data-[swipe-direction=up]:inset-x-0 data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:mb-24 data-[swipe-direction=up]:max-h-[80vh] data-[swipe-direction=up]:rounded-b-lg data-[swipe-direction=up]:border-b", "data-[swipe-direction=left]:inset-y-0 data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:w-3/4 data-[swipe-direction=left]:rounded-r-lg data-[swipe-direction=left]:border-r data-[swipe-direction=left]:sm:max-w-sm", "data-[swipe-direction=right]:inset-y-0 data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:w-3/4 data-[swipe-direction=right]:rounded-l-lg data-[swipe-direction=right]:border-l data-[swipe-direction=right]:sm:max-w-sm", "data-[swipe-direction=down]:data-[starting-style]:translate-y-full data-[swipe-direction=down]:data-[ending-style]:translate-y-full", "data-[swipe-direction=up]:data-[starting-style]:-translate-y-full data-[swipe-direction=up]:data-[ending-style]:-translate-y-full", "data-[swipe-direction=left]:data-[starting-style]:-translate-x-full data-[swipe-direction=left]:data-[ending-style]:-translate-x-full", "data-[swipe-direction=right]:data-[starting-style]:translate-x-full data-[swipe-direction=right]:data-[ending-style]:translate-x-full", className),
49
+ className: cn("group/drawer-content bg-foundation fixed z-50 flex flex-col overflow-y-auto border-contour text-sm shadow-lg focus-visible:outline-hidden", "transition-[translate] duration-(--duration-lg) ease-(--ease) data-[swiping]:duration-0", "data-[swipe-direction=down]:inset-x-0 data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:mt-24 data-[swipe-direction=down]:max-h-[80vh] data-[swipe-direction=down]:rounded-t-lg data-[swipe-direction=down]:border-t", "data-[swipe-direction=up]:inset-x-0 data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:mb-24 data-[swipe-direction=up]:max-h-[80vh] data-[swipe-direction=up]:rounded-b-lg data-[swipe-direction=up]:border-b", "data-[swipe-direction=left]:inset-y-0 data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:w-3/4 data-[swipe-direction=left]:rounded-r-lg data-[swipe-direction=left]:border-r data-[swipe-direction=left]:sm:max-w-sm", "data-[swipe-direction=right]:inset-y-0 data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:w-3/4 data-[swipe-direction=right]:rounded-l-lg data-[swipe-direction=right]:border-l data-[swipe-direction=right]:sm:max-w-sm", "data-[swipe-direction=down]:data-[starting-style]:translate-y-full data-[swipe-direction=down]:data-[ending-style]:translate-y-full", "data-[swipe-direction=up]:data-[starting-style]:-translate-y-full data-[swipe-direction=up]:data-[ending-style]:-translate-y-full", "data-[swipe-direction=left]:data-[starting-style]:-translate-x-full data-[swipe-direction=left]:data-[ending-style]:-translate-x-full", "data-[swipe-direction=right]:data-[starting-style]:translate-x-full data-[swipe-direction=right]:data-[ending-style]:translate-x-full", className),
50
50
  ...props,
51
51
  children: [
52
52
  /* @__PURE__ */ jsx("div", {
@@ -236,7 +236,7 @@ function GradientRevealText({ text, duration = 0, colors = DEFAULT_COLORS, baseO
236
236
  y: "50%",
237
237
  textAnchor: "middle",
238
238
  dominantBaseline: "central",
239
- className: baseColor ? "font-bold" : "font-bold stroke-contour",
239
+ className: baseColor ? "font-bold" : "font-bold stroke-line",
240
240
  style: {
241
241
  ...textStyle,
242
242
  ...baseColor ? { stroke: baseColor } : {},
@@ -6,7 +6,7 @@ import { Textarea } from "./textarea.js";
6
6
  import { jsx } from "react/jsx-runtime";
7
7
  import { cva } from "class-variance-authority";
8
8
  //#region src/input-group.tsx
9
- const inputGroupVariants = cva("bg-shade hover:border-focus has-[[data-slot=input-group-control]:focus-visible]:border-focus has-[[data-slot=input-group-control]:focus-visible]:ring-focus/50 has-[[data-slot][aria-invalid=true]]:ring-danger/30 has-[[data-slot][aria-invalid=true]]:border-danger group/input-group relative flex w-full min-w-0 items-center rounded-md border border-transparent motion-color outline-hidden in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:pointer-events-none has-disabled:opacity-30 not-has-disabled:has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3", {
9
+ const inputGroupVariants = cva("bg-neutral hover:border-focus has-[[data-slot=input-group-control]:focus-visible]:border-focus has-[[data-slot=input-group-control]:focus-visible]:ring-focus/50 has-[[data-slot][aria-invalid=true]]:ring-danger/30 has-[[data-slot][aria-invalid=true]]:border-danger group/input-group relative flex w-full min-w-0 items-center rounded-md border border-transparent motion-color has-disabled:pointer-events-none has-disabled:opacity-30 not-has-disabled:has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3", {
10
10
  variants: { size: {
11
11
  xs: "h-6 rounded-sm",
12
12
  sm: "h-8",
package/dist/input-otp.js CHANGED
@@ -26,7 +26,7 @@ function InputOTPSlot({ index, className, ...props }) {
26
26
  return /* @__PURE__ */ jsxs("div", {
27
27
  "data-slot": "input-otp-slot",
28
28
  "data-active": isActive || void 0,
29
- className: cn("border-shade relative flex size-9 items-center justify-center border-y border-r text-sm motion-color outline-hidden first:rounded-l-md first:border-l last:rounded-r-md", "data-active:border-focus data-active:ring-3 data-active:ring-focus/50 data-active:z-10", "group-has-aria-invalid/input-otp:border-danger group-has-aria-invalid/input-otp:data-active:ring-3 group-has-aria-invalid/input-otp:data-active:ring-danger/30", className),
29
+ className: cn("border-contour relative flex size-9 items-center justify-center border-y border-r text-sm motion-color data-active:outline-hidden first:rounded-l-md first:border-l last:rounded-r-md", "data-active:border-focus data-active:ring-3 data-active:ring-focus/50 data-active:z-10", "group-has-aria-invalid/input-otp:border-danger group-has-aria-invalid/input-otp:data-active:ring-3 group-has-aria-invalid/input-otp:data-active:ring-danger/30", className),
30
30
  ...props,
31
31
  children: [char, hasFakeCaret && /* @__PURE__ */ jsx("div", {
32
32
  className: "pointer-events-none absolute inset-0 flex items-center justify-center",
package/dist/input.js CHANGED
@@ -3,7 +3,7 @@ import { jsx } from "react/jsx-runtime";
3
3
  import { cva } from "class-variance-authority";
4
4
  import { Input as Input$1 } from "@base-ui/react/input";
5
5
  //#region src/input.tsx
6
- const inputVariants = cva("bg-shade hover:border-focus focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 aria-invalid:border-danger placeholder:text-soft flex w-full min-w-0 items-center overflow-hidden rounded-md border border-transparent motion-color outline-hidden file:inline-flex file:my-[3px] file:items-center file:me-3 file:cursor-clickable file:rounded-md file:border-0 file:bg-primary file:px-2.5 file:leading-none file:font-medium file:text-white file:motion-color file:hover:bg-primary/80 focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 aria-invalid:ring-3", {
6
+ const inputVariants = cva("bg-neutral hover:border-focus focus-visible:border-focus focus-visible:ring-focus/50 aria-invalid:ring-danger/30 aria-invalid:border-danger placeholder:text-subtle flex w-full min-w-0 items-center overflow-hidden rounded-md border border-transparent motion-color focus-visible:outline-hidden file:inline-flex file:my-[3px] file:items-center file:me-3 file:cursor-clickable file:rounded-md file:border-0 file:bg-primary file:px-2.5 file:leading-none file:font-medium file:text-white file:motion-color file:hover:bg-primary/80 focus-visible:ring-3 data-disabled:pointer-events-none data-disabled:opacity-30 aria-invalid:ring-3", {
7
7
  variants: { size: {
8
8
  xs: "h-6 rounded-sm px-2 text-xs file:-ms-[5px] file:h-4",
9
9
  sm: "h-8 px-3 text-sm file:-ms-[9px] file:h-6",