@cl-light-ds/ui 0.1.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 (254) hide show
  1. package/README.md +45 -0
  2. package/package.json +59 -0
  3. package/src/components/accordion/Accordion.astro +248 -0
  4. package/src/components/accordion/AccordionContent.astro +26 -0
  5. package/src/components/accordion/AccordionItem.astro +36 -0
  6. package/src/components/accordion/AccordionTrigger.astro +118 -0
  7. package/src/components/accordion/CHANGELOG.md +41 -0
  8. package/src/components/accordion/index.ts +4 -0
  9. package/src/components/alert/Alert.astro +167 -0
  10. package/src/components/alert/AlertDescription.astro +24 -0
  11. package/src/components/alert/AlertTitle.astro +24 -0
  12. package/src/components/alert/CHANGELOG.md +5 -0
  13. package/src/components/alert/index.ts +4 -0
  14. package/src/components/avatar/Avatar.astro +197 -0
  15. package/src/components/avatar/AvatarBadge.astro +44 -0
  16. package/src/components/avatar/AvatarFallback.astro +26 -0
  17. package/src/components/avatar/AvatarGroup.astro +26 -0
  18. package/src/components/avatar/AvatarGroupCount.astro +30 -0
  19. package/src/components/avatar/AvatarImage.astro +46 -0
  20. package/src/components/avatar/CHANGELOG.md +44 -0
  21. package/src/components/avatar/index.ts +6 -0
  22. package/src/components/badge/Badge.astro +167 -0
  23. package/src/components/badge/CHANGELOG.md +49 -0
  24. package/src/components/badge/index.ts +2 -0
  25. package/src/components/breadcrumb/Breadcrumb.astro +76 -0
  26. package/src/components/breadcrumb/BreadcrumbItem.astro +32 -0
  27. package/src/components/breadcrumb/BreadcrumbList.astro +26 -0
  28. package/src/components/breadcrumb/BreadcrumbSeparator.astro +26 -0
  29. package/src/components/breadcrumb/CHANGELOG.md +24 -0
  30. package/src/components/breadcrumb/index.ts +5 -0
  31. package/src/components/button/Button.astro +233 -0
  32. package/src/components/button/CHANGELOG.md +41 -0
  33. package/src/components/button/index.ts +2 -0
  34. package/src/components/button-group/ButtonGroup.astro +130 -0
  35. package/src/components/button-group/ButtonGroupSeparator.astro +30 -0
  36. package/src/components/button-group/ButtonGroupText.astro +21 -0
  37. package/src/components/button-group/CHANGELOG.md +34 -0
  38. package/src/components/button-group/index.ts +3 -0
  39. package/src/components/card/CHANGELOG.md +119 -0
  40. package/src/components/card/Card.astro +182 -0
  41. package/src/components/card/CardAction.astro +26 -0
  42. package/src/components/card/CardContent.astro +28 -0
  43. package/src/components/card/CardDescription.astro +28 -0
  44. package/src/components/card/CardFooter.astro +24 -0
  45. package/src/components/card/CardHeader.astro +30 -0
  46. package/src/components/card/CardMedia.astro +27 -0
  47. package/src/components/card/CardOverlay.astro +32 -0
  48. package/src/components/card/CardTitle.astro +21 -0
  49. package/src/components/card/index.ts +10 -0
  50. package/src/components/carousel/CHANGELOG.md +5 -0
  51. package/src/components/carousel/Carousel.astro +106 -0
  52. package/src/components/carousel/CarouselSlide.astro +22 -0
  53. package/src/components/carousel/index.ts +3 -0
  54. package/src/components/checkbox/CHANGELOG.md +58 -0
  55. package/src/components/checkbox/Checkbox.astro +159 -0
  56. package/src/components/checkbox/index.ts +1 -0
  57. package/src/components/collapsible/CHANGELOG.md +5 -0
  58. package/src/components/collapsible/Collapsible.astro +202 -0
  59. package/src/components/collapsible/CollapsibleContent.astro +36 -0
  60. package/src/components/collapsible/CollapsibleTrigger.astro +34 -0
  61. package/src/components/collapsible/index.ts +4 -0
  62. package/src/components/combobox/CHANGELOG.md +27 -0
  63. package/src/components/combobox/Combobox.astro +365 -0
  64. package/src/components/combobox/ComboboxContent.astro +37 -0
  65. package/src/components/combobox/ComboboxEmpty.astro +18 -0
  66. package/src/components/combobox/ComboboxGroup.astro +19 -0
  67. package/src/components/combobox/ComboboxInput.astro +74 -0
  68. package/src/components/combobox/ComboboxItem.astro +39 -0
  69. package/src/components/combobox/ComboboxLabel.astro +18 -0
  70. package/src/components/combobox/ComboboxList.astro +21 -0
  71. package/src/components/combobox/ComboboxSeparator.astro +17 -0
  72. package/src/components/combobox/ComboboxTrigger.astro +30 -0
  73. package/src/components/combobox/ComboboxValue.astro +22 -0
  74. package/src/components/combobox/index.ts +11 -0
  75. package/src/components/date/CHANGELOG.md +18 -0
  76. package/src/components/date/Date.astro +137 -0
  77. package/src/components/date/index.ts +2 -0
  78. package/src/components/dialog/CHANGELOG.md +39 -0
  79. package/src/components/dialog/Dialog.astro +196 -0
  80. package/src/components/dialog/DialogClose.astro +23 -0
  81. package/src/components/dialog/DialogContent.astro +42 -0
  82. package/src/components/dialog/DialogDescription.astro +18 -0
  83. package/src/components/dialog/DialogFooter.astro +18 -0
  84. package/src/components/dialog/DialogHeader.astro +18 -0
  85. package/src/components/dialog/DialogOverlay.astro +19 -0
  86. package/src/components/dialog/DialogTitle.astro +18 -0
  87. package/src/components/dialog/DialogTrigger.astro +37 -0
  88. package/src/components/dialog/index.ts +9 -0
  89. package/src/components/dropdown-menu/CHANGELOG.md +194 -0
  90. package/src/components/dropdown-menu/DropdownMenu.astro +226 -0
  91. package/src/components/dropdown-menu/DropdownMenuCheckboxItem.astro +114 -0
  92. package/src/components/dropdown-menu/DropdownMenuContent.astro +42 -0
  93. package/src/components/dropdown-menu/DropdownMenuGroup.astro +19 -0
  94. package/src/components/dropdown-menu/DropdownMenuItem.astro +220 -0
  95. package/src/components/dropdown-menu/DropdownMenuItemContent.astro +79 -0
  96. package/src/components/dropdown-menu/DropdownMenuLabel.astro +20 -0
  97. package/src/components/dropdown-menu/DropdownMenuPortal.astro +13 -0
  98. package/src/components/dropdown-menu/DropdownMenuRadioGroup.astro +13 -0
  99. package/src/components/dropdown-menu/DropdownMenuRadioItem.astro +101 -0
  100. package/src/components/dropdown-menu/DropdownMenuSeparator.astro +18 -0
  101. package/src/components/dropdown-menu/DropdownMenuShortcut.astro +18 -0
  102. package/src/components/dropdown-menu/DropdownMenuTrigger.astro +49 -0
  103. package/src/components/dropdown-menu/dropdown-menu-item-variants.ts +24 -0
  104. package/src/components/dropdown-menu/index.ts +12 -0
  105. package/src/components/field/CHANGELOG.md +33 -0
  106. package/src/components/field/Field.astro +664 -0
  107. package/src/components/field/FieldContent.astro +20 -0
  108. package/src/components/field/FieldDescription.astro +22 -0
  109. package/src/components/field/FieldError.astro +51 -0
  110. package/src/components/field/FieldGroup.astro +20 -0
  111. package/src/components/field/FieldLabel.astro +22 -0
  112. package/src/components/field/FieldLegend.astro +23 -0
  113. package/src/components/field/FieldSeparator.astro +30 -0
  114. package/src/components/field/FieldSet.astro +20 -0
  115. package/src/components/field/FieldTitle.astro +20 -0
  116. package/src/components/field/index.ts +10 -0
  117. package/src/components/hover-card/CHANGELOG.md +20 -0
  118. package/src/components/hover-card/HoverCard.astro +235 -0
  119. package/src/components/hover-card/HoverCardContent.astro +54 -0
  120. package/src/components/hover-card/HoverCardTrigger.astro +38 -0
  121. package/src/components/hover-card/index.ts +3 -0
  122. package/src/components/input/CHANGELOG.md +29 -0
  123. package/src/components/input/Input.astro +130 -0
  124. package/src/components/input/index.ts +2 -0
  125. package/src/components/input-group/CHANGELOG.md +49 -0
  126. package/src/components/input-group/InputGroup.astro +135 -0
  127. package/src/components/input-group/InputGroupAddon.astro +49 -0
  128. package/src/components/input-group/InputGroupButton.astro +58 -0
  129. package/src/components/input-group/InputGroupInput.astro +18 -0
  130. package/src/components/input-group/InputGroupText.astro +21 -0
  131. package/src/components/input-group/InputGroupTextarea.astro +17 -0
  132. package/src/components/input-group/controlClasses.ts +2 -0
  133. package/src/components/input-group/index.ts +6 -0
  134. package/src/components/item/CHANGELOG.md +27 -0
  135. package/src/components/item/Item.astro +122 -0
  136. package/src/components/item/ItemActions.astro +21 -0
  137. package/src/components/item/ItemContent.astro +25 -0
  138. package/src/components/item/ItemDescription.astro +25 -0
  139. package/src/components/item/ItemFooter.astro +24 -0
  140. package/src/components/item/ItemGroup.astro +24 -0
  141. package/src/components/item/ItemHeader.astro +24 -0
  142. package/src/components/item/ItemMedia.astro +47 -0
  143. package/src/components/item/ItemSeparator.astro +21 -0
  144. package/src/components/item/ItemTitle.astro +25 -0
  145. package/src/components/item/index.ts +10 -0
  146. package/src/components/kbd/CHANGELOG.md +5 -0
  147. package/src/components/kbd/Kbd.astro +145 -0
  148. package/src/components/kbd/KbdGroup.astro +55 -0
  149. package/src/components/kbd/index.ts +2 -0
  150. package/src/components/label/CHANGELOG.md +28 -0
  151. package/src/components/label/Label.astro +97 -0
  152. package/src/components/label/index.ts +2 -0
  153. package/src/components/link-group/CHANGELOG.md +75 -0
  154. package/src/components/link-group/LinkGroup.astro +67 -0
  155. package/src/components/link-group/LinkGroupItem.astro +32 -0
  156. package/src/components/link-group/LinkGroupList.astro +25 -0
  157. package/src/components/link-group/LinkGroupTitle.astro +22 -0
  158. package/src/components/link-group/index.ts +5 -0
  159. package/src/components/link-group/link-group-list-variants.ts +15 -0
  160. package/src/components/marquee/CHANGELOG.md +5 -0
  161. package/src/components/marquee/Marquee.astro +119 -0
  162. package/src/components/marquee/index.ts +2 -0
  163. package/src/components/native-select/CHANGELOG.md +5 -0
  164. package/src/components/native-select/NativeSelect.astro +125 -0
  165. package/src/components/native-select/NativeSelectOptGroup.astro +14 -0
  166. package/src/components/native-select/NativeSelectOption.astro +9 -0
  167. package/src/components/native-select/index.ts +3 -0
  168. package/src/components/navigation-menu/CHANGELOG.md +63 -0
  169. package/src/components/navigation-menu/NavigationMenu.astro +414 -0
  170. package/src/components/navigation-menu/NavigationMenuContent.astro +37 -0
  171. package/src/components/navigation-menu/NavigationMenuIndicator.astro +24 -0
  172. package/src/components/navigation-menu/NavigationMenuItem.astro +22 -0
  173. package/src/components/navigation-menu/NavigationMenuLink.astro +18 -0
  174. package/src/components/navigation-menu/NavigationMenuList.astro +21 -0
  175. package/src/components/navigation-menu/NavigationMenuPositioner.astro +44 -0
  176. package/src/components/navigation-menu/NavigationMenuTrigger.astro +30 -0
  177. package/src/components/navigation-menu/NavigationMenuViewport.astro +19 -0
  178. package/src/components/navigation-menu/index.ts +10 -0
  179. package/src/components/popover/CHANGELOG.md +5 -0
  180. package/src/components/popover/Popover.astro +210 -0
  181. package/src/components/popover/PopoverClose.astro +18 -0
  182. package/src/components/popover/PopoverContent.astro +49 -0
  183. package/src/components/popover/PopoverDescription.astro +18 -0
  184. package/src/components/popover/PopoverHeader.astro +18 -0
  185. package/src/components/popover/PopoverTitle.astro +18 -0
  186. package/src/components/popover/PopoverTrigger.astro +29 -0
  187. package/src/components/popover/index.ts +7 -0
  188. package/src/components/radio-group/CHANGELOG.md +9 -0
  189. package/src/components/radio-group/RadioGroup.astro +81 -0
  190. package/src/components/radio-group/RadioGroupItem.astro +42 -0
  191. package/src/components/radio-group/index.ts +3 -0
  192. package/src/components/select/CHANGELOG.md +39 -0
  193. package/src/components/select/Select.astro +373 -0
  194. package/src/components/select/SelectContent.astro +91 -0
  195. package/src/components/select/SelectGroup.astro +19 -0
  196. package/src/components/select/SelectItem.astro +48 -0
  197. package/src/components/select/SelectLabel.astro +18 -0
  198. package/src/components/select/SelectSeparator.astro +17 -0
  199. package/src/components/select/SelectTrigger.astro +34 -0
  200. package/src/components/select/SelectValue.astro +22 -0
  201. package/src/components/select/index.ts +8 -0
  202. package/src/components/separator/CHANGELOG.md +5 -0
  203. package/src/components/separator/Separator.astro +60 -0
  204. package/src/components/separator/index.ts +2 -0
  205. package/src/components/skeleton/CHANGELOG.md +5 -0
  206. package/src/components/skeleton/Skeleton.astro +121 -0
  207. package/src/components/skeleton/index.ts +1 -0
  208. package/src/components/slider/CHANGELOG.md +5 -0
  209. package/src/components/slider/Slider.astro +198 -0
  210. package/src/components/slider/index.ts +1 -0
  211. package/src/components/spinner/CHANGELOG.md +5 -0
  212. package/src/components/spinner/Spinner.astro +134 -0
  213. package/src/components/spinner/index.ts +1 -0
  214. package/src/components/sticky-surface/CHANGELOG.md +5 -0
  215. package/src/components/sticky-surface/StickySurface.astro +152 -0
  216. package/src/components/sticky-surface/index.ts +2 -0
  217. package/src/components/switch/CHANGELOG.md +9 -0
  218. package/src/components/switch/Switch.astro +106 -0
  219. package/src/components/switch/index.ts +1 -0
  220. package/src/components/table/CHANGELOG.md +5 -0
  221. package/src/components/table/Table.astro +250 -0
  222. package/src/components/table/TableBody.astro +18 -0
  223. package/src/components/table/TableCaption.astro +17 -0
  224. package/src/components/table/TableCell.astro +21 -0
  225. package/src/components/table/TableFooter.astro +21 -0
  226. package/src/components/table/TableHead.astro +21 -0
  227. package/src/components/table/TableHeader.astro +17 -0
  228. package/src/components/table/TableRow.astro +21 -0
  229. package/src/components/table/index.ts +9 -0
  230. package/src/components/tabs/CHANGELOG.md +5 -0
  231. package/src/components/tabs/Tabs.astro +306 -0
  232. package/src/components/tabs/TabsContent.astro +47 -0
  233. package/src/components/tabs/TabsList.astro +69 -0
  234. package/src/components/tabs/TabsTrigger.astro +40 -0
  235. package/src/components/tabs/index.ts +6 -0
  236. package/src/components/textarea/CHANGELOG.md +5 -0
  237. package/src/components/textarea/Textarea.astro +36 -0
  238. package/src/components/textarea/index.ts +2 -0
  239. package/src/components/toggle/CHANGELOG.md +5 -0
  240. package/src/components/toggle/Toggle.astro +138 -0
  241. package/src/components/toggle/index.ts +1 -0
  242. package/src/components/toggle-group/CHANGELOG.md +5 -0
  243. package/src/components/toggle-group/ToggleGroup.astro +224 -0
  244. package/src/components/toggle-group/ToggleGroupItem.astro +48 -0
  245. package/src/components/toggle-group/index.ts +2 -0
  246. package/src/components/tooltip/CHANGELOG.md +5 -0
  247. package/src/components/tooltip/Tooltip.astro +331 -0
  248. package/src/components/tooltip/TooltipContent.astro +60 -0
  249. package/src/components/tooltip/TooltipTrigger.astro +34 -0
  250. package/src/components/tooltip/index.ts +3 -0
  251. package/src/lib/toggle-group-controller.ts +113 -0
  252. package/src/lib/toggle-shared.ts +26 -0
  253. package/src/lib/utils.ts +6 -0
  254. package/src/styles/globals.css +177 -0
