shapes-ui 0.4.2 → 0.6.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.
Files changed (180) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +47 -0
  2. package/.github/ISSUE_TEMPLATE/config.yml +1 -0
  3. package/.github/ISSUE_TEMPLATE/feature_request.yml +31 -0
  4. package/.github/pull_request_template.md +14 -0
  5. package/.github/workflows/pr-preview.yml +75 -0
  6. package/.github/workflows/release.yml +8 -0
  7. package/CHANGELOG.md +30 -0
  8. package/CODE_OF_CONDUCT.md +41 -0
  9. package/CONTRIBUTING.md +52 -0
  10. package/README.md +18 -0
  11. package/SECURITY.md +0 -0
  12. package/content/components/accordion.mdx +13 -0
  13. package/content/components/alert-dialog.mdx +34 -0
  14. package/content/components/autocomplete.mdx +62 -0
  15. package/content/components/avatar.mdx +11 -0
  16. package/content/components/button.mdx +8 -0
  17. package/content/components/checkbox.mdx +11 -0
  18. package/content/components/collapsible.mdx +11 -0
  19. package/content/components/combobox.mdx +33 -0
  20. package/content/components/context-menu.mdx +29 -0
  21. package/content/components/dialog.mdx +33 -0
  22. package/content/components/drawer.mdx +38 -0
  23. package/content/components/field.mdx +23 -2
  24. package/content/components/fieldset.mdx +11 -1
  25. package/content/components/form.mdx +8 -0
  26. package/content/components/input.mdx +4 -0
  27. package/content/components/menu.mdx +27 -0
  28. package/content/components/menubar.mdx +31 -0
  29. package/content/components/meter.mdx +14 -0
  30. package/content/components/navigation-menu.mdx +28 -0
  31. package/content/components/number-field.mdx +25 -0
  32. package/content/components/popover.mdx +22 -0
  33. package/content/components/preview-card.mdx +14 -2
  34. package/content/components/progress.mdx +15 -1
  35. package/content/components/radio.mdx +31 -0
  36. package/content/components/scroll-area.mdx +23 -0
  37. package/content/components/select.mdx +57 -0
  38. package/content/components/separator.mdx +29 -0
  39. package/content/components/slider.mdx +52 -0
  40. package/content/components/switch.mdx +30 -0
  41. package/content/components/tabs.mdx +47 -0
  42. package/content/components/toast.mdx +70 -0
  43. package/content/components/toggle-group.mdx +37 -0
  44. package/content/components/toggle.mdx +46 -2
  45. package/content/components/toolbar.mdx +48 -0
  46. package/content/components/tooltip.mdx +38 -0
  47. package/content/docs/installation.mdx +30 -0
  48. package/content-collections.ts +65 -1
  49. package/dist/cli.js +947 -101
  50. package/examples/__index.tsx +320 -66
  51. package/examples/autocomplete-align.tsx +39 -0
  52. package/examples/autocomplete-controlled.tsx +44 -0
  53. package/examples/autocomplete-groups.tsx +65 -0
  54. package/examples/autocomplete-no-clear.tsx +40 -0
  55. package/examples/avatar-demo.tsx +3 -3
  56. package/examples/checkbox-demo.tsx +1 -1
  57. package/examples/checkbox-form.tsx +3 -3
  58. package/examples/field-custom-control.tsx +33 -9
  59. package/examples/form-demo.tsx +5 -10
  60. package/examples/input-group-with-button.tsx +1 -1
  61. package/examples/menu-advanced.tsx +1 -3
  62. package/examples/menu-align.tsx +19 -16
  63. package/examples/menu-checkbox.tsx +2 -3
  64. package/examples/menu-demo.tsx +1 -3
  65. package/examples/menu-group.tsx +1 -3
  66. package/examples/menu-radio.tsx +1 -3
  67. package/examples/menu-submenu.tsx +2 -3
  68. package/examples/meter-demo.tsx +10 -2
  69. package/examples/meter-flip.tsx +8 -8
  70. package/examples/meter-no-label.tsx +9 -2
  71. package/examples/meter-no-value.tsx +7 -8
  72. package/examples/radio-card.tsx +28 -0
  73. package/examples/radio-demo.tsx +19 -1
  74. package/examples/radio-description.tsx +26 -0
  75. package/examples/radio-orientation.tsx +21 -0
  76. package/examples/select-alignment.tsx +51 -0
  77. package/examples/select-demo.tsx +36 -1
  78. package/examples/select-disabled.tsx +38 -0
  79. package/examples/select-groups.tsx +54 -0
  80. package/examples/select-invalid.tsx +41 -0
  81. package/examples/select-scrollable.tsx +112 -0
  82. package/examples/separator-demo.tsx +13 -0
  83. package/examples/separator-horizontal.tsx +18 -0
  84. package/examples/slider-controlled.tsx +28 -0
  85. package/examples/slider-demo.tsx +3 -1
  86. package/examples/slider-disabled.tsx +7 -0
  87. package/examples/slider-edge.tsx +13 -0
  88. package/examples/slider-multiple.tsx +7 -0
  89. package/examples/slider-range.tsx +5 -0
  90. package/examples/slider-vertical.tsx +10 -0
  91. package/examples/switch-demo.tsx +19 -1
  92. package/examples/switch-disabled.tsx +20 -0
  93. package/examples/switch-sizes.tsx +24 -0
  94. package/examples/switch-with-label.tsx +16 -0
  95. package/examples/tabs-demo.tsx +14 -1
  96. package/examples/tabs-disabled.tsx +21 -0
  97. package/examples/tabs-line.tsx +18 -0
  98. package/examples/tabs-vertical.tsx +13 -0
  99. package/examples/toast-action.tsx +39 -0
  100. package/examples/toast-anchored.tsx +36 -0
  101. package/examples/toast-demo.tsx +27 -1
  102. package/examples/toast-positions.tsx +54 -0
  103. package/examples/toast-promise.tsx +51 -0
  104. package/examples/toast-stacked.tsx +30 -0
  105. package/examples/toast-timeout.tsx +43 -0
  106. package/examples/toast-update.tsx +38 -0
  107. package/examples/toast-variants.tsx +54 -0
  108. package/examples/toggle-controlled.tsx +20 -0
  109. package/examples/toggle-demo.tsx +7 -51
  110. package/examples/toggle-group-demo.tsx +19 -0
  111. package/examples/toggle-group-multiple.tsx +19 -0
  112. package/examples/toggle-icon-fill.tsx +12 -0
  113. package/examples/toolbar-demo.tsx +45 -21
  114. package/examples/toolbar-input-link.tsx +35 -0
  115. package/examples/toolbar-menu.tsx +53 -0
  116. package/examples/tooltip-demo.tsx +48 -0
  117. package/examples/tooltip-positions.tsx +60 -0
  118. package/package.json +19 -18
  119. package/public/base-ui.svg +1 -0
  120. package/public/r/drawer.json +1 -1
  121. package/public/r/field.json +1 -1
  122. package/public/r/meter.json +1 -1
  123. package/public/r/number-field.json +1 -1
  124. package/public/r/progress.json +1 -1
  125. package/public/r/radio.json +1 -1
  126. package/public/r/select.json +1 -1
  127. package/public/r/slider.json +1 -1
  128. package/public/r/switch.json +1 -1
  129. package/public/r/tabs.json +1 -1
  130. package/public/r/toast.json +2 -1
  131. package/public/r/toggle.json +1 -1
  132. package/public/r/toolbar.json +1 -1
  133. package/public/r/tooltip.json +15 -0
  134. package/src/assets/base-ui.svg +1 -0
  135. package/src/commands/add.ts +79 -38
  136. package/src/commands/cli.ts +50 -3
  137. package/src/commands/create.ts +262 -0
  138. package/src/commands/init.ts +45 -12
  139. package/src/commands/palette.ts +55 -0
  140. package/src/components/docs/layout/footer.tsx +2 -2
  141. package/src/components/docs/layout/header.tsx +7 -19
  142. package/src/components/docs/layout/mobile-menu.tsx +26 -78
  143. package/src/components/docs/layout/nav-list.tsx +27 -21
  144. package/src/components/docs/layout/page-header.tsx +52 -7
  145. package/src/components/docs/layout/split-layout.tsx +11 -9
  146. package/src/components/docs/layout/table-of-content.tsx +145 -0
  147. package/src/components/docs/markdown/components.tsx +142 -29
  148. package/src/components/docs/markdown/copy-button.tsx +41 -0
  149. package/src/components/docs/markdown/installation-block.tsx +5 -24
  150. package/src/components/docs/markdown/render-preview.tsx +1 -1
  151. package/src/components/ui/badge.tsx +1 -1
  152. package/src/components/ui/button-group.tsx +1 -1
  153. package/src/components/ui/checkbox.tsx +1 -1
  154. package/src/components/ui/drawer.tsx +1 -1
  155. package/src/components/ui/field.tsx +9 -28
  156. package/src/components/ui/form.tsx +1 -1
  157. package/src/components/ui/meter.tsx +12 -26
  158. package/src/components/ui/number-field.tsx +1 -1
  159. package/src/components/ui/radio.tsx +32 -19
  160. package/src/components/ui/scroll-area.tsx +11 -2
  161. package/src/components/ui/select.tsx +6 -6
  162. package/src/components/ui/slider.tsx +8 -5
  163. package/src/components/ui/switch.tsx +13 -17
  164. package/src/components/ui/tabs.tsx +23 -10
  165. package/src/components/ui/toast.tsx +190 -29
  166. package/src/components/ui/toggle.tsx +1 -1
  167. package/src/components/ui/toolbar.tsx +17 -4
  168. package/src/components/ui/tooltip.tsx +54 -0
  169. package/src/lib/docs-headings.ts +72 -0
  170. package/src/routeTree.gen.ts +60 -3
  171. package/src/routes/__root.tsx +3 -5
  172. package/src/routes/components.$slug.tsx +20 -4
  173. package/src/routes/docs.$slug.tsx +78 -0
  174. package/src/routes/docs.tsx +15 -0
  175. package/src/styles/styles.css +1 -1
  176. package/src/utils/cli-utils.ts +8 -8
  177. package/src/utils/dependency-installer.ts +30 -0
  178. package/src/utils/package-manager.ts +4 -4
  179. package/src/utils/palette.ts +666 -0
  180. package/src/utils/schema.ts +6 -0
