@xingxingmofashu/ui 0.1.2 → 0.1.3

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 (50) hide show
  1. package/README.md +21 -6
  2. package/dist/components/accordion.d.ts +14 -10
  3. package/dist/components/accordion.mjs +78 -20
  4. package/dist/components/alert-dialog.d.ts +7 -2
  5. package/dist/components/alert-dialog.mjs +74 -33
  6. package/dist/components/button.d.ts +6 -2
  7. package/dist/components/button.mjs +20 -11
  8. package/dist/components/card.d.ts +6 -1
  9. package/dist/components/card.mjs +27 -4
  10. package/dist/components/checkbox.d.ts +5 -1
  11. package/dist/components/checkbox.mjs +53 -14
  12. package/dist/components/dialog.d.ts +7 -2
  13. package/dist/components/dialog.mjs +66 -20
  14. package/dist/components/drawer.d.ts +7 -2
  15. package/dist/components/drawer.mjs +66 -20
  16. package/dist/components/input.d.ts +5 -1
  17. package/dist/components/input.mjs +60 -33
  18. package/dist/components/popover.d.ts +7 -2
  19. package/dist/components/popover.mjs +53 -14
  20. package/dist/components/progress.d.ts +21 -0
  21. package/dist/components/progress.mjs +71 -0
  22. package/dist/components/scroll-area.d.ts +7 -2
  23. package/dist/components/scroll-area.mjs +48 -14
  24. package/dist/components/slider.d.ts +7 -2
  25. package/dist/components/slider.mjs +38 -22
  26. package/dist/components/switch.d.ts +5 -1
  27. package/dist/components/switch.mjs +47 -23
  28. package/dist/components/toast.d.ts +6 -1
  29. package/dist/components/toast.mjs +68 -15
  30. package/dist/components/toggle-group.d.ts +11 -5
  31. package/dist/components/toggle-group.mjs +54 -6
  32. package/dist/components/toggle.d.ts +5 -1
  33. package/dist/components/toggle.mjs +36 -5
  34. package/dist/index.css +1 -1
  35. package/dist/index.d.ts +1 -0
  36. package/dist/index.mjs +1 -0
  37. package/dist/internal/tv.d.ts +17 -0
  38. package/dist/internal/tv.mjs +0 -0
  39. package/dist/keyframes.css +1 -1
  40. package/dist/theme/alert-dialog.mjs +1 -1
  41. package/dist/theme/checkbox.mjs +4 -4
  42. package/dist/theme/dialog.mjs +1 -1
  43. package/dist/theme/drawer.mjs +1 -1
  44. package/dist/theme/popover.mjs +2 -2
  45. package/dist/theme/progress.d.ts +80 -0
  46. package/dist/theme/progress.mjs +64 -0
  47. package/dist/theme/slider.mjs +8 -0
  48. package/dist/theme/switch.mjs +2 -0
  49. package/dist/theme/toast.mjs +1 -1
  50. package/package.json +7 -2
package/README.md CHANGED
@@ -15,24 +15,40 @@
15
15
  </div>
16
16
 