@@ -0,0 +1,22 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ interface Props extends HTMLAttributes<"p"> {}
6
+
7
+ const { class: className = "", ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <p
11
+ data-slot="field-description"
12
+ class={cn(
13
+ "text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5",
14
+ "leading-normal font-normal group-has-data-horizontal/field:text-balance",
15
+ "last:mt-0 nth-last-2:-mt-1",
16
+ "[&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary",
17
+ className,
18
+ )}
19
+ {...rest}
20
+ >
21
+ <slot />
22
+ </p>
@@ -0,0 +1,51 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ type ErrorItem = { message?: string } | undefined;
6
+
7
+ interface Props extends HTMLAttributes<"div"> {
8
+ errors?: ErrorItem[];
9
+ forceMount?: boolean;
10
+ }
11
+
12
+ const {
13
+ class: className = "",
14
+ errors = [],
15
+ forceMount = false,
16
+ ...rest
17
+ } = Astro.props as Props;
18
+
19
+ const hasContent = Astro.slots.has("default");
20
+
21
+ const uniqueMessages = Array.from(
22
+ new Set(
23
+ errors
24
+ .map((error) => error?.message)
25
+ .filter((message): message is string => Boolean(message)),
26
+ ),
27
+ );
28
+
29
+ const shouldRender = forceMount || hasContent || uniqueMessages.length > 0;
30
+ ---
31
+
32
+ {
33
+ shouldRender && (
34
+ <div
35
+ role="alert"
36
+ data-slot="field-error"
37
+ class={cn("text-destructive text-sm font-normal", className)}
38
+ {...rest}
39
+ >
40
+ {hasContent && <slot />}
41
+ {!hasContent && uniqueMessages.length === 1 && uniqueMessages[0]}
42
+ {!hasContent && uniqueMessages.length > 1 && (
43
+ <ul class="ml-4 flex list-disc flex-col gap-1">
44
+ {uniqueMessages.map((message) => (
45
+ <li>{message}</li>
46
+ ))}
47
+ </ul>
48
+ )}
49
+ </div>
50
+ )
51
+ }
@@ -0,0 +1,20 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className = "", ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <div
11
+ data-slot="field-group"
12
+ class={cn(
13
+ "gap-7 data-[slot=checkbox-group]:gap-3 *:data-[slot=field-group]:gap-4",
14
+ "group/field-group @container/field-group flex w-full flex-col",
15
+ className,
16
+ )}
17
+ {...rest}
18
+ >
19
+ <slot />
20
+ </div>
@@ -0,0 +1,22 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+ import { Label } from "../label";
5
+
6
+ interface Props extends HTMLAttributes<"label"> {}
7
+
8
+ const { class: className = "", ...rest } = Astro.props as Props;
9
+ ---
10
+
11
+ <Label
12
+ data-slot="field-label"
13
+ class={cn(
14
+ "has-data-checked:bg-primary/5 has-data-checked:border-primary/30 dark:has-data-checked:border-primary/20 dark:has-data-checked:bg-primary/10 gap-2 group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border *:data-[slot=field]:p-3",
15
+ "group/field-label peer/field-label flex w-fit leading-snug",
16
+ "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col",
17
+ className,
18
+ )}
19
+ {...rest}
20
+ >
21
+ <slot />
22
+ </Label>
@@ -0,0 +1,23 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ interface Props extends HTMLAttributes<"legend"> {
6
+ variant?: "legend" | "label";
7
+ }
8
+
9
+ const {
10
+ class: className = "",
11
+ variant = "legend",
12
+ ...rest
13
+ } = Astro.props as Props;
14
+ ---
15
+
16
+ <legend
17
+ data-slot="field-legend"
18
+ data-variant={variant}
19
+ class={cn("mb-3 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base", className)}
20
+ {...rest}
21
+ >
22
+ <slot />
23
+ </legend>
@@ -0,0 +1,30 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+ import { Separator } from "../separator";
5
+
6
+ interface Props extends HTMLAttributes<"div"> {}
7
+
8
+ const { class: className = "", ...rest } = Astro.props as Props;
9
+
10
+ const hasContent = Astro.slots.has("default");
11
+ ---
12
+
13
+ <div
14
+ data-slot="field-separator"
15
+ data-content={hasContent ? "true" : undefined}
16
+ class={cn("-my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2 relative", className)}
17
+ {...rest}
18
+ >
19
+ <Separator class="absolute inset-0 top-1/2" />
20
+ {
21
+ hasContent && (
22
+ <span
23
+ class="text-muted-foreground px-2 relative mx-auto block w-fit bg-background"
24
+ data-slot="field-separator-content"
25
+ >
26
+ <slot />
27
+ </span>
28
+ )
29
+ }
30
+ </div>
@@ -0,0 +1,20 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ interface Props extends HTMLAttributes<"fieldset"> {}
6
+
7
+ const { class: className = "", ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <fieldset
11
+ data-slot="field-set"
12
+ class={cn(
13
+ "gap-6 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
14
+ "gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col",
15
+ className,
16
+ )}
17
+ {...rest}
18
+ >
19
+ <slot />
20
+ </fieldset>
@@ -0,0 +1,20 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+
5
+ interface Props extends HTMLAttributes<"div"> {}
6
+
7
+ const { class: className = "", ...rest } = Astro.props as Props;
8
+ ---
9
+
10
+ <div
11
+ data-slot="field-title"
12
+ class={cn(
13
+ "gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50",
14
+ "flex w-fit items-center leading-snug",
15
+ className,
16
+ )}
17
+ {...rest}
18
+ >
19
+ <slot />
20
+ </div>
@@ -0,0 +1,10 @@
1
+ export { default as Field } from "./Field.astro";
2
+ export { default as FieldContent } from "./FieldContent.astro";
3
+ export { default as FieldDescription } from "./FieldDescription.astro";
4
+ export { default as FieldError } from "./FieldError.astro";
5
+ export { default as FieldGroup } from "./FieldGroup.astro";
6
+ export { default as FieldLabel } from "./FieldLabel.astro";
7
+ export { default as FieldLegend } from "./FieldLegend.astro";
8
+ export { default as FieldSeparator } from "./FieldSeparator.astro";
9
+ export { default as FieldSet } from "./FieldSet.astro";
10
+ export { default as FieldTitle } from "./FieldTitle.astro";
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `HoverCard` component family (`HoverCard`, `HoverCardTrigger`, `HoverCardContent`) are documented in this file.
4
+
5
+ ## 2026-09-09 — Figma alignment (ClickLearn Lightning Design Library, node `5455-14770`)
6
+
7
+ Figma shows three content **Variants** (Default, Simple, Avatar) and two **States** (Default, Focus) for the card surface.
8
+
9
+ ### Fixed
10
+
11
+ - `HoverCardContent`: added the missing `@figmaUrl` to `HoverCard.astro`'s JSDoc (this component had never had one).
12
+ - `HoverCardContent`: replaced the `ring-1 ring-foreground/10` border approximation with a real `border border-border`, and `shadow-md` → `shadow-lg` — matching Figma's spec'd tokens (`--border` = `#e4e4e7`, and a named `shadow-lg` multi-layer drop shadow), the same category of fix already made to `DialogContent` in the previous pass.
13
+ - `HoverCardContent`: added a focus-visible ring (`has-[:focus-visible]:border-ring has-[:focus-visible]:ring-3 has-[:focus-visible]:ring-ring/50`) to match Figma's "Focus" state (`--ring` = `#5f9de6`), using the same `border-ring` + `ring-3 ring-ring/50` idiom already established for Accordion/Checkbox/Dialog. This activates whenever a keyboard-focusable element inside custom `HoverCardContent` children receives focus — none of the current demos happen to place one, so it isn't visually exercised yet, but the capability is now available.
14
+ - `HoverCardContent`: removed a dead, redundant raw class string that duplicated almost the entire `contentVariants()` class list directly on the rendered div — the same class of bug already fixed in `DialogFooter`/`TooltipContent`. It also silently conflicted on `duration-100` vs. `contentVariants()`'s `duration-150`; since `contentVariants()` came later in the `cn()` call, `150ms` was already winning and `100ms` was fully dead code.
15
+
16
+ ### Notes
17
+
18
+ - Figma's three content variants (Default/Simple/Avatar) are pure content compositions, not distinct props — the existing headless `HoverCardContent` already supports all three via whatever children are passed in (Preview ≈ Default, "With avatar" ≈ Avatar, "Positioning options"/"Custom timing" ≈ Simple). No new props or sub-components added, matching the same call made for Combobox.
19
+ - Typography (bold title, `text-muted-foreground text-xs` meta line) and sizing (`w-64`, `rounded-lg`, `p-3`, avatar `size-10`) already matched Figma's tokens exactly — no changes needed there.
20
+ - No changes to `HoverCardTrigger` — Figma's Focus frame shows only the card, not trigger-specific styling.
@@ -0,0 +1,235 @@
1
+ ---
2
+ /**
3
+ * @component HoverCard
4
+ * @title Hover Card
5
+ * @description For sighted users to preview content available behind a link.
6
+ * @figmaUrl https://www.figma.com/design/qXkzdqZ3QPQqgckU3AwIAH/ClickLearn-Lightning-Design-Library?node-id=5455-14770
7
+ *
8
+ * @preview
9
+ *
10
+ * <HoverCard delay={10} closeDelay={100}>
11
+ * <HoverCardTrigger asChild>
12
+ * <Button variant="link">@data-slot</Button>
13
+ * </HoverCardTrigger>
14
+ * <HoverCardContent class="flex w-64 flex-col gap-0.5">
15
+ * <div class="font-semibold">@data-slot</div>
16
+ * <div>Headless UI components for vanilla JavaScript.</div>
17
+ * <div class="text-muted-foreground mt-1 text-xs">
18
+ * Created by Bejamas in 2026
19
+ * </div>
20
+ * </HoverCardContent>
21
+ * </HoverCard>
22
+ *
23
+ * @usage
24
+ *
25
+ * ```astro nocollapse
26
+ * ---
27
+ * import {
28
+ * HoverCard,
29
+ * HoverCardContent,
30
+ * HoverCardTrigger,
31
+ * } from '@bejamas/ui/components/hover-card';
32
+ * import { Button } from '@bejamas/ui/components/button';
33
+ * ---
34
+ *
35
+ * <HoverCard>
36
+ * <HoverCardTrigger asChild>
37
+ * <Button variant="link">Hover Here</Button>
38
+ * </HoverCardTrigger>
39
+ * <HoverCardContent>
40
+ * <div class="font-semibold">@nextjs</div>
41
+ * <div>The React Framework - created and maintained by @vercel.</div>
42
+ * </HoverCardContent>
43
+ * </HoverCard>
44
+ * ```
45
+ *
46
+ * @api
47
+ *
48
+ * ### Events
49
+ *
50
+ * The hover card emits custom events that you can listen to:
51
+ *
52
+ * | Event | Detail | Description |
53
+ * |-------|--------|-------------|
54
+ * | `hover-card:change` | `{ open: boolean, reason: string, trigger: HTMLElement, content: HTMLElement }` | Fired when visibility changes |
55
+ *
56
+ * ```astro nocollapse console
57
+ * <HoverCard id="my-hover-card">
58
+ * <HoverCardTrigger asChild>
59
+ * <Button variant="outline">Hover me</Button>
60
+ * </HoverCardTrigger>
61
+ * <HoverCardContent>
62
+ * Hover card content
63
+ * </HoverCardContent>
64
+ * </HoverCard>
65
+ * ```
66
+ *
67
+ * ```js nocollapse
68
+ * const hoverCard = document.getElementById('my-hover-card');
69
+ *
70
+ * hoverCard.addEventListener('hover-card:change', (e) => {
71
+ * console.log('Is open:', e.detail.open);
72
+ * console.log('Reason:', e.detail.reason);
73
+ * });
74
+ * ```
75
+ *
76
+ * ### Programmatic Control
77
+ *
78
+ * You can control the hover card programmatically by dispatching a `hover-card:set` event:
79
+ *
80
+ * ```js nocollapse
81
+ * const hoverCard = document.getElementById('my-hover-card');
82
+ *
83
+ * // Open the hover card
84
+ * hoverCard.dispatchEvent(new CustomEvent('hover-card:set', {
85
+ * detail: { open: true }
86
+ * }));
87
+ *
88
+ * // Close the hover card
89
+ * hoverCard.dispatchEvent(new CustomEvent('hover-card:set', {
90
+ * detail: { open: false }
91
+ * }));
92
+ * ```
93
+ *
94
+ * ### Data Attributes
95
+ *
96
+ * The hover card sets these data attributes that you can use for styling or querying state:
97
+ *
98
+ * | Attribute | Element | Description |
99
+ * |-----------|---------|-------------|
100
+ * | `data-state` | hover-card, hover-card-content | Current state (`open` or `closed`) |
101
+ * | `data-open` | hover-card, hover-card-content | Present while open |
102
+ * | `data-closed` | hover-card, hover-card-content | Present while closed |
103
+ * | `data-side` | hover-card-content | Position relative to trigger (`top`, `right`, `bottom`, or `left`) |
104
+ * | `data-align` | hover-card-content | Alignment (`start`, `center`, or `end`) |
105
+ * | `data-side-offset` | hover-card-content | Distance from trigger in pixels (default `4`) |
106
+ * | `data-align-offset` | hover-card-content | Alignment-axis offset in pixels (default `0`) |
107
+ *
108
+ * @examples
109
+ *
110
+ * ### With Avatar
111
+ *
112
+ * <HoverCard>
113
+ * <HoverCardTrigger asChild>
114
+ * <Button variant="link">@thom</Button>
115
+ * </HoverCardTrigger>
116
+ * <HoverCardContent class="flex w-72 gap-3 p-3">
117
+ * <Avatar class="size-10 rounded-full">
118
+ * <AvatarImage>
119
+ * <img src="https://github.com/thomkrupa.png" alt="@thom" />
120
+ * </AvatarImage>
121
+ * <AvatarFallback>TK</AvatarFallback>
122
+ * </Avatar>
123
+ * <div class="space-y-1">
124
+ * <div class="text-sm font-semibold leading-none">@thom</div>
125
+ * <p class="text-muted-foreground text-sm">
126
+ * Building design systems and UI tooling.
127
+ * </p>
128
+ * </div>
129
+ * </HoverCardContent>
130
+ * </HoverCard>
131
+ *
132
+ * ### Different sides
133
+ *
134
+ * <div class="flex flex-wrap items-center gap-3 py-8">
135
+ * <HoverCard delay={10} closeDelay={80} skipDelayDuration={0}>
136
+ * <HoverCardTrigger asChild>
137
+ * <Button variant="outline">Left</Button>
138
+ * </HoverCardTrigger>
139
+ * <HoverCardContent side="left">Appears on left.</HoverCardContent>
140
+ * </HoverCard>
141
+ * <HoverCard delay={10} closeDelay={80} skipDelayDuration={0}>
142
+ * <HoverCardTrigger asChild>
143
+ * <Button variant="outline">Top</Button>
144
+ * </HoverCardTrigger>
145
+ * <HoverCardContent side="top">Appears on top.</HoverCardContent>
146
+ * </HoverCard>
147
+ * <HoverCard delay={10} closeDelay={80} skipDelayDuration={0}>
148
+ * <HoverCardTrigger asChild>
149
+ * <Button variant="outline">Bottom</Button>
150
+ * </HoverCardTrigger>
151
+ * <HoverCardContent side="bottom">Appears on bottom.</HoverCardContent>
152
+ * </HoverCard>
153
+ * <HoverCard delay={10} closeDelay={80} skipDelayDuration={0}>
154
+ * <HoverCardTrigger asChild>
155
+ * <Button variant="outline">Right</Button>
156
+ * </HoverCardTrigger>
157
+ * <HoverCardContent side="right">Appears on right.</HoverCardContent>
158
+ * </HoverCard>
159
+ * </div>
160
+ *
161
+ * ### Positioning options
162
+ *
163
+ * Configure placement options on `HoverCardContent`:
164
+ *
165
+ * <HoverCard>
166
+ * <HoverCardTrigger asChild>
167
+ * <Button variant="outline">Custom positioning</Button>
168
+ * </HoverCardTrigger>
169
+ * <HoverCardContent
170
+ * side="top"
171
+ * sideOffset={8}
172
+ * align="start"
173
+ * >
174
+ * Uses content-level positioning options.
175
+ * </HoverCardContent>
176
+ * </HoverCard>
177
+ *
178
+ * ### Custom timing
179
+ *
180
+ * <HoverCard delay={600} closeDelay={200} skipDelayDuration={300}>
181
+ * <HoverCardTrigger asChild>
182
+ * <Button variant="outline">Hover with delay</Button>
183
+ * </HoverCardTrigger>
184
+ * <HoverCardContent>
185
+ * Opens after 600ms, closes after 200ms.
186
+ * </HoverCardContent>
187
+ * </HoverCard>
188
+ */
189
+
190
+ import type { HTMLAttributes } from "astro/types";
191
+ import { cn } from "@cl-light-ds/ui/lib/utils";
192
+
193
+ interface Props extends HTMLAttributes<"div"> {
194
+ class?: string;
195
+ defaultOpen?: boolean;
196
+ delay?: number;
197
+ skipDelayDuration?: number;
198
+ closeDelay?: number;
199
+ closeOnClickOutside?: boolean;
200
+ closeOnEscape?: boolean;
201
+ }
202
+
203
+ const {
204
+ class: className = "",
205
+ defaultOpen = false,
206
+ delay = 700,
207
+ skipDelayDuration = 300,
208
+ closeDelay = 300,
209
+ closeOnClickOutside = true,
210
+ closeOnEscape = true,
211
+ ...rest
212
+ } = Astro.props as Props;
213
+ ---
214
+
215
+ <div
216
+ {...rest}
217
+ data-slot="hover-card"
218
+ data-default-open={String(defaultOpen)}
219
+ data-delay={delay}
220
+ data-skip-delay-duration={skipDelayDuration}
221
+ data-close-delay={closeDelay}
222
+ data-close-on-click-outside={String(closeOnClickOutside)}
223
+ data-close-on-escape={String(closeOnEscape)}
224
+ class={cn("", "inline-block", className)}
225
+ >
226
+ <slot />
227
+ </div>
228
+
229
+ <script>
230
+ import { createHoverCard } from "@data-slot/hover-card";
231
+
232
+ document.querySelectorAll('[data-slot="hover-card"]').forEach((el) => {
233
+ createHoverCard(el);
234
+ });
235
+ </script>
@@ -0,0 +1,54 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types";
3
+ import { cn } from "@cl-light-ds/ui/lib/utils";
4
+ import { cva } from "class-variance-authority";
5
+
6
+ interface Props extends HTMLAttributes<"div"> {
7
+ side?: "top" | "bottom" | "left" | "right";
8
+ sideOffset?: number;
9
+ align?: "start" | "center" | "end";
10
+ alignOffset?: number;
11
+ class?: string;
12
+ }
13
+
14
+ const {
15
+ class: className = "",
16
+ side = "bottom",
17
+ sideOffset = 4,
18
+ align = "center",
19
+ alignOffset = 0,
20
+ ...rest
21
+ } = Astro.props as Props;
22
+
23
+ const contentVariants = cva([
24
+ // visibility
25
+ "duration-150 ease data-instant:duration-0 transition-discrete outline-hidden",
26
+ // animations
27
+ "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
28
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
29
+ "data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2",
30
+ "data-[instant]:transition-none! data-[instant]:animate-none!",
31
+ "data-instant:data-[state=closed]:animate-none! data-instant:data-[state=closed]:fade-out-0! data-instant:data-[state=closed]:opacity-100! data-instant:data-[state=closed]:scale-100! data-instant:data-[state=closed]:translate-x-0! data-instant:data-[state=closed]:translate-y-0!",
32
+ // styles
33
+ "bg-popover text-popover-foreground w-64 rounded-lg border border-border p-3 text-sm shadow-lg has-[:focus-visible]:border-ring has-[:focus-visible]:ring-3 has-[:focus-visible]:ring-ring/50",
34
+ // origin from positioner
35
+ "origin-(--transform-origin)",
36
+ ]);
37
+ ---
38
+
39
+ <div data-slot="hover-card-portal" class="">
40
+ <div data-slot="hover-card-positioner" class="isolate z-50">
41
+ <div
42
+ {...rest}
43
+ hidden
44
+ data-slot="hover-card-content"
45
+ data-side={side}
46
+ data-side-offset={sideOffset}
47
+ data-align={align}
48
+ data-align-offset={alignOffset}
49
+ class={cn(contentVariants(), className)}
50
+ >
51
+ <slot />
52
+ </div>
53
+ </div>
54
+ </div>
@@ -0,0 +1,38 @@
1
+ ---
2
+ import { cn } from "@cl-light-ds/ui/lib/utils";
3
+ import type { HTMLAttributes } from "astro/types";
4
+
5
+ interface Props extends HTMLAttributes<"button"> {
6
+ class?: string;
7
+ /** Radix-like: render wrapper so the child can be the interactive element */
8
+ asChild?: boolean;
9
+ }
10
+
11
+ const {
12
+ class: className = "",
13
+ asChild = false,
14
+ type = "button",
15
+ ...rest
16
+ } = Astro.props as Props;
17
+ ---
18
+
19
+ {
20
+ asChild ? (
21
+ <div
22
+ data-slot="hover-card-trigger"
23
+ data-as-child
24
+ class={cn("", "inline-flex items-center", className)}
25
+ >
26
+ <slot />
27
+ </div>
28
+ ) : (
29
+ <button
30
+ {...rest}
31
+ type={type}
32
+ data-slot="hover-card-trigger"
33
+ class={cn("", "inline-flex items-center", className)}
34
+ >
35
+ <slot />
36
+ </button>
37
+ )
38
+ }
@@ -0,0 +1,3 @@
1
+ export { default as HoverCard } from "./HoverCard.astro";
2
+ export { default as HoverCardTrigger } from "./HoverCardTrigger.astro";
3
+ export { default as HoverCardContent } from "./HoverCardContent.astro";
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `Input` component will be documented in this file.
4
+
5
+ ## 2026-09-09 — Figma alignment (ClickLearn Lightning Design Library, node `145-3`)
6
+
7
+ Figma documents Input across four pages: Variants (Default, Lead, Tail, Complex, Wide), Sizes (Default 32px, Large 40px), States (Default, Hover, Pressed, Focus, Disabled, Error), and Contents (Default, Lead Icon, Tail Icon, Label, Counter, Helper, Error text, All Details).
8
+
9
+ ### Fixed
10
+
11
+ - Updated `@figmaUrl` from the old Bejamas file to the ClickLearn Lightning Design Library link.
12
+ - Background: `bg-transparent dark:bg-input/30` → `bg-card` — Figma's surface token is `card` (`#ffffff`), which genuinely differs from `--background`/transparent in dark mode, same category of fix already made to `DialogContent`/`HoverCardContent`.
13
+ - Disabled: replaced the blanket `disabled:opacity-50` fade with an explicit `disabled:bg-muted disabled:text-muted-foreground`, matching Figma's actual flat muted-gray disabled treatment (same category of fix as Checkbox's disabled state).
14
+ - Large size: `data-[size=lg]:md:text-base` (16px) → `data-[size=lg]:md:text-sm` (14px) — Figma's Large instance binds the identical 14px font token as Default; only padding/height grow, not font size. **Reverted in the follow-up below** — the three sizes read as visually indistinct with matching font sizes, so the user asked to keep them differentiated.
15
+ - Added a Pressed (`:active`) state: `active:border-ring`, matching Figma's Pressed state (same border-color token as Focus, without Focus's outer glow).
16
+ - Removed dead, redundant unconditional legacy classes (`h-9`, `rounded-md`, `px-2.5 py-1`, `text-base`, `md:text-sm`) that were fully superseded by the newer `data-[size=*]:...` gated system already present in the same class string — same class of cleanup already done on Dialog/HoverCard/TooltipContent.
17
+
18
+ ### Notes (not changed)
19
+
20
+ - Border color (`border-input`), radius (`rounded-lg`), Focus (`focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50`), and Error/`aria-invalid` styling already matched Figma's tokens exactly — no changes needed.
21
+ - Figma's Hover state isn't implemented, per the standing project direction to skip hover states ("ignore hover states, they are not necessary... I will delete from figma").
22
+ - Figma's two documented sizes — Default (32px) and Large (40px) — correspond exactly to the existing `sm` (`h-8`) and `lg` (`h-10`) tiers. The code's own literal `"default"` tier (`h-9`, 36px) isn't represented in Figma at all — flagging in case you want to rename in Figma, same as was done for Accordion/Checkbox.
23
+ - Lead/Tail/Complex/Wide (icon and toolbar compositions) are already fully covered by the existing `InputGroup` family — no new props added to `Input`. Added storybook examples for all four so they're visibly demonstrated on the Input docs page.
24
+ - Label/Helper/Error-text content variants are already covered by the existing `Field`/`FieldLabel`/`FieldDescription`/`FieldError` primitives (shared across the whole design system, not Input-specific) — no new props added. Added a storybook example combining `Field` + `Input` to demonstrate Helper text, a character counter, and an Error state, since none of these Figma-documented compositions had a visible Input demo before. The small icon Figma shows before Helper/Error text is left as consumer-supplied slot content rather than hardcoded, since `Field` is used well beyond Input.
25
+ - Counter (e.g. "10/100") has no dedicated primitive — it's a plain flex row + a counter `<span>` next to `FieldLabel`, demonstrated in the new storybook example above.
26
+
27
+ ### Fixed (follow-up)
28
+
29
+ - User correction: the three sizes weren't visually distinct enough with matching font sizes (per Figma's literal token match above). Restored a differentiated type scale across the existing Tailwind tokens: `sm` → `text-xs` (12px, unchanged), `default` → `text-sm` (14px, unchanged), `lg` → `text-base` (16px, reverted from the Figma-matched 14px).