@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,270 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { useState } from "react";
3
+ import {
4
+ RiDashboardLine,
5
+ RiFolderLine,
6
+ RiNotification3Line,
7
+ RiSettings4Line,
8
+ RiTeamLine,
9
+ } from "@remixicon/react";
10
+
11
+ import {
12
+ AppShell,
13
+ AppShellFooter,
14
+ AppShellHeader,
15
+ AppShellMain,
16
+ AppShellSidebar,
17
+ } from "./app-shell";
18
+ import { Avatar, AvatarFallback } from "./avatar";
19
+ import { Badge } from "./badge";
20
+ import { Breadcrumbs } from "./breadcrumb";
21
+ import { Button } from "./button";
22
+ import { PageHeader } from "./page-header";
23
+ import {
24
+ Sidebar,
25
+ SidebarBody,
26
+ SidebarBrand,
27
+ SidebarCollapseToggle,
28
+ SidebarFooter,
29
+ SidebarGroup,
30
+ SidebarGroupLabel,
31
+ SidebarItem,
32
+ SidebarSubItem,
33
+ } from "./sidebar";
34
+ import { TopBar, TopBarBrand, TopBarEnd, TopBarStart } from "./top-bar";
35
+
36
+ const meta: Meta<typeof AppShell> = {
37
+ title: "Layout/AppShell",
38
+ component: AppShell,
39
+ parameters: { layout: "fullscreen" },
40
+ argTypes: {
41
+ variant: { control: "select", options: ["default", "header-only", "sidebar-only", "minimal"] },
42
+ sidebarPosition: { control: "select", options: ["start", "end"] },
43
+ sidebarWidth: { control: "select", options: ["sm", "md", "lg"] },
44
+ headerHeight: { control: "select", options: ["sm", "md", "lg"] },
45
+ sidebarBreakpoint: { control: "select", options: ["sm", "md", "lg"] },
46
+ stickyHeader: { control: "boolean" },
47
+ bordered: { control: "boolean" },
48
+ defaultSidebarCollapsed: { control: "boolean" },
49
+ },
50
+ };
51
+
52
+ export default meta;
53
+ type Story = StoryObj<typeof AppShell>;
54
+
55
+ function ShellBrand() {
56
+ return (
57
+ <SidebarBrand>
58
+ <span className="inline-flex size-6 items-center justify-center rounded bg-primary text-primary-foreground text-xs font-bold">
59
+ E
60
+ </span>
61
+ <span>Emara</span>
62
+ </SidebarBrand>
63
+ );
64
+ }
65
+
66
+ function ShellTopBarBrand() {
67
+ return (
68
+ <TopBarBrand>
69
+ <span className="inline-flex size-6 items-center justify-center rounded bg-primary text-primary-foreground text-xs font-bold">
70
+ E
71
+ </span>
72
+ <span>Emara</span>
73
+ </TopBarBrand>
74
+ );
75
+ }
76
+
77
+ function SidebarContents({
78
+ collapsed,
79
+ onToggle,
80
+ }: {
81
+ collapsed: boolean;
82
+ onToggle: () => void;
83
+ }) {
84
+ return (
85
+ <Sidebar collapsed={collapsed} className="h-full">
86
+ <ShellBrand />
87
+ <SidebarBody>
88
+ <SidebarGroup>
89
+ <SidebarGroupLabel>Workspace</SidebarGroupLabel>
90
+ <SidebarItem icon={<RiDashboardLine />} label="Dashboard" tooltip="Dashboard" active />
91
+ <SidebarItem
92
+ icon={<RiTeamLine />}
93
+ label="Team"
94
+ tooltip="Team"
95
+ badge={<Badge size="xs" variant="info">12</Badge>}
96
+ />
97
+ <SidebarItem
98
+ icon={<RiFolderLine />}
99
+ label="Projects"
100
+ tooltip="Projects"
101
+ expandable
102
+ defaultExpanded
103
+ >
104
+ <SidebarSubItem label="Apollo" />
105
+ <SidebarSubItem label="Mercury" active />
106
+ <SidebarSubItem label="Gemini" />
107
+ </SidebarItem>
108
+ </SidebarGroup>
109
+ <SidebarGroup>
110
+ <SidebarGroupLabel>Settings</SidebarGroupLabel>
111
+ <SidebarItem icon={<RiSettings4Line />} label="Preferences" tooltip="Preferences" />
112
+ </SidebarGroup>
113
+ </SidebarBody>
114
+ <SidebarFooter>
115
+ <SidebarCollapseToggle onClick={onToggle} />
116
+ </SidebarFooter>
117
+ </Sidebar>
118
+ );
119
+ }
120
+
121
+ function ShellHeader() {
122
+ return (
123
+ <TopBar bordered>
124
+ <TopBarStart>
125
+ <ShellTopBarBrand />
126
+ </TopBarStart>
127
+ <TopBarEnd>
128
+ <Button variant="ghost" size="icon-sm" aria-label="Notifications">
129
+ <RiNotification3Line />
130
+ </Button>
131
+ <Avatar size="sm">
132
+ <AvatarFallback>AZ</AvatarFallback>
133
+ </Avatar>
134
+ </TopBarEnd>
135
+ </TopBar>
136
+ );
137
+ }
138
+
139
+ function PageContent() {
140
+ return (
141
+ <div className="p-6">
142
+ <PageHeader
143
+ title="Dashboard"
144
+ description="Welcome back — here's what's happening today."
145
+ breadcrumb={
146
+ <Breadcrumbs
147
+ items={[
148
+ { label: "Home", href: "/" },
149
+ { label: "Dashboard" },
150
+ ]}
151
+ />
152
+ }
153
+ actions={<Button>New report</Button>}
154
+ divider
155
+ />
156
+ <div className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-3">
157
+ {[1, 2, 3, 4, 5, 6].map((i) => (
158
+ <div
159
+ key={i}
160
+ className="rounded-md border border-border bg-card p-4 shadow-sm"
161
+ >
162
+ <div className="text-xs text-muted-foreground">Metric {i}</div>
163
+ <div className="mt-1 text-2xl font-semibold tabular-nums">
164
+ {(i * 1234).toLocaleString()}
165
+ </div>
166
+ </div>
167
+ ))}
168
+ </div>
169
+ </div>
170
+ );
171
+ }
172
+
173
+ export const Default: Story = {
174
+ render: (args) => {
175
+ function Demo() {
176
+ const [collapsed, setCollapsed] = useState(false);
177
+ return (
178
+ <AppShell {...args} sidebarCollapsed={collapsed} onSidebarCollapsedChange={setCollapsed}>
179
+ <AppShellHeader>
180
+ <ShellHeader />
181
+ </AppShellHeader>
182
+ <AppShellSidebar>
183
+ <SidebarContents collapsed={collapsed} onToggle={() => setCollapsed((v) => !v)} />
184
+ </AppShellSidebar>
185
+ <AppShellMain>
186
+ <PageContent />
187
+ </AppShellMain>
188
+ </AppShell>
189
+ );
190
+ }
191
+ return <Demo />;
192
+ },
193
+ };
194
+
195
+ export const HeaderOnly: Story = {
196
+ args: { variant: "header-only" },
197
+ render: (args) => (
198
+ <AppShell {...args}>
199
+ <AppShellHeader>
200
+ <ShellHeader />
201
+ </AppShellHeader>
202
+ <AppShellMain>
203
+ <PageContent />
204
+ </AppShellMain>
205
+ </AppShell>
206
+ ),
207
+ };
208
+
209
+ export const SidebarOnly: Story = {
210
+ args: { variant: "sidebar-only" },
211
+ render: (args) => {
212
+ function Demo() {
213
+ const [collapsed, setCollapsed] = useState(false);
214
+ return (
215
+ <AppShell {...args} sidebarCollapsed={collapsed} onSidebarCollapsedChange={setCollapsed}>
216
+ <AppShellSidebar>
217
+ <SidebarContents collapsed={collapsed} onToggle={() => setCollapsed((v) => !v)} />
218
+ </AppShellSidebar>
219
+ <AppShellMain>
220
+ <PageContent />
221
+ </AppShellMain>
222
+ </AppShell>
223
+ );
224
+ }
225
+ return <Demo />;
226
+ },
227
+ };
228
+
229
+ export const Minimal: Story = {
230
+ args: { variant: "minimal" },
231
+ render: (args) => (
232
+ <AppShell {...args}>
233
+ <AppShellMain>
234
+ <PageContent />
235
+ </AppShellMain>
236
+ </AppShell>
237
+ ),
238
+ };
239
+
240
+ export const SidebarEnd: Story = {
241
+ args: { sidebarPosition: "end" },
242
+ render: Default.render!,
243
+ };
244
+
245
+ export const WithFooter: Story = {
246
+ render: (args) => {
247
+ function Demo() {
248
+ const [collapsed, setCollapsed] = useState(false);
249
+ return (
250
+ <AppShell {...args} sidebarCollapsed={collapsed} onSidebarCollapsedChange={setCollapsed}>
251
+ <AppShellHeader>
252
+ <ShellHeader />
253
+ </AppShellHeader>
254
+ <AppShellSidebar>
255
+ <SidebarContents collapsed={collapsed} onToggle={() => setCollapsed((v) => !v)} />
256
+ </AppShellSidebar>
257
+ <AppShellMain>
258
+ <PageContent />
259
+ </AppShellMain>
260
+ <AppShellFooter>
261
+ <div className="px-6 py-3 text-xs text-muted-foreground">
262
+ © 2026 Emara. All rights reserved.
263
+ </div>
264
+ </AppShellFooter>
265
+ </AppShell>
266
+ );
267
+ }
268
+ return <Demo />;
269
+ },
270
+ };