@emara/ui 1.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 (218) hide show
  1. package/components/ui/.gitkeep +0 -0
  2. package/components/ui/accordion.stories.tsx +231 -0
  3. package/components/ui/accordion.tsx +250 -0
  4. package/components/ui/app-shell.stories.tsx +270 -0
  5. package/components/ui/app-shell.tsx +491 -0
  6. package/components/ui/avatar.stories.tsx +174 -0
  7. package/components/ui/avatar.tsx +257 -0
  8. package/components/ui/badge.stories.tsx +127 -0
  9. package/components/ui/badge.tsx +146 -0
  10. package/components/ui/breadcrumb.stories.tsx +92 -0
  11. package/components/ui/breadcrumb.tsx +302 -0
  12. package/components/ui/button.stories.tsx +186 -0
  13. package/components/ui/button.tsx +128 -0
  14. package/components/ui/card.stories.tsx +279 -0
  15. package/components/ui/card.tsx +250 -0
  16. package/components/ui/checkbox.stories.tsx +93 -0
  17. package/components/ui/checkbox.tsx +131 -0
  18. package/components/ui/combobox.stories.tsx +489 -0
  19. package/components/ui/combobox.tsx +874 -0
  20. package/components/ui/context-menu.stories.tsx +202 -0
  21. package/components/ui/context-menu.tsx +309 -0
  22. package/components/ui/data-table.stories.tsx +227 -0
  23. package/components/ui/data-table.tsx +539 -0
  24. package/components/ui/date-picker.stories.tsx +225 -0
  25. package/components/ui/date-picker.tsx +597 -0
  26. package/components/ui/dialog.stories.tsx +193 -0
  27. package/components/ui/dialog.tsx +262 -0
  28. package/components/ui/divider.stories.tsx +84 -0
  29. package/components/ui/divider.tsx +135 -0
  30. package/components/ui/drawer.stories.tsx +218 -0
  31. package/components/ui/drawer.tsx +329 -0
  32. package/components/ui/dropdown-menu.stories.tsx +270 -0
  33. package/components/ui/dropdown-menu.tsx +353 -0
  34. package/components/ui/empty-state.stories.tsx +121 -0
  35. package/components/ui/empty-state.tsx +289 -0
  36. package/components/ui/field-group.stories.tsx +201 -0
  37. package/components/ui/field-group.tsx +276 -0
  38. package/components/ui/form.stories.tsx +219 -0
  39. package/components/ui/form.tsx +542 -0
  40. package/components/ui/input.stories.tsx +154 -0
  41. package/components/ui/input.tsx +208 -0
  42. package/components/ui/label.stories.tsx +84 -0
  43. package/components/ui/label.tsx +98 -0
  44. package/components/ui/page-header.stories.tsx +136 -0
  45. package/components/ui/page-header.tsx +315 -0
  46. package/components/ui/pagination.stories.tsx +136 -0
  47. package/components/ui/pagination.tsx +427 -0
  48. package/components/ui/popover.stories.tsx +212 -0
  49. package/components/ui/popover.tsx +167 -0
  50. package/components/ui/radio-group.stories.tsx +96 -0
  51. package/components/ui/radio-group.tsx +250 -0
  52. package/components/ui/select.stories.tsx +203 -0
  53. package/components/ui/select.tsx +318 -0
  54. package/components/ui/sidebar.stories.tsx +186 -0
  55. package/components/ui/sidebar.tsx +623 -0
  56. package/components/ui/skeleton.stories.tsx +131 -0
  57. package/components/ui/skeleton.tsx +311 -0
  58. package/components/ui/switch.stories.tsx +74 -0
  59. package/components/ui/switch.tsx +186 -0
  60. package/components/ui/table.stories.tsx +107 -0
  61. package/components/ui/table.tsx +285 -0
  62. package/components/ui/tabs.stories.tsx +222 -0
  63. package/components/ui/tabs.tsx +287 -0
  64. package/components/ui/textarea.stories.tsx +96 -0
  65. package/components/ui/textarea.tsx +182 -0
  66. package/components/ui/toast.stories.tsx +169 -0
  67. package/components/ui/toast.tsx +250 -0
  68. package/components/ui/tooltip.stories.tsx +146 -0
  69. package/components/ui/tooltip.tsx +156 -0
  70. package/components/ui/top-bar.stories.tsx +182 -0
  71. package/components/ui/top-bar.tsx +155 -0
  72. package/dist/components/ui/accordion.d.ts +45 -0
  73. package/dist/components/ui/accordion.d.ts.map +1 -0
  74. package/dist/components/ui/accordion.js +99 -0
  75. package/dist/components/ui/accordion.js.map +1 -0
  76. package/dist/components/ui/app-shell.d.ts +70 -0
  77. package/dist/components/ui/app-shell.d.ts.map +1 -0
  78. package/dist/components/ui/app-shell.js +199 -0
  79. package/dist/components/ui/app-shell.js.map +1 -0
  80. package/dist/components/ui/avatar.d.ts +41 -0
  81. package/dist/components/ui/avatar.d.ts.map +1 -0
  82. package/dist/components/ui/avatar.js +104 -0
  83. package/dist/components/ui/avatar.js.map +1 -0
  84. package/dist/components/ui/badge.d.ts +27 -0
  85. package/dist/components/ui/badge.d.ts.map +1 -0
  86. package/dist/components/ui/badge.js +65 -0
  87. package/dist/components/ui/badge.js.map +1 -0
  88. package/dist/components/ui/breadcrumb.d.ts +35 -0
  89. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  90. package/dist/components/ui/breadcrumb.js +88 -0
  91. package/dist/components/ui/breadcrumb.js.map +1 -0
  92. package/dist/components/ui/button.d.ts +26 -0
  93. package/dist/components/ui/button.d.ts.map +1 -0
  94. package/dist/components/ui/button.js +73 -0
  95. package/dist/components/ui/button.js.map +1 -0
  96. package/dist/components/ui/card.d.ts +52 -0
  97. package/dist/components/ui/card.d.ts.map +1 -0
  98. package/dist/components/ui/card.js +96 -0
  99. package/dist/components/ui/card.js.map +1 -0
  100. package/dist/components/ui/checkbox.d.ts +18 -0
  101. package/dist/components/ui/checkbox.d.ts.map +1 -0
  102. package/dist/components/ui/checkbox.js +59 -0
  103. package/dist/components/ui/checkbox.js.map +1 -0
  104. package/dist/components/ui/combobox.d.ts +194 -0
  105. package/dist/components/ui/combobox.d.ts.map +1 -0
  106. package/dist/components/ui/combobox.js +361 -0
  107. package/dist/components/ui/combobox.js.map +1 -0
  108. package/dist/components/ui/context-menu.d.ts +46 -0
  109. package/dist/components/ui/context-menu.d.ts.map +1 -0
  110. package/dist/components/ui/context-menu.js +95 -0
  111. package/dist/components/ui/context-menu.js.map +1 -0
  112. package/dist/components/ui/data-table.d.ts +53 -0
  113. package/dist/components/ui/data-table.d.ts.map +1 -0
  114. package/dist/components/ui/data-table.js +163 -0
  115. package/dist/components/ui/data-table.js.map +1 -0
  116. package/dist/components/ui/date-picker.d.ts +103 -0
  117. package/dist/components/ui/date-picker.d.ts.map +1 -0
  118. package/dist/components/ui/date-picker.js +306 -0
  119. package/dist/components/ui/date-picker.js.map +1 -0
  120. package/dist/components/ui/dialog.d.ts +40 -0
  121. package/dist/components/ui/dialog.d.ts.map +1 -0
  122. package/dist/components/ui/dialog.js +110 -0
  123. package/dist/components/ui/dialog.js.map +1 -0
  124. package/dist/components/ui/divider.d.ts +30 -0
  125. package/dist/components/ui/divider.d.ts.map +1 -0
  126. package/dist/components/ui/divider.js +62 -0
  127. package/dist/components/ui/divider.js.map +1 -0
  128. package/dist/components/ui/drawer.d.ts +56 -0
  129. package/dist/components/ui/drawer.d.ts.map +1 -0
  130. package/dist/components/ui/drawer.js +147 -0
  131. package/dist/components/ui/drawer.js.map +1 -0
  132. package/dist/components/ui/dropdown-menu.d.ts +63 -0
  133. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  134. package/dist/components/ui/dropdown-menu.js +116 -0
  135. package/dist/components/ui/dropdown-menu.js.map +1 -0
  136. package/dist/components/ui/empty-state.d.ts +43 -0
  137. package/dist/components/ui/empty-state.d.ts.map +1 -0
  138. package/dist/components/ui/empty-state.js +128 -0
  139. package/dist/components/ui/empty-state.js.map +1 -0
  140. package/dist/components/ui/field-group.d.ts +38 -0
  141. package/dist/components/ui/field-group.d.ts.map +1 -0
  142. package/dist/components/ui/field-group.js +107 -0
  143. package/dist/components/ui/field-group.js.map +1 -0
  144. package/dist/components/ui/form.d.ts +67 -0
  145. package/dist/components/ui/form.d.ts.map +1 -0
  146. package/dist/components/ui/form.js +286 -0
  147. package/dist/components/ui/form.js.map +1 -0
  148. package/dist/components/ui/input.d.ts +36 -0
  149. package/dist/components/ui/input.d.ts.map +1 -0
  150. package/dist/components/ui/input.js +99 -0
  151. package/dist/components/ui/input.js.map +1 -0
  152. package/dist/components/ui/label.d.ts +37 -0
  153. package/dist/components/ui/label.d.ts.map +1 -0
  154. package/dist/components/ui/label.js +34 -0
  155. package/dist/components/ui/label.js.map +1 -0
  156. package/dist/components/ui/page-header.d.ts +65 -0
  157. package/dist/components/ui/page-header.d.ts.map +1 -0
  158. package/dist/components/ui/page-header.js +140 -0
  159. package/dist/components/ui/page-header.js.map +1 -0
  160. package/dist/components/ui/pagination.d.ts +67 -0
  161. package/dist/components/ui/pagination.d.ts.map +1 -0
  162. package/dist/components/ui/pagination.js +109 -0
  163. package/dist/components/ui/pagination.js.map +1 -0
  164. package/dist/components/ui/popover.d.ts +28 -0
  165. package/dist/components/ui/popover.d.ts.map +1 -0
  166. package/dist/components/ui/popover.js +85 -0
  167. package/dist/components/ui/popover.js.map +1 -0
  168. package/dist/components/ui/radio-group.d.ts +35 -0
  169. package/dist/components/ui/radio-group.d.ts.map +1 -0
  170. package/dist/components/ui/radio-group.js +103 -0
  171. package/dist/components/ui/radio-group.js.map +1 -0
  172. package/dist/components/ui/select.d.ts +42 -0
  173. package/dist/components/ui/select.d.ts.map +1 -0
  174. package/dist/components/ui/select.js +86 -0
  175. package/dist/components/ui/select.js.map +1 -0
  176. package/dist/components/ui/sidebar.d.ts +59 -0
  177. package/dist/components/ui/sidebar.d.ts.map +1 -0
  178. package/dist/components/ui/sidebar.js +189 -0
  179. package/dist/components/ui/sidebar.js.map +1 -0
  180. package/dist/components/ui/skeleton.d.ts +77 -0
  181. package/dist/components/ui/skeleton.d.ts.map +1 -0
  182. package/dist/components/ui/skeleton.js +115 -0
  183. package/dist/components/ui/skeleton.js.map +1 -0
  184. package/dist/components/ui/switch.d.ts +26 -0
  185. package/dist/components/ui/switch.d.ts.map +1 -0
  186. package/dist/components/ui/switch.js +84 -0
  187. package/dist/components/ui/switch.js.map +1 -0
  188. package/dist/components/ui/table.d.ts +52 -0
  189. package/dist/components/ui/table.d.ts.map +1 -0
  190. package/dist/components/ui/table.js +109 -0
  191. package/dist/components/ui/table.js.map +1 -0
  192. package/dist/components/ui/tabs.d.ts +42 -0
  193. package/dist/components/ui/tabs.d.ts.map +1 -0
  194. package/dist/components/ui/tabs.js +163 -0
  195. package/dist/components/ui/tabs.js.map +1 -0
  196. package/dist/components/ui/textarea.d.ts +26 -0
  197. package/dist/components/ui/textarea.d.ts.map +1 -0
  198. package/dist/components/ui/textarea.js +96 -0
  199. package/dist/components/ui/textarea.js.map +1 -0
  200. package/dist/components/ui/toast.d.ts +77 -0
  201. package/dist/components/ui/toast.d.ts.map +1 -0
  202. package/dist/components/ui/toast.js +141 -0
  203. package/dist/components/ui/toast.js.map +1 -0
  204. package/dist/components/ui/tooltip.d.ts +31 -0
  205. package/dist/components/ui/tooltip.d.ts.map +1 -0
  206. package/dist/components/ui/tooltip.js +71 -0
  207. package/dist/components/ui/tooltip.js.map +1 -0
  208. package/dist/components/ui/top-bar.d.ts +30 -0
  209. package/dist/components/ui/top-bar.d.ts.map +1 -0
  210. package/dist/components/ui/top-bar.js +64 -0
  211. package/dist/components/ui/top-bar.js.map +1 -0
  212. package/dist/lib/utils.d.ts +3 -0
  213. package/dist/lib/utils.d.ts.map +1 -0
  214. package/dist/lib/utils.js +6 -0
  215. package/dist/lib/utils.js.map +1 -0
  216. package/lib/utils.ts +6 -0
  217. package/package.json +112 -0
  218. package/styles/globals.css +685 -0
