shapes-ui 0.4.1 → 0.5.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 (149) 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 +68 -0
  6. package/.github/workflows/release.yml +8 -0
  7. package/.idea/compiler.xml +6 -0
  8. package/.idea/copilot.data.migration.ask2agent.xml +6 -0
  9. package/.idea/vcs.xml +6 -0
  10. package/CHANGELOG.md +31 -0
  11. package/CODE_OF_CONDUCT.md +41 -0
  12. package/CONTRIBUTING.md +52 -0
  13. package/README.md +5 -0
  14. package/SECURITY.md +0 -0
  15. package/content/components/field.mdx +2 -2
  16. package/content/components/fieldset.mdx +1 -1
  17. package/content/components/menubar.mdx +4 -2
  18. package/content/components/meter.mdx +13 -1
  19. package/content/components/navigation-menu.mdx +6 -0
  20. package/content/components/number-field.mdx +24 -0
  21. package/content/components/popover.mdx +20 -0
  22. package/content/components/preview-card.mdx +11 -0
  23. package/content/components/progress.mdx +2 -0
  24. package/content/components/radio.mdx +20 -0
  25. package/content/components/select.mdx +30 -0
  26. package/content/components/slider.mdx +48 -0
  27. package/content/components/switch.mdx +26 -0
  28. package/content/components/tabs.mdx +32 -0
  29. package/content/components/toast.mdx +60 -0
  30. package/content/components/toggle.mdx +34 -2
  31. package/content/components/toolbar.mdx +26 -0
  32. package/content/components/tooltip.mdx +25 -0
  33. package/content-collections.ts +1 -1
  34. package/examples/__index.tsx +231 -0
  35. package/examples/checkbox-demo.tsx +1 -1
  36. package/examples/checkbox-form.tsx +3 -3
  37. package/examples/field-custom-control.tsx +33 -9
  38. package/examples/form-demo.tsx +5 -10
  39. package/examples/menu-advanced.tsx +1 -3
  40. package/examples/menu-align.tsx +19 -16
  41. package/examples/menu-checkbox.tsx +2 -3
  42. package/examples/menu-demo.tsx +1 -3
  43. package/examples/menu-group.tsx +1 -3
  44. package/examples/menu-radio.tsx +1 -3
  45. package/examples/menu-submenu.tsx +2 -3
  46. package/examples/menubar-advanced.tsx +91 -0
  47. package/examples/meter-demo.tsx +8 -21
  48. package/examples/meter-flip.tsx +13 -0
  49. package/examples/meter-no-label.tsx +12 -0
  50. package/examples/meter-no-value.tsx +12 -0
  51. package/examples/navigation-menu-demo.tsx +113 -1
  52. package/examples/number-field-buttons-end.tsx +20 -0
  53. package/examples/number-field-demo.tsx +17 -1
  54. package/examples/number-field-scrub.tsx +38 -0
  55. package/examples/popover-demo.tsx +18 -1
  56. package/examples/popover-form.tsx +46 -0
  57. package/examples/popover-positions.tsx +54 -0
  58. package/examples/preview-card-demo.tsx +26 -1
  59. package/examples/preview-card-links.tsx +38 -0
  60. package/examples/progress-demo.tsx +33 -1
  61. package/examples/radio-card.tsx +28 -0
  62. package/examples/radio-demo.tsx +19 -1
  63. package/examples/radio-description.tsx +26 -0
  64. package/examples/radio-orientation.tsx +21 -0
  65. package/examples/select-alignment.tsx +51 -0
  66. package/examples/select-demo.tsx +36 -1
  67. package/examples/select-disabled.tsx +38 -0
  68. package/examples/select-groups.tsx +54 -0
  69. package/examples/select-invalid.tsx +41 -0
  70. package/examples/select-scrollable.tsx +112 -0
  71. package/examples/slider-controlled.tsx +28 -0
  72. package/examples/slider-demo.tsx +3 -1
  73. package/examples/slider-disabled.tsx +7 -0
  74. package/examples/slider-edge.tsx +13 -0
  75. package/examples/slider-multiple.tsx +7 -0
  76. package/examples/slider-range.tsx +5 -0
  77. package/examples/slider-vertical.tsx +10 -0
  78. package/examples/switch-demo.tsx +19 -1
  79. package/examples/switch-disabled.tsx +20 -0
  80. package/examples/switch-sizes.tsx +24 -0
  81. package/examples/switch-with-label.tsx +16 -0
  82. package/examples/tabs-demo.tsx +14 -1
  83. package/examples/tabs-disabled.tsx +21 -0
  84. package/examples/tabs-line.tsx +18 -0
  85. package/examples/tabs-vertical.tsx +13 -0
  86. package/examples/toast-action.tsx +39 -0
  87. package/examples/toast-anchored.tsx +36 -0
  88. package/examples/toast-demo.tsx +27 -1
  89. package/examples/toast-positions.tsx +54 -0
  90. package/examples/toast-promise.tsx +51 -0
  91. package/examples/toast-stacked.tsx +30 -0
  92. package/examples/toast-timeout.tsx +43 -0
  93. package/examples/toast-update.tsx +38 -0
  94. package/examples/toast-variants.tsx +54 -0
  95. package/examples/toggle-controlled.tsx +20 -0
  96. package/examples/toggle-demo.tsx +7 -51
  97. package/examples/toggle-group-demo.tsx +19 -0
  98. package/examples/toggle-group-multiple.tsx +19 -0
  99. package/examples/toggle-icon-fill.tsx +12 -0
  100. package/examples/toolbar-demo.tsx +45 -21
  101. package/examples/toolbar-input-link.tsx +35 -0
  102. package/examples/toolbar-menu.tsx +53 -0
  103. package/examples/tooltip-demo.tsx +48 -0
  104. package/examples/tooltip-positions.tsx +60 -0
  105. package/package.json +8 -8
  106. package/public/r/drawer.json +1 -1
  107. package/public/r/field.json +1 -1
  108. package/public/r/menubar.json +1 -1
  109. package/public/r/meter.json +1 -1
  110. package/public/r/navigation-menu.json +1 -1
  111. package/public/r/number-field.json +4 -2
  112. package/public/r/popover.json +1 -1
  113. package/public/r/preview-card.json +1 -1
  114. package/public/r/progress.json +1 -1
  115. package/public/r/radio.json +1 -1
  116. package/public/r/select.json +1 -1
  117. package/public/r/slider.json +1 -1
  118. package/public/r/switch.json +1 -1
  119. package/public/r/tabs.json +1 -1
  120. package/public/r/toast.json +2 -1
  121. package/public/r/toggle.json +1 -1
  122. package/public/r/toolbar.json +1 -1
  123. package/public/r/tooltip.json +15 -0
  124. package/src/components/docs/layout/header.tsx +4 -14
  125. package/src/components/docs/layout/mobile-menu.tsx +27 -78
  126. package/src/components/docs/layout/nav-list.tsx +27 -21
  127. package/src/components/docs/layout/split-layout.tsx +6 -3
  128. package/src/components/ui/badge.tsx +1 -1
  129. package/src/components/ui/checkbox.tsx +1 -1
  130. package/src/components/ui/drawer.tsx +1 -1
  131. package/src/components/ui/field.tsx +9 -28
  132. package/src/components/ui/form.tsx +1 -1
  133. package/src/components/ui/menubar.tsx +52 -18
  134. package/src/components/ui/meter.tsx +12 -24
  135. package/src/components/ui/navigation-menu.tsx +121 -38
  136. package/src/components/ui/number-field.tsx +42 -46
  137. package/src/components/ui/popover.tsx +7 -2
  138. package/src/components/ui/preview-card.tsx +4 -2
  139. package/src/components/ui/progress.tsx +7 -18
  140. package/src/components/ui/radio.tsx +32 -19
  141. package/src/components/ui/select.tsx +6 -6
  142. package/src/components/ui/slider.tsx +8 -5
  143. package/src/components/ui/switch.tsx +13 -17
  144. package/src/components/ui/tabs.tsx +23 -10
  145. package/src/components/ui/toast.tsx +190 -29
  146. package/src/components/ui/toggle.tsx +1 -1
  147. package/src/components/ui/toolbar.tsx +17 -4
  148. package/src/components/ui/tooltip.tsx +54 -0
  149. package/src/routes/__root.tsx +3 -5
