@syscore/ui-library 1.1.12 → 1.2.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 (100) hide show
  1. package/client/components/icons/AchievementBadges.tsx +33 -0
  2. package/client/components/icons/ConceptIcons.tsx +169 -22
  3. package/client/components/icons/NavLogo.tsx +4 -4
  4. package/client/components/icons/ProviderBadges.tsx +28 -28
  5. package/client/components/icons/ProviderSeals.tsx +35 -35
  6. package/client/components/icons/StandardLogo.tsx +47 -0
  7. package/client/components/icons/UtilityChevronDown.tsx +1 -1
  8. package/client/components/icons/UtilityClearRegular.tsx +43 -0
  9. package/client/components/icons/UtilityCompare.tsx +71 -0
  10. package/client/components/icons/UtilityHome.tsx +26 -0
  11. package/client/components/icons/UtilityReset.tsx +7 -7
  12. package/client/components/icons/UtilitySave.tsx +35 -0
  13. package/client/components/icons/UtilityScopeLarge.tsx +86 -0
  14. package/client/components/icons/UtilityShow.tsx +41 -0
  15. package/client/components/icons/UtilityTarget.tsx +21 -0
  16. package/client/components/icons/UtilityTargetActive.tsx +34 -0
  17. package/client/components/icons/UtilityText.tsx +8 -8
  18. package/client/components/ui/accordion.tsx +6 -9
  19. package/client/components/ui/alert-dialog.tsx +6 -19
  20. package/client/components/ui/alert.tsx +5 -6
  21. package/client/components/ui/avatar.tsx +3 -9
  22. package/client/components/ui/badge.tsx +5 -8
  23. package/client/components/ui/breadcrumb.tsx +24 -11
  24. package/client/components/ui/button.tsx +40 -56
  25. package/client/components/ui/calendar.tsx +24 -28
  26. package/client/components/ui/card.tsx +6 -9
  27. package/client/components/ui/carousel.tsx +14 -14
  28. package/client/components/ui/chart.tsx +25 -28
  29. package/client/components/ui/checkbox.tsx +3 -8
  30. package/client/components/ui/code-badge.tsx +22 -0
  31. package/client/components/ui/command.tsx +12 -48
  32. package/client/components/ui/context-menu.tsx +17 -32
  33. package/client/components/ui/dialog.tsx +9 -18
  34. package/client/components/ui/drawer.tsx +7 -13
  35. package/client/components/ui/dropdown-menu.tsx +17 -29
  36. package/client/components/ui/form.tsx +4 -4
  37. package/client/components/ui/hover-card.tsx +1 -4
  38. package/client/components/ui/input-otp.tsx +7 -10
  39. package/client/components/ui/input.tsx +34 -9
  40. package/client/components/ui/label.tsx +2 -4
  41. package/client/components/ui/menubar.tsx +19 -40
  42. package/client/components/ui/navigation-menu.tsx +10 -27
  43. package/client/components/ui/navigation.tsx +861 -0
  44. package/client/components/ui/pagination.tsx +8 -8
  45. package/client/components/ui/popover.tsx +1 -4
  46. package/client/components/ui/progress.tsx +2 -5
  47. package/client/components/ui/radio-group.tsx +4 -7
  48. package/client/components/ui/resizable.tsx +4 -10
  49. package/client/components/ui/scroll-area.tsx +5 -8
  50. package/client/components/ui/{SearchField.tsx → search.tsx} +7 -10
  51. package/client/components/ui/select.tsx +19 -44
  52. package/client/components/ui/separator.tsx +2 -2
  53. package/client/components/ui/sheet.tsx +12 -23
  54. package/client/components/ui/sidebar.tsx +55 -82
  55. package/client/components/ui/skeleton.tsx +1 -1
  56. package/client/components/ui/slider.tsx +4 -7
  57. package/client/components/ui/sonner.tsx +5 -8
  58. package/client/components/ui/switch.tsx +2 -9
  59. package/client/components/ui/table.tsx +9 -18
  60. package/client/components/ui/tabs.tsx +43 -203
  61. package/client/components/ui/tag.tsx +68 -0
  62. package/client/components/ui/textarea.tsx +1 -4
  63. package/client/components/ui/toast.tsx +9 -19
  64. package/client/components/ui/toaster.tsx +1 -1
  65. package/client/components/ui/toggle-group.tsx +20 -3
  66. package/client/components/ui/toggle.tsx +13 -13
  67. package/client/components/ui/tooltip.tsx +147 -10
  68. package/client/global.css +5421 -1049
  69. package/client/storybook.css +1164 -0
  70. package/client/ui/AspectRatio.stories.tsx +1 -1
  71. package/client/ui/Button.stories.tsx +5 -5
  72. package/client/ui/Card.stories.tsx +223 -2
  73. package/client/ui/CodeBadge.stories.tsx +76 -0
  74. package/client/ui/Dialog.stories.tsx +52 -5
  75. package/client/ui/Icons.stories.tsx +31 -31
  76. package/client/ui/Input.stories.tsx +125 -0
  77. package/client/ui/Label.stories.tsx +8 -11
  78. package/client/ui/Navigation.stories.tsx +1 -1
  79. package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
  80. package/client/ui/SearchField.stories.tsx +1 -1
  81. package/client/ui/{Select/Select.stories.tsx → Select.stories.tsx} +2 -2
  82. package/client/ui/{Switch/Switch.stories.tsx → Switch.stories.tsx} +3 -3
  83. package/client/ui/Tabs.stories.tsx +174 -10
  84. package/client/ui/Tag.stories.tsx +48 -1
  85. package/client/ui/{Textarea/Textarea.stories.tsx → Textarea.stories.tsx} +9 -10
  86. package/client/ui/Toggle.stories.tsx +3 -3
  87. package/client/ui/Tooltip.stories.tsx +28 -4
  88. package/dist/ui/index.cjs.js +1 -1
  89. package/dist/ui/index.d.ts +4 -6
  90. package/dist/ui/index.es.js +1227 -2235
  91. package/dist/ui/ui-library.css +1 -0
  92. package/package.json +3 -3
  93. package/client/components/ui/Navigation.tsx +0 -958
  94. package/client/components/ui/StrategyTable.tsx +0 -303
  95. package/client/components/ui/Tag.tsx +0 -127
  96. package/client/ui/Input/Input.stories.tsx +0 -69
  97. package/client/ui/StrategyTable.stories.tsx +0 -138
  98. package/client/ui/WELLDashboard/WELLDashboard.stories.tsx +0 -115
  99. package/client/ui/WELLDashboard/index.tsx +0 -317
  100. /package/client/hooks/{UseTabs.tsx → use-tabs.tsx} +0 -0
