@shadow-js/ui 0.0.0-stage → 1.0.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 (190) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +598 -2
  4. package/dist/cli.mjs +2293 -0
  5. package/dist/dev/cli/schema.d.ts +73 -0
  6. package/dist/dev/index.d.ts +6 -0
  7. package/dist/dev/index.js +5 -0
  8. package/dist/dev/locales/ar.d.ts +141 -0
  9. package/dist/dev/locales/ar.js +128 -0
  10. package/dist/dev/locales/ar.js.map +1 -0
  11. package/dist/dev/locales/en.d.ts +141 -0
  12. package/dist/dev/locales/en.js +128 -0
  13. package/dist/dev/locales/en.js.map +1 -0
  14. package/dist/dev/registry/utils/utils.d.ts +29 -0
  15. package/dist/dev/registry/utils/utils.js +27 -0
  16. package/dist/dev/registry/utils/utils.js.map +1 -0
  17. package/dist/dev/theme/theme-logic.d.ts +187 -0
  18. package/dist/dev/theme/theme-logic.js +184 -0
  19. package/dist/dev/theme/theme-logic.js.map +1 -0
  20. package/dist/dev/theme/theme-provider.d.ts +90 -0
  21. package/dist/dev/theme/theme-provider.js +150 -0
  22. package/dist/dev/theme/theme-provider.js.map +1 -0
  23. package/dist/prod/index.js +1 -0
  24. package/dist/prod/locales/ar.js +2 -0
  25. package/dist/prod/locales/ar.js.map +1 -0
  26. package/dist/prod/locales/en.js +2 -0
  27. package/dist/prod/locales/en.js.map +1 -0
  28. package/dist/prod/registry/utils/utils.js +2 -0
  29. package/dist/prod/registry/utils/utils.js.map +1 -0
  30. package/dist/prod/theme/theme-logic.js +2 -0
  31. package/dist/prod/theme/theme-logic.js.map +1 -0
  32. package/dist/prod/theme/theme-provider.js +2 -0
  33. package/dist/prod/theme/theme-provider.js.map +1 -0
  34. package/package.json +102 -4
  35. package/registry/accordion/accordion.tsx +210 -0
  36. package/registry/accordion/item.json +4 -0
  37. package/registry/alert/alert.tsx +200 -0
  38. package/registry/alert/item.json +4 -0
  39. package/registry/alert-dialog/alert-dialog.tsx +530 -0
  40. package/registry/alert-dialog/item.json +4 -0
  41. package/registry/aspect-ratio/aspect-ratio.tsx +71 -0
  42. package/registry/aspect-ratio/item.json +4 -0
  43. package/registry/attachment/attachment.tsx +459 -0
  44. package/registry/attachment/item.json +4 -0
  45. package/registry/avatar/avatar.tsx +385 -0
  46. package/registry/avatar/item.json +4 -0
  47. package/registry/badge/badge.tsx +108 -0
  48. package/registry/badge/item.json +4 -0
  49. package/registry/breadcrumb/breadcrumb.tsx +354 -0
  50. package/registry/breadcrumb/item.json +4 -0
  51. package/registry/bubble/bubble.tsx +260 -0
  52. package/registry/bubble/item.json +4 -0
  53. package/registry/button/button.tsx +125 -0
  54. package/registry/button/item.json +4 -0
  55. package/registry/button-group/button-group.tsx +189 -0
  56. package/registry/button-group/item.json +4 -0
  57. package/registry/calendar/calendar.tsx +348 -0
  58. package/registry/calendar/item.json +4 -0
  59. package/registry/card/card.tsx +311 -0
  60. package/registry/card/item.json +4 -0
  61. package/registry/carousel/carousel.tsx +851 -0
  62. package/registry/carousel/item.json +4 -0
  63. package/registry/chart/chart.tsx +1956 -0
  64. package/registry/chart/item.json +4 -0
  65. package/registry/chart-scale/chart-scale.ts +670 -0
  66. package/registry/chart-scale/item.json +5 -0
  67. package/registry/checkbox/checkbox.tsx +79 -0
  68. package/registry/checkbox/item.json +4 -0
  69. package/registry/code-block/code-block.tsx +470 -0
  70. package/registry/code-block/item.json +4 -0
  71. package/registry/collapsible/collapsible.tsx +117 -0
  72. package/registry/collapsible/item.json +4 -0
  73. package/registry/combobox/combobox.tsx +977 -0
  74. package/registry/combobox/item.json +4 -0
  75. package/registry/command/command.tsx +757 -0
  76. package/registry/command/item.json +4 -0
  77. package/registry/context-menu/context-menu.tsx +697 -0
  78. package/registry/context-menu/item.json +4 -0
  79. package/registry/data-table/data-table.tsx +437 -0
  80. package/registry/data-table/item.json +4 -0
  81. package/registry/date-picker/date-picker.tsx +349 -0
  82. package/registry/date-picker/item.json +4 -0
  83. package/registry/dialog/dialog.tsx +412 -0
  84. package/registry/dialog/item.json +4 -0
  85. package/registry/direction/direction.tsx +88 -0
  86. package/registry/direction/item.json +4 -0
  87. package/registry/drawer/drawer.tsx +787 -0
  88. package/registry/drawer/item.json +4 -0
  89. package/registry/dropdown-menu/dropdown-menu.tsx +692 -0
  90. package/registry/dropdown-menu/item.json +4 -0
  91. package/registry/empty/empty.tsx +240 -0
  92. package/registry/empty/item.json +4 -0
  93. package/registry/field/field.tsx +624 -0
  94. package/registry/field/item.json +4 -0
  95. package/registry/form/form.tsx +1112 -0
  96. package/registry/form/item.json +4 -0
  97. package/registry/hover-card/hover-card.tsx +144 -0
  98. package/registry/hover-card/item.json +4 -0
  99. package/registry/icons/icons.tsx +1691 -0
  100. package/registry/icons/item.json +4 -0
  101. package/registry/input/input.tsx +43 -0
  102. package/registry/input/item.json +4 -0
  103. package/registry/input-group/input-group.tsx +315 -0
  104. package/registry/input-group/item.json +4 -0
  105. package/registry/input-otp/input-otp.tsx +329 -0
  106. package/registry/input-otp/item.json +4 -0
  107. package/registry/item/item.json +4 -0
  108. package/registry/item/item.tsx +439 -0
  109. package/registry/kbd/item.json +4 -0
  110. package/registry/kbd/kbd.tsx +65 -0
  111. package/registry/label/item.json +4 -0
  112. package/registry/label/label.tsx +60 -0
  113. package/registry/marker/item.json +4 -0
  114. package/registry/marker/marker.tsx +175 -0
  115. package/registry/menubar/item.json +4 -0
  116. package/registry/menubar/menubar.tsx +694 -0
  117. package/registry/message/item.json +4 -0
  118. package/registry/message/message.tsx +280 -0
  119. package/registry/message-scroller/item.json +4 -0
  120. package/registry/message-scroller/message-scroller.tsx +262 -0
  121. package/registry/native-select/item.json +4 -0
  122. package/registry/native-select/native-select.tsx +113 -0
  123. package/registry/navigation-menu/item.json +4 -0
  124. package/registry/navigation-menu/navigation-menu.tsx +362 -0
  125. package/registry/pagination/item.json +4 -0
  126. package/registry/pagination/pagination.tsx +460 -0
  127. package/registry/password-input/item.json +5 -0
  128. package/registry/password-input/password-input.tsx +494 -0
  129. package/registry/popover/item.json +4 -0
  130. package/registry/popover/popover.tsx +284 -0
  131. package/registry/progress/item.json +4 -0
  132. package/registry/progress/progress.tsx +190 -0
  133. package/registry/questionnaire/item.json +4 -0
  134. package/registry/questionnaire/questionnaire.tsx +569 -0
  135. package/registry/radio-group/item.json +4 -0
  136. package/registry/radio-group/radio-group.tsx +101 -0
  137. package/registry/resizable/item.json +4 -0
  138. package/registry/resizable/resizable.tsx +455 -0
  139. package/registry/scroll-area/item.json +4 -0
  140. package/registry/scroll-area/scroll-area.tsx +149 -0
  141. package/registry/select/item.json +4 -0
  142. package/registry/select/select.tsx +571 -0
  143. package/registry/separator/item.json +4 -0
  144. package/registry/separator/separator.tsx +52 -0
  145. package/registry/sheet/item.json +4 -0
  146. package/registry/sheet/sheet.tsx +476 -0
  147. package/registry/sidebar/item.json +4 -0
  148. package/registry/sidebar/sidebar.tsx +1870 -0
  149. package/registry/skeleton/item.json +4 -0
  150. package/registry/skeleton/skeleton.tsx +47 -0
  151. package/registry/slider/item.json +4 -0
  152. package/registry/slider/slider.tsx +149 -0
  153. package/registry/spinner/item.json +4 -0
  154. package/registry/spinner/spinner.tsx +51 -0
  155. package/registry/switch/item.json +4 -0
  156. package/registry/switch/switch.tsx +93 -0
  157. package/registry/table/item.json +4 -0
  158. package/registry/table/table.tsx +373 -0
  159. package/registry/tabs/item.json +4 -0
  160. package/registry/tabs/tabs.tsx +209 -0
  161. package/registry/textarea/item.json +4 -0
  162. package/registry/textarea/textarea.tsx +51 -0
  163. package/registry/toast/item.json +4 -0
  164. package/registry/toast/toast.tsx +949 -0
  165. package/registry/toggle/item.json +4 -0
  166. package/registry/toggle/toggle.tsx +110 -0
  167. package/registry/toggle-group/item.json +4 -0
  168. package/registry/toggle-group/toggle-group.tsx +189 -0
  169. package/registry/tooltip/item.json +4 -0
  170. package/registry/tooltip/tooltip.tsx +169 -0
  171. package/registry/trace/item.json +4 -0
  172. package/registry/trace/trace.tsx +356 -0
  173. package/registry/ui-strings/item.json +5 -0
  174. package/registry/ui-strings/ui-strings.tsx +454 -0
  175. package/registry/use-highlighted-code/item.json +5 -0
  176. package/registry/use-highlighted-code/use-highlighted-code.tsx +145 -0
  177. package/registry/use-mobile/item.json +5 -0
  178. package/registry/use-mobile/use-mobile.ts +46 -0
  179. package/registry/utils/item.json +5 -0
  180. package/registry/utils/utils.ts +38 -0
  181. package/registry.json +3274 -0
  182. package/styles/animations.css +321 -0
  183. package/styles/theme-core.css +55 -0
  184. package/styles/theme.css +12 -0
  185. package/styles/themes/gray.css +69 -0
  186. package/styles/themes/neutral.css +69 -0
  187. package/styles/themes/slate.css +69 -0
  188. package/styles/themes/stone.css +69 -0
  189. package/styles/themes/zinc.css +69 -0
  190. package/styles/typeset.css +251 -0
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Toggle",
3
+ "description": "A two-state button that can be either on or off."
4
+ }
@@ -0,0 +1,110 @@
1
+ import { splitProps } from "@shadow-js/core";
2
+ import {
3
+ type PolymorphicTarget,
4
+ Toggle as TogglePrimitive,
5
+ type ToggleProps as TogglePrimitiveProps,
6
+ } from "@shadow-js/primitives";
7
+ import type { JSX } from "@shadow-js/web";
8
+ import { cva, type VariantProps } from "class-variance-authority";
9
+ import { type ClassValue, cn } from "@/lib/utils";
10
+
11
+ /**
12
+ * The class list of a toggle, built from `variant` and `size`. Use it to style another element
13
+ * (for example a link) like a toggle. The pressed look comes from `data-state="on"`, which
14
+ * {@link Toggle} sets.
15
+ *
16
+ * @param props - Optional `variant` (`"default"` or `"outline"`) and `size` (`"default"`, `"sm"` or
17
+ * `"lg"`), and an optional `class` to add.
18
+ * @returns The class string.
19
+ * @example
20
+ * ```tsx
21
+ * import { toggleVariants } from "@/components/ui/toggle";
22
+ *
23
+ * export function BoldLink() {
24
+ * return (
25
+ * <a href="/bold" class={toggleVariants({ variant: "outline", size: "sm" })}>
26
+ * Bold
27
+ * </a>
28
+ * );
29
+ * }
30
+ * ```
31
+ * @since 1.0.0
32
+ * @see {@link Toggle}
33
+ */
34
+ const toggleVariants = cva(
35
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 motion-reduce:transition-none data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 forced-colors:data-[state=on]:bg-[Highlight] forced-colors:data-[state=on]:text-[HighlightText] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-transparent",
36
+ {
37
+ variants: {
38
+ variant: {
39
+ default: "bg-transparent",
40
+ outline:
41
+ "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground",
42
+ },
43
+ size: {
44
+ default: "h-9 min-w-9 px-2",
45
+ sm: "h-8 min-w-8 px-1.5",
46
+ lg: "h-10 min-w-10 px-2.5",
47
+ },
48
+ },
49
+ defaultVariants: {
50
+ variant: "default",
51
+ size: "default",
52
+ },
53
+ },
54
+ );
55
+
56
+ /** The props as the implementation sees them. */
57
+ type Loose = VariantProps<typeof toggleVariants> & {
58
+ readonly class?: ClassValue;
59
+ readonly [prop: string]: unknown;
60
+ };
61
+
62
+ /**
63
+ * Props of {@link Toggle}: the primitive's props (`pressed`, `defaultPressed`, `onPressedChange`,
64
+ * `disabled`), `variant` (`"default"` or `"outline"`) and `size` (`"default"`, `"sm"` or `"lg"`),
65
+ * and the attributes of the rendered `button`. `as` renders another element instead.
66
+ * @since 1.0.0
67
+ * @see {@link Toggle}
68
+ */
69
+ export type ToggleProps<T extends PolymorphicTarget = "button"> = TogglePrimitiveProps<T> &
70
+ VariantProps<typeof toggleVariants>;
71
+
72
+ /**
73
+ * A two-state button that is either pressed (on) or not. Controlled with `pressed` and
74
+ * `onPressedChange`, or uncontrolled with `defaultPressed`. Pick a `variant` and a `size`.
75
+ *
76
+ * Keyboard and ARIA: Space, Enter and a click toggle it. It is a `button` with `aria-pressed`
77
+ * (`"true"` or `"false"`) and `data-state` (`"on"` or `"off"`). Disabled, it is a disabled button.
78
+ * A toggle that shows only an icon needs an `aria-label`, because the icon has no text to name it.
79
+ *
80
+ * shadcn/ui differences: `class` replaces `className`, and `as` replaces `asChild`.
81
+ *
82
+ * @param props - The props, see {@link ToggleProps}.
83
+ * @returns The toggle `button`.
84
+ * @example
85
+ * ```tsx
86
+ * import { Toggle } from "@/components/ui/toggle";
87
+ *
88
+ * export function BoldToggle() {
89
+ * return (
90
+ * <Toggle aria-label="Toggle bold" variant="outline" onPressedChange={(on: boolean) => console.log(on)}>
91
+ * B
92
+ * </Toggle>
93
+ * );
94
+ * }
95
+ * ```
96
+ * @since 1.0.0
97
+ * @see {@link toggleVariants}
98
+ */
99
+ function Toggle<T extends PolymorphicTarget = "button">(props: ToggleProps<T>): JSX.Element {
100
+ const [local, rest] = splitProps(props as unknown as Loose, ["class", "variant", "size"]);
101
+ return (
102
+ <TogglePrimitive
103
+ data-slot="toggle"
104
+ class={cn(toggleVariants({ variant: local.variant, size: local.size }), local.class)}
105
+ {...rest}
106
+ />
107
+ );
108
+ }
109
+
110
+ export { Toggle, toggleVariants };
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Toggle Group",
3
+ "description": "A set of two-state buttons that can be toggled on or off."
4
+ }
@@ -0,0 +1,189 @@
1
+ import { createContext, splitProps, useContext } from "@shadow-js/core";
2
+ import {
3
+ type PolymorphicTarget,
4
+ type ToggleGroupItemProps as ToggleGroupItemPrimitiveProps,
5
+ ToggleGroup as ToggleGroupPrimitive,
6
+ type ToggleGroupProps as ToggleGroupPrimitiveProps,
7
+ } from "@shadow-js/primitives";
8
+ import type { JSX } from "@shadow-js/web";
9
+ import type { VariantProps } from "class-variance-authority";
10
+ import { toggleVariants } from "@/components/ui/toggle";
11
+ import { type ClassValue, cn } from "@/lib/utils";
12
+
13
+ type ToggleVariants = VariantProps<typeof toggleVariants>;
14
+
15
+ /** What the items read from their group. */
16
+ interface ToggleGroupContextValue {
17
+ readonly variant: () => ToggleVariants["variant"];
18
+ readonly size: () => ToggleVariants["size"];
19
+ readonly spacing: () => number;
20
+ }
21
+
22
+ const ToggleGroupContext = createContext<ToggleGroupContextValue>({
23
+ variant: () => "default",
24
+ size: () => "default",
25
+ spacing: () => 0,
26
+ });
27
+
28
+ /** The props as the implementation sees them. */
29
+ type Loose = ToggleVariants & {
30
+ readonly class?: ClassValue;
31
+ readonly children?: JSX.Element;
32
+ readonly [prop: string]: unknown;
33
+ };
34
+
35
+ /**
36
+ * Props of {@link ToggleGroup}: the primitive's props (`type="single" | "multiple"`, `value`,
37
+ * `defaultValue`, `onValueChange`, `disabled`, `orientation`, `dir`, `loop`, `rovingFocus`),
38
+ * `variant` and `size` (inherited by the items) and the attributes of the rendered `div`.
39
+ * @since 1.0.0
40
+ * @see {@link ToggleGroup}
41
+ */
42
+ export type ToggleGroupProps<T extends PolymorphicTarget = "div"> = ToggleGroupPrimitiveProps<T> &
43
+ ToggleVariants & {
44
+ /**
45
+ * The gap between the items, in units of the spacing scale (`spacing={2}` is 0.5 rem). `0` keeps the
46
+ * items connected: they share their borders and only the two ends are rounded. Any other value puts
47
+ * a gap between them and every item keeps its own corners and borders.
48
+ * @default 0
49
+ * @see {@link ToggleGroup}
50
+ */
51
+ readonly spacing?: number | undefined;
52
+ };
53
+
54
+ /**
55
+ * Props of {@link ToggleGroupItem}: the primitive's props (`value`, `disabled`), `variant` and
56
+ * `size` (they win over the group's) and the attributes of the rendered `button`.
57
+ * @since 1.0.0
58
+ * @see {@link ToggleGroupItem}
59
+ */
60
+ export type ToggleGroupItemProps<T extends PolymorphicTarget = "button"> =
61
+ ToggleGroupItemPrimitiveProps<T> & ToggleVariants;
62
+
63
+ /**
64
+ * A row of toggles that share one look. With `type="single"` at most one item is pressed, and the
65
+ * items are radios. With `type="multiple"` any number can be pressed. Control it with `value` and
66
+ * `onValueChange`, or start it with `defaultValue`. A single group reports one string (`""` when
67
+ * the pressed item is pressed again), and a multiple group reports an array. `variant` and `size`
68
+ * reach every item, unless an item sets its own.
69
+ *
70
+ * Keyboard and ARIA: the root is a `role="group"` and needs a name from you (`aria-label` or
71
+ * `aria-labelledby`). The group is one tab stop: the item that had focus last, else the pressed
72
+ * item, else the first enabled item. The arrow keys move between items (all four arrows unless
73
+ * `orientation` is set; Left and Right swap in a right-to-left group), Home and End go to the ends,
74
+ * and the group wraps and skips disabled items. Space and Enter press the focused item. In a single
75
+ * group an item is a `role="radio"` with `aria-checked`; in a multiple group it has `aria-pressed`.
76
+ *
77
+ * shadcn/ui differences: `class` replaces `className`.
78
+ *
79
+ * @param props - The props, see {@link ToggleGroupProps}.
80
+ * @returns The group `div` with its items inside.
81
+ * @example
82
+ * ```tsx
83
+ * import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
84
+ *
85
+ * export function TextStyle() {
86
+ * return (
87
+ * <ToggleGroup type="multiple" variant="outline" aria-label="Text style">
88
+ * <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
89
+ * <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
90
+ * </ToggleGroup>
91
+ * );
92
+ * }
93
+ * ```
94
+ * @since 1.0.0
95
+ * @see {@link ToggleGroupItem}
96
+ */
97
+ function ToggleGroup<T extends PolymorphicTarget = "div">(props: ToggleGroupProps<T>): JSX.Element {
98
+ const [local, rest] = splitProps(props as unknown as Loose, [
99
+ "class",
100
+ "variant",
101
+ "size",
102
+ "spacing",
103
+ "children",
104
+ ]);
105
+ const spacing = (): number => (local.spacing as number | undefined) ?? 0;
106
+ return (
107
+ <ToggleGroupPrimitive
108
+ data-slot="toggle-group"
109
+ data-variant={local.variant}
110
+ data-size={local.size}
111
+ data-spacing={spacing()}
112
+ style={{ "--gap": String(spacing()) }}
113
+ class={cn(
114
+ "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[orientation=vertical]:flex-col data-[orientation=vertical]:items-stretch data-[variant=outline]:shadow-xs",
115
+ local.class,
116
+ )}
117
+ {...(rest as unknown as ToggleGroupPrimitiveProps)}
118
+ >
119
+ <ToggleGroupContext.Provider
120
+ value={{ variant: () => local.variant, size: () => local.size, spacing }}
121
+ >
122
+ {local.children}
123
+ </ToggleGroupContext.Provider>
124
+ </ToggleGroupPrimitive>
125
+ );
126
+ }
127
+
128
+ /**
129
+ * One toggle of a {@link ToggleGroup}, identified by its `value`. Items sit flush against each
130
+ * other, so only the first and last item have rounded outer corners. A `variant` or `size` set on
131
+ * the item wins over the group's.
132
+ *
133
+ * Keyboard and ARIA: as for the group (see {@link ToggleGroup}). Space and Enter press the item. It
134
+ * is a `role="radio"` with `aria-checked` in a single group, and a `button` with `aria-pressed` in a
135
+ * multiple group. An item that shows only an icon needs an `aria-label`.
136
+ *
137
+ * @param props - The props: `value` (required), `disabled`, `variant`, `size`, and the attributes of
138
+ * the `button`.
139
+ * @returns The item `button`.
140
+ * @example
141
+ * ```tsx
142
+ * import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
143
+ *
144
+ * export function Alignment() {
145
+ * return (
146
+ * <ToggleGroup type="single" aria-label="Alignment">
147
+ * <ToggleGroupItem value="left" aria-label="Align left">
148
+ * Left
149
+ * </ToggleGroupItem>
150
+ * <ToggleGroupItem value="right" aria-label="Align right">
151
+ * Right
152
+ * </ToggleGroupItem>
153
+ * </ToggleGroup>
154
+ * );
155
+ * }
156
+ * ```
157
+ * @since 1.0.0
158
+ * @see {@link ToggleGroup}
159
+ */
160
+ function ToggleGroupItem<T extends PolymorphicTarget = "button">(
161
+ props: ToggleGroupItemProps<T>,
162
+ ): JSX.Element {
163
+ const group = useContext(ToggleGroupContext);
164
+ const [local, rest] = splitProps(props as unknown as Loose & { readonly value: string }, [
165
+ "class",
166
+ "variant",
167
+ "size",
168
+ "value",
169
+ ]);
170
+ const variant = (): ToggleVariants["variant"] => local.variant ?? group.variant();
171
+ const size = (): ToggleVariants["size"] => local.size ?? group.size();
172
+ return (
173
+ <ToggleGroupPrimitive.Item
174
+ data-slot="toggle-group-item"
175
+ data-variant={variant()}
176
+ data-size={size()}
177
+ data-spacing={group.spacing()}
178
+ value={local.value}
179
+ class={cn(
180
+ toggleVariants({ variant: variant(), size: size() }),
181
+ "min-w-0 flex-1 shrink-0 shadow-none focus:z-10 focus-visible:z-10 data-[spacing=0]:rounded-none data-[spacing=0]:first:rounded-s-md data-[spacing=0]:last:rounded-e-md data-[spacing=0]:data-[variant=outline]:border-s-0 data-[spacing=0]:data-[variant=outline]:first:border-s group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:first:rounded-t-md group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:first:rounded-b-none group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:last:rounded-b-md group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:last:rounded-t-none group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=outline]:border-s group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-[orientation=vertical]/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
182
+ local.class,
183
+ )}
184
+ {...rest}
185
+ />
186
+ );
187
+ }
188
+
189
+ export { ToggleGroup, ToggleGroupItem };
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Tooltip",
3
+ "description": "A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it."
4
+ }
@@ -0,0 +1,169 @@
1
+ import { splitProps } from "@shadow-js/core";
2
+ import {
3
+ type PolymorphicTarget,
4
+ type TooltipContentProps,
5
+ Tooltip as TooltipPrimitive,
6
+ type TooltipProps,
7
+ type TooltipProviderProps,
8
+ type TooltipTriggerProps,
9
+ tooltipGroupContext,
10
+ } from "@shadow-js/primitives";
11
+ import type { JSX } from "@shadow-js/web";
12
+ import { cn } from "@/lib/utils";
13
+
14
+ /**
15
+ * Shares the open delays between the tooltips inside it. `delayDuration` is how long the pointer
16
+ * must rest on a trigger before its tooltip opens, and it defaults to `0` here. `skipDelayDuration`
17
+ * is the window after one tooltip closes during which the next one opens without a delay. Renders
18
+ * no element; put one near the root of the application.
19
+ *
20
+ * @param props - The props: `delayDuration`, `skipDelayDuration`, and the other provider props.
21
+ * @returns The provider, wrapping its children.
22
+ * @example
23
+ * ```tsx
24
+ * import { TooltipProvider } from "@/components/ui/tooltip";
25
+ *
26
+ * export function App() {
27
+ * return (
28
+ * <TooltipProvider delayDuration={400}>
29
+ * <p>Hover a control to see its tooltip.</p>
30
+ * </TooltipProvider>
31
+ * );
32
+ * }
33
+ * ```
34
+ * @since 1.0.0
35
+ * @see {@link Tooltip}
36
+ */
37
+ function TooltipProvider(props: TooltipProviderProps): JSX.Element {
38
+ return <TooltipPrimitive.Provider {...props} delayDuration={props.delayDuration ?? 0} />;
39
+ }
40
+
41
+ /**
42
+ * A short label that appears when its trigger is hovered or focused. Put a {@link TooltipTrigger}
43
+ * and a {@link TooltipContent} inside it. Control it with `open` and `onOpenChange`, or start it
44
+ * with `defaultOpen`. Inside a {@link TooltipProvider} it uses the provider's delays. On its own it
45
+ * opens without a delay.
46
+ *
47
+ * Keyboard and ARIA: keyboard focus on the trigger opens the tooltip at once, and blurring the
48
+ * trigger closes it. Escape closes it too. A mouse that rests on the trigger opens it after the
49
+ * delay, and touch never opens it. The trigger is a `button` with `aria-describedby` pointing at the
50
+ * content while it is open, and the content is a `role="tooltip"`. A tooltip describes its trigger
51
+ * and does not name it, so give an icon-only trigger an `aria-label`.
52
+ *
53
+ * shadcn/ui differences: `as` replaces `asChild` on the trigger, and `class` replaces `className`.
54
+ *
55
+ * @param props - The props, see {@link TooltipProps}.
56
+ * @returns The tooltip, with its trigger and content inside.
57
+ * @example
58
+ * ```tsx
59
+ * import { Button } from "@/components/ui/button";
60
+ * import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
61
+ *
62
+ * export function SaveHint() {
63
+ * return (
64
+ * <Tooltip>
65
+ * <TooltipTrigger as={Button} variant="outline">
66
+ * Save
67
+ * </TooltipTrigger>
68
+ * <TooltipContent>Save the document</TooltipContent>
69
+ * </Tooltip>
70
+ * );
71
+ * }
72
+ * ```
73
+ * @since 1.0.0
74
+ * @see {@link TooltipProvider}
75
+ */
76
+ function Tooltip(props: TooltipProps): JSX.Element {
77
+ // A tooltip with a provider above it keeps that provider's delay and skip window.
78
+ const grouped = tooltipGroupContext.useOptional() !== undefined;
79
+ return grouped ? (
80
+ <TooltipPrimitive {...props} />
81
+ ) : (
82
+ <TooltipProvider>
83
+ <TooltipPrimitive {...props} />
84
+ </TooltipProvider>
85
+ );
86
+ }
87
+
88
+ /**
89
+ * The element the tooltip describes, and its anchor. It renders a `button`; `as` renders another
90
+ * element instead, such as a shadcn/ui `Button`.
91
+ *
92
+ * Keyboard and ARIA: it takes focus, which opens the tooltip; blurring, pressing, clicking or
93
+ * pressing Escape closes it. While the tooltip is open it has `aria-describedby` pointing at the
94
+ * content, and its `data-state` is `"closed"`, `"delayed-open"` or `"instant-open"`.
95
+ *
96
+ * shadcn/ui differences: `as` replaces `asChild`, and `class` replaces `className`.
97
+ *
98
+ * @param props - The props: `as` and the attributes of the trigger element.
99
+ * @returns The trigger element.
100
+ * @example
101
+ * ```tsx
102
+ * import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
103
+ *
104
+ * export function BoldHint() {
105
+ * return (
106
+ * <Tooltip>
107
+ * <TooltipTrigger aria-label="Bold">B</TooltipTrigger>
108
+ * <TooltipContent>Bold</TooltipContent>
109
+ * </Tooltip>
110
+ * );
111
+ * }
112
+ * ```
113
+ * @since 1.0.0
114
+ */
115
+ function TooltipTrigger<T extends PolymorphicTarget = "button">(
116
+ props: TooltipTriggerProps<T>,
117
+ ): JSX.Element {
118
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />;
119
+ }
120
+
121
+ /**
122
+ * The tooltip bubble with its arrow. It is rendered in `document.body` and placed above the trigger
123
+ * by default; `side` and `sideOffset` change that. Assistive technology reads a visually hidden copy
124
+ * of the content with `role="tooltip"`, so the visible content may hold markup and styling.
125
+ *
126
+ * Keyboard and ARIA: the content takes no focus and has no keys of its own; Escape closes the
127
+ * tooltip (see {@link Tooltip}). The trigger's `aria-describedby` points at the hidden copy.
128
+ *
129
+ * shadcn/ui differences: `class` replaces `className`.
130
+ *
131
+ * @param props - The props: `side`, `sideOffset`, `ariaLabel`, and the attributes of the bubble.
132
+ * @returns The bubble, rendered in a portal.
133
+ * @example
134
+ * ```tsx
135
+ * import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
136
+ *
137
+ * export function AddHint() {
138
+ * return (
139
+ * <Tooltip>
140
+ * <TooltipTrigger aria-label="Add">+</TooltipTrigger>
141
+ * <TooltipContent side="bottom">Add to library</TooltipContent>
142
+ * </Tooltip>
143
+ * );
144
+ * }
145
+ * ```
146
+ * @since 1.0.0
147
+ * @see {@link Tooltip}
148
+ */
149
+ function TooltipContent(props: TooltipContentProps): JSX.Element {
150
+ const [local, rest] = splitProps(props, ["class", "sideOffset", "children"]);
151
+ return (
152
+ <TooltipPrimitive.Portal>
153
+ <TooltipPrimitive.Content
154
+ data-slot="tooltip-content"
155
+ sideOffset={local.sideOffset ?? 0}
156
+ class={cn(
157
+ "z-50 w-fit origin-(--primitives-transform-origin) animate-in rounded-md bg-foreground px-3 py-1.5 text-xs text-balance text-background fade-in-0 zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 forced-colors:border",
158
+ local.class,
159
+ )}
160
+ {...rest}
161
+ >
162
+ {local.children}
163
+ <TooltipPrimitive.Arrow class="fill-foreground" width={10} height={5} />
164
+ </TooltipPrimitive.Content>
165
+ </TooltipPrimitive.Portal>
166
+ );
167
+ }
168
+
169
+ export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Trace",
3
+ "description": "A list of lines for the steps an agent takes: reasoning, tool calls, sources, plans and tasks, each with an icon, a title and a status, and optionally expandable."
4
+ }