@@ -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>
@@ -0,0 +1,91 @@
1
+ import { FolderIcon, FileTextIcon, FileCode2Icon } from "lucide-react";
2
+ import { useState } from "react";
3
+
4
+ import {
5
+ Menubar,
6
+ Menu,
7
+ MenuTrigger,
8
+ MenuPopup,
9
+ MenuItem,
10
+ MenuSeparator,
11
+ MenuCheckboxItem,
12
+ MenuShortcut,
13
+ MenuSub,
14
+ MenuSubPopup,
15
+ MenuSubTrigger,
16
+ } from "@/components/ui/menubar";
17
+
18
+ export default function MenubarDemo() {
19
+ const [autosave, setAutosave] = useState(true);
20
+
21
+ return (
22
+ <Menubar>
23
+ <Menu>
24
+ <MenuTrigger>File</MenuTrigger>
25
+ <MenuPopup>
26
+ <MenuItem>
27
+ New <MenuShortcut>⌘N</MenuShortcut>
28
+ </MenuItem>
29
+ <MenuItem>
30
+ Open <MenuShortcut>⌘O</MenuShortcut>{" "}
31
+ </MenuItem>
32
+ <MenuSeparator />
33
+ <MenuItem>
34
+ Exit <MenuShortcut>⌘Q</MenuShortcut>
35
+ </MenuItem>
36
+ </MenuPopup>
37
+ </Menu>
38
+ <Menu>
39
+ <MenuTrigger>Edit</MenuTrigger>
40
+ <MenuPopup>
41
+ <MenuItem>
42
+ Undo <MenuShortcut>⌘N</MenuShortcut>
43
+ </MenuItem>
44
+ <MenuItem>
45
+ Redo <MenuShortcut>⇧⌘R</MenuShortcut>
46
+ </MenuItem>
47
+ <MenuSeparator />
48
+ <MenuItem>
49
+ Cut <MenuShortcut>⌘X</MenuShortcut>
50
+ </MenuItem>
51
+ <MenuItem>
52
+ Copy <MenuShortcut>⌘C</MenuShortcut>
53
+ </MenuItem>
54
+ <MenuItem>
55
+ Paste <MenuShortcut>⌘V</MenuShortcut>
56
+ </MenuItem>
57
+ <MenuSeparator />
58
+ <MenuSub>
59
+ <MenuSubTrigger>
60
+ <FolderIcon />
61
+ Open recent
62
+ </MenuSubTrigger>
63
+ <MenuSubPopup>
64
+ <MenuItem>
65
+ <FileCode2Icon />
66
+ button.tsx
67
+ </MenuItem>
68
+ <MenuItem>
69
+ <FileCode2Icon />
70
+ build-script.ts
71
+ </MenuItem>
72
+ <MenuItem>
73
+ <FileTextIcon />
74
+ feature-spec.md
75
+ </MenuItem>
76
+ </MenuSubPopup>
77
+ </MenuSub>
78
+ </MenuPopup>
79
+ </Menu>
80
+ <Menu>
81
+ <MenuTrigger>View</MenuTrigger>
82
+ <MenuPopup>
83
+ <MenuCheckboxItem checked={autosave} onCheckedChange={setAutosave}>
84
+ Auto Save
85
+ </MenuCheckboxItem>
86
+ <MenuItem>Full Screen</MenuItem>
87
+ </MenuPopup>
88
+ </Menu>
89
+ </Menubar>
90
+ );
91
+ }
@@ -1,26 +1,13 @@
1
- import { useState } from "react";
2
-
3
- import { Meter } from "@/components/ui/meter";
1
+ import { Meter, MeterLabel, MeterValue, MeterIndicator, MeterTrack } from "@/components/ui/meter";
4
2
 