@@ -1,13 +1,16 @@
1
1
  "use client";
2
2
 
3
3
  import React from "react";
4
-
5
- import { AnimatePresence, motion } from "motion/react";
6
4
  import * as TabsPrimitive from "@radix-ui/react-tabs";
5
+ import { AnimatePresence, motion, Transition } from "motion/react";
7
6
 
8
- import { useTabs, type Tab } from "../../hooks/UseTabs";
7
+ import { useTabs, type Tab as BaseTab } from "@/hooks/use-tabs";
9
8
  import { cn } from "@/lib/utils";
10
9
 
10
+ export type Tab = BaseTab & {
11
+ content?: React.ReactNode;
12
+ };
13
+
11
14
  interface AnimatedTabsProps {
12
15
  tabs: Tab[];
13
16
  }
@@ -18,177 +21,23 @@ const transition = {
18
21
  duration: 0.15,
19
22
  };
20
23
 
21
- const getHoverAnimationProps = (hoveredRect: DOMRect, navRect: DOMRect) => ({
22
- x: hoveredRect.left - navRect.left - 10,
23
- y: hoveredRect.top - navRect.top - 4,
24
- width: hoveredRect.width + 20,
25
- height: hoveredRect.height + 10,
26
- });
24
+ // const getHoverAnimationProps = (hoveredRect: DOMRect, navRect: DOMRect) => ({
25
+ // x: hoveredRect.left - navRect.left - 10,
26
+ // y: hoveredRect.top - navRect.top - 4,
27
+ // width: hoveredRect.width + 20,
28
+ // height: hoveredRect.height + 10,
29
+ // });
27
30
 
