@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.
- package/client/components/icons/AchievementBadges.tsx +33 -0
- package/client/components/icons/ConceptIcons.tsx +169 -22
- package/client/components/icons/NavLogo.tsx +4 -4
- package/client/components/icons/ProviderBadges.tsx +28 -28
- package/client/components/icons/ProviderSeals.tsx +35 -35
- package/client/components/icons/StandardLogo.tsx +47 -0
- package/client/components/icons/UtilityChevronDown.tsx +1 -1
- package/client/components/icons/UtilityClearRegular.tsx +43 -0
- package/client/components/icons/UtilityCompare.tsx +71 -0
- package/client/components/icons/UtilityHome.tsx +26 -0
- package/client/components/icons/UtilityReset.tsx +7 -7
- package/client/components/icons/UtilitySave.tsx +35 -0
- package/client/components/icons/UtilityScopeLarge.tsx +86 -0
- package/client/components/icons/UtilityShow.tsx +41 -0
- package/client/components/icons/UtilityTarget.tsx +21 -0
- package/client/components/icons/UtilityTargetActive.tsx +34 -0
- package/client/components/icons/UtilityText.tsx +8 -8
- package/client/components/ui/accordion.tsx +6 -9
- package/client/components/ui/alert-dialog.tsx +6 -19
- package/client/components/ui/alert.tsx +5 -6
- package/client/components/ui/avatar.tsx +3 -9
- package/client/components/ui/badge.tsx +5 -8
- package/client/components/ui/breadcrumb.tsx +24 -11
- package/client/components/ui/button.tsx +40 -56
- package/client/components/ui/calendar.tsx +24 -28
- package/client/components/ui/card.tsx +6 -9
- package/client/components/ui/carousel.tsx +14 -14
- package/client/components/ui/chart.tsx +25 -28
- package/client/components/ui/checkbox.tsx +3 -8
- package/client/components/ui/code-badge.tsx +22 -0
- package/client/components/ui/command.tsx +12 -48
- package/client/components/ui/context-menu.tsx +17 -32
- package/client/components/ui/dialog.tsx +9 -18
- package/client/components/ui/drawer.tsx +7 -13
- package/client/components/ui/dropdown-menu.tsx +17 -29
- package/client/components/ui/form.tsx +4 -4
- package/client/components/ui/hover-card.tsx +1 -4
- package/client/components/ui/input-otp.tsx +7 -10
- package/client/components/ui/input.tsx +34 -9
- package/client/components/ui/label.tsx +2 -4
- package/client/components/ui/menubar.tsx +19 -40
- package/client/components/ui/navigation-menu.tsx +10 -27
- package/client/components/ui/navigation.tsx +861 -0
- package/client/components/ui/pagination.tsx +8 -8
- package/client/components/ui/popover.tsx +1 -4
- package/client/components/ui/progress.tsx +2 -5
- package/client/components/ui/radio-group.tsx +4 -7
- package/client/components/ui/resizable.tsx +4 -10
- package/client/components/ui/scroll-area.tsx +5 -8
- package/client/components/ui/{SearchField.tsx → search.tsx} +7 -10
- package/client/components/ui/select.tsx +19 -44
- package/client/components/ui/separator.tsx +2 -2
- package/client/components/ui/sheet.tsx +12 -23
- package/client/components/ui/sidebar.tsx +55 -82
- package/client/components/ui/skeleton.tsx +1 -1
- package/client/components/ui/slider.tsx +4 -7
- package/client/components/ui/sonner.tsx +5 -8
- package/client/components/ui/switch.tsx +2 -9
- package/client/components/ui/table.tsx +9 -18
- package/client/components/ui/tabs.tsx +43 -203
- package/client/components/ui/tag.tsx +68 -0
- package/client/components/ui/textarea.tsx +1 -4
- package/client/components/ui/toast.tsx +9 -19
- package/client/components/ui/toaster.tsx +1 -1
- package/client/components/ui/toggle-group.tsx +20 -3
- package/client/components/ui/toggle.tsx +13 -13
- package/client/components/ui/tooltip.tsx +147 -10
- package/client/global.css +5421 -1049
- package/client/storybook.css +1164 -0
- package/client/ui/AspectRatio.stories.tsx +1 -1
- package/client/ui/Button.stories.tsx +5 -5
- package/client/ui/Card.stories.tsx +223 -2
- package/client/ui/CodeBadge.stories.tsx +76 -0
- package/client/ui/Dialog.stories.tsx +52 -5
- package/client/ui/Icons.stories.tsx +31 -31
- package/client/ui/Input.stories.tsx +125 -0
- package/client/ui/Label.stories.tsx +8 -11
- package/client/ui/Navigation.stories.tsx +1 -1
- package/client/ui/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/client/ui/SearchField.stories.tsx +1 -1
- package/client/ui/{Select/Select.stories.tsx → Select.stories.tsx} +2 -2
- package/client/ui/{Switch/Switch.stories.tsx → Switch.stories.tsx} +3 -3
- package/client/ui/Tabs.stories.tsx +174 -10
- package/client/ui/Tag.stories.tsx +48 -1
- package/client/ui/{Textarea/Textarea.stories.tsx → Textarea.stories.tsx} +9 -10
- package/client/ui/Toggle.stories.tsx +3 -3
- package/client/ui/Tooltip.stories.tsx +28 -4
- package/dist/ui/index.cjs.js +1 -1
- package/dist/ui/index.d.ts +4 -6
- package/dist/ui/index.es.js +1227 -2235
- package/dist/ui/ui-library.css +1 -0
- package/package.json +3 -3
- package/client/components/ui/Navigation.tsx +0 -958
- package/client/components/ui/StrategyTable.tsx +0 -303
- package/client/components/ui/Tag.tsx +0 -127
- package/client/ui/Input/Input.stories.tsx +0 -69
- package/client/ui/StrategyTable.stories.tsx +0 -138
- package/client/ui/WELLDashboard/WELLDashboard.stories.tsx +0 -115
- package/client/ui/WELLDashboard/index.tsx +0 -317
- /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 "
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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.
|
|
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'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 "Marketing Campaign" 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'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="
|
|
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="
|
|
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("
|
|
246
|
-
"
|
|
247
|
-
"
|
|
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" ? "
|
|
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={
|
|
291
|
-
selectedTabIndex ===
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
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
|
|
299
|
-
x:
|
|
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((
|
|
317
|
-
|
|
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="
|
|
329
|
-
<div className="
|
|
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("
|
|
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
|
-
"
|
|
23
|
+
"toast",
|
|
27
24
|
{
|
|
28
25
|
variants: {
|
|
29
26
|
variant: {
|
|
30
|
-
default: "
|
|
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="
|
|
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("
|
|
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("
|
|
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="
|
|
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
|
-
|
|
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("
|
|
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
|
-
"
|
|
7
|
+
"toggle",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
|
-
default: "
|
|
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: "
|
|
17
|
-
sm: "
|
|
18
|
-
lg: "
|
|
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
|
-
"
|
|
62
|
-
|
|
63
|
-
? "
|
|
64
|
-
: "
|
|
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={
|
|
68
|
+
data-active={isActive}
|
|
69
69
|
>
|
|
70
70
|
{isReactElement ? (
|
|
71
71
|
option.label
|