@brijbyte/agentic-ui 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/README.md +280 -53
  2. package/dist/accordion/accordion.d.ts +14 -0
  3. package/dist/accordion/accordion.d.ts.map +1 -1
  4. package/dist/accordion/accordion.js +5 -0
  5. package/dist/accordion/accordion.js.map +1 -1
  6. package/dist/accordion/index.d.ts +2 -2
  7. package/dist/accordion/index.js +2 -2
  8. package/dist/accordion/parts.d.ts +6 -14
  9. package/dist/accordion/parts.d.ts.map +1 -1
  10. package/dist/accordion/parts.js +7 -6
  11. package/dist/accordion/parts.js.map +1 -1
  12. package/dist/alert-dialog/alert-dialog.d.ts +11 -0
  13. package/dist/alert-dialog/alert-dialog.d.ts.map +1 -1
  14. package/dist/alert-dialog/alert-dialog.js +5 -0
  15. package/dist/alert-dialog/alert-dialog.js.map +1 -1
  16. package/dist/alert-dialog/parts.d.ts +4 -12
  17. package/dist/alert-dialog/parts.d.ts.map +1 -1
  18. package/dist/alert-dialog/parts.js +17 -19
  19. package/dist/alert-dialog/parts.js.map +1 -1
  20. package/dist/badge/badge.d.ts +6 -0
  21. package/dist/badge/badge.d.ts.map +1 -1
  22. package/dist/badge/badge.js +4 -0
  23. package/dist/badge/badge.js.map +1 -1
  24. package/dist/button/button.d.ts +12 -1
  25. package/dist/button/button.d.ts.map +1 -1
  26. package/dist/button/button.js +5 -0
  27. package/dist/button/button.js.map +1 -1
  28. package/dist/card/card.d.ts +10 -0
  29. package/dist/card/card.d.ts.map +1 -1
  30. package/dist/card/card.js +7 -0
  31. package/dist/card/card.js.map +1 -1
  32. package/dist/checkbox/checkbox.d.ts +13 -0
  33. package/dist/checkbox/checkbox.d.ts.map +1 -1
  34. package/dist/checkbox/checkbox.js +4 -0
  35. package/dist/checkbox/checkbox.js.map +1 -1
  36. package/dist/checkbox/parts.d.ts +2 -5
  37. package/dist/checkbox/parts.d.ts.map +1 -1
  38. package/dist/checkbox/parts.js +3 -2
  39. package/dist/checkbox/parts.js.map +1 -1
  40. package/dist/collapsible/collapsible.d.ts +11 -0
  41. package/dist/collapsible/collapsible.d.ts.map +1 -1
  42. package/dist/collapsible/collapsible.js +5 -0
  43. package/dist/collapsible/collapsible.js.map +1 -1
  44. package/dist/collapsible/parts.d.ts +3 -9
  45. package/dist/collapsible/parts.d.ts.map +1 -1
  46. package/dist/collapsible/parts.js +7 -6
  47. package/dist/collapsible/parts.js.map +1 -1
  48. package/dist/context-menu/context-menu.d.ts +5 -0
  49. package/dist/context-menu/context-menu.d.ts.map +1 -1
  50. package/dist/context-menu/context-menu.js +4 -0
  51. package/dist/context-menu/context-menu.js.map +1 -1
  52. package/dist/context-menu/parts.d.ts +6 -18
  53. package/dist/context-menu/parts.d.ts.map +1 -1
  54. package/dist/context-menu/parts.js +16 -16
  55. package/dist/context-menu/parts.js.map +1 -1
  56. package/dist/dialog/dialog.d.ts +13 -1
  57. package/dist/dialog/dialog.d.ts.map +1 -1
  58. package/dist/dialog/dialog.js +6 -0
  59. package/dist/dialog/dialog.js.map +1 -1
  60. package/dist/dialog/parts.d.ts +6 -18
  61. package/dist/dialog/parts.d.ts.map +1 -1
  62. package/dist/dialog/parts.js +8 -9
  63. package/dist/dialog/parts.js.map +1 -1
  64. package/dist/drawer/drawer.d.ts +11 -0
  65. package/dist/drawer/drawer.d.ts.map +1 -1
  66. package/dist/drawer/drawer.js +5 -0
  67. package/dist/drawer/drawer.js.map +1 -1
  68. package/dist/drawer/parts.d.ts +7 -19
  69. package/dist/drawer/parts.d.ts.map +1 -1
  70. package/dist/drawer/parts.js +14 -13
  71. package/dist/drawer/parts.js.map +1 -1
  72. package/dist/index.css +1580 -1150
  73. package/dist/index.d.ts +20 -11
  74. package/dist/index.js +15 -2
  75. package/dist/input/input.d.ts +8 -0
  76. package/dist/input/input.d.ts.map +1 -1
  77. package/dist/input/input.js +5 -0
  78. package/dist/input/input.js.map +1 -1
  79. package/dist/menu/menu.css +3 -8
  80. package/dist/menu/menu.d.ts +11 -4
  81. package/dist/menu/menu.d.ts.map +1 -1
  82. package/dist/menu/menu.js +10 -24
  83. package/dist/menu/menu.js.map +1 -1
  84. package/dist/menu/menu.module.js +1 -1
  85. package/dist/menu/menu.module.js.map +1 -1
  86. package/dist/menu/parts.d.ts +6 -18
  87. package/dist/menu/parts.d.ts.map +1 -1
  88. package/dist/menu/parts.js +7 -6
  89. package/dist/menu/parts.js.map +1 -1
  90. package/dist/meter/circular-meter.d.ts +48 -0
  91. package/dist/meter/circular-meter.d.ts.map +1 -0
  92. package/dist/meter/circular-meter.js +86 -0
  93. package/dist/meter/circular-meter.js.map +1 -0
  94. package/dist/meter/index.d.ts +4 -0
  95. package/dist/meter/index.js +5 -0
  96. package/dist/meter/meter.css +152 -0
  97. package/dist/meter/meter.d.ts +58 -0
  98. package/dist/meter/meter.d.ts.map +1 -0
  99. package/dist/meter/meter.js +50 -0
  100. package/dist/meter/meter.js.map +1 -0
  101. package/dist/meter/meter.module.css.d.ts +2 -0
  102. package/dist/meter/meter.module.js +27 -0
  103. package/dist/meter/meter.module.js.map +1 -0
  104. package/dist/meter/meterState.js +18 -0
  105. package/dist/meter/meterState.js.map +1 -0
  106. package/dist/meter/parts.d.ts +25 -0
  107. package/dist/meter/parts.d.ts.map +1 -0
  108. package/dist/meter/parts.js +57 -0
  109. package/dist/meter/parts.js.map +1 -0
  110. package/dist/number-field/number-field.d.ts +16 -0
  111. package/dist/number-field/number-field.d.ts.map +1 -1
  112. package/dist/number-field/number-field.js +4 -0
  113. package/dist/number-field/number-field.js.map +1 -1
  114. package/dist/number-field/parts.d.ts +6 -18
  115. package/dist/number-field/parts.d.ts.map +1 -1
  116. package/dist/number-field/parts.js +7 -6
  117. package/dist/number-field/parts.js.map +1 -1
  118. package/dist/popover/index.d.ts +3 -0
  119. package/dist/popover/index.js +4 -0
  120. package/dist/popover/parts.d.ts +29 -0
  121. package/dist/popover/parts.d.ts.map +1 -0
  122. package/dist/popover/parts.js +93 -0
  123. package/dist/popover/parts.js.map +1 -0
  124. package/dist/popover/popover.css +173 -0
  125. package/dist/popover/popover.d.ts +49 -0
  126. package/dist/popover/popover.d.ts.map +1 -0
  127. package/dist/popover/popover.js +68 -0
  128. package/dist/popover/popover.js.map +1 -0
  129. package/dist/popover/popover.module.css.d.ts +2 -0
  130. package/dist/popover/popover.module.js +16 -0
  131. package/dist/popover/popover.module.js.map +1 -0
  132. package/dist/progress/parts.d.ts +2 -4
  133. package/dist/progress/parts.d.ts.map +1 -1
  134. package/dist/progress/parts.js +3 -6
  135. package/dist/progress/parts.js.map +1 -1
  136. package/dist/progress/progress.d.ts +11 -0
  137. package/dist/progress/progress.d.ts.map +1 -1
  138. package/dist/progress/progress.js +5 -0
  139. package/dist/progress/progress.js.map +1 -1
  140. package/dist/radio/index.d.ts +3 -0
  141. package/dist/radio/index.js +4 -0
  142. package/dist/radio/parts.d.ts +14 -0
  143. package/dist/radio/parts.d.ts.map +1 -0
  144. package/dist/radio/parts.js +43 -0
  145. package/dist/radio/parts.js.map +1 -0
  146. package/dist/radio/radio.css +84 -0
  147. package/dist/radio/radio.d.ts +31 -0
  148. package/dist/radio/radio.d.ts.map +1 -0
  149. package/dist/radio/radio.js +33 -0
  150. package/dist/radio/radio.js.map +1 -0
  151. package/dist/radio/radio.module.css.d.ts +2 -0
  152. package/dist/radio/radio.module.js +11 -0
  153. package/dist/radio/radio.module.js.map +1 -0
  154. package/dist/radio-group/index.d.ts +3 -0
  155. package/dist/radio-group/index.js +4 -0
  156. package/dist/radio-group/parts.d.ts +11 -0
  157. package/dist/radio-group/parts.d.ts.map +1 -0
  158. package/dist/radio-group/parts.js +32 -0
  159. package/dist/radio-group/parts.js.map +1 -0
  160. package/dist/radio-group/radio-group.css +17 -0
  161. package/dist/radio-group/radio-group.d.ts +37 -0
  162. package/dist/radio-group/radio-group.d.ts.map +1 -0
  163. package/dist/radio-group/radio-group.js +28 -0
  164. package/dist/radio-group/radio-group.js.map +1 -0
  165. package/dist/radio-group/radio-group.module.css.d.ts +2 -0
  166. package/dist/radio-group/radio-group.module.js +9 -0
  167. package/dist/radio-group/radio-group.module.js.map +1 -0
  168. package/dist/reset-scoped.css +112 -0
  169. package/dist/select/parts.d.ts +11 -32
  170. package/dist/select/parts.d.ts.map +1 -1
  171. package/dist/select/parts.js +10 -9
  172. package/dist/select/parts.js.map +1 -1
  173. package/dist/select/select.d.ts +14 -1
  174. package/dist/select/select.d.ts.map +1 -1
  175. package/dist/select/select.js +4 -0
  176. package/dist/select/select.js.map +1 -1
  177. package/dist/separator/separator.d.ts +4 -0
  178. package/dist/separator/separator.d.ts.map +1 -1
  179. package/dist/separator/separator.js +4 -0
  180. package/dist/separator/separator.js.map +1 -1
  181. package/dist/shared/PopupArrow.js +22 -0
  182. package/dist/shared/PopupArrow.js.map +1 -0
  183. package/dist/slider/parts.d.ts +6 -18
  184. package/dist/slider/parts.d.ts.map +1 -1
  185. package/dist/slider/parts.js +7 -6
  186. package/dist/slider/parts.js.map +1 -1
  187. package/dist/slider/slider.d.ts +18 -0
  188. package/dist/slider/slider.d.ts.map +1 -1
  189. package/dist/slider/slider.js +6 -0
  190. package/dist/slider/slider.js.map +1 -1
  191. package/dist/switch/parts.d.ts +2 -6
  192. package/dist/switch/parts.d.ts.map +1 -1
  193. package/dist/switch/parts.js +3 -2
  194. package/dist/switch/parts.js.map +1 -1
  195. package/dist/switch/switch.css +11 -2
  196. package/dist/switch/switch.d.ts +12 -0
  197. package/dist/switch/switch.d.ts.map +1 -1
  198. package/dist/switch/switch.js +4 -0
  199. package/dist/switch/switch.js.map +1 -1
  200. package/dist/switch/switch.module.js.map +1 -1
  201. package/dist/tabs/parts.d.ts +3 -9
  202. package/dist/tabs/parts.d.ts.map +1 -1
  203. package/dist/tabs/parts.js +4 -3
  204. package/dist/tabs/parts.js.map +1 -1
  205. package/dist/tabs/tabs.d.ts +8 -1
  206. package/dist/tabs/tabs.d.ts.map +1 -1
  207. package/dist/tabs/tabs.js +4 -0
  208. package/dist/tabs/tabs.js.map +1 -1
  209. package/dist/toast/parts.d.ts +5 -15
  210. package/dist/toast/parts.d.ts.map +1 -1
  211. package/dist/toast/parts.js +6 -5
  212. package/dist/toast/parts.js.map +1 -1
  213. package/dist/toast/toast.d.ts +11 -0
  214. package/dist/toast/toast.d.ts.map +1 -1
  215. package/dist/toast/toast.js +8 -0
  216. package/dist/toast/toast.js.map +1 -1
  217. package/dist/tooltip/parts.d.ts +3 -9
  218. package/dist/tooltip/parts.d.ts.map +1 -1
  219. package/dist/tooltip/parts.js +4 -3
  220. package/dist/tooltip/parts.js.map +1 -1
  221. package/dist/tooltip/tooltip.d.ts +9 -0
  222. package/dist/tooltip/tooltip.d.ts.map +1 -1
  223. package/dist/tooltip/tooltip.js +4 -0
  224. package/dist/tooltip/tooltip.js.map +1 -1
  225. package/dist/utils/resolveClassName.js +25 -0
  226. package/dist/utils/resolveClassName.js.map +1 -0
  227. package/package.json +25 -4
  228. package/src/accordion/accordion.tsx +14 -0
  229. package/src/accordion/index.ts +1 -1
  230. package/src/accordion/parts.tsx +10 -17
  231. package/src/alert-dialog/alert-dialog.tsx +11 -0
  232. package/src/alert-dialog/parts.tsx +23 -31
  233. package/src/badge/badge.tsx +6 -0
  234. package/src/button/button.tsx +12 -1
  235. package/src/card/card.tsx +10 -0
  236. package/src/checkbox/checkbox.tsx +13 -0
  237. package/src/checkbox/parts.tsx +5 -7
  238. package/src/collapsible/collapsible.tsx +11 -0
  239. package/src/collapsible/parts.tsx +10 -15
  240. package/src/context-menu/context-menu.tsx +5 -0
  241. package/src/context-menu/parts.tsx +34 -34
  242. package/src/dialog/dialog.tsx +13 -1
  243. package/src/dialog/parts.tsx +14 -27
  244. package/src/drawer/drawer.tsx +11 -0
  245. package/src/drawer/parts.tsx +30 -38
  246. package/src/index.ts +4 -0
  247. package/src/input/input.tsx +8 -0
  248. package/src/menu/menu.module.css +3 -10
  249. package/src/menu/menu.tsx +13 -26
  250. package/src/menu/parts.tsx +13 -24
  251. package/src/meter/circular-meter.tsx +114 -0
  252. package/src/meter/index.ts +9 -0
  253. package/src/meter/meter.module.css +162 -0
  254. package/src/meter/meter.tsx +86 -0
  255. package/src/meter/meterState.ts +29 -0
  256. package/src/meter/parts.tsx +73 -0
  257. package/src/number-field/number-field.tsx +16 -0
  258. package/src/number-field/parts.tsx +33 -24
  259. package/src/popover/index.ts +14 -0
  260. package/src/popover/parts.tsx +105 -0
  261. package/src/popover/popover.module.css +189 -0
  262. package/src/popover/popover.tsx +80 -0
  263. package/src/progress/parts.tsx +13 -6
  264. package/src/progress/progress.tsx +11 -0
  265. package/src/radio/index.ts +6 -0
  266. package/src/radio/parts.tsx +42 -0
  267. package/src/radio/radio.module.css +96 -0
  268. package/src/radio/radio.tsx +37 -0
  269. package/src/radio-group/index.ts +5 -0
  270. package/src/radio-group/parts.tsx +31 -0
  271. package/src/radio-group/radio-group.module.css +17 -0
  272. package/src/radio-group/radio-group.tsx +63 -0
  273. package/src/select/parts.tsx +34 -41
  274. package/src/select/select.tsx +14 -1
  275. package/src/separator/separator.tsx +4 -0
  276. package/src/shared/PopupArrow.tsx +41 -0
  277. package/src/slider/parts.tsx +13 -24
  278. package/src/slider/slider.tsx +18 -0
  279. package/src/styles/reset-scoped.css +112 -0
  280. package/src/switch/parts.tsx +5 -8
  281. package/src/switch/switch.module.css +11 -2
  282. package/src/switch/switch.tsx +12 -0
  283. package/src/tabs/parts.tsx +7 -12
  284. package/src/tabs/tabs.tsx +8 -1
  285. package/src/toast/parts.tsx +11 -20
  286. package/src/toast/toast.tsx +11 -0
  287. package/src/tooltip/parts.tsx +7 -12
  288. package/src/tooltip/tooltip.tsx +9 -0
  289. package/src/utils/resolveClassName.ts +24 -0