28
31
  const TabContent = ({ tab }: { tab: Tab }) => {
29
32
  return (
30
33
  <motion.div
34
+ key={tab.value}
31
35
  initial={{ opacity: 0, y: 10 }}
32
36
  animate={{ opacity: 1, y: 0 }}
33
37
  exit={{ opacity: 0, y: -10 }}
34
- transition={transition}
35
- className="p-6 bg-zinc-50 dark:bg-zinc-900 rounded-lg mt-4 h-[55vh]"
38
+ transition={transition as Transition}
36
39
  >
37
- {tab.value === "home" && (
38
- <div className="space-y-6">
39
- <div className="border-b pb-6 dark:border-zinc-800">
40
- <h2 className="text-3xl font-bold mb-4">Welcome to Our Platform</h2>
41
- <p className="text-zinc-600 dark:text-zinc-400 mb-4">
42
- Discover a new way to manage your projects and collaborate with
43
- your team.
44
- </p>
45
- <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
46
- <div className="p-4 bg-white dark:bg-zinc-800 rounded-lg">
47
- <h3 className="font-semibold mb-2">Quick Start</h3>
48
- <p className="text-sm text-zinc-600 dark:text-zinc-400">
49
- Get started with our platform in minutes
50
- </p>
51
- </div>
52
- <div className="p-4 bg-white dark:bg-zinc-800 rounded-lg">
53
- <h3 className="font-semibold mb-2">Latest Updates</h3>
54
- <p className="text-sm text-zinc-600 dark:text-zinc-400">
55
- See what&apos;s new in our latest release
56
- </p>
57
- </div>
58
- <div className="p-4 bg-white dark:bg-zinc-800 rounded-lg">
59
- <h3 className="font-semibold mb-2">Resources</h3>
60
- <p className="text-sm text-zinc-600 dark:text-zinc-400">
61
- Access guides and documentation
62
- </p>
63
- </div>
64
- </div>
65
- </div>
66
- <div>
67
- <h3 className="text-xl font-semibold mb-4">Recent Activity</h3>
68
- <div className="space-y-3">
69
- <div className="flex items-center gap-3 p-3 bg-white dark:bg-zinc-800 rounded-lg">
70
- <div className="w-2 h-2 bg-green-500 rounded-full"></div>
71
- <p className="text-sm">
72
- Project &quot;Marketing Campaign&quot; was updated 2 hours ago
73
- </p>
74
- </div>
75
- <div className="flex items-center gap-3 p-3 bg-white dark:bg-zinc-800 rounded-lg">
76
- <div className="w-2 h-2 bg-blue-500 rounded-full"></div>
77
- <p className="text-sm">
78
- New team member John Doe joined the platform
79
- </p>
80
- </div>
81
- </div>
82
- </div>
83
- </div>
84
- )}
85
- {tab.value === "about" && (
86
- <div className="space-y-8">
87
- <div>
88
- <h2 className="text-3xl font-bold mb-4">About Us</h2>
89
- <p className="text-zinc-600 dark:text-zinc-400 mb-6">
90
- We&apos;re a team of passionate individuals working together to
91
- create amazing solutions for our clients.
92
- </p>
93
- <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
94
- <div>
95
- <h3 className="text-xl font-semibold mb-3">Our Mission</h3>
96
- <p className="text-zinc-600 dark:text-zinc-400">
97
- To empower businesses with innovative tools and solutions that
98
- drive growth and success in the digital age.
99
- </p>
100
- </div>
101
- <div>
102
- <h3 className="text-xl font-semibold mb-3">Our Vision</h3>
103
- <p className="text-zinc-600 dark:text-zinc-400">
104
- To become the leading platform for business transformation and
105
- digital innovation worldwide.
106
- </p>
107
- </div>
108
- </div>
109
- </div>
110
- </div>
111
- )}
112
- {tab.value === "contact" && (
113
- <div className="max-w-2xl mx-auto">
114
- <h2 className="text-3xl font-bold mb-6">Get in Touch</h2>
115
- <div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-8">
116
- <div>
117
- <h3 className="text-xl font-semibold mb-4">
118
- Contact Information
119
- </h3>
120
- <div className="space-y-4">
121
- <div>
122
- <p className="font-medium">Address</p>
123
- <p className="text-zinc-600 dark:text-zinc-400">
124
- 123 Business Street
125
- </p>
126
- <p className="text-zinc-600 dark:text-zinc-400">
127
- San Francisco, CA 94105
128
- </p>
129
- </div>
130
- <div>
131
- <p className="font-medium">Email</p>
132
- <p className="text-zinc-600 dark:text-zinc-400">
133
- contact@example.com
134
- </p>
135
- </div>
136
- <div>
137
- <p className="font-medium">Phone</p>
138
- <p className="text-zinc-600 dark:text-zinc-400">
139
- +1 (555) 123-4567
140
- </p>
141
- </div>
142
- </div>
143
- </div>
144
- <div className="space-y-4">
145
- <div>
146
- <label className="block text-sm font-medium mb-1">Name</label>
147
- <input
148
- type="text"
149
- className="w-full p-2 rounded-md border dark:bg-zinc-800 dark:border-zinc-700"
150
- />
151
- </div>
152
- <div>
153
- <label className="block text-sm font-medium mb-1">Email</label>
154
- <input
155
- type="email"
156
- className="w-full p-2 rounded-md border dark:bg-zinc-800 dark:border-zinc-700"
157
- />
158
- </div>
159
- <button className="w-full bg-black text-white dark:bg-white dark:text-black py-2 rounded-md font-medium">
160
- Send Message
161
- </button>
162
- </div>
163
- </div>
164
- </div>
165
- )}
166
- {tab.value === "danger-zone" && (
167
- <div className="max-w-2xl mx-auto">
168
- <h2 className="text-2xl font-bold mb-6 text-red-500">Caution!</h2>
169
- <div className="space-y-6">
170
- <div className="border border-red-200 dark:border-red-900 rounded-lg p-6 bg-red-50 dark:bg-red-900/20">
171
- <h3 className="text-lg font-semibold text-red-600 dark:text-red-400 mb-2">
172
- Delete Account
173
- </h3>
174
- <p className="text-red-600/80 dark:text-red-400/80 mb-4">
175
- This action cannot be undone. This will permanently delete your
176
- account and remove your data from our servers.
177
- </p>
178
- <div className="flex items-center gap-4">
179
- <input
180
- type="text"
181
- placeholder="Type 'delete' to confirm"
182
- className="flex-1 p-2 rounded-md border border-red-200 dark:border-red-800 dark:bg-red-900/30"
183
- />
184
- <button className="bg-red-500 text-white px-4 py-2 rounded-md hover:bg-red-600 transition-colors">
185
- Delete Account
186
- </button>
187
- </div>
188
- </div>
189
- </div>
190
- </div>
191
- )}
40
+ {tab.content}
192
41
  </motion.div>
193
42
  );
194
43
  };