5
3
  export default function MeterDemo() {
6
- const [value, setValue] = useState(65);
7
-
8
4
  return (
9
- <div className="space-y-6">
10
- <div>
11
- <Meter value={value} label="Storage" showLabel showValue />
12
- <input
13
- type="range"
14
- min="0"
15
- max="100"
16
- value={value}
17
- onChange={(e) => setValue(Number(e.target.value))}
18
- className="mt-4 w-80"
19
- />
20
- </div>
21
- <div>
22
- <Meter value={75} label="Memory" showLabel showValue />
23
- </div>
24
- </div>
5
+ <Meter className={"w-72"} value={54}>
6
+ <MeterLabel>Progress</MeterLabel>
7
+ <MeterValue />
8
+ <MeterTrack>
9
+ <MeterIndicator />
10
+ </MeterTrack>
11
+ </Meter>
25
12
  );
26
13
  }
@@ -0,0 +1,13 @@
1
+ import { Meter, MeterIndicator, MeterLabel, MeterTrack, MeterValue } from "@/components/ui/meter";
2
+
3
+ export default function MeterIndicatorDemo() {
4
+ return (
5
+ <Meter className={"w-72"} value={32}>
6
+ <MeterTrack>
7
+ <MeterIndicator />
8
+ </MeterTrack>
9
+ <MeterLabel>Progress</MeterLabel>
10
+ <MeterValue />
11
+ </Meter>
12
+ );
13
+ }
@@ -0,0 +1,12 @@
1
+ import { Meter, MeterIndicator, MeterTrack, MeterValue } from "@/components/ui/meter";
2
+
3
+ export default function MeterNoLabelDemo() {
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
+ );
12
+ }
@@ -0,0 +1,12 @@
1
+ import { Meter, MeterIndicator, MeterLabel, MeterTrack } from "@/components/ui/meter";
2
+
3
+ export default function MeterNoValueDemo() {
4
+ return (
5
+ <Meter className={"w-72"} value={54}>
6
+ <MeterLabel>File transfer</MeterLabel>
7
+ <MeterTrack>
8
+ <MeterIndicator />
9
+ </MeterTrack>
10
+ </Meter>
11
+ );
12
+ }
@@ -1,3 +1,115 @@
1
+ import {
2
+ NavigationMenu,
3
+ NavigationMenuTrigger,
4
+ NavigationMenuItem,
5
+ NavigationMenuContent,
6
+ NavigationMenuLink,
7
+ NavigationMenuPopup,
8
+ NavigationMenuList,
9
+ } from "@/components/ui/navigation-menu";
10
+
1
11
  export default function NavigationMenuDemo() {
2
- return <div></div>;
12
+ return (
13
+ <div>
14
+ <NavigationMenu>
15
+ <NavigationMenuList>
16
+ <NavigationMenuItem>
17
+ <NavigationMenuTrigger>Overview</NavigationMenuTrigger>
18
+ <NavigationMenuContent>
19
+ <ul className="grid max-w-md grid-cols-2 gap-4 p-2">
20
+ {overviewLinks.map((item) => (
21
+ <li key={item.href}>
22
+ <NavigationMenuLink href={item.href}>
23
+ <div className="flex flex-col">
24
+ <h3 className="text-sm leading-5 font-medium">{item.title}</h3>
25
+ <p className="text-xs leading-tight text-muted-foreground">
26
+ {item.description}
27
+ </p>
28
+ </div>
29
+ </NavigationMenuLink>
30
+ </li>
31
+ ))}
32
+ </ul>
33
+ </NavigationMenuContent>
34
+ </NavigationMenuItem>
35
+
36
+ <NavigationMenuItem>
37
+ <NavigationMenuTrigger>Handbook</NavigationMenuTrigger>
38
+ <NavigationMenuContent>
39
+ <ul className="grid max-w-md grid-cols-2 gap-2 p-2">
40
+ {handbookLinks.map((item) => (
41
+ <li key={item.href}>
42
+ <NavigationMenuLink href={item.href}>
43
+ <div className="flex flex-col">
44
+ <h3 className="text-sm leading-5 font-medium">{item.title}</h3>
45
+ <p className="text-xs leading-tight text-muted-foreground">
46
+ {item.description}
47
+ </p>
48
+ </div>
49
+ </NavigationMenuLink>
50
+ </li>
51
+ ))}
52
+ </ul>
53
+ </NavigationMenuContent>
54
+ </NavigationMenuItem>
55
+
56
+ <NavigationMenuItem>
57
+ <NavigationMenuLink
58
+ className={
59
+ "flex items-center gap-1 rounded-lg px-3 py-1.5 text-sm font-medium transition-all duration-50 hover:bg-accent/60 hover:text-accent-foreground focus:bg-accent/60"
60
+ }
61
+ >
62
+ About
63
+ </NavigationMenuLink>
64
+ </NavigationMenuItem>
65
+ </NavigationMenuList>
66
+
67
+ <NavigationMenuPopup />
68
+ </NavigationMenu>
69
+ </div>
70
+ );
3
71
  }