@@ -0,0 +1,156 @@
1
+ "use client";
2
+
3
+ import { forwardRef } from "react";
4
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "@/lib/utils";
8
+
9
+ // Per docs/emara-ui-phase-3-components.md §4. Brought forward into v0.1 per
10
+ // docs/emara-ui-implementation-plan.md §5.
11
+
12
+ // ----------------------------------------------------------------------------
13
+ // TooltipProvider — typically wraps the app once. Re-export so consumers
14
+ // don't have to import from Radix directly.
15
+ // ----------------------------------------------------------------------------
16
+
17
+ const TooltipProvider = TooltipPrimitive.Provider;
18
+
19
+ // ----------------------------------------------------------------------------
20
+ // Tooltip root — Radix props passthrough.
21
+ // ----------------------------------------------------------------------------
22
+
23
+ const Tooltip = TooltipPrimitive.Root;
24
+ const TooltipTrigger = TooltipPrimitive.Trigger;
25
+
26
+ // ----------------------------------------------------------------------------
27
+ // TooltipContent
28
+ // ----------------------------------------------------------------------------
29
+
30
+ const tooltipContentVariants = cva(
31
+ [
32
+ "z-tooltip select-none px-2 py-1 text-xs leading-snug rounded-md shadow-md",
33
+ // Animations driven by Radix data-state. Side-specific slide-in.
34
+ "data-[state=delayed-open]:animate-[scale-in_var(--duration-fast)_var(--ease-out)]",
35
+ "data-[state=closed]:animate-[scale-out_var(--duration-fast)_var(--ease-in)]",
36
+ "data-[side=top]:data-[state=delayed-open]:animate-[slide-in-from-bottom_var(--duration-fast)_var(--ease-out)]",
37
+ "data-[side=bottom]:data-[state=delayed-open]:animate-[slide-in-from-top_var(--duration-fast)_var(--ease-out)]",
38
+ "data-[side=left]:data-[state=delayed-open]:animate-[slide-in-from-end_var(--duration-fast)_var(--ease-out)]",
39
+ "data-[side=right]:data-[state=delayed-open]:animate-[slide-in-from-start_var(--duration-fast)_var(--ease-out)]",
40
+ ].join(" "),
41
+ {
42
+ variants: {
43
+ variant: {
44
+ // Dark bubble against any surface — classic tooltip.
45
+ default: "bg-foreground text-background",
46
+ // Inverse — light bubble for dark contexts (e.g. dark sidebar).
47
+ inverse: "bg-background text-foreground border border-border",
48
+ // Keyboard-shortcut style — uses kbd key caps inside.
49
+ kbd: "bg-foreground text-background font-mono",
50
+ },
51
+ multiline: {
52
+ // Single-line tooltip truncates; multi-line wraps within maxWidth.
53
+ true: "whitespace-normal",
54
+ false: "whitespace-nowrap",
55
+ },
56
+ },
57
+ defaultVariants: { variant: "default", multiline: false },
58
+ },
59
+ );
60
+
61
+ const arrowFillClass: Record<"default" | "inverse" | "kbd", string> = {
62
+ default: "fill-foreground",
63
+ inverse: "fill-background",
64
+ kbd: "fill-foreground",
65
+ };
66
+
67
+ type TooltipContentProps = React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> &
68
+ VariantProps<typeof tooltipContentVariants> & {
69
+ /** Cap width when `multiline` is true (or just for sizing in general). */
70
+ maxWidth?: number | string;
71
+ /** When set, renders the children as keyboard-shortcut key caps. Wraps each token in a `<kbd>` element with a styled appearance. */
72
+ kbd?: string[];
73
+ /** Default `true`. Set to `false` to hide the arrow. */
74
+ arrow?: boolean;
75
+ };
76
+
77
+ function Kbd({ k }: { k: string }) {
78
+ // `min-w-[1.25em]` is intentionally em-relative (not a Tailwind spacing
79
+ // token): kbd keys scale with the surrounding text size, and the visual
80
+ // contract is "always at least one character wide" — that's an em-bound
81
+ // measurement, not a px one. Per design-tokens §4.2 sub-canonical note.
82
+ return (
83
+ <kbd className="border-background/30 bg-background/10 inline-block min-w-[1.25em] rounded border px-1 text-center font-mono text-[10px] leading-tight">
84
+ {k}
85
+ </kbd>
86
+ );
87
+ }
88
+
89
+ const TooltipContent = forwardRef<
90
+ React.ElementRef<typeof TooltipPrimitive.Content>,
91
+ TooltipContentProps
92
+ >(function TooltipContent(
93
+ {
94
+ className,
95
+ variant,
96
+ multiline,
97
+ maxWidth,
98
+ kbd,
99
+ arrow = true,
100
+ sideOffset = 6,
101
+ style,
102
+ children,
103
+ ...props
104
+ },
105
+ ref,
106
+ ) {
107
+ const resolvedVariant = variant ?? (kbd ? "kbd" : "default");
108
+ const widthStyle: React.CSSProperties | undefined =
109
+ maxWidth !== undefined
110
+ ? { maxWidth: typeof maxWidth === "number" ? `${maxWidth}px` : maxWidth }
111
+ : undefined;
112
+
113
+ const body = kbd ? (
114
+ <span className="inline-flex items-center gap-1">
115
+ {children ? (
116
+ <>
117
+ <span>{children}</span>
118
+ <span className="opacity-70">·</span>
119
+ </>
120
+ ) : null}
121
+ {kbd.map((k, i) => (
122
+ <span key={`${k}-${i}`} className="inline-flex items-center gap-0.5">
123
+ {i > 0 ? <span className="opacity-70">+</span> : null}
124
+ <Kbd k={k} />
125
+ </span>
126
+ ))}
127
+ </span>
128
+ ) : (
129
+ children
130
+ );
131
+
132
+ return (
133
+ <TooltipPrimitive.Portal>
134
+ <TooltipPrimitive.Content
135
+ ref={ref}
136
+ sideOffset={sideOffset}
137
+ style={{ ...widthStyle, ...style }}
138
+ className={cn(tooltipContentVariants({ variant: resolvedVariant, multiline }), className)}
139
+ {...props}
140
+ >
141
+ {body}
142
+ {arrow ? (
143
+ <TooltipPrimitive.Arrow
144
+ width={10}
145
+ height={5}
146
+ className={cn(arrowFillClass[resolvedVariant])}
147
+ />
148
+ ) : null}
149
+ </TooltipPrimitive.Content>
150
+ </TooltipPrimitive.Portal>
151
+ );
152
+ });
153
+ TooltipContent.displayName = "TooltipContent";
154
+
155
+ export { TooltipProvider, Tooltip, TooltipTrigger, TooltipContent, tooltipContentVariants };
156
+ export type { TooltipContentProps };
@@ -0,0 +1,182 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import {
3
+ RiMenuLine,
4
+ RiNotification3Line,
5
+ RiSearchLine,
6
+ RiSettings4Line,
7
+ RiUser3Line,
8
+ } from "@remixicon/react";
9
+
10
+ import { Avatar, AvatarFallback } from "./avatar";
11
+ import { Badge } from "./badge";
12
+ import { Button } from "./button";
13
+ import {
14
+ DropdownMenu,
15
+ DropdownMenuContent,
16
+ DropdownMenuItem,
17
+ DropdownMenuLabel,
18
+ DropdownMenuSeparator,
19
+ DropdownMenuTrigger,
20
+ } from "./dropdown-menu";
21
+ import { Input } from "./input";
22
+ import { TopBar, TopBarBrand, TopBarCenter, TopBarEnd, TopBarStart } from "./top-bar";
23
+
24
+ const meta: Meta<typeof TopBar> = {
25
+ title: "Layout/TopBar",
26
+ component: TopBar,
27
+ parameters: { layout: "fullscreen" },
28
+ argTypes: {
29
+ variant: { control: "select", options: ["default", "elevated", "transparent"] },
30
+ size: { control: "select", options: ["sm", "md", "lg"] },
31
+ sticky: { control: "boolean" },
32
+ bordered: { control: "boolean" },
33
+ },
34
+ };
35
+
36
+ export default meta;
37
+ type Story = StoryObj<typeof TopBar>;
38
+
39
+ function BrandMark() {
40
+ return (
41
+ <TopBarBrand>
42
+ <span className="bg-primary text-primary-foreground inline-flex size-6 items-center justify-center rounded text-xs font-bold">
43
+ E
44
+ </span>
45
+ <span>Emara</span>
46
+ </TopBarBrand>
47
+ );
48
+ }
49
+
50
+ function UserMenu() {
51
+ return (
52
+ <DropdownMenu>
53
+ <DropdownMenuTrigger
54
+ aria-label="User menu"
55
+ className="focus-visible:ring-ring inline-flex items-center rounded-full focus-visible:ring-2 focus-visible:outline-none"
56
+ >
57
+ <Avatar size="sm">
58
+ <AvatarFallback>AZ</AvatarFallback>
59
+ </Avatar>
60
+ </DropdownMenuTrigger>
61
+ <DropdownMenuContent align="end">
62
+ <DropdownMenuLabel>Abdelkader</DropdownMenuLabel>
63
+ <DropdownMenuSeparator />
64
+ <DropdownMenuItem icon={<RiUser3Line />}>Profile</DropdownMenuItem>
65
+ <DropdownMenuItem icon={<RiSettings4Line />}>Settings</DropdownMenuItem>
66
+ <DropdownMenuSeparator />
67
+ <DropdownMenuItem variant="destructive">Sign out</DropdownMenuItem>
68
+ </DropdownMenuContent>
69
+ </DropdownMenu>
70
+ );
71
+ }
72
+
73
+ export const Default: Story = {
74
+ render: (args) => (
75
+ <TopBar {...args}>
76
+ <TopBarStart>
77
+ <BrandMark />
78
+ </TopBarStart>
79
+ <TopBarEnd>
80
+ <Button variant="ghost" size="icon-sm" aria-label="Notifications">
81
+ <RiNotification3Line />
82
+ </Button>
83
+ <UserMenu />
84
+ </TopBarEnd>
85
+ </TopBar>
86
+ ),
87
+ };
88
+
89
+ export const WithSearch: Story = {
90
+ render: (args) => (
91
+ <TopBar {...args}>
92
+ <TopBarStart>
93
+ <Button variant="ghost" size="icon-sm" aria-label="Toggle navigation">
94
+ <RiMenuLine />
95
+ </Button>
96
+ <BrandMark />
97
+ </TopBarStart>
98
+ <TopBarCenter role="search">
99
+ <div className="w-full max-w-md">
100
+ <Input type="search" placeholder="Search…" startAdornment={<RiSearchLine />} clearable />
101
+ </div>
102
+ </TopBarCenter>
103
+ <TopBarEnd>
104
+ <Button variant="ghost" size="icon-sm" aria-label="Notifications">
105
+ <RiNotification3Line />
106
+ </Button>
107
+ <UserMenu />
108
+ </TopBarEnd>
109
+ </TopBar>
110
+ ),
111
+ };
112
+
113
+ export const Elevated: Story = {
114
+ args: { variant: "elevated" },
115
+ render: Default.render!,
116
+ };
117
+
118
+ export const Transparent: Story = {
119
+ args: { variant: "transparent" },
120
+ render: (args) => (
121
+ <div className="from-primary/20 via-info/10 to-success/20 bg-gradient-to-r p-2">
122
+ <TopBar {...args}>
123
+ <TopBarStart>
124
+ <BrandMark />
125
+ </TopBarStart>
126
+ <TopBarEnd>
127
+ <Button variant="ghost" size="icon-sm" aria-label="Notifications">
128
+ <RiNotification3Line />
129
+ </Button>
130
+ <UserMenu />
131
+ </TopBarEnd>
132
+ </TopBar>
133
+ </div>
134
+ ),
135
+ };
136
+
137
+ export const Sizes: Story = {
138
+ render: () => (
139
+ <div className="space-y-3">
140
+ {(["sm", "md", "lg"] as const).map((size) => (
141
+ <TopBar key={size} size={size}>
142
+ <TopBarStart>
143
+ <BrandMark />
144
+ <Badge size="xs" variant="info">
145
+ {size}
146
+ </Badge>
147
+ </TopBarStart>
148
+ <TopBarEnd>
149
+ <UserMenu />
150
+ </TopBarEnd>
151
+ </TopBar>
152
+ ))}
153
+ </div>
154
+ ),
155
+ };
156
+
157
+ export const Marketing: Story = {
158
+ render: (args) => (
159
+ <TopBar {...args}>
160
+ <TopBarStart>
161
+ <BrandMark />
162
+ <nav className="ms-4 hidden gap-1 md:flex">
163
+ <Button asChild variant="ghost" size="sm">
164
+ <a href="/product">Product</a>
165
+ </Button>
166
+ <Button asChild variant="ghost" size="sm">
167
+ <a href="/pricing">Pricing</a>
168
+ </Button>
169
+ <Button asChild variant="ghost" size="sm">
170
+ <a href="/docs">Docs</a>
171
+ </Button>
172
+ </nav>
173
+ </TopBarStart>
174
+ <TopBarEnd>
175
+ <Button variant="ghost" size="sm">
176
+ Sign in
177
+ </Button>
178
+ <Button size="sm">Sign up</Button>
179
+ </TopBarEnd>
180
+ </TopBar>
181
+ ),
182
+ };
@@ -0,0 +1,155 @@
1
+ "use client";
2
+
3
+ import { forwardRef } from "react";
4
+ import { Slot } from "@radix-ui/react-slot";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+
7
+ import { cn } from "@/lib/utils";
8
+
9
+ // Per docs/emara-ui-phase-5-components.md §3.
10
+
11
+ // --- Root -------------------------------------------------------------------
12
+
13
+ const topBarVariants = cva("flex w-full items-center bg-background text-foreground", {
14
+ variants: {
15
+ variant: {
16
+ default: "border-b border-border",
17
+ elevated: "shadow-sm",
18
+ transparent: "bg-transparent",
19
+ },
20
+ size: {
21
+ // Heights match the AppShell `header-sm|md|lg` tokens.
22
+ sm: "h-12 px-3",
23
+ md: "h-14 px-4",
24
+ lg: "h-16 px-5",
25
+ },
26
+ sticky: {
27
+ true: "sticky top-0 z-sticky",
28
+ false: "",
29
+ },
30
+ bordered: {
31
+ true: "border-b border-border",
32
+ false: "",
33
+ },
34
+ },
35
+ defaultVariants: {
36
+ variant: "default",
37
+ size: "md",
38
+ sticky: false,
39
+ bordered: false,
40
+ },
41
+ });
42
+
43
+ type TopBarVariants = VariantProps<typeof topBarVariants>;
44
+
45
+ type TopBarProps = Omit<React.HTMLAttributes<HTMLElement>, "size"> &
46
+ TopBarVariants & {
47
+ asChild?: boolean;
48
+ /** Override the rendered element. Default `<header>`. */
49
+ as?: "header" | "div";
50
+ };
51
+
52
+ const TopBar = forwardRef<HTMLElement, TopBarProps>(function TopBar(
53
+ {
54
+ className,
55
+ variant = "default",
56
+ size = "md",
57
+ sticky = false,
58
+ bordered = false,
59
+ asChild = false,
60
+ as = "header",
61
+ ...props
62
+ },
63
+ ref,
64
+ ) {
65
+ const Comp = (asChild ? Slot : as) as React.ElementType;
66
+ return (
67
+ <Comp
68
+ ref={ref}
69
+ data-slot="top-bar"
70
+ role={as === "header" && !asChild ? "banner" : undefined}
71
+ className={cn(topBarVariants({ variant, size, sticky, bordered }), className)}
72
+ {...props}
73
+ />
74
+ );
75
+ });
76
+ TopBar.displayName = "TopBar";
77
+
78
+ // --- Slots ------------------------------------------------------------------
79
+
80
+ const TopBarStart = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
81
+ function TopBarStart({ className, ...props }, ref) {
82
+ return (
83
+ <div
84
+ ref={ref}
85
+ data-slot="top-bar-start"
86
+ className={cn("me-auto flex min-w-0 items-center gap-2", className)}
87
+ {...props}
88
+ />
89
+ );
90
+ },
91
+ );
92
+ TopBarStart.displayName = "TopBarStart";
93
+
94
+ const TopBarCenter = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
95
+ function TopBarCenter({ className, role, ...props }, ref) {
96
+ return (
97
+ <div
98
+ ref={ref}
99
+ data-slot="top-bar-center"
100
+ // Hides on narrow viewports — consumers can override.
101
+ className={cn(
102
+ "hidden min-w-0 flex-1 items-center justify-center gap-2 px-3 md:flex",
103
+ className,
104
+ )}
105
+ // Honor consumer `role` (e.g. role="search" when this slot wraps a search input).
106
+ {...(role ? { role } : {})}
107
+ {...props}
108
+ />
109
+ );
110
+ },
111
+ );
112
+ TopBarCenter.displayName = "TopBarCenter";
113
+
114
+ const TopBarEnd = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
115
+ function TopBarEnd({ className, ...props }, ref) {
116
+ return (
117
+ <div
118
+ ref={ref}
119
+ data-slot="top-bar-end"
120
+ className={cn("ms-auto flex items-center gap-2", className)}
121
+ {...props}
122
+ />
123
+ );
124
+ },
125
+ );
126
+ TopBarEnd.displayName = "TopBarEnd";
127
+
128
+ // --- TopBar.Brand (convenience) --------------------------------------------
129
+
130
+ type TopBarBrandProps = React.HTMLAttributes<HTMLDivElement> & {
131
+ asChild?: boolean;
132
+ };
133
+
134
+ const TopBarBrand = forwardRef<HTMLDivElement, TopBarBrandProps>(function TopBarBrand(
135
+ { className, asChild = false, ...props },
136
+ ref,
137
+ ) {
138
+ const Comp = asChild ? Slot : "div";
139
+ return (
140
+ <Comp
141
+ ref={ref}
142
+ data-slot="top-bar-brand"
143
+ className={cn(
144
+ "text-foreground inline-flex items-center gap-2 font-semibold",
145
+ "[&_svg]:size-5 [&_svg]:shrink-0",
146
+ className,
147
+ )}
148
+ {...props}
149
+ />
150
+ );
151
+ });
152
+ TopBarBrand.displayName = "TopBarBrand";
153
+
154
+ export { TopBar, TopBarStart, TopBarCenter, TopBarEnd, TopBarBrand, topBarVariants };
155
+ export type { TopBarProps, TopBarBrandProps };
@@ -0,0 +1,45 @@
1
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
2
+ type AccordionVariant = "default" | "bordered" | "separated" | "filled";
3
+ type AccordionSize = "sm" | "md" | "lg";
4
+ type IconPosition = "start" | "end";
5
+ interface UseAccordionAPI {
6
+ value: string[];
7
+ setValue: (next: string[]) => void;
8
+ openAll: (allValues: string[]) => void;
9
+ closeAll: () => void;
10
+ toggle: (value: string) => void;
11
+ isOpen: (value: string) => boolean;
12
+ }
13
+ declare function useAccordion(initial?: string[]): UseAccordionAPI;
14
+ declare const accordionVariants: (props?: ({
15
+ variant?: "default" | "bordered" | "separated" | "filled" | null | undefined;
16
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
17
+ type AccordionRootProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Root> & {
18
+ variant?: AccordionVariant;
19
+ size?: AccordionSize;
20
+ iconPosition?: IconPosition;
21
+ };
22
+ declare const Accordion: import("react").ForwardRefExoticComponent<AccordionRootProps & import("react").RefAttributes<HTMLDivElement>>;
23
+ declare const accordionItemVariants: (props?: ({
24
+ variant?: "default" | "bordered" | "separated" | "filled" | null | undefined;
25
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
26
+ type AccordionItemProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>;
27
+ declare const AccordionItem: import("react").ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionItemProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
28
+ declare const accordionTriggerVariants: (props?: ({
29
+ size?: "sm" | "md" | "lg" | null | undefined;
30
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
31
+ type AccordionTriggerProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger> & {
32
+ icon?: React.ReactNode;
33
+ badge?: React.ReactNode;
34
+ description?: React.ReactNode;
35
+ };
36
+ declare const AccordionTrigger: import("react").ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionTriggerProps & import("react").RefAttributes<HTMLButtonElement>, "ref"> & {
37
+ icon?: React.ReactNode;
38
+ badge?: React.ReactNode;
39
+ description?: React.ReactNode;
40
+ } & import("react").RefAttributes<HTMLButtonElement>>;
41
+ type AccordionContentProps = React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>;
42
+ declare const AccordionContent: import("react").ForwardRefExoticComponent<Omit<AccordionPrimitive.AccordionContentProps & import("react").RefAttributes<HTMLDivElement>, "ref"> & import("react").RefAttributes<HTMLDivElement>>;
43
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent, useAccordion, accordionVariants, accordionItemVariants, accordionTriggerVariants, };
44
+ export type { AccordionRootProps, AccordionItemProps, AccordionTriggerProps, AccordionContentProps, UseAccordionAPI, };
45
+ //# sourceMappingURL=accordion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.d.ts","sourceRoot":"","sources":["../../../components/ui/accordion.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,kBAAkB,MAAM,2BAA2B,CAAC;AAQhE,KAAK,gBAAgB,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;AACxE,KAAK,aAAa,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AACxC,KAAK,YAAY,GAAG,OAAO,GAAG,KAAK,CAAC;AAkBpC,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACnC,OAAO,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CACpC;AAED,iBAAS,YAAY,CAAC,OAAO,GAAE,MAAM,EAAO,GAAG,eAAe,CAW7D;AAID,QAAA,MAAM,iBAAiB;;8EAUrB,CAAC;AAEH,KAAK,kBAAkB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,GAAG;IACzF,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,QAAA,MAAM,SAAS,+GAgBd,CAAC;AAKF,QAAA,MAAM,qBAAqB;;8EAUzB,CAAC;AAEH,KAAK,kBAAkB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;AAEzF,QAAA,MAAM,aAAa,+LAYjB,CAAC;AAKH,QAAA,MAAM,wBAAwB;;8EAmB7B,CAAC;AAEF,KAAK,qBAAqB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,GAAG;IAC/F,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC/B,CAAC;AAEF,QAAA,MAAM,gBAAgB;WALb,KAAK,CAAC,SAAS;YACd,KAAK,CAAC,SAAS;kBACT,KAAK,CAAC,SAAS;qDA2C7B,CAAC;AAgBH,KAAK,qBAAqB,GAAG,KAAK,CAAC,wBAAwB,CAAC,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAE/F,QAAA,MAAM,gBAAgB,kMAoBpB,CAAC;AAGH,OAAO,EACL,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,EACrB,wBAAwB,GACzB,CAAC;AACF,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,qBAAqB,EACrB,eAAe,GAChB,CAAC"}
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, forwardRef, useCallback, useContext, useMemo, useState } from "react";
4
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
5
+ import { RiArrowDownSLine } from "@remixicon/react";
6
+ import { cva } from "class-variance-authority";
7
+ import { cn } from "@/lib/utils";
8
+ const AccordionContext = createContext(null);
9
+ function useAccordionContext() {
10
+ const ctx = useContext(AccordionContext);
11
+ if (!ctx)
12
+ throw new Error("Accordion subcomponents must be used inside <Accordion>");
13
+ return ctx;
14
+ }
15
+ function useAccordion(initial = []) {
16
+ const [value, setValue] = useState(initial);
17
+ const openAll = useCallback((all) => setValue([...new Set(all)]), []);
18
+ const closeAll = useCallback(() => setValue([]), []);
19
+ const toggle = useCallback((v) => setValue((prev) => (prev.includes(v) ? prev.filter((x) => x !== v) : [...prev, v])), []);
20
+ const isOpen = useCallback((v) => value.includes(v), [value]);
21
+ return { value, setValue, openAll, closeAll, toggle, isOpen };
22
+ }
23
+ // --- Accordion (root) -------------------------------------------------------
24
+ const accordionVariants = cva("", {
25
+ variants: {
26
+ variant: {
27
+ default: "",
28
+ bordered: "rounded-md border border-border overflow-hidden",
29
+ separated: "space-y-2",
30
+ filled: "",
31
+ },
32
+ },
33
+ defaultVariants: { variant: "default" },
34
+ });
35
+ const Accordion = forwardRef(function Accordion({ className, variant = "default", size = "md", iconPosition = "end", ...props }, ref) {
36
+ const ctx = useMemo(() => ({ variant, size, iconPosition }), [variant, size, iconPosition]);
37
+ return (_jsx(AccordionContext.Provider, { value: ctx, children: _jsx(AccordionPrimitive.Root, { ref: ref, className: cn(accordionVariants({ variant }), className), ...props }) }));
38
+ });
39
+ Accordion.displayName = "Accordion";
40
+ // --- AccordionItem ----------------------------------------------------------
41
+ const accordionItemVariants = cva("", {
42
+ variants: {
43
+ variant: {
44
+ default: "border-b border-border last:border-b-0",
45
+ bordered: "border-b border-border last:border-b-0",
46
+ separated: "rounded-md border border-border overflow-hidden",
47
+ filled: ["rounded-md", "data-[state=open]:bg-muted"].join(" "),
48
+ },
49
+ },
50
+ defaultVariants: { variant: "default" },
51
+ });
52
+ const AccordionItem = forwardRef(function AccordionItem({ className, ...props }, ref) {
53
+ const { variant } = useAccordionContext();
54
+ return (_jsx(AccordionPrimitive.Item, { ref: ref, className: cn(accordionItemVariants({ variant }), className), ...props }));
55
+ });
56
+ AccordionItem.displayName = "AccordionItem";
57
+ // --- AccordionTrigger -------------------------------------------------------
58
+ const accordionTriggerVariants = cva([
59
+ "flex w-full items-center gap-3 font-medium text-foreground select-none cursor-pointer",
60
+ "transition-colors",
61
+ "hover:bg-accent/50",
62
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
63
+ "disabled:cursor-not-allowed disabled:opacity-50",
64
+ "[&_svg]:size-4 [&_svg]:shrink-0",
65
+ ].join(" "), {
66
+ variants: {
67
+ size: {
68
+ sm: "px-3 py-2 text-xs",
69
+ md: "px-4 py-3 text-sm",
70
+ lg: "px-5 py-4 text-base",
71
+ },
72
+ },
73
+ defaultVariants: { size: "md" },
74
+ });
75
+ const AccordionTrigger = forwardRef(function AccordionTrigger({ className, icon, badge, description, children, ...props }, ref) {
76
+ const { size, iconPosition } = useAccordionContext();
77
+ return (_jsx(AccordionPrimitive.Header, { className: "flex", children: _jsxs(AccordionPrimitive.Trigger, { ref: ref, className: cn(accordionTriggerVariants({ size }), "group", "data-[state=open]:[&_[data-chevron]]:rotate-180", className), ...props, children: [iconPosition === "start" ? (_jsx("span", { "data-chevron": true, className: "duration-normal shrink-0 transition-transform", children: _jsx(RiArrowDownSLine, {}) })) : null, icon ? _jsx("span", { className: "shrink-0", children: icon }) : null, _jsxs("span", { className: "flex-1 text-start", children: [_jsx("span", { className: "block", children: children }), description ? (_jsx("span", { className: "text-muted-foreground mt-0.5 block text-xs font-normal", children: description })) : null] }), badge ? _jsx("span", { className: "shrink-0", children: badge }) : null, iconPosition === "end" ? (_jsx("span", { "data-chevron": true, className: "duration-normal shrink-0 transition-transform", children: _jsx(RiArrowDownSLine, {}) })) : null] }) }));
78
+ });
79
+ AccordionTrigger.displayName = "AccordionTrigger";
80
+ // --- AccordionContent -------------------------------------------------------
81
+ const accordionContentSizeVariants = cva("text-foreground", {
82
+ variants: {
83
+ size: {
84
+ sm: "px-3 pb-2 text-xs",
85
+ md: "px-4 pb-3 text-sm",
86
+ lg: "px-5 pb-4 text-base",
87
+ },
88
+ },
89
+ defaultVariants: { size: "md" },
90
+ });
91
+ const AccordionContent = forwardRef(function AccordionContent({ className, children, ...props }, ref) {
92
+ const { size } = useAccordionContext();
93
+ return (_jsx(AccordionPrimitive.Content, { ref: ref, className: cn("overflow-hidden", "data-[state=open]:animate-[collapse-down_var(--duration-normal,200ms)_var(--ease-out,ease-out)]", "data-[state=closed]:animate-[collapse-up_var(--duration-normal,200ms)_var(--ease-in,ease-in)]",
94
+ // Expose the natural height to the keyframe via the variable set by Radix.
95
+ "[--collapsible-content-height:var(--radix-accordion-content-height)]"), ...props, children: _jsx("div", { className: cn(accordionContentSizeVariants({ size }), className), children: children }) }));
96
+ });
97
+ AccordionContent.displayName = "AccordionContent";
98
+ export { Accordion, AccordionItem, AccordionTrigger, AccordionContent, useAccordion, accordionVariants, accordionItemVariants, accordionTriggerVariants, };
99
+ //# sourceMappingURL=accordion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../components/ui/accordion.tsx"],"names":[],"mappings":"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"}