@@ -224,7 +73,7 @@ const Tabs = ({
224
73
  return (
225
74
  <nav
226
75
  ref={navRef}
227
- className="flex flex-shrink-0 justify-center items-center relative z-0 py-2"
76
+ className="tabs-nav"
228
77
  onPointerLeave={() => setHoveredTabIndex(null)}
229
78
  >
230
79
  {tabs.map((item, i) => {
@@ -233,7 +82,7 @@ const Tabs = ({
233
82
  return (
234
83
  <button
235
84
  key={item.value}
236
- className="text-sm relative rounded-md flex items-center h-8 px-4 z-20 bg-transparent cursor-pointer select-none transition-colors"
85
+ className="tabs-nav-button"
237
86
  onPointerEnter={() => setHoveredTabIndex(i)}
238
87
  onFocus={() => setHoveredTabIndex(i)}
239
88
  onClick={() => setSelectedTab([i, i > selectedTabIndex ? 1 : -1])}
@@ -242,13 +91,13 @@ const Tabs = ({
242
91
  ref={(el) => {
243
92
  buttonRefs[i] = el as HTMLButtonElement;
244
93
  }}
245
- className={cn("block", {
246
- "text-gray-500": !isActive,
247
- "text-gray-800 dark:text-white font-semibold": isActive,
94
+ className={cn("tabs-nav-button-text", {
95
+ "tabs-nav-button-text--inactive": !isActive,
96
+ "tabs-nav-button-text--active": isActive,
248
97
  })}
249
98
  >
250
99
  <small
251
- className={item.value === "danger-zone" ? "text-red-500" : ""}
100
+ className={item.value === "danger-zone" ? "tabs-nav-button-text--danger" : ""}
252
101
  >
253
102
  {item.label}
254
103
  </small>
@@ -257,7 +106,7 @@ const Tabs = ({
257
106
  );
258
107
  })}
259
108
 
260
- <AnimatePresence>
109
+ {/* <AnimatePresence>
261
110
  {hoveredRect && navRect && (
262
111
  <motion.div
263
112
  key="hover"
@@ -279,30 +128,32 @@ const Tabs = ({
279
128
  ...getHoverAnimationProps(hoveredRect, navRect),
280
129
  opacity: 0,
281
130
  }}
282
- transition={transition}
131
+ transition={transition as Transition}
283
132
  />
284
133
  )}
285
- </AnimatePresence>
134
+ </AnimatePresence> */}
286
135
 
287
136
  <AnimatePresence>
288
137
  {selectedRect && navRect && (
289
138
  <motion.div
290
- className={`absolute z-10 bottom-0 left-0 h-[2px] ${
291
- selectedTabIndex ===
292
- tabs.findIndex(({ value }) => value === "danger-zone")
293
- ? "bg-red-500"
294
- : "bg-cyan-700"
295
- }`}
139
+ className={cn("tabs-nav-indicator", {
140
+ "tabs-nav-indicator--danger": selectedTabIndex ===
141
+ tabs.findIndex(({ value }) => value === "danger-zone"),
142
+ "tabs-nav-indicator--default": selectedTabIndex !==
143
+ tabs.findIndex(({ value }) => value === "danger-zone"),
144
+ })}
296
145
  initial={false}
297
146
  animate={{
298
- width: selectedRect.width + 18,
299
- x: `calc(${selectedRect.left - navRect.left - 9}px)`,
147
+ width: selectedRect.width,
148
+ x: selectedRect.left - navRect.left,
300
149
  opacity: 1,
301
150
  }}
302
- transition={transition}
151
+ transition={transition as Transition}
303
152
  />
304
153
  )}
305
154
  </AnimatePresence>
155
+
156
+ <div className="tabs-nav-underline" />
306
157
  </nav>
307
158
  );
308
159
  };
@@ -313,10 +164,8 @@ export function AnimatedTabs({ tabs }: AnimatedTabsProps) {
313
164
  tabs.find((tab) => tab.value === "home")?.value || tabs[0].value;
314
165
 
315
166
  return {
316
- tabs: tabs.map(({ label, value, subRoutes }) => ({
317
- label,
318
- value,
319
- subRoutes,
167
+ tabs: tabs.map((tab) => ({
168
+ ...tab,
320
169
  })),
321
170
  initialTabId,
322
171
  };
@@ -325,8 +174,8 @@ export function AnimatedTabs({ tabs }: AnimatedTabsProps) {
325
174
  const framer = useTabs(hookProps);
326
175
 
327
176
  return (
328
- <div className="w-full">
329
- <div className="relative flex w-full shrink-0 items-center justify-between overflow-x-auto overflow-y-hidden">
177
+ <div className="tabs-container">
178
+ <div className="tabs-container-inner">
330
179
  <Tabs {...framer.tabProps} />
331
180
  </div>
332
181
  <AnimatePresence mode="wait">
@@ -343,7 +192,7 @@ const TabsRoot = React.forwardRef<
343
192
  >(({ className, ...props }, ref) => (
344
193
  <TabsPrimitive.Root
345
194
  ref={ref}
346
- className={cn("w-full", className)}
195
+ className={cn("tabs", className)}
347
196
  {...props}
348
197
  />
349
198
  ));
@@ -355,10 +204,7 @@ const TabsList = React.forwardRef<
355
204
  >(({ className, ...props }, ref) => (
356
205
  <TabsPrimitive.List
357
206
  ref={ref}
358
- className={cn(
359
- "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
360
- className,
361
- )}
207
+ className={cn("tabs-list", className)}
362
208
  {...props}
363
209
  />
364
210
  ));
@@ -370,10 +216,7 @@ const TabsTrigger = React.forwardRef<
370
216
  >(({ className, ...props }, ref) => (
371
217
  <TabsPrimitive.Trigger
372
218
  ref={ref}
373
- className={cn(
374
- "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
375
- className,
376
- )}
219
+ className={cn("tabs-trigger", className)}
377
220
  {...props}
378
221
  />
379
222
  ));
@@ -385,10 +228,7 @@ const TabsContent = React.forwardRef<
385
228
  >(({ className, ...props }, ref) => (
386
229
  <TabsPrimitive.Content
387
230
  ref={ref}
388
- className={cn(
389
- "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
390
- className,
391
- )}
231
+ className={cn("tabs-content", className)}
392
232
  {...props}
393
233
  />
394
234
  ));
@@ -0,0 +1,68 @@
1
+ import * as React from "react";
2
+ import { cn } from "@/lib/utils";
3
+
4
+ export type TagStatus = "todo" | "low" | "medium" | "high" | "done";
5
+
6
+ export interface TagProps
7
+ extends React.ButtonHTMLAttributes<HTMLButtonElement> {
8
+ children: React.ReactNode;
9
+ active?: boolean;
10
+ status?: TagStatus;
11
+ variant?: "light" | "dark";
12
+ onClick?: () => void;
13
+ }
14
+
15
+ const getStatusClass = (
16
+ status: TagStatus,
17
+ variant: "light" | "dark" = "light"
18
+ ) => {
19
+ return `tag tag--${variant}-${status}`;
20
+ };
21
+
22
+ export const Tag = React.forwardRef<HTMLButtonElement, TagProps>(
23
+ (
24
+ {
25
+ children,
26
+ active = false,
27
+ status,
28
+ variant = "light",
29
+ className,
30
+ onClick,
31
+ ...props
32
+ },
33
+ ref
34
+ ) => {
35
+ // Status tag styling
36
+ if (status) {
37
+ const statusClass = getStatusClass(status, variant);
38
+ return (
39
+ <button
40
+ ref={ref}
41
+ onClick={onClick}
42
+ className={cn(statusClass, className)}
43
+ {...props}
44
+ >
45
+ <span className="overline-medium">{children}</span>
46
+ </button>
47
+ );
48
+ }
49
+
50
+ // Dual-state general purpose tag styling
51
+ return (
52
+ <button
53
+ ref={ref}
54
+ onClick={onClick}
55
+ className={cn(
56
+ "tag-general",
57
+ active ? "tag-general--active" : "tag-general--inactive",
58
+ className
59
+ )}
60
+ {...props}
61
+ >
62
+ <span className="body-small font-semibold">{children}</span>
63
+ </button>
64
+ );
65
+ }
66
+ );
67
+
68
+ Tag.displayName = "Tag";
@@ -9,10 +9,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
9
9
  ({ className, ...props }, ref) => {
10
10
  return (
11
11
  <textarea
12
- className={cn(
13
- "flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
14
- className,
15
- )}
12
+ className={cn("textarea body-base", className)}
16
13
  ref={ref}
17
14
  {...props}
18
15
  />
@@ -13,23 +13,19 @@ const ToastViewport = React.forwardRef<
13
13
  >(({ className, ...props }, ref) => (
14
14
  <ToastPrimitives.Viewport
15
15
  ref={ref}
16
- className={cn(
17
- "fixed top-0 z-100 flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
18
- className,
19
- )}
16
+ className={cn("toast-viewport", className)}
20
17
  {...props}
21
18
  />
22
19
  ));
23
20
  ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
24
21
 
25
22
  const toastVariants = cva(
26
- "group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full sm:data-[state=open]:slide-in-from-bottom-full",
23
+ "toast",
27
24
  {
28
25
  variants: {
29
26
  variant: {
30
- default: "border bg-background text-foreground",
31
- destructive:
32
- "destructive group border-destructive bg-destructive text-destructive-foreground",
27
+ default: "toast--default",
28
+ destructive: "toast--destructive",
33
29
  },
34
30
  },
35
31
  defaultVariants: {
@@ -59,10 +55,7 @@ const ToastAction = React.forwardRef<
59
55
  >(({ className, ...props }, ref) => (
60
56
  <ToastPrimitives.Action
61
57
  ref={ref}
62
- className={cn(
63
- "inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors hover:bg-secondary focus:outline-hidden focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 group-[.destructive]:border-muted/40 hover:group-[.destructive]:border-destructive/30 hover:group-[.destructive]:bg-destructive hover:group-[.destructive]:text-destructive-foreground focus:group-[.destructive]:ring-destructive",
64
- className,
65
- )}
58
+ className={cn("toast-action", className)}
66
59
  {...props}
67
60
  />
68
61
  ));
@@ -74,14 +67,11 @@ const ToastClose = React.forwardRef<
74
67
  >(({ className, ...props }, ref) => (
75
68
  <ToastPrimitives.Close
76
69
  ref={ref}
77
- className={cn(
78
- "absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity hover:text-foreground focus:opacity-100 focus:outline-hidden focus:ring-2 group-hover:opacity-100 group-[.destructive]:text-red-300 hover:group-[.destructive]:text-red-50 focus:group-[.destructive]:ring-red-400 focus:group-[.destructive]:ring-offset-red-600",
79
- className,
80
- )}
70
+ className={cn("toast-close", className)}
81
71
  toast-close=""
82
72
  {...props}
83
73
  >
84
- <X className="h-4 w-4" />
74
+ <X className="icon-4" />
85
75
  </ToastPrimitives.Close>
86
76
  ));
87
77
  ToastClose.displayName = ToastPrimitives.Close.displayName;
@@ -92,7 +82,7 @@ const ToastTitle = React.forwardRef<
92
82
  >(({ className, ...props }, ref) => (
93
83
  <ToastPrimitives.Title
94
84
  ref={ref}
95
- className={cn("text-sm font-semibold", className)}
85
+ className={cn("toast-title", className)}
96
86
  {...props}
97
87
  />
98
88
  ));
@@ -104,7 +94,7 @@ const ToastDescription = React.forwardRef<
104
94
  >(({ className, ...props }, ref) => (
105
95
  <ToastPrimitives.Description
106
96
  ref={ref}
107
- className={cn("text-sm opacity-90", className)}
97
+ className={cn("toast-description", className)}
108
98
  {...props}
109
99
  />
110
100
  ));
@@ -16,7 +16,7 @@ export function Toaster() {
16
16
  {toasts.map(function ({ id, title, description, action, ...props }) {
17
17
  return (
18
18
  <Toast key={id} {...props}>
19
- <div className="grid gap-1">
19
+ <div className="toast-content">
20
20
  {title && <ToastTitle>{title}</ToastTitle>}
21
21
  {description && (
22
22
  <ToastDescription>{description}</ToastDescription>
@@ -1,9 +1,26 @@
1
1
  import * as React from "react";
2
2
  import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
3
- import { type VariantProps } from "class-variance-authority";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
4
 
5
5
  import { cn } from "@/lib/utils";
6
- import { toggleVariants } from "@/components/ui/toggle";
6
+
7
+ const toggleVariants = cva(
8
+ "toggle-group-item",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "toggle-group-item--default",
13
+ },
14
+ size: {
15
+ default: "toggle-group-item--size-default",
16
+ },
17
+ },
18
+ defaultVariants: {
19
+ variant: "default",
20
+ size: "default",
21
+ },
22
+ },
23
+ );
7
24
 
8
25
  const ToggleGroupContext = React.createContext<
9
26
  VariantProps<typeof toggleVariants>
@@ -19,7 +36,7 @@ const ToggleGroup = React.forwardRef<
19
36
  >(({ className, variant, size, children, ...props }, ref) => (
20
37
  <ToggleGroupPrimitive.Root
21
38
  ref={ref}
22
- className={cn("flex items-center justify-center gap-1", className)}
39
+ className={cn("toggle-group", className)}
23
40
  {...props}
24
41
  >
25
42
  <ToggleGroupContext.Provider value={{ variant, size }}>
@@ -4,18 +4,17 @@ import { cn } from "../../lib/utils";
4
4
  import { useSegmentedControl } from "../../hooks/use-segmented-control";
5
5
 
6
6
  const toggleVariants = cva(
7
- "inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
7
+ "toggle",
8
8
  {
9
9
  variants: {
10
10
  variant: {
11
- default: "bg-transparent",
12
- outline:
13
- "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
11
+ default: "toggle--default",
12
+ outline: "toggle--outline",
14
13
  },
15
14
  size: {
16
- default: "h-10 px-3",
17
- sm: "h-9 px-2.5",
18
- lg: "h-11 px-5",
15
+ default: "toggle--size-default",
16
+ sm: "toggle--size-sm",
17
+ lg: "toggle--size-lg",
19
18
  },
20
19
  },
21
20
  defaultVariants: {
@@ -50,22 +49,23 @@ const SegmentedControlInner = React.forwardRef<
50
49
  });
51
50
 
52
51
  return (
53
- <div ref={ref} className={cn(className)} {...props}>
52
+ <div ref={ref} className={cn("segmented-control", className)} {...props}>
54
53
  {options.map((option) => {
55
54
  const isReactElement = React.isValidElement(option.label);
55
+ const isActive = selectedValue === option.value;
56
56
 
57
57
  return (
58
58
  <button
59
59
  key={option.value}
60
60
  className={cn(
61
- "inline-flex items-center justify-center h-8 px-6 rounded-full transition-all focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
62
- selectedValue === option.value
63
- ? "bg-cyan-700 text-white font-semibold"
64
- : "text-gray-600 hover:bg-gray-50 font-medium",
61
+ "segmented-control-button",
62
+ isActive
63
+ ? "segmented-control-button--active"
64
+ : "segmented-control-button--inactive",
65
65
  )}
66
66
  onClick={() => handleValueChange(option.value)}
67
67
  type="button"
68
- data-active={selectedValue === option.value}
68
+ data-active={isActive}
69
69
  >
70
70
  {isReactElement ? (
71
71
  option.label