72
+
73
+ const overviewLinks = [
74
+ {
75
+ href: "/react/overview/quick-start",
76
+ title: "Quick Start",
77
+ description: "Install and assemble your first component.",
78
+ },
79
+ {
80
+ href: "/react/overview/accessibility",
81
+ title: "Accessibility",
82
+ description: "Learn how we build accessible components.",
83
+ },
84
+ {
85
+ href: "/react/overview/releases",
86
+ title: "Releases",
87
+ description: "See what’s new in the latest Base UI versions.",
88
+ },
89
+ {
90
+ href: "/react/overview/about",
91
+ title: "About",
92
+ description: "Learn more about Base UI and our mission.",
93
+ },
94
+ ] as const;
95
+
96
+ const handbookLinks = [
97
+ {
98
+ href: "/react/handbook/styling",
99
+ title: "Styling",
100
+ description:
101
+ "Base UI components can be styled with plain CSS, Tailwind CSS, CSS-in-JS, or CSS Modules.",
102
+ },
103
+ {
104
+ href: "/react/handbook/animation",
105
+ title: "Animation",
106
+ description:
107
+ "Base UI components can be animated with CSS transitions, CSS animations, or JavaScript libraries.",
108
+ },
109
+ {
110
+ href: "/react/handbook/composition",
111
+ title: "Composition",
112
+ description:
113
+ "Base UI components can be replaced and composed with your own existing components.",
114
+ },
115
+ ] as const;
@@ -0,0 +1,20 @@
1
+ import {
2
+ NumberField,
3
+ NumberFieldGroup,
4
+ NumberFieldInput,
5
+ NumberFieldDecrement,
6
+ NumberFieldIncrement,
7
+ } from "@/components/ui/number-field";
8
+
9
+ export default function NumberFieldButtonsEndExample() {
10
+ return (
11
+ <NumberField defaultValue={8} className="w-40">
12
+ <NumberFieldGroup>
13
+ <NumberFieldInput />
14
+ {/* align props aren't required — data-align/read-order handled by props in component */}
15
+ <NumberFieldDecrement align="end" />
16
+ <NumberFieldIncrement align="end" />
17
+ </NumberFieldGroup>
18
+ </NumberField>
19
+ );
20
+ }
@@ -1,3 +1,19 @@
1
+ import {
2
+ NumberField,
3
+ NumberFieldDecrement,
4
+ NumberFieldGroup,
5
+ NumberFieldIncrement,
6
+ NumberFieldInput,
7
+ } from "@/components/ui/number-field";
8
+
1
9
  export default function NumberFieldDemo() {
2
- return <div></div>;
10
+ return (
11
+ <NumberField defaultValue={21}>
12
+ <NumberFieldGroup>
13
+ <NumberFieldDecrement data-align="start" />
14
+ <NumberFieldInput />
15
+ <NumberFieldIncrement data-align="end" />
16
+ </NumberFieldGroup>
17
+ </NumberField>
18
+ );
3
19
  }