@@ -0,0 +1,96 @@
1
+ @layer components {
2
+ /* ── Single radio item layout ───────────────────────────────────── */
3
+
4
+ .item {
5
+ display: flex;
6
+ align-items: center;
7
+ gap: var(--space-2);
8
+ cursor: pointer;
9
+ user-select: none;
10
+ }
11
+
12
+ .item:has([data-disabled]) {
13
+ cursor: not-allowed;
14
+ }
15
+
16
+ .item:has([data-disabled]) .label {
17
+ opacity: 0.44;
18
+ }
19
+
20
+ /* ── Radio button (the circle) ──────────────────────────────────── */
21
+
22
+ .radio {
23
+ flex-shrink: 0;
24
+ width: 16px;
25
+ height: 16px;
26
+ border-radius: var(--radius-full);
27
+ border: var(--border-width-base) solid var(--color-line-strong);
28
+ background-color: var(--color-surface-1);
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ transition:
33
+ background-color var(--duration-fast) var(--easing-standard),
34
+ border-color var(--duration-fast) var(--easing-standard),
35
+ box-shadow var(--duration-fast) var(--easing-standard);
36
+ outline: none;
37
+ position: relative;
38
+ /* Reset button/span defaults */
39
+ padding: 0;
40
+ margin: 0;
41
+ }
42
+
43
+ .radio:focus-visible {
44
+ box-shadow: var(--shadow-focus);
45
+ border-color: var(--color-accent);
46
+ }
47
+
48
+ .radio:hover:not([data-disabled]) {
49
+ border-color: var(--color-accent);
50
+ }
51
+
52
+ .radio[data-checked] {
53
+ background-color: var(--color-accent);
54
+ border-color: var(--color-accent);
55
+ }
56
+
57
+ .radio[data-checked]:hover:not([data-disabled]) {
58
+ background-color: var(--color-accent-hover);
59
+ border-color: var(--color-accent-hover);
60
+ }
61
+
62
+ .radio[data-disabled] {
63
+ opacity: 0.44;
64
+ cursor: not-allowed;
65
+ pointer-events: none;
66
+ }
67
+
68
+ /* ── Indicator (inner dot) ──────────────────────────────────────── */
69
+
70
+ .indicator {
71
+ width: 6px;
72
+ height: 6px;
73
+ border-radius: var(--radius-full);
74
+ background-color: var(--color-on-accent);
75
+ transform: scale(0);
76
+ transition:
77
+ transform var(--duration-fast) var(--easing-spring),
78
+ opacity var(--duration-fast) var(--easing-standard);
79
+ opacity: 0;
80
+ }
81
+
82
+ /* data-checked is on the Root; the Indicator inherits it */
83
+ .radio[data-checked] .indicator {
84
+ transform: scale(1);
85
+ opacity: 1;
86
+ }
87
+
88
+ /* ── Label text ─────────────────────────────────────────────────── */
89
+
90
+ .label {
91
+ font-family: var(--font-mono);
92
+ font-size: var(--font-size-sm);
93
+ color: var(--color-primary);
94
+ line-height: var(--line-height-normal);
95
+ }
96
+ }
@@ -0,0 +1,37 @@
1
+ import { useId } from "react";
2
+ import type { ReactNode } from "react";
3
+ import { Radio as BaseRadio } from "@base-ui/react/radio";
4
+ import styles from "./radio.module.css";
5
+
6
+ export interface RadioProps {
7
+ /** Value submitted with the form and matched against the group's value. */
8
+ value: string;
9
+ /** Label rendered next to the button. */
10
+ children?: ReactNode;
11
+ disabled?: boolean;
12
+ readOnly?: boolean;
13
+ required?: boolean;
14
+ /** Override the auto-generated element id. */
15
+ id?: string;
16
+ className?: string;
17
+ }
18
+
19
+ /**
20
+ * A single radio button with an optional label.
21
+ * Must be placed inside `<RadioGroup>` or a raw base-ui RadioGroup.
22
+ */
23
+ export function Radio({ value, children, id, className, ...props }: RadioProps) {
24
+ // eslint-disable-next-line react-hooks/rules-of-hooks
25
+ const radioId = id ?? useId();
26
+
27
+ return (
28
+ <label className={`${styles.item} ${className ?? ""}`} htmlFor={radioId}>
29
+ <BaseRadio.Root id={radioId} value={value} className={styles.radio} {...props}>
30
+ <BaseRadio.Indicator keepMounted className={styles.indicator} />
31
+ </BaseRadio.Root>
32
+ {children && <span className={styles.label}>{children}</span>}
33
+ </label>
34
+ );
35
+ }
36
+
37
+ export { styles as RadioStyles };
@@ -0,0 +1,5 @@
1
+ export { RadioGroup, RadioGroupStyles } from "./radio-group";
2
+ export type { RadioGroupProps, RadioOption } from "./radio-group";
3
+
4
+ export { RadioGroupRoot } from "./parts";
5
+ export type { RadioGroupRootProps } from "./parts";
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Styled primitive for RadioGroup.
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * import { Radio } from '@brijbyte/agentic-ui/radio';
7
+ * import { RadioGroupRoot } from '@brijbyte/agentic-ui/radio-group';
8
+ *
9
+ * <RadioGroupRoot defaultValue="b" name="plan">
10
+ * <Radio value="a">Hobby</Radio>
11
+ * <Radio value="b">Pro</Radio>
12
+ * <Radio value="c">Enterprise</Radio>
13
+ * </RadioGroupRoot>
14
+ * ```
15
+ */
16
+ import { forwardRef } from "react";
17
+ import type { ComponentRef, ComponentPropsWithoutRef } from "react";
18
+ import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
19
+ import styles from "./radio-group.module.css";
20
+ import { resolveClassName, cx } from "../utils/resolveClassName";
21
+
22
+ type BaseGroupProps = ComponentPropsWithoutRef<typeof BaseRadioGroup>;
23
+
24
+ export interface RadioGroupRootProps extends BaseGroupProps {}
25
+
26
+ export const RadioGroupRoot = forwardRef<ComponentRef<typeof BaseRadioGroup>, RadioGroupRootProps>(function RadioGroupRoot(
27
+ { className, ...props },
28
+ ref,
29
+ ) {
30
+ return <BaseRadioGroup ref={ref} className={(state) => cx(styles.group, resolveClassName(className, state))} {...props} />;
31
+ });
@@ -0,0 +1,17 @@
1
+ @layer components {
2
+ .group {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--space-2);
6
+ }
7
+
8
+ .group-label {
9
+ font-family: var(--font-mono);
10
+ font-size: var(--font-size-xs);
11
+ font-weight: var(--font-weight-semibold);
12
+ color: var(--color-tertiary);
13
+ text-transform: uppercase;
14
+ letter-spacing: var(--letter-spacing-wide);
15
+ margin-bottom: var(--space-1);
16
+ }
17
+ }
@@ -0,0 +1,63 @@
1
+ import { useId } from "react";
2
+ import type { ReactNode } from "react";
3
+ import { RadioGroup as BaseRadioGroup } from "@base-ui/react/radio-group";
4
+ import { Radio } from "../radio/radio";
5
+ import styles from "./radio-group.module.css";
6
+
7
+ export interface RadioOption {
8
+ value: string;
9
+ label: ReactNode;
10
+ disabled?: boolean;
11
+ }
12
+
13
+ export interface RadioGroupProps {
14
+ /** The options to render. Each becomes one `<Radio>` item. */
15
+ options: RadioOption[];
16
+ /** Accessible group label rendered above the options. */
17
+ label?: ReactNode;
18
+ /** Controlled selected value. */
19
+ value?: string;
20
+ /** Initial selected value (uncontrolled). */
21
+ defaultValue?: string;
22
+ onValueChange?: (value: string, eventDetails: unknown) => void;
23
+ disabled?: boolean;
24
+ readOnly?: boolean;
25
+ required?: boolean;
26
+ /** HTML name for form submission. */
27
+ name?: string;
28
+ className?: string;
29
+ }
30
+
31
+ /**
32
+ * A labelled group of radio buttons. Renders a base-ui RadioGroup with one
33
+ * `<Radio>` per option.
34
+ *
35
+ * For full control over layout or behaviour use `RadioGroupRoot` with
36
+ * individual `<Radio>` or `<RadioRoot>` elements.
37
+ */
38
+ export { styles as RadioGroupStyles };
39
+
40
+ export function RadioGroup({ options, label, className, onValueChange, ...props }: RadioGroupProps) {
41
+ // eslint-disable-next-line react-hooks/rules-of-hooks
42
+ const labelId = useId();
43
+
44
+ return (
45
+ <BaseRadioGroup
46
+ aria-labelledby={label ? labelId : undefined}
47
+ className={`${styles.group} ${className ?? ""}`}
48
+ onValueChange={onValueChange as never}
49
+ {...props}
50
+ >
51
+ {label && (
52
+ <div id={labelId} className={styles["group-label"]}>
53
+ {label}
54
+ </div>
55
+ )}
56
+ {options.map((opt) => (
57
+ <Radio key={opt.value} value={opt.value} {...(opt.disabled !== undefined && { disabled: opt.disabled })}>
58
+ {opt.label}
59
+ </Radio>
60
+ ))}
61
+ </BaseRadioGroup>
62
+ );
63
+ }
@@ -33,6 +33,7 @@ import { forwardRef } from "react";
33
33
  import type { ComponentRef, ComponentPropsWithoutRef, ReactNode } from "react";
34
34
  import { Select as BaseSelect } from "@base-ui/react/select";
35
35
  import styles from "./select.module.css";
36
+ import { resolveClassName, cx } from "../utils/resolveClassName";
36
37
 
37
38
  type BaseTriggerProps = ComponentPropsWithoutRef<typeof BaseSelect.Trigger>;
38
39
  type BaseValueProps = ComponentPropsWithoutRef<typeof BaseSelect.Value>;
@@ -46,41 +47,20 @@ type BaseGroupProps = ComponentPropsWithoutRef<typeof BaseSelect.Group>;
46
47
  type BaseGroupLabelProps = ComponentPropsWithoutRef<typeof BaseSelect.GroupLabel>;
47
48
  type BaseSeparatorProps = ComponentPropsWithoutRef<typeof BaseSelect.Separator>;
48
49
 
49
- export interface SelectTriggerProps extends Omit<BaseTriggerProps, "className"> {
50
- className?: string;
51
- }
52
- export interface SelectValueProps extends Omit<BaseValueProps, "className"> {
53
- className?: string;
54
- }
55
- export interface SelectPositionerProps extends Omit<BasePositionerProps, "className"> {
56
- className?: string;
57
- }
58
- export interface SelectPopupProps extends Omit<BasePopupProps, "className"> {
59
- className?: string;
60
- }
61
- export interface SelectListProps extends Omit<BaseListProps, "className"> {
62
- className?: string;
63
- }
64
- export interface SelectItemProps extends Omit<BaseItemProps, "className"> {
65
- className?: string;
66
- }
67
- export interface SelectItemTextProps extends Omit<BaseItemTextProps, "className"> {
68
- className?: string;
69
- }
70
- export interface SelectItemIndicatorProps extends Omit<BaseItemIndicatorProps, "className"> {
71
- className?: string;
50
+ export interface SelectTriggerProps extends BaseTriggerProps {}
51
+ export interface SelectValueProps extends BaseValueProps {}
52
+ export interface SelectPositionerProps extends BasePositionerProps {}
53
+ export interface SelectPopupProps extends BasePopupProps {}
54
+ export interface SelectListProps extends BaseListProps {}
55
+ export interface SelectItemProps extends BaseItemProps {}
56
+ export interface SelectItemTextProps extends BaseItemTextProps {}
57
+ export interface SelectItemIndicatorProps extends BaseItemIndicatorProps {
72
58
  /** Custom icon. Defaults to a checkmark SVG. */
73
59
  children?: ReactNode;
74
60
  }
75
- export interface SelectGroupProps extends Omit<BaseGroupProps, "className"> {
76
- className?: string;
77
- }
78
- export interface SelectGroupLabelProps extends Omit<BaseGroupLabelProps, "className"> {
79
- className?: string;
80
- }
81
- export interface SelectSeparatorProps extends Omit<BaseSeparatorProps, "className"> {
82
- className?: string;
83
- }
61
+ export interface SelectGroupProps extends BaseGroupProps {}
62
+ export interface SelectGroupLabelProps extends BaseGroupLabelProps {}
63
+ export interface SelectSeparatorProps extends BaseSeparatorProps {}
84
64
 
85
65
  function DefaultCheckIcon() {
86
66
  return (
@@ -94,42 +74,49 @@ export const SelectTrigger = forwardRef<ComponentRef<typeof BaseSelect.Trigger>,
94
74
  { className, ...props },
95
75
  ref,
96
76
  ) {
97
- return <BaseSelect.Trigger ref={ref} className={`${styles.trigger} ${className ?? ""}`} {...props} />;
77
+ return <BaseSelect.Trigger ref={ref} className={(state) => cx(styles.trigger, resolveClassName(className, state))} {...props} />;
98
78
  });
99
79
 
100
80
  export const SelectValue = forwardRef<ComponentRef<typeof BaseSelect.Value>, SelectValueProps>(function SelectValue(
101
81
  { className, ...props },
102
82
  ref,
103
83
  ) {
104
- return <BaseSelect.Value ref={ref} className={`${styles["trigger-value"]} ${className ?? ""}`} {...props} />;
84
+ return <BaseSelect.Value ref={ref} className={(state) => cx(styles["trigger-value"], resolveClassName(className, state))} {...props} />;
105
85
  });
106
86
 
107
87
  export const SelectPositioner = forwardRef<ComponentRef<typeof BaseSelect.Positioner>, SelectPositionerProps>(function SelectPositioner(
108
88
  { className, sideOffset = 4, ...props },
109
89
  ref,
110
90
  ) {
111
- return <BaseSelect.Positioner ref={ref} className={`${styles.positioner} ${className ?? ""}`} sideOffset={sideOffset} {...props} />;
91
+ return (
92
+ <BaseSelect.Positioner
93
+ ref={ref}
94
+ className={(state) => cx(styles.positioner, resolveClassName(className, state))}
95
+ sideOffset={sideOffset}
96
+ {...props}
97
+ />
98
+ );
112
99
  });
113
100
 
114
101
  export const SelectPopup = forwardRef<ComponentRef<typeof BaseSelect.Popup>, SelectPopupProps>(function SelectPopup(
115
102
  { className, ...props },
116
103
  ref,
117
104
  ) {
118
- return <BaseSelect.Popup ref={ref} className={`${styles.popup} ${className ?? ""}`} {...props} />;
105
+ return <BaseSelect.Popup ref={ref} className={(state) => cx(styles.popup, resolveClassName(className, state))} {...props} />;
119
106
  });
120
107
 
121
108
  export const SelectList = forwardRef<ComponentRef<typeof BaseSelect.List>, SelectListProps>(function SelectList(
122
109
  { className, ...props },
123
110
  ref,
124
111
  ) {
125
- return <BaseSelect.List ref={ref} className={`${styles.list ?? ""} ${className ?? ""}`} {...props} />;
112
+ return <BaseSelect.List ref={ref} className={(state) => cx(styles.list ?? "", resolveClassName(className, state))} {...props} />;
126
113
  });
127
114
 
128
115
  export const SelectItem = forwardRef<ComponentRef<typeof BaseSelect.Item>, SelectItemProps>(function SelectItem(
129
116
  { className, ...props },
130
117
  ref,
131
118
  ) {
132
- return <BaseSelect.Item ref={ref} className={`${styles.item} ${className ?? ""}`} {...props} />;
119
+ return <BaseSelect.Item ref={ref} className={(state) => cx(styles.item, resolveClassName(className, state))} {...props} />;
133
120
  });
134
121
 
135
122
  export const SelectItemText = forwardRef<ComponentRef<typeof BaseSelect.ItemText>, SelectItemTextProps>(function SelectItemText(
@@ -142,7 +129,11 @@ export const SelectItemText = forwardRef<ComponentRef<typeof BaseSelect.ItemText
142
129
  export const SelectItemIndicator = forwardRef<ComponentRef<typeof BaseSelect.ItemIndicator>, SelectItemIndicatorProps>(
143
130
  function SelectItemIndicator({ className, children, ...props }, ref) {
144
131
  return (
145
- <BaseSelect.ItemIndicator ref={ref} className={`${styles["item-indicator"]} ${className ?? ""}`} {...props}>
132
+ <BaseSelect.ItemIndicator
133
+ ref={ref}
134
+ className={(state) => cx(styles["item-indicator"], resolveClassName(className, state))}
135
+ {...props}
136
+ >
146
137
  {children ?? <DefaultCheckIcon />}
147
138
  </BaseSelect.ItemIndicator>
148
139
  );
@@ -160,12 +151,14 @@ export const SelectGroupLabel = forwardRef<ComponentRef<typeof BaseSelect.GroupL
160
151
  { className, ...props },
161
152
  ref,
162
153
  ) {
163
- return <BaseSelect.GroupLabel ref={ref} className={`${styles["group-label"]} ${className ?? ""}`} {...props} />;
154
+ return (
155
+ <BaseSelect.GroupLabel ref={ref} className={(state) => cx(styles["group-label"], resolveClassName(className, state))} {...props} />
156
+ );
164
157
  });
165
158
 
166
159
  export const SelectSeparator = forwardRef<ComponentRef<typeof BaseSelect.Separator>, SelectSeparatorProps>(function SelectSeparator(
167
160
  { className, ...props },
168
161
  ref,
169
162
  ) {
170
- return <BaseSelect.Separator ref={ref} className={`${styles.separator} ${className ?? ""}`} {...props} />;
163
+ return <BaseSelect.Separator ref={ref} className={(state) => cx(styles.separator, resolveClassName(className, state))} {...props} />;
171
164
  });
@@ -14,17 +14,26 @@ export interface SelectGroup {
14
14
  }
15
15
 
16
16
  export interface SelectProps {
17
+ /** Currently selected value (controlled). */
17
18
  value?: string;
19
+ /** Initially selected value (uncontrolled). */
18
20
  defaultValue?: string;
19
- /** `eventDetails` is the base-ui event details object. Value may be null when cleared. */
21
+ /** Called when the selection changes. `eventDetails` is the base-ui event details object. Value may be null when cleared. */
20
22
  onValueChange?: (value: string | null, eventDetails: unknown) => void;
23
+ /** Prevent interaction. */
21
24
  disabled?: boolean;
25
+ /** Mark the field as required for form validation. */
22
26
  required?: boolean;
27
+ /** HTML name attribute for form submission. */
23
28
  name?: string;
29
+ /** Text shown when no value is selected. */
24
30
  placeholder?: string;
31
+ /** Flat list of options (use `groups` for grouped options). */
25
32
  options?: SelectOption[];
33
+ /** Grouped options with optional section labels. */
26
34
  groups?: SelectGroup[];
27
35
  className?: string;
36
+ /** Override the auto-generated element id. */
28
37
  id?: string;
29
38
  }
30
39
 
@@ -55,6 +64,10 @@ function SelectItem({ option }: { option: SelectOption }) {
55
64
  );
56
65
  }
57
66
 
67
+ /**
68
+ * Dropdown select with keyboard navigation, grouping, and search. Pass
69
+ * `options` for a flat list or `groups` for sections with optional labels.
70
+ */
58
71
  export function Select({ placeholder = "Select…", options, groups, className, onValueChange, value, defaultValue, ...props }: SelectProps) {
59
72
  const allOptions = useMemo(() => [...(options ?? []), ...(groups?.flatMap((g) => g.options) ?? [])], [options, groups]);
60
73
 
@@ -11,6 +11,10 @@ export interface SeparatorProps extends Omit<BaseSeparatorProps, "className"> {
11
11
  className?: string;
12
12
  }
13
13
 
14
+ /**
15
+ * A semantic divider accessible to screen readers. Renders a horizontal
16
+ * line by default; switch to vertical for inline layouts.
17
+ */
14
18
  export const Separator = forwardRef<ComponentRef<typeof BaseSeparator>, SeparatorProps>(function Separator(
15
19
  { className, orientation = "horizontal", ...props },
16
20
  ref,
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Shared arrow SVG used by Menu and Popover.
3
+ *
4
+ * Two paths:
5
+ * 1. Fill — the arrow body, matches the popup surface colour.
6
+ * 2. Seam — a thin strip in the border colour at the base, covering
7
+ * the popup border at the junction so it doesn't bleed through.
8
+ *
9
+ * All CSS classes come from the importing component's own CSS module
10
+ * so the rules are bundled into the component's CSS file, not a
11
+ * separate shared chunk that consumers would need to import separately.
12
+ *
13
+ * @example
14
+ * ```tsx
15
+ * <BaseMenu.Arrow className={styles.arrow}>
16
+ * <PopupArrow fillClass={styles["arrow-fill"]!} seamClass={styles["arrow-seam"]!} />
17
+ * </BaseMenu.Arrow>
18
+ * ```
19
+ */
20
+
21
+ interface PopupArrowProps {
22
+ fillClass: string;
23
+ seamClass: string;
24
+ }
25
+
26
+ export function PopupArrow({ fillClass, seamClass }: PopupArrowProps) {
27
+ return (
28
+ <svg width="20" height="10" viewBox="0 0 20 10" fill="none" aria-hidden>
29
+ {/* Body — surface colour */}
30
+ <path
31
+ d="M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z"
32
+ className={fillClass}
33
+ />
34
+ {/* Seam — border colour strip at the base, covers the popup border at the junction */}
35
+ <path
36
+ d="M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z"
37
+ className={seamClass}
38
+ />
39
+ </svg>
40
+ );
41
+ }
@@ -20,6 +20,7 @@ import { forwardRef } from "react";
20
20
  import type { ComponentRef, ComponentPropsWithoutRef } from "react";
21
21
  import { Slider as BaseSlider } from "@base-ui/react/slider";
22
22
  import styles from "./slider.module.css";
23
+ import { resolveClassName, cx } from "../utils/resolveClassName";
23
24
 
24
25
  type BaseControlProps = ComponentPropsWithoutRef<typeof BaseSlider.Control>;
25
26
  type BaseTrackProps = ComponentPropsWithoutRef<typeof BaseSlider.Track>;
@@ -28,63 +29,51 @@ type BaseThumbProps = ComponentPropsWithoutRef<typeof BaseSlider.Thumb>;
28
29
  type BaseLabelProps = ComponentPropsWithoutRef<typeof BaseSlider.Label>;
29
30
  type BaseValueProps = ComponentPropsWithoutRef<typeof BaseSlider.Value>;
30
31
 
31
- export interface SliderControlProps extends Omit<BaseControlProps, "className"> {
32
- className?: string;
33
- }
34
- export interface SliderTrackProps extends Omit<BaseTrackProps, "className"> {
35
- className?: string;
36
- }
37
- export interface SliderIndicatorProps extends Omit<BaseIndicatorProps, "className"> {
38
- className?: string;
39
- }
40
- export interface SliderThumbProps extends Omit<BaseThumbProps, "className"> {
41
- className?: string;
42
- }
43
- export interface SliderLabelProps extends Omit<BaseLabelProps, "className"> {
44
- className?: string;
45
- }
46
- export interface SliderValueProps extends Omit<BaseValueProps, "className"> {
47
- className?: string;
48
- }
32
+ export interface SliderControlProps extends BaseControlProps {}
33
+ export interface SliderTrackProps extends BaseTrackProps {}
34
+ export interface SliderIndicatorProps extends BaseIndicatorProps {}
35
+ export interface SliderThumbProps extends BaseThumbProps {}
36
+ export interface SliderLabelProps extends BaseLabelProps {}
37
+ export interface SliderValueProps extends BaseValueProps {}
49
38
 
50
39
  export const SliderControl = forwardRef<ComponentRef<typeof BaseSlider.Control>, SliderControlProps>(function SliderControl(
51
40
  { className, ...props },
52
41
  ref,
53
42
  ) {
54
- return <BaseSlider.Control ref={ref} className={`${styles.control} ${className ?? ""}`} {...props} />;
43
+ return <BaseSlider.Control ref={ref} className={(state) => cx(styles.control, resolveClassName(className, state))} {...props} />;
55
44
  });
56
45
 
57
46
  export const SliderTrack = forwardRef<ComponentRef<typeof BaseSlider.Track>, SliderTrackProps>(function SliderTrack(
58
47
  { className, ...props },
59
48
  ref,
60
49
  ) {
61
- return <BaseSlider.Track ref={ref} className={`${styles.track} ${className ?? ""}`} {...props} />;
50
+ return <BaseSlider.Track ref={ref} className={(state) => cx(styles.track, resolveClassName(className, state))} {...props} />;
62
51
  });
63
52
 
64
53
  export const SliderIndicator = forwardRef<ComponentRef<typeof BaseSlider.Indicator>, SliderIndicatorProps>(function SliderIndicator(
65
54
  { className, ...props },
66
55
  ref,
67
56
  ) {
68
- return <BaseSlider.Indicator ref={ref} className={`${styles.indicator} ${className ?? ""}`} {...props} />;
57
+ return <BaseSlider.Indicator ref={ref} className={(state) => cx(styles.indicator, resolveClassName(className, state))} {...props} />;
69
58
  });
70
59
 
71
60
  export const SliderThumb = forwardRef<ComponentRef<typeof BaseSlider.Thumb>, SliderThumbProps>(function SliderThumb(
72
61
  { className, ...props },
73
62
  ref,
74
63
  ) {
75
- return <BaseSlider.Thumb ref={ref} className={`${styles.thumb} ${className ?? ""}`} {...props} />;
64
+ return <BaseSlider.Thumb ref={ref} className={(state) => cx(styles.thumb, resolveClassName(className, state))} {...props} />;
76
65
  });
77
66
 
78
67
  export const SliderLabel = forwardRef<ComponentRef<typeof BaseSlider.Label>, SliderLabelProps>(function SliderLabel(
79
68
  { className, ...props },
80
69
  ref,
81
70
  ) {
82
- return <BaseSlider.Label ref={ref} className={`${styles.label} ${className ?? ""}`} {...props} />;
71
+ return <BaseSlider.Label ref={ref} className={(state) => cx(styles.label, resolveClassName(className, state))} {...props} />;
83
72
  });
84
73
 
85
74
  export const SliderValue = forwardRef<ComponentRef<typeof BaseSlider.Value>, SliderValueProps>(function SliderValue(
86
75
  { className, ...props },
87
76
  ref,
88
77
  ) {
89
- return <BaseSlider.Value ref={ref} className={`${styles.value} ${className ?? ""}`} {...props} />;
78
+ return <BaseSlider.Value ref={ref} className={(state) => cx(styles.value, resolveClassName(className, state))} {...props} />;
90
79
  });
@@ -3,17 +3,29 @@ import { Slider as BaseSlider } from "@base-ui/react/slider";
3
3
  import styles from "./slider.module.css";
4
4
 
5
5
  export interface SliderProps {
6
+ /** Current value (controlled). Pass an array for range sliders. */
6
7
  value?: number | number[];
8
+ /** Initial value (uncontrolled). Pass an array for range sliders. */
7
9
  defaultValue?: number | number[];
10
+ /** Called on every value change while dragging. */
8
11
  onValueChange?: (value: number | number[], eventDetails: unknown) => void;
12
+ /** Called once when the user finishes dragging. */
9
13
  onValueCommitted?: (value: number | number[], eventDetails: unknown) => void;
14
+ /** Minimum allowed value. @default 0 */
10
15
  min?: number;
16
+ /** Maximum allowed value. @default 100 */
11
17
  max?: number;
18
+ /** Step increment. @default 1 */
12
19
  step?: number;
20
+ /** Step used for Page Up / Page Down keyboard shortcuts. @default 10 */
13
21
  largeStep?: number;
22
+ /** Prevent interaction. */
14
23
  disabled?: boolean;
24
+ /** HTML name attribute for form submission. */
15
25
  name?: string;
26
+ /** Axis direction. @default "horizontal" */
16
27
  orientation?: "horizontal" | "vertical";
28
+ /** `Intl.NumberFormatOptions` for value display formatting. */
17
29
  format?: Intl.NumberFormatOptions;
18
30
  /** Visible label rendered above the track. */
19
31
  label?: ReactNode;
@@ -24,6 +36,12 @@ export interface SliderProps {
24
36
  className?: string;
25
37
  }
26
38
 
39
+ /**
40
+ * An accessible range input with full keyboard and touch support. Pass a
41
+ * single number for a standard slider or an array for a range slider with
42
+ * two thumbs. Supports steps, large steps (Page Up/Down), and
43
+ * `Intl.NumberFormat` display formatting.
44
+ */
27
45
  export function Slider({
28
46
  label,
29
47
  showValue = false,