17
17
  `@xingxingmofashu/ui` is a collection of accessible, typed [React](https://react.dev)
18
- components with a Liquid Glass visual style, built on [Base UI](https://base-ui.com),
19
- [Tailwind CSS](https://tailwindcss.com), and
18
+ components with a Liquid Glass visual style, built with
19
+ [Tailwind CSS](https://tailwindcss.com) and
20
20
  [Tailwind Variants](https://www.tailwind-variants.org). Glass surfaces, rim
21
21
  highlights, and inner shadows are drawn entirely with CSS.
22
22
 
23
- The package ships fifteen components: Accordion, Alert Dialog, Button, Card,
24
- Checkbox, Dialog, Drawer, Input, Popover, Scroll Area, Slider, Switch, Toast,
25
- Toggle, and Toggle Group.
23
+ The package ships sixteen components: Accordion, Alert Dialog, Button, Card,
24
+ Checkbox, Dialog, Drawer, Input, Popover, Progress, Scroll Area, Slider, Switch,
25
+ Toast, Toggle, and Toggle Group.
26
26
 
27
27
  > [!NOTE]
28
28
  > Requires React 19, React DOM 19, Tailwind CSS 4, Node.js 22+, and an
29
29
  > ESM-capable bundler. `Card` is server-safe; the interactive components are
30
30
  > client components.
31
31
 
32
+ ## Preview
33
+
34
+ <picture>
35
+ <source media="(prefers-color-scheme: dark)" srcset=".github/assets/playground-dark.png">
36
+ <source media="(prefers-color-scheme: light)" srcset=".github/assets/playground-light.png">
37
+ <img alt="The Liquid Glass playground showing live component previews in light mode." width="1440" src=".github/assets/playground-light.png">
38
+ </picture>
39
+
40
+ Every component is rendered live in the local playground. Run
41
+ `pnpm playground:dev`, open <http://localhost:3002>, and switch between light and
42
+ dark to compare the same previews in both themes.
43
+
32
44
  ## Documentation
33
45
 
34
46
  - [English](https://xingxingmofashu.github.io/ui/docs/en/get-started/introduction)
35
47
  - [简体中文](https://xingxingmofashu.github.io/ui/docs/zh/get-started/introduction)
48
+ - [llms.txt](https://xingxingmofashu.github.io/ui/llms.txt) — a compact index for
49
+ language models and agents
50
+ - [llms-full.txt](https://xingxingmofashu.github.io/ui/llms-full.txt) — every
51
+ guide and component page in one file
36
52
 
37
53
  ## Installation
38
54
 
@@ -169,7 +185,6 @@ a reproduction. Before opening a pull request, run `pnpm lint`, `pnpm test`, and
169
185
 
170
186
  ## Credits
171
187
 
172
- - [Base UI](https://base-ui.com)
173
188
  - [Tailwind CSS](https://tailwindcss.com)
174
189
  - [Tailwind Variants](https://www.tailwind-variants.org)
175
190
 
@@ -1,28 +1,32 @@
1
1
  import { Accordion as UIAccordion } from "@base-ui/react/accordion";
2
2
  import * as React from "react";
3
3
  import { type VariantProps } from "tailwind-variants";
4
+ import { type ComponentConfig } from "../internal/tv";
4
5
  import theme from "../theme/accordion";
6
+ type Accordion = ComponentConfig<typeof theme>;
5
7
  /** One panel managed by the accordion. */
6
- type AccordionItemProps = {
8
+ type AccordionItemProps<Value extends string = string> = Omit<UIAccordion.Item.Props, "children" | "className" | "style" | "title" | "value"> & {
7
9
  /** Value that identifies the item in the accordion value. */
8
- value: string;
10
+ value: Value;
9
11
  /** Visible heading inside the trigger. */
10
12
  title: React.ReactNode;
11
13
  /** Panel content. */
12
14
  content?: React.ReactNode;
13
- /** Disables this item. */
14
- disabled?: boolean;
15
- /** Called when this panel opens or closes. */
16
- onOpenChange?: UIAccordion.Item.Props["onOpenChange"];
15
+ /** Replaces the default plus icon. Set to `false` to hide the indicator. */
16
+ indicator?: React.ReactNode | false;
17
17
  /** Tailwind classes merged into the item root. */
18
- className?: any;
18
+ className?: string;
19
+ /** Tailwind classes for this item's internal slots, keyed by `data-slot`. */
20
+ ui?: Partial<Pick<Accordion["slots"], "item" | "header" | "trigger" | "title" | "indicator" | "indicatorIcon" | "panel" | "panelContent">>;
19
21
  };
20
22
  type AccordionProps<Value extends string = string> = Omit<UIAccordion.Root.Props<Value>, "className" | "style" | "children"> & VariantProps<typeof theme> & {
21
23
  /** Panels rendered by the accordion. */
22
- items: readonly AccordionItemProps[];
24
+ items: readonly AccordionItemProps<Value>[];
23
25
  /** Tailwind classes merged into the root. */
24
- className?: any;
26
+ className?: string;
27
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
28
+ ui?: Accordion["slots"];
25
29
  };
26
- declare function Accordion<Value extends string = string>({ className, size, items, ...props }: AccordionProps<Value>): React.JSX.Element;
30
+ declare function Accordion<Value extends string = string>({ className, ui, size, items, ...props }: AccordionProps<Value>): React.JSX.Element;
27
31
  export { Accordion };
28
32
  export type { AccordionItemProps, AccordionProps };
@@ -6,27 +6,52 @@ import theme from "../theme/accordion.mjs";
6
6
  import { PlusIcon } from "./icons/plus.mjs";
7
7
  function Accordion({
8
8
  className,
9
+ ui,
9
10
  size,
10
11
  items,
11
12
  ...props
12
13
  }) {
13
- const ui = theme({ size });
14
+ const styles = theme({ size });
14
15
  return /* @__PURE__ */ React.createElement(
15
16
  UIAccordion.Root,
16
17
  {
17
18
  ...props,
18
19
  "data-slot": "root",
19
- className: cn(ui.root(), className)
20
+ className: cn(styles.root(), ui?.root, className)
20
21
  },
21
- /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true", "data-slot": "glass", className: ui.glass() }, /* @__PURE__ */ React.createElement(
22
+ /* @__PURE__ */ React.createElement(
22
23
  "span",
23
24
  {
24
25
  "aria-hidden": "true",
25
- "data-slot": "overlay",
26
- className: ui.overlay()
26
+ "data-slot": "glass",
27
+ className: cn(styles.glass(), ui?.glass)
28
+ },
29
+ /* @__PURE__ */ React.createElement(
30
+ "span",
31
+ {
32
+ "aria-hidden": "true",
33
+ "data-slot": "overlay",
34
+ className: cn(styles.overlay(), ui?.overlay)
35
+ }
36
+ )
37
+ ),
38
+ /* @__PURE__ */ React.createElement("div", { "data-slot": "content", className: cn(styles.content(), ui?.content) }, items.map((item) => /* @__PURE__ */ React.createElement(
39
+ AccordionItem,
40
+ {
41
+ key: item.value,
42
+ ...item,
43
+ ui: {
44
+ item: cn(ui?.item, item.ui?.item),
45
+ header: cn(ui?.header, item.ui?.header),
46
+ trigger: cn(ui?.trigger, item.ui?.trigger),
47
+ title: cn(ui?.title, item.ui?.title),
48
+ indicator: cn(ui?.indicator, item.ui?.indicator),
49
+ indicatorIcon: cn(ui?.indicatorIcon, item.ui?.indicatorIcon),
50
+ panel: cn(ui?.panel, item.ui?.panel),
51
+ panelContent: cn(ui?.panelContent, item.ui?.panelContent)
52
+ }
27
53
  }
28
- )),
29
- /* @__PURE__ */ React.createElement("div", { "data-slot": "content", className: ui.content() }, items.map((item) => /* @__PURE__ */ React.createElement(AccordionItem, { key: item.value, ...item })))
54
+ )))
30
55
  );
31
56
  }
32
57
  function AccordionItem({
@@ -34,33 +59,66 @@ function AccordionItem({
34
59
  title,
35
60
  content,
36
61
  className,
62
+ ui,
63
+ indicator,
64
+ ref,
37
65
  ...props
38
66
  }) {
39
- const ui = theme();
67
+ const styles = theme();
40
68
  return /* @__PURE__ */ React.createElement(
41
69
  UIAccordion.Item,
42
70
  {
43
71
  ...props,
72
+ ref,
44
73
  value,
45
74
  "data-slot": "item",
46
- className: cn(ui.item(), className)
75
+ className: cn(styles.item(), ui?.item, className)
47
76
  },
48
- /* @__PURE__ */ React.createElement(UIAccordion.Header, { "data-slot": "header", className: ui.header() }, /* @__PURE__ */ React.createElement(UIAccordion.Trigger, { "data-slot": "trigger", className: ui.trigger() }, /* @__PURE__ */ React.createElement("span", { "data-slot": "title", className: ui.title() }, title), /* @__PURE__ */ React.createElement(
49
- "span",
77
+ /* @__PURE__ */ React.createElement(
78
+ UIAccordion.Header,
50
79
  {
51
- "aria-hidden": "true",
52
- "data-slot": "indicator",
53
- className: ui.indicator()
80
+ "data-slot": "header",
81
+ className: cn(styles.header(), ui?.header)
54
82
  },
55
83
  /* @__PURE__ */ React.createElement(
56
- PlusIcon,
84
+ UIAccordion.Trigger,
57
85
  {
58
- "data-slot": "indicator-icon",
59
- className: ui.indicatorIcon()
60
- }
86
+ "data-slot": "trigger",
87
+ className: cn(styles.trigger(), ui?.trigger)
88
+ },
89
+ /* @__PURE__ */ React.createElement("span", { "data-slot": "title", className: cn(styles.title(), ui?.title) }, title),
90
+ indicator === false ? null : /* @__PURE__ */ React.createElement(
91
+ "span",
92
+ {
93
+ "aria-hidden": "true",
94
+ "data-slot": "indicator",
95
+ className: cn(styles.indicator(), ui?.indicator)
96
+ },
97
+ indicator === void 0 ? /* @__PURE__ */ React.createElement(
98
+ PlusIcon,
99
+ {
100
+ "data-slot": "indicator-icon",
101
+ className: cn(styles.indicatorIcon(), ui?.indicatorIcon)
102
+ }
103
+ ) : indicator
104
+ )
105
+ )
106
+ ),
107
+ /* @__PURE__ */ React.createElement(
108
+ UIAccordion.Panel,
109
+ {
110
+ "data-slot": "panel",
111
+ className: cn(styles.panel(), ui?.panel)
112
+ },
113
+ /* @__PURE__ */ React.createElement(
114
+ "div",
115
+ {
116
+ "data-slot": "panel-content",
117
+ className: cn(styles.panelContent(), ui?.panelContent)
118
+ },
119
+ content
61
120
  )
62
- ))),
63
- /* @__PURE__ */ React.createElement(UIAccordion.Panel, { "data-slot": "panel", className: ui.panel() }, /* @__PURE__ */ React.createElement("div", { "data-slot": "panel-content", className: ui.panelContent() }, content))
121
+ )
64
122
  );
65
123
  }
66
124
  export { Accordion };
@@ -1,5 +1,8 @@
1
1
  import { AlertDialog as UIAlertDialog } from "@base-ui/react/alert-dialog";
2
2
  import * as React from "react";
3
+ import { type ComponentConfig } from "../internal/tv";
4
+ import theme from "../theme/alert-dialog";
5
+ type AlertDialog = ComponentConfig<typeof theme>;
3
6
  type AlertDialogProps = Omit<UIAlertDialog.Root.Props, "children"> & {
4
7
  /** Dialog heading. */
5
8
  title: React.ReactNode;
@@ -16,8 +19,10 @@ type AlertDialogProps = Omit<UIAlertDialog.Root.Props, "children"> & {
16
19
  /** Called when the confirm button is pressed. */
17
20
  onConfirm?: React.MouseEventHandler<HTMLButtonElement>;
18
21
  /** Tailwind classes merged into the popup. */
19
- className?: any;
22
+ className?: string;
23
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
24
+ ui?: AlertDialog["slots"];
20
25
  };
21
- declare function AlertDialog({ title, description, children, cancelLabel, confirmLabel, onCancel, onConfirm, className, ...props }: AlertDialogProps): React.JSX.Element;
26
+ declare function AlertDialog({ title, description, children, cancelLabel, confirmLabel, onCancel, onConfirm, className, ui, ...props }: AlertDialogProps): React.JSX.Element;
22
27
  export { AlertDialog };
23
28
  export type { AlertDialogProps };
@@ -13,49 +13,90 @@ function AlertDialog({
13
13
  onCancel,
14
14
  onConfirm,
15
15
  className,
16
+ ui,
16
17
  ...props
17
18
  }) {
18
- const ui = theme();
19
+ const styles = theme();
19
20
  return /* @__PURE__ */ React.createElement(UIAlertDialog.Root, { ...props }, /* @__PURE__ */ React.createElement(UIAlertDialog.Portal, null, /* @__PURE__ */ React.createElement(
20
21
  UIAlertDialog.Backdrop,
21
22
  {
22
23
  "data-slot": "backdrop",
23
- className: ui.backdrop()
24
+ className: cn(styles.backdrop(), ui?.backdrop)
24
25
  }
25
- ), /* @__PURE__ */ React.createElement(UIAlertDialog.Viewport, { "data-slot": "viewport", className: ui.viewport() }, /* @__PURE__ */ React.createElement(
26
- UIAlertDialog.Popup,
26
+ ), /* @__PURE__ */ React.createElement(
27
+ UIAlertDialog.Viewport,
27
28
  {
28
- "data-slot": "popup",
29
- className: cn(ui.popup(), className)
29
+ "data-slot": "viewport",
30
+ className: cn(styles.viewport(), ui?.viewport)
30
31
  },
31
- /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true", "data-slot": "glass", className: ui.glass() }, /* @__PURE__ */ React.createElement(
32
- "span",
32
+ /* @__PURE__ */ React.createElement(
33
+ UIAlertDialog.Popup,
33
34
  {
34
- "aria-hidden": "true",
35
- "data-slot": "overlay",
36
- className: ui.overlay()
37
- }
38
- )),
39
- /* @__PURE__ */ React.createElement("div", { "data-slot": "content", className: ui.content() }, /* @__PURE__ */ React.createElement(UIAlertDialog.Title, { "data-slot": "title", className: ui.title() }, title), description ? /* @__PURE__ */ React.createElement(
40
- UIAlertDialog.Description,
41
- {
42
- "data-slot": "description",
43
- className: ui.description()
35
+ "data-slot": "popup",
36
+ className: cn(styles.popup(), ui?.popup, className)
44
37
  },
45
- description
46
- ) : null, children ? /* @__PURE__ */ React.createElement("div", { "data-slot": "body", className: ui.body() }, children) : null, /* @__PURE__ */ React.createElement("div", { "data-slot": "footer", className: ui.footer() }, /* @__PURE__ */ React.createElement(
47
- UIAlertDialog.Close,
48
- {
49
- onClick: onCancel,
50
- render: /* @__PURE__ */ React.createElement(Button, { label: cancelLabel })
51
- }
52
- ), /* @__PURE__ */ React.createElement(
53
- UIAlertDialog.Close,
54
- {
55
- onClick: onConfirm,
56
- render: /* @__PURE__ */ React.createElement(Button, { label: confirmLabel })
57
- }
58
- )))
59
- ))));
38
+ /* @__PURE__ */ React.createElement(
39
+ "span",
40
+ {
41
+ "aria-hidden": "true",
42
+ "data-slot": "glass",
43
+ className: cn(styles.glass(), ui?.glass)
44
+ },
45
+ /* @__PURE__ */ React.createElement(
46
+ "span",
47
+ {
48
+ "aria-hidden": "true",
49
+ "data-slot": "overlay",
50
+ className: cn(styles.overlay(), ui?.overlay)
51
+ }
52
+ )
53
+ ),
54
+ /* @__PURE__ */ React.createElement(
55
+ "div",
56
+ {
57
+ "data-slot": "content",
58
+ className: cn(styles.content(), ui?.content)
59
+ },
60
+ /* @__PURE__ */ React.createElement(
61
+ UIAlertDialog.Title,
62
+ {
63
+ "data-slot": "title",
64
+ className: cn(styles.title(), ui?.title)
65
+ },
66
+ title
67
+ ),
68
+ description ? /* @__PURE__ */ React.createElement(
69
+ UIAlertDialog.Description,
70
+ {
71
+ "data-slot": "description",
72
+ className: cn(styles.description(), ui?.description)
73
+ },
74
+ description
75
+ ) : null,
76
+ children ? /* @__PURE__ */ React.createElement("div", { "data-slot": "body", className: cn(styles.body(), ui?.body) }, children) : null,
77
+ /* @__PURE__ */ React.createElement(
78
+ "div",
79
+ {
80
+ "data-slot": "footer",
81
+ className: cn(styles.footer(), ui?.footer)
82
+ },
83
+ /* @__PURE__ */ React.createElement(
84
+ UIAlertDialog.Close,
85
+ {
86
+ onClick: onCancel,
87
+ render: /* @__PURE__ */ React.createElement(Button, { label: cancelLabel })
88
+ }
89
+ ),
90
+ /* @__PURE__ */ React.createElement(
91
+ UIAlertDialog.Close,
92
+ {
93
+ onClick: onConfirm,
94
+ render: /* @__PURE__ */ React.createElement(Button, { label: confirmLabel })
95
+ }
96
+ )
97
+ )
98
+ )
99
+ )
100
+ )));
60
101
  }
61
102
  export { AlertDialog };
@@ -1,12 +1,16 @@
1
1
  import { type ButtonProps as UIButtonProps } from "@base-ui/react/button";
2
2
  import * as React from "react";
3
3
  import { type VariantProps } from "tailwind-variants";
4
+ import { type ComponentConfig } from "../internal/tv";
4
5
  import theme from "../theme/button";
6
+ type Button = ComponentConfig<typeof theme>;
5
7
  interface ButtonProps extends Omit<UIButtonProps, "ref" | "style" | "className">, VariantProps<typeof theme> {
6
8
  /** Ref to the rendered root element. */
7
9
  ref?: React.Ref<HTMLElement>;
8
10
  /** Tailwind classes merged into the outer click area. */
9
- className?: any;
11
+ className?: string;
12
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
13
+ ui?: Button["slots"];
10
14
  /** Text or content rendered inside the button. */
11
15
  label?: React.ReactNode;
12
16
  /** Icon rendered before the label. */
@@ -14,6 +18,6 @@ interface ButtonProps extends Omit<UIButtonProps, "ref" | "style" | "className">
14
18
  /** Icon rendered after the label. */
15
19
  trailingIcon?: React.ReactNode;
16
20
  }
17
- declare function Button({ className, children, label, leadingIcon, trailingIcon, size, ...props }: ButtonProps): React.JSX.Element;
21
+ declare function Button({ className, ui, children, label, leadingIcon, trailingIcon, size, ...props }: ButtonProps): React.JSX.Element;
18
22
  export { Button };
19
23
  export type { ButtonProps };
@@ -7,6 +7,7 @@ import * as React from "react";
7
7
  import theme from "../theme/button.mjs";
8
8
  function Button({
9
9
  className,
10
+ ui,
10
11
  children,
11
12
  label,
12
13
  leadingIcon,
@@ -14,34 +15,42 @@ function Button({
14
15
  size,
15
16
  ...props
16
17
  }) {
17
- const ui = theme({ size });
18
+ const styles = theme({ size });
18
19
  return /* @__PURE__ */ React.createElement(
19
20
  UIButton,
20
21
  {
21
22
  "data-slot": "root",
22
- className: cn(ui.root(), className),
23
+ className: cn(styles.root(), ui?.root, className),
23
24
  ...props
24
25
  },
25
- /* @__PURE__ */ React.createElement("span", { "data-slot": "base", className: ui.base() }, /* @__PURE__ */ React.createElement("span", { "data-slot": "glass", "aria-hidden": "true", className: ui.glass() }, /* @__PURE__ */ React.createElement(
26
+ /* @__PURE__ */ React.createElement("span", { "data-slot": "base", className: cn(styles.base(), ui?.base) }, /* @__PURE__ */ React.createElement(
26
27
  "span",
27
28
  {
28
- "data-slot": "overlay",
29
- className: ui.overlay(),
30
- "aria-hidden": "true"
31
- }
32
- )), leadingIcon ? /* @__PURE__ */ React.createElement(
29
+ "data-slot": "glass",
30
+ "aria-hidden": "true",
31
+ className: cn(styles.glass(), ui?.glass)
32
+ },
33
+ /* @__PURE__ */ React.createElement(
34
+ "span",
35
+ {
36
+ "data-slot": "overlay",
37
+ className: cn(styles.overlay(), ui?.overlay),
38
+ "aria-hidden": "true"
39
+ }
40
+ )
41
+ ), leadingIcon ? /* @__PURE__ */ React.createElement(
33
42
  "span",
34
43
  {
35
44
  "data-slot": "leading-icon",
36
- className: ui.leadingIcon(),
45
+ className: cn(styles.leadingIcon(), ui?.leadingIcon),
37
46
  "aria-hidden": "true"
38
47
  },
39
48
  leadingIcon
40
- ) : null, /* @__PURE__ */ React.createElement("span", { "data-slot": "label", className: ui.label() }, label || children), trailingIcon ? /* @__PURE__ */ React.createElement(
49
+ ) : null, /* @__PURE__ */ React.createElement("span", { "data-slot": "label", className: cn(styles.label(), ui?.label) }, label || children), trailingIcon ? /* @__PURE__ */ React.createElement(
41
50
  "span",
42
51
  {
43
52
  "data-slot": "trailing-icon",
44
- className: ui.trailingIcon(),
53
+ className: cn(styles.trailingIcon(), ui?.trailingIcon),
45
54
  "aria-hidden": "true"
46
55
  },
47
56
  trailingIcon
@@ -1,7 +1,12 @@
1
1
  import * as React from "react";
2
+ import { type ComponentConfig } from "../internal/tv";
3
+ import theme from "../theme/card";
4
+ type Card = ComponentConfig<typeof theme>;
2
5
  type CardProps = Omit<React.ComponentProps<"div">, "title"> & {
3
6
  /** Classes merged into the root element. */
4
7
  className?: string;
8
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
9
+ ui?: Card["slots"];
5
10
  /** Optional visible title rendered inside the card header. */
6
11
  title?: React.ReactNode;
7
12
  /** Optional supporting copy rendered under the title. */
@@ -9,6 +14,6 @@ type CardProps = Omit<React.ComponentProps<"div">, "title"> & {
9
14
  /** Optional footer row rendered below the body. */
10
15
  footer?: React.ReactNode;
11
16
  };
12
- declare function Card({ className, title, description, footer, children, ...props }: CardProps): React.JSX.Element;
17
+ declare function Card({ className, ui, title, description, footer, children, ...props }: CardProps): React.JSX.Element;
13
18
  export { Card };
14
19
  export type { CardProps };
@@ -3,22 +3,45 @@ import * as React from "react";
3
3
  import theme from "../theme/card.mjs";
4
4
  function Card({
5
5
  className,
6
+ ui,
6
7
  title,
7
8
  description,
8
9
  footer,
9
10
  children,
10
11
  ...props
11
12
  }) {
12
- const ui = theme();
13
+ const styles = theme();
13
14
  return /* @__PURE__ */ React.createElement(
14
15
  "div",
15
16
  {
16
17
  "data-slot": "root",
17
- className: cn(ui.root(), className),
18
+ className: cn(styles.root(), ui?.root, className),
18
19
  ...props
19
20
  },
20
- /* @__PURE__ */ React.createElement("div", { "aria-hidden": "true", className: ui.glass() }, /* @__PURE__ */ React.createElement("span", { "aria-hidden": "true", className: ui.overlay() })),
21
- /* @__PURE__ */ React.createElement("div", { className: ui.layout() }, title || description ? /* @__PURE__ */ React.createElement("div", { "data-slot": "header", className: ui.header() }, title ? /* @__PURE__ */ React.createElement("div", { "data-slot": "title", className: ui.title() }, title) : null, description ? /* @__PURE__ */ React.createElement("div", { "data-slot": "description", className: ui.description() }, description) : null) : null, children ? /* @__PURE__ */ React.createElement("div", { "data-slot": "body", className: ui.body() }, children) : null, footer ? /* @__PURE__ */ React.createElement("div", { "data-slot": "footer", className: ui.footer() }, footer) : null)
21
+ /* @__PURE__ */ React.createElement(
22
+ "div",
23
+ {
24
+ "aria-hidden": "true",
25
+ "data-slot": "glass",
26
+ className: cn(styles.glass(), ui?.glass)
27
+ },
28
+ /* @__PURE__ */ React.createElement(
29
+ "span",
30
+ {
31
+ "aria-hidden": "true",
32
+ "data-slot": "overlay",
33
+ className: cn(styles.overlay(), ui?.overlay)
34
+ }
35
+ )
36
+ ),
37
+ /* @__PURE__ */ React.createElement("div", { "data-slot": "layout", className: cn(styles.layout(), ui?.layout) }, title || description ? /* @__PURE__ */ React.createElement("div", { "data-slot": "header", className: cn(styles.header(), ui?.header) }, title ? /* @__PURE__ */ React.createElement("div", { "data-slot": "title", className: cn(styles.title(), ui?.title) }, title) : null, description ? /* @__PURE__ */ React.createElement(
38
+ "div",
39
+ {
40
+ "data-slot": "description",
41
+ className: cn(styles.description(), ui?.description)
42
+ },
43
+ description
44
+ ) : null) : null, children ? /* @__PURE__ */ React.createElement("div", { "data-slot": "body", className: cn(styles.body(), ui?.body) }, children) : null, footer ? /* @__PURE__ */ React.createElement("div", { "data-slot": "footer", className: cn(styles.footer(), ui?.footer) }, footer) : null)
22
45
  );
23
46
  }
24
47
  export { Card };
@@ -1,17 +1,21 @@
1
1
  import { Checkbox as UICheckbox } from "@base-ui/react/checkbox";
2
2
  import * as React from "react";
3
3
  import { type VariantProps } from "tailwind-variants";
4
+ import { type ComponentConfig } from "../internal/tv";
4
5
  import theme from "../theme/checkbox";
6
+ type Checkbox = ComponentConfig<typeof theme>;
5
7
  interface CheckboxProps extends Omit<UICheckbox.Root.Props, "className" | "children" | "style" | "ref">, VariantProps<typeof theme> {
6
8
  /** Ref to the rendered root element. */
7
9
  ref?: React.Ref<HTMLElement>;
8
10
  /** Tailwind classes merged into the Base UI checkbox root. */
9
11
  className?: string;
12
+ /** Tailwind classes for internal slots, keyed by `data-slot`. */
13
+ ui?: Checkbox["slots"];
10
14
  /** Visible label. */
11
15
  label?: React.ReactNode;
12
16
  /** Optional supporting text. */
13
17
  description?: React.ReactNode;
14
18
  }
15
- declare function Checkbox({ className, label, description, size, indeterminate, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: CheckboxProps): React.JSX.Element;
19
+ declare function Checkbox({ className, ui, label, description, size, indeterminate, "aria-describedby": ariaDescribedBy, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, ...props }: CheckboxProps): React.JSX.Element;
16
20
  export { Checkbox };
17
21
  export type { CheckboxProps };