@@ -0,0 +1,38 @@
1
+ import { ChevronsLeftRightEllipsis } from "lucide-react";
2
+ import * as React from "react";
3
+
4
+ import {
5
+ NumberField,
6
+ NumberFieldGroup,
7
+ NumberFieldInput,
8
+ NumberFieldIncrement,
9
+ NumberFieldDecrement,
10
+ NumberFieldScrubArea,
11
+ NumberFieldScrubAreaCursor,
12
+ } from "@/components/ui/number-field";
13
+
14
+ export default function NumberFieldScrubExample() {
15
+ const id = React.useId();
16
+ const [value, setValue] = React.useState<number | null>(120);
17
+
18
+ return (
19
+ <div className="flex flex-col gap-2">
20
+ <NumberField id={id} value={value} onValueChange={(v) => setValue(v)}>
21
+ <NumberFieldScrubArea>
22
+ <label htmlFor={id} className="text-sm font-medium">
23
+ Amount
24
+ </label>
25
+ <NumberFieldScrubAreaCursor>
26
+ <ChevronsLeftRightEllipsis className="size-4" />
27
+ </NumberFieldScrubAreaCursor>
28
+
29
+ <NumberFieldGroup>
30
+ <NumberFieldDecrement data-align="start" />
31
+ <NumberFieldInput />
32
+ <NumberFieldIncrement data-align="end" />
33
+ </NumberFieldGroup>
34
+ </NumberFieldScrubArea>
35
+ </NumberField>
36
+ </div>
37
+ );
38
+ }
@@ -1,3 +1,20 @@
1
+ import { Button } from "@/components/ui/button";
2
+ import {
3
+ Popover,
4
+ PopoverDescription,
5
+ PopoverPopup,
6
+ PopoverTitle,
7
+ PopoverTrigger,
8
+ } from "@/components/ui/popover";
9
+
1
10
  export default function PopoverDemo() {
2
- return <div></div>;
11
+ return (
12
+ <Popover>
13
+ <PopoverTrigger render={<Button variant={"secondary"}>Open popover</Button>} />
14
+ <PopoverPopup>
15
+ <PopoverTitle>Popover component</PopoverTitle>
16
+ <PopoverDescription>This is the popover description content.</PopoverDescription>
17
+ </PopoverPopup>
18
+ </Popover>
19
+ );
3
20
  }
