@waveso/ui 0.16.0 → 0.18.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
@@ -83,20 +83,31 @@ Wave pays close attention to token taxonomy. Surfaces encode elevation; borders
83
83
 
84
84
  - `--contrast` — titles, primary text
85
85
  - `--muted` — body text, icons, any mark
86
- - `--soft` — placeholders, hints
86
+ - `--subtle` — placeholders, hints
87
87
 
88
- ### Form
88
+ ### Lines and fills
89
89
 
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.
90
+ The theme's foreground made translucent, so each reads the same on any surface, and each keeps one job.
91
91
 
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)
92
+ Lines:
93
+
94
+ - `--line` (5%) — what divides: separators, dividers, hairlines
95
+ - `--edge` (10%) — what bounds a surface: cards, dialogs, popups, toasts
96
+ - `--contour` (15%) — what outlines a control or a region: outline buttons, badges, toggles, layout regions
97
+
98
+ Fills:
99
+
100
+ - `--highlighted` (10%) — where attention lands: hovered, keyboard-highlighted and open items
101
+ - `--neutral` (15%) — what gives a control its body, its look before anything is chosen: field and track fills, unchecked boxes. Not Tailwind's `neutral-*` grey palette, which Wave doesn't use
95
102
 
96
103
  ### Ring
97
104
 
98
105
  - `--focus` — active / focus states
99
106
 
107
+ ### Selected
108
+
109
+ - `--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
110
+
100
111
  ### Brand
101
112
 
102
113
  - `--primary` — wired to the Wave ramp
@@ -107,7 +118,7 @@ The theme's foreground made translucent, at three strengths — the way a draugh
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-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 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",
package/dist/item.js CHANGED
@@ -7,11 +7,11 @@ import { cva } from "class-variance-authority";
7
7
  import { mergeProps } from "@base-ui/react/merge-props";
8
8
  import { useRender } from "@base-ui/react/use-render";
9
9
  //#region src/item.tsx
10
- const itemVariants = cva("[a,button]:hover:bg-highlight [a,button]:cursor-clickable rounded-md border text-sm w-full group/item focus-visible:border-focus focus-visible:ring-focus/50 flex items-center flex-wrap outline-hidden motion-color focus-visible:ring-3 disabled:pointer-events-none disabled:opacity-30 aria-disabled:pointer-events-none aria-disabled:opacity-30", {
10
+ const itemVariants = cva("[a,button]:hover:bg-highlighted [a,button]:cursor-clickable rounded-md border text-sm w-full group/item focus-visible:border-focus focus-visible:ring-focus/50 flex items-center flex-wrap focus-visible:outline-hidden motion-color focus-visible:ring-3 disabled:pointer-events-none disabled:opacity-30 aria-disabled:pointer-events-none aria-disabled:opacity-30", {
11
11
  variants: {
12
12
  variant: {
13
13
  default: "border-transparent",
14
- outline: "border-contour",
14
+ outline: "border-line",
15
15
  muted: "bg-secondary/50 border-transparent [a,button]:hover:bg-secondary"
16
16
  },
17
17
  size: {
package/dist/menu.d.ts CHANGED
@@ -40,7 +40,7 @@ type MenuShortcutProps = React.ComponentProps<"span">;
40
40
  declare function Menu(props: MenuProps): React.JSX.Element;
41
41
  declare function MenuPortal(props: MenuPortalProps): React.JSX.Element;
42
42
  declare function MenuTrigger(props: MenuTriggerProps): React.JSX.Element;
43
- declare function MenuContent({ align, alignOffset, side, sideOffset, className, restoreFocusOnClose, finalFocus, ...props }: MenuContentProps): React.JSX.Element;
43
+ declare function MenuContent({ align, alignOffset, side, sideOffset, className, restoreFocusOnClose, finalFocus, onKeyDown, children, ...props }: MenuContentProps): React.JSX.Element;
44
44
  declare function MenuGroup(props: MenuGroupProps): React.JSX.Element;
45
45
  declare function MenuLabel({ className, inset, ...props }: MenuLabelProps): React.JSX.Element;
46
46
  declare function MenuItem({ className, inset, variant, ...props }: MenuItemProps): React.JSX.Element;