@@ -0,0 +1,39 @@
1
+ import { useState } from "react";
2
+
3
+ import {
4
+ Autocomplete,
5
+ AutocompleteEmpty,
6
+ AutocompleteItem,
7
+ AutocompleteList,
8
+ AutocompletePopup,
9
+ } from "@/components/ui/autocomplete";
10
+
11
+ const languages = ["TypeScript", "JavaScript", "Rust", "Go", "Python"];
12
+
13
+ export default function AutocompleteAlign() {
14
+ const [open, setOpen] = useState(false);
15
+ const [value, setValue] = useState("");
16
+
17
+ const filtered = languages.filter((item) => item.toLowerCase().includes(value.toLowerCase()));
18
+
19
+ return (
20
+ <Autocomplete
21
+ open={open}
22
+ onOpenChange={setOpen}
23
+ value={value}
24
+ onValueChange={setValue}
25
+ placeholder="Search language..."
26
+ >
27
+ <AutocompletePopup align="start" sideOffset={4} className="max-w-64">
28
+ <AutocompleteList>
29
+ {filtered.map((item) => (
30
+ <AutocompleteItem key={item} value={item}>
31
+ {item}
32
+ </AutocompleteItem>
33
+ ))}
34
+ {filtered.length === 0 && <AutocompleteEmpty>No results found</AutocompleteEmpty>}
35
+ </AutocompleteList>
36
+ </AutocompletePopup>
37
+ </Autocomplete>
38
+ );
39
+ }
@@ -0,0 +1,44 @@
1
+ import { useState } from "react";
2
+
3
+ import {
4
+ Autocomplete,
5
+ AutocompleteEmpty,
6
+ AutocompleteItem,
7
+ AutocompleteList,
8
+ AutocompletePopup,
9
+ } from "@/components/ui/autocomplete";
10
+
11
+ const options = ["Apple", "Banana", "Blueberry", "Cherry", "Orange"];
12
+
13
+ export default function AutocompleteControlled() {
14
+ const [open, setOpen] = useState(false);
15
+ const [value, setValue] = useState("");
16
+
17
+ const filtered = options.filter((item) => item.toLowerCase().includes(value.toLowerCase()));
18
+
19
+ return (
20
+ <div className="space-y-3">
21
+ <Autocomplete
22
+ open={open}
23
+ onOpenChange={setOpen}
24
+ value={value}
25
+ onValueChange={setValue}
26
+ placeholder="Select a fruit..."
27
+ >
28
+ <AutocompletePopup>
29
+ <AutocompleteList>
30
+ {filtered.map((item) => (
31
+ <AutocompleteItem key={item} value={item}>
32
+ {item}
33
+ </AutocompleteItem>
34
+ ))}
35
+ {filtered.length === 0 && <AutocompleteEmpty>No results found</AutocompleteEmpty>}
36
+ </AutocompleteList>
37
+ </AutocompletePopup>
38
+ </Autocomplete>
39
+ <p className="text-sm text-muted-foreground">
40
+ Selected value: <span className="font-medium text-foreground">{value || "—"}</span>
41
+ </p>
42
+ </div>
43
+ );
44
+ }
@@ -0,0 +1,65 @@
1
+ import { useState } from "react";
2
+
3
+ import {
4
+ Autocomplete,
5
+ AutocompleteEmpty,
6
+ AutocompleteGroup,
7
+ AutocompleteGroupLabel,
8
+ AutocompleteItem,
9
+ AutocompleteList,
10
+ AutocompletePopup,
11
+ AutocompleteSeparator,
12
+ } from "@/components/ui/autocomplete";
13
+
14
+ const frameworks = ["React", "Vue", "Svelte", "Solid"];
15
+ const metaFrameworks = ["Next.js", "Nuxt", "Remix", "Astro"];
16
+
17
+ export default function AutocompleteGroups() {
18
+ const [open, setOpen] = useState(false);
19
+ const [value, setValue] = useState("");
20
+
21
+ const query = value.toLowerCase();
22
+ const filteredFrameworks = frameworks.filter((item) => item.toLowerCase().includes(query));
23
+ const filteredMeta = metaFrameworks.filter((item) => item.toLowerCase().includes(query));
24
+ const hasResults = filteredFrameworks.length > 0 || filteredMeta.length > 0;
25
+
26
+ return (
27
+ <Autocomplete
28
+ open={open}
29
+ onOpenChange={setOpen}
30
+ value={value}
31
+ onValueChange={setValue}
32
+ placeholder="Search frameworks..."
33
+ >
34
+ <AutocompletePopup>
35
+ <AutocompleteList>
36
+ {!hasResults && <AutocompleteEmpty>No results found</AutocompleteEmpty>}
37
+
38
+ {filteredFrameworks.length > 0 && (
39
+ <AutocompleteGroup>
40
+ <AutocompleteGroupLabel>Frameworks</AutocompleteGroupLabel>
41
+ {filteredFrameworks.map((item) => (
42
+ <AutocompleteItem key={item} value={item}>
43
+ {item}
44
+ </AutocompleteItem>
45
+ ))}
46
+ </AutocompleteGroup>
47
+ )}
48
+
49
+ {filteredFrameworks.length > 0 && filteredMeta.length > 0 && <AutocompleteSeparator />}
50
+
51
+ {filteredMeta.length > 0 && (
52
+ <AutocompleteGroup>
53
+ <AutocompleteGroupLabel>Meta Frameworks</AutocompleteGroupLabel>
54
+ {filteredMeta.map((item) => (
55
+ <AutocompleteItem key={item} value={item}>
56
+ {item}
57
+ </AutocompleteItem>
58
+ ))}
59
+ </AutocompleteGroup>
60
+ )}
61
+ </AutocompleteList>
62
+ </AutocompletePopup>
63
+ </Autocomplete>
64
+ );
65
+ }
@@ -0,0 +1,40 @@
1
+ import { useState } from "react";
2
+
3
+ import {
4
+ Autocomplete,
5
+ AutocompleteEmpty,
6
+ AutocompleteItem,
7
+ AutocompleteList,
8
+ AutocompletePopup,
9
+ } from "@/components/ui/autocomplete";
10
+
11
+ const tags = ["Design", "Frontend", "Backend", "DevOps", "Testing"];
12
+
13
+ export default function AutocompleteNoClear() {
14
+ const [open, setOpen] = useState(false);
15
+ const [value, setValue] = useState("");
16
+
17
+ const filtered = tags.filter((item) => item.toLowerCase().includes(value.toLowerCase()));
18
+
19
+ return (
20
+ <Autocomplete
21
+ open={open}
22
+ onOpenChange={setOpen}
23
+ value={value}
24
+ onValueChange={setValue}
25
+ placeholder="Pick a tag..."
26
+ showClearButton={false}
27
+ >
28
+ <AutocompletePopup>
29
+ <AutocompleteList>
30
+ {filtered.map((item) => (
31
+ <AutocompleteItem key={item} value={item}>
32
+ {item}
33
+ </AutocompleteItem>
34
+ ))}
35
+ {filtered.length === 0 && <AutocompleteEmpty>No tags found</AutocompleteEmpty>}
36
+ </AutocompleteList>
37
+ </AutocompletePopup>
38
+ </Autocomplete>
39
+ );
40
+ }
@@ -4,15 +4,15 @@ export default function AvatarDemo() {
4
4
  return (
5
5
  <div className="flex items-center gap-4">
6
6
  <Avatar>
7
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
7
+ <AvatarImage src="/shps_black.svg" alt="Shapes UI" className={"bg-muted"} />
8
8
  <AvatarFallback>CN</AvatarFallback>
9
9
  </Avatar>
10
10
  <Avatar size="sm">
11
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
11
+ <AvatarImage src="/shps_black.svg" alt="Shapes UI" className={"bg-muted"} />
12
12
  <AvatarFallback>CN</AvatarFallback>
13
13
  </Avatar>
14
14
  <Avatar size="lg">
15
- <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
15
+ <AvatarImage src="/shps_black.svg" alt="Shapes UI" className={"bg-muted"} />
16
16
  <AvatarFallback>CN</AvatarFallback>
17
17
  </Avatar>
18
18
  <Avatar>
@@ -3,7 +3,7 @@ import { Field, FieldLabel } from "@/components/ui/field";
3
3
 
4
4
  export default function CheckboxDemo() {
5
5
  return (
6
- <Field orientation={"horizontal"} className={"mx-auto"}>
6
+ <Field className="mx-auto flex-row items-center *:w-auto">
7
7
  <Checkbox />
8
8
  <FieldLabel>Accept terms and conditions</FieldLabel>
9
9
  </Field>
@@ -6,7 +6,7 @@ import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
6
6
  export default function CheckboxFormDemo() {
7
7
  return (
8
8
  <form className="max-w-md space-y-4">
9
- <Field name="marketing" orientation="horizontal">
9
+ <Field name="marketing">
10
10
  <FieldLabel>
11
11
  <Checkbox />
12
12
  <span className="text-sm">Marketing emails</span>
@@ -14,7 +14,7 @@ export default function CheckboxFormDemo() {
14
14
  <FieldDescription>Receive emails about new products and features.</FieldDescription>
15
15
  </Field>
16
16
 
17
- <Field name="newsletter" orientation="horizontal">
17
+ <Field name="newsletter">
18
18
  <FieldLabel>
19
19
  <Checkbox />
20
20
  <span className="text-sm">Newsletter</span>
@@ -22,7 +22,7 @@ export default function CheckboxFormDemo() {
22
22
  <FieldDescription>Get our weekly newsletter with tips and updates.</FieldDescription>
23
23
  </Field>
24
24
 
25
- <Field name="security" orientation="horizontal">
25
+ <Field name="security">
26
26
  <FieldLabel>
27
27
  <Checkbox defaultChecked />
28
28
  <span className="text-sm">Security alerts</span>
@@ -1,17 +1,41 @@
1
1
  import { Field, FieldLabel, FieldDescription } from "@/components/ui/field";
2
+ import {
3
+ Select,
4
+ SelectGroup,
5
+ SelectItem,
6
+ SelectLabel,
7
+ SelectPopup,
8
+ SelectTrigger,
9
+ SelectValue,
10
+ } from "@/components/ui/select";
2
11
 
3
12
  export default function FieldCustomControl() {
4
13
  return (
5
14
  <Field name="color" className="max-w-md">
6
- <FieldLabel>Favorite Color</FieldLabel>
7
- <select className="flex h-9 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm transition-colors focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none">
8
- <option value="">Select a color</option>
9
- <option value="red">Red</option>
10
- <option value="blue">Blue</option>
11
- <option value="green">Green</option>
12
- <option value="yellow">Yellow</option>
13
- </select>
14
- <FieldDescription>Select your favorite color from the dropdown.</FieldDescription>
15
+ <FieldLabel>Favourite Color</FieldLabel>
16
+ <Select items={colors}>
17
+ <SelectTrigger className="w-full max-w-48">
18
+ <SelectValue />
19
+ </SelectTrigger>
20
+ <SelectPopup>
21
+ <SelectGroup>
22
+ <SelectLabel>Colors</SelectLabel>
23
+ {colors.map((color) => (
24
+ <SelectItem key={color.value} value={color.value}>
25
+ {color.label}
26
+ </SelectItem>
27
+ ))}
28
+ </SelectGroup>
29
+ </SelectPopup>
30
+ </Select>
31
+ <FieldDescription>Select your favourite color from the dropdown.</FieldDescription>
15
32
  </Field>
16
33
  );
17
34
  }
35
+
36
+ const colors = [
37
+ { value: "red", label: "Red" },
38
+ { value: "blue", label: "Blue" },
39
+ { value: "green", label: "Green" },
40
+ { value: "yellow", label: "Yellow" },
41
+ ];
@@ -1,23 +1,18 @@
1
1
  import { Button } from "@/components/ui/button";
2
2
  import { Field, FieldLabel, FieldControl, FieldDescription } from "@/components/ui/field";
3
3
  import { Form } from "@/components/ui/form";
4
- import { Input } from "@/components/ui/input";
5
4
 
6
5
  export default function FormDemo() {
7
6
  return (
8
- <Form onSubmit={(e) => e.preventDefault()} className="w-full max-w-sm space-y-6">
9
- <Field orientation="vertical">
7
+ <Form onFormSubmit={(event) => event.preventDefault()} className="w-full max-w-sm space-y-6">
8
+ <Field>
10
9
  <FieldLabel>Email</FieldLabel>
11
- <FieldControl>
12
- <Input type="email" placeholder="Enter your email" required />
13
- </FieldControl>
10
+ <FieldControl type="email" placeholder="Enter your email" required />
14
11
  <FieldDescription>We'll never share your email.</FieldDescription>
15
12
  </Field>
16
- <Field orientation="vertical">
13
+ <Field>
17
14
  <FieldLabel>Password</FieldLabel>
18
- <FieldControl>
19
- <Input type="password" placeholder="Enter your password" required />
20
- </FieldControl>
15
+ <FieldControl type="password" placeholder="Enter your password" required />
21
16
  </Field>
22
17
  <Button type="submit" className="w-full">
23
18
  Submit
@@ -16,7 +16,7 @@ export default function InputGroupButtonExample() {
16
16
  return (
17
17
  <div className="grid w-full max-w-sm gap-6">
18
18
  <InputGroup>
19
- <InputGroupInput placeholder="https://x.com/shadcn" readOnly />
19
+ <InputGroupInput placeholder="https://shapes-ui.com" readOnly />
20
20
  <InputGroupAddon align="inline-end">
21
21
  <InputGroupButton aria-label="Copy" title="Copy" size="icon-xs">
22
22
  <CopyIcon />
@@ -35,9 +35,7 @@ export default function MenuAdvancedDemo() {
35
35
 
36
36
  return (
37
37
  <Menu>
38
- <MenuTrigger>
39
- <Button variant="outline">Advanced menu</Button>
40
- </MenuTrigger>
38
+ <MenuTrigger render={<Button variant="outline">Advanced menu</Button>} />
41
39
 
42
40
  <MenuPopup>
43
41
  <div className="flex items-center gap-2 p-3">
@@ -9,22 +9,25 @@ export default function MenuDemo() {
9
9
 
10
10
  return (
11
11
  <Menu>
12
- <MenuTrigger>
13
- <ButtonGroup>
14
- <Button variant="outline" onClick={() => setSide("bottom")}>
15
- Bottom
16
- </Button>
17
- <Button variant="outline" onClick={() => setSide("top")}>
18
- Top
19
- </Button>
20
- <Button variant="outline" onClick={() => setSide("left")}>
21
- Left
22
- </Button>
23
- <Button variant="outline" onClick={() => setSide("right")}>
24
- Right
25
- </Button>
26
- </ButtonGroup>
27
- </MenuTrigger>
12
+ <MenuTrigger
13
+ nativeButton={false}
14
+ render={
15
+ <ButtonGroup>
16
+ <Button variant="outline" onClick={() => setSide("bottom")}>
17
+ Bottom
18
+ </Button>
19
+ <Button variant="outline" onClick={() => setSide("top")}>
20
+ Top
21
+ </Button>
22
+ <Button variant="outline" onClick={() => setSide("left")}>
23
+ Left
24
+ </Button>
25
+ <Button variant="outline" onClick={() => setSide("right")}>
26
+ Right
27
+ </Button>
28
+ </ButtonGroup>
29
+ }
30
+ ></MenuTrigger>
28
31
  <MenuPopup side={side}>
29
32
  <MenuItem>{side.charAt(0).toUpperCase() + side.slice(1)}</MenuItem>
30
33
  </MenuPopup>
@@ -9,9 +9,8 @@ export default function MenuCheckboxDemo() {
9
9
 
10
10
  return (
11
11
  <Menu>
12
- <MenuTrigger>
13
- <Button variant="outline">Checkbox items</Button>
14
- </MenuTrigger>
12
+ <MenuTrigger render={<Button variant="outline">Checkbox items</Button>} />
13
+
15
14
  <MenuPopup>
16
15
  <MenuCheckboxItem
17
16
  checked={showHidden}
@@ -16,9 +16,7 @@ import {
16
16
  export default function MenuDemo() {
17
17
  return (
18
18
  <Menu>
19
- <MenuTrigger>
20
- <Button variant="outline">Open Menu</Button>
21
- </MenuTrigger>
19
+ <MenuTrigger render={<Button variant="outline">Open Menu</Button>} />
22
20
  <MenuPopup>
23
21
  <div className="flex items-center justify-between gap-2 p-3">
24
22
  <Avatar size="sm">
@@ -14,9 +14,7 @@ import {
14
14
  export default function MenuGroupDemo() {
15
15
  return (
16
16
  <Menu>
17
- <MenuTrigger>
18
- <Button variant="outline">Group menu</Button>
19
- </MenuTrigger>
17
+ <MenuTrigger render={<Button variant="outline">Group menu</Button>} />
20
18
  <MenuPopup>
21
19
  <MenuGroup>
22
20
  <MenuLabel>Account</MenuLabel>
@@ -8,9 +8,7 @@ export default function MenuRadioDemo() {
8
8
 
9
9
  return (
10
10
  <Menu>
11
- <MenuTrigger>
12
- <Button variant="outline">Radio items</Button>
13
- </MenuTrigger>
11
+ <MenuTrigger render={<Button variant="outline">Radio items</Button>} />
14
12
  <MenuPopup>
15
13
  <MenuRadioGroup value={view} onValueChange={(v) => setView(v as any)}>
16
14
  <MenuRadioItem value="list">List view</MenuRadioItem>
@@ -14,9 +14,8 @@ import {
14
14
  export default function MenuSubmenuDemo() {
15
15
  return (
16
16
  <Menu>
17
- <MenuTrigger>
18
- <Button variant="outline">Submenu</Button>
19
- </MenuTrigger>
17
+ <MenuTrigger render={<Button variant="outline">Submenu</Button>} />
18
+
20
19
  <MenuPopup>
21
20
  <MenuItem>New file</MenuItem>
22
21
  <MenuItem>Open…</MenuItem>
@@ -1,5 +1,13 @@
1
- import { Meter } from "@/components/ui/meter";
1
+ import { Meter, MeterLabel, MeterValue, MeterIndicator, MeterTrack } from "@/components/ui/meter";
2
2
 
3
3
  export default function MeterDemo() {
4
- return <Meter className={"w-72"} value={54} label="Storage" showLabel showValue />;
4
+ return (
5
+ <Meter className={"w-72"} value={54}>
6
+ <MeterLabel>Progress</MeterLabel>
7
+ <MeterValue />
8
+ <MeterTrack>
9
+ <MeterIndicator />
10
+ </MeterTrack>
11
+ </Meter>
12
+ );
5
13
  }
@@ -1,13 +1,13 @@
1
- import { Meter } from "@/components/ui/meter";
1
+ import { Meter, MeterIndicator, MeterLabel, MeterTrack, MeterValue } from "@/components/ui/meter";
2
2
 
3
3
  export default function MeterIndicatorDemo() {
4
4
  return (
5
- <Meter
6
- className={"w-72 flex-col-reverse"}
7
- value={32}
8
- label="Request usage"
9
- showLabel
10
- showValue
11
- />
5
+ <Meter className={"w-72"} value={32}>
6
+ <MeterTrack>
7
+ <MeterIndicator />
8
+ </MeterTrack>
9
+ <MeterLabel>Progress</MeterLabel>
10
+ <MeterValue />
11
+ </Meter>
12
12
  );
13
13
  }
@@ -1,5 +1,12 @@
1
- import { Meter } from "@/components/ui/meter";
1
+ import { Meter, MeterIndicator, MeterTrack, MeterValue } from "@/components/ui/meter";
2
2
 
3
3
  export default function MeterNoLabelDemo() {
4
- return <Meter className={"w-72"} value={32} label="Storage" showLabel={false} showValue />;
4
+ return (
5
+ <Meter className={"w-72"} value={54}>
6
+ <MeterValue className={"col-span-2 text-left"} />
7
+ <MeterTrack>
8
+ <MeterIndicator />
9
+ </MeterTrack>
10
+ </Meter>
11
+ );
5
12
  }
@@ -1,13 +1,12 @@
1
- import { Meter } from "@/components/ui/meter";
1
+ import { Meter, MeterIndicator, MeterLabel, MeterTrack } from "@/components/ui/meter";
2
2
 
3
3
  export default function MeterNoValueDemo() {
4
4
  return (
5
- <Meter
6
- className={"w-72"}
7
- value={69.3}
8
- label="Daily allowance"
9
- showLabel={true}
10
- showValue={false}
11
- />
5
+ <Meter className={"w-72"} value={54}>
6
+ <MeterLabel>File transfer</MeterLabel>
7
+ <MeterTrack>
8
+ <MeterIndicator />
9
+ </MeterTrack>
10
+ </Meter>
12
11
  );
13
12
  }
@@ -0,0 +1,28 @@
1
+ import { Radio, RadioGroup } from "@/components/ui/radio";
2
+
3
+ export default function RadioCardDemo() {
4
+ return (
5
+ <RadioGroup name="card-plan" defaultValue="team" className="gap-4= grid md:grid-cols-2">
6
+ <label
7
+ htmlFor="personal"
8
+ className="flex h-24 cursor-pointer items-start gap-3 rounded-lg border p-4 has-checked:border-primary has-checked:bg-primary/5"
9
+ >
10
+ <Radio value="personal" id="personal" className="mt-0.5" />
11
+ <div className="grid gap-1">
12
+ <span className="font-medium">Personal</span>
13
+ <span className="text-sm text-muted-foreground">For individual use</span>
14
+ </div>
15
+ </label>
16
+ <label
17
+ htmlFor="team"
18
+ className="flex h-24 cursor-pointer items-start gap-3 rounded-lg border p-4 has-checked:border-primary has-checked:bg-primary/5"
19
+ >
20
+ <Radio value="team" id="team" className="mt-0.5" />
21
+ <div className="grid gap-1">
22
+ <span className="font-medium">Team</span>
23
+ <span className="text-sm text-muted-foreground">For small teams</span>
24
+ </div>
25
+ </label>
26
+ </RadioGroup>
27
+ );
28
+ }
@@ -1,3 +1,21 @@
1
+ import { Field, FieldLabel } from "@/components/ui/field";
2
+ import { Radio, RadioGroup } from "@/components/ui/radio";
3
+
1
4
  export default function RadioDemo() {
2
- return <div></div>;
5
+ return (
6
+ <RadioGroup>
7
+ <Field className="flex-row items-center *:w-auto">
8
+ <Radio value={"default"} />
9
+ <FieldLabel>Default</FieldLabel>
10
+ </Field>
11
+ <Field className="flex-row items-center *:w-auto">
12
+ <Radio value={"spacious"} />
13
+ <FieldLabel>Spacious</FieldLabel>
14
+ </Field>
15
+ <Field className="flex-row items-center *:w-auto">
16
+ <Radio value={"compact"} />
17
+ <FieldLabel>Compact</FieldLabel>
18
+ </Field>
19
+ </RadioGroup>
20
+ );
3
21
  }
@@ -0,0 +1,26 @@
1
+ import { Radio, RadioGroup } from "@/components/ui/radio";
2
+
3
+ export default function RadioDescriptionDemo() {
4
+ return (
5
+ <RadioGroup orientation="vertical" className={"gap-4"}>
6
+ <div className="flex h-fit items-start gap-3">
7
+ <Radio value="comfortable" id="comfortable" className="mt-1" />
8
+ <div className="grid">
9
+ <label htmlFor="comfortable" className="text-sm">
10
+ Default
11
+ </label>
12
+ <p className="text-sm text-muted-foreground">Default spacing for most users.</p>
13
+ </div>
14
+ </div>
15
+ <div className="flex h-fit items-start gap-3">
16
+ <Radio value="compact" id="compact" className="mt-1" />
17
+ <div className="grid">
18
+ <label htmlFor="compact" className="text-sm">
19
+ Compact
20
+ </label>
21
+ <p className="text-sm text-muted-foreground">Reduced spacing for dense layouts.</p>
22
+ </div>
23
+ </div>
24
+ </RadioGroup>
25
+ );
26
+ }
@@ -0,0 +1,21 @@
1
+ import { Field, FieldLabel } from "@/components/ui/field";
2
+ import { Radio, RadioGroup } from "@/components/ui/radio";
3
+
4
+ export default function RadioOrientationDemo() {
5
+ return (
6
+ <RadioGroup orientation="horizontal">
7
+ <Field className="flex-row items-center *:w-auto">
8
+ <Radio value={"left"} />
9
+ <FieldLabel>Left</FieldLabel>
10
+ </Field>
11
+ <Field className="flex-row items-center *:w-auto">
12
+ <Radio value={"middle"} />
13
+ <FieldLabel>Middle</FieldLabel>
14
+ </Field>
15
+ <Field className="flex-row items-center *:w-auto">
16
+ <Radio value={"right"} />
17
+ <FieldLabel>Right</FieldLabel>
18
+ </Field>
19
+ </RadioGroup>
20
+ );
21
+ }