@@ -0,0 +1,46 @@
1
+ "use client";
2
+
3
+ import { Button } from "@/components/ui/button";
4
+ import { Field, FieldLabel, FieldControl } from "@/components/ui/field";
5
+ import {
6
+ Popover,
7
+ PopoverTrigger,
8
+ PopoverPopup,
9
+ PopoverTitle,
10
+ PopoverClose,
11
+ } from "@/components/ui/popover";
12
+
13
+ export default function PopoverFormExample() {
14
+ return (
15
+ <Popover>
16
+ <PopoverTrigger render={<Button>Open Form</Button>} />
17
+ <PopoverPopup>
18
+ <PopoverTitle>User Information</PopoverTitle>
19
+ <div className="space-y-3">
20
+ <Field name="firstName" className="w-full">
21
+ <FieldLabel>First Name</FieldLabel>
22
+ <FieldControl type="text" placeholder="John" />
23
+ </Field>
24
+ <Field name="lastName" className="w-full">
25
+ <FieldLabel>Last Name</FieldLabel>
26
+ <FieldControl type="text" placeholder="Doe" />
27
+ </Field>
28
+ <Field name="email" className="w-full">
29
+ <FieldLabel>Email</FieldLabel>
30
+ <FieldControl type="email" placeholder="john@example.com" />
31
+ </Field>
32
+ <div className="flex justify-end gap-2 pt-2">
33
+ <Button size="sm">Submit</Button>
34
+ <PopoverClose
35
+ render={
36
+ <Button variant="outline" size="sm">
37
+ Cancel
38
+ </Button>
39
+ }
40
+ />
41
+ </div>
42
+ </div>
43
+ </PopoverPopup>
44
+ </Popover>
45
+ );
46
+ }
@@ -0,0 +1,54 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+
5
+ import { Button } from "@/components/ui/button";
6
+ import { ButtonGroup } from "@/components/ui/button-group";
7
+ import {
8
+ Popover,
9
+ PopoverTrigger,
10
+ PopoverPopup,
11
+ PopoverTitle,
12
+ PopoverDescription,
13
+ PopoverClose,
14
+ } from "@/components/ui/popover";
15
+
16
+ export default function PopoverPositionsExample() {
17
+ const [activePosition, setActivePosition] = React.useState(positions[0]);
18
+ return (
19
+ <div className="flex flex-wrap gap-4">
20
+ <Popover>
21
+ <ButtonGroup>
22
+ {positions.map((pos) => (
23
+ <PopoverTrigger
24
+ key={pos.side}
25
+ render={<Button variant={"outline"}>{pos.label}</Button>}
26
+ onClick={() => setActivePosition(pos)}
27
+ />
28
+ ))}
29
+ </ButtonGroup>
30
+ <PopoverPopup side={activePosition.side}>
31
+ <PopoverTitle>Position Example</PopoverTitle>
32
+ <PopoverDescription>
33
+ This popover is positioned on the {activePosition.label.toLowerCase()} side.
34
+ </PopoverDescription>
35
+ <PopoverClose
36
+ render={
37
+ <Button variant="ghost" size="sm" className={"ml-auto"}>
38
+ Close
39
+ </Button>
40
+ }
41
+ />
42
+ </PopoverPopup>
43
+ </Popover>
44
+ </div>
45
+ );
46
+ }
47
+
48
+ const positions: Position[] = [
49
+ { label: "Left", side: "left" },
50
+ { label: "Center", side: "bottom" },
51
+ { label: "Right", side: "right" },
52
+ ];
53
+
54
+ type Position = { label: string; side: "top" | "right" | "bottom" | "left" };
@@ -1,3 +1,28 @@
1
+ import { PreviewCard, PreviewCardPopup, PreviewCardTrigger } from "@/components/ui/preview-card";
2
+
1
3
  export default function PreviewCardDemo() {
2
- return <div></div>;
4
+ return (
5
+ <PreviewCard>
6
+ <p className={' text-sm'}>
7
+ Apple's{" "}
8
+ <PreviewCardTrigger
9
+ target={"_blank"}
10
+ href={"https://developer.apple.com/documentation/TechnologyOverviews/liquid-glass"}
11
+ >
12
+ Liquid Glass
13
+ </PreviewCardTrigger>{" "}
14
+ has been a controversial release.
15
+ </p>
16
+ <PreviewCardPopup className={"flex w-fit flex-col gap-2 items-center justify-center p-3"}>
17
+ <img
18
+ alt={"Liquid Glass UI"}
19
+ className={"w-72 rounded-lg bg-muted object-cover p-2"}
20
+ src={
21
+ "https://docs-assets.developer.apple.com/published/2299e5e8eafedded6947927a8f704c34/landing-page-intoducing-liquid-glass-hero~dark%402x.png"
22
+ }
23
+ />
24
+ <p className={"text-xs"}>Liquid glass affects SwiftUI, UIKit, and AppKit.</p>
25
+ </PreviewCardPopup>
26
+ </PreviewCard>
27
+ );
3
28
  }
@@ -0,0 +1,38 @@
1
+ import {
2
+ Card,
3
+ CardContent,
4
+ CardDescription,
5
+ CardHeader,
6
+ CardTitle,
7
+ } from "@/components/ui/card.tsx";
8
+ import { Meter } from "@/components/ui/meter.tsx";
9
+ import { PreviewCard, PreviewCardPopup, PreviewCardTrigger } from "@/components/ui/preview-card";
10
+ import { Button } from "@/components/ui/button.tsx";
11
+ import { Badge } from "@/components/ui/badge.tsx";
12
+
13
+ export default function PreviewCardLinks() {
14
+ return (
15
+ <PreviewCard>
16
+ <Card size={"sm"} className={"w-md"}>
17
+ <CardHeader className={"flex flex-row items-center justify-between"}>
18
+ <CardTitle>Quote usage</CardTitle>
19
+ <Badge variant={'warning'}>Basic</Badge>
20
+ </CardHeader>
21
+ <CardContent className={'space-y-3'}>
22
+ <Meter value={72} className={"w-full"} />
23
+ <div className={'flex flex-col'}>
24
+ <CardDescription>
25
+ 72 out of 100 requests used this <PreviewCardTrigger>month</PreviewCardTrigger>.
26
+ </CardDescription>
27
+ </div>
28
+ </CardContent>
29
+ </Card>
30
+ <PreviewCardPopup side={"bottom"} className={'w-sm p-4'}>
31
+ <div className="flex flex-col gap-2">
32
+ <p className={'text-xs text-muted-foreground'}>Usage resets {new Date(Date.now() + 4 * 7 * 24 * 60 * 60 * 1000).toLocaleDateString()} (4 weeks from now).</p>
33
+ <Button variant={'secondary'} className={'ml-auto'} size={'sm'}>Upgrade to Pro</Button>
34
+ </div>
35
+ </PreviewCardPopup>
36
+ </PreviewCard>
37
+ );
38
+ }