omnira-ui 0.6.0 → 0.6.6
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/README.md +3 -3
- package/cli/omnira-init.mjs +25 -1
- package/components/ui/ActivityFeed/ActivityFeed.module.css +143 -0
- package/components/ui/ActivityFeed/ActivityFeed.tsx +94 -0
- package/components/ui/ActivityFeed/index.ts +2 -0
- package/components/ui/AgentThinking/AgentThinking.module.css +7 -0
- package/components/ui/AgentThinking/AgentThinking.tsx +27 -21
- package/components/ui/Button/Button.module.css +5 -5
- package/components/ui/ButtonGroup/ButtonGroup.module.css +103 -0
- package/components/ui/ButtonGroup/ButtonGroup.tsx +153 -0
- package/components/ui/ButtonGroup/index.ts +2 -0
- package/components/ui/Carousel/Carousel.module.css +95 -0
- package/components/ui/Carousel/Carousel.tsx +137 -0
- package/components/ui/Carousel/index.ts +2 -0
- package/components/ui/CodeSnippet/CodeSnippet.module.css +38 -18
- package/components/ui/CodeSnippet/CodeSnippet.tsx +84 -2
- package/components/ui/CommandMenu/CommandMenu.module.css +187 -0
- package/components/ui/CommandMenu/CommandMenu.tsx +205 -0
- package/components/ui/CommandMenu/index.ts +2 -0
- package/components/ui/EmailTemplate/EmailTemplate.module.css +303 -0
- package/components/ui/EmailTemplate/EmailTemplate.tsx +298 -0
- package/components/ui/EmailTemplate/index.ts +2 -0
- package/components/ui/FeaturedIcon/FeaturedIcon.module.css +212 -0
- package/components/ui/FeaturedIcon/FeaturedIcon.tsx +46 -0
- package/components/ui/FeaturedIcon/index.ts +2 -0
- package/components/ui/ForgotPassword/ForgotPassword.module.css +332 -0
- package/components/ui/ForgotPassword/ForgotPassword.tsx +387 -0
- package/components/ui/ForgotPassword/index.ts +2 -0
- package/components/ui/HeaderNavigation/HeaderNavigation.module.css +99 -0
- package/components/ui/HeaderNavigation/HeaderNavigation.tsx +103 -0
- package/components/ui/HeaderNavigation/index.ts +2 -0
- package/components/ui/InlineCTA/InlineCTA.module.css +101 -0
- package/components/ui/InlineCTA/InlineCTA.tsx +59 -0
- package/components/ui/InlineCTA/index.ts +2 -0
- package/components/ui/LineBarChart/LineBarChart.module.css +41 -0
- package/components/ui/LineBarChart/LineBarChart.tsx +191 -0
- package/components/ui/LineBarChart/index.ts +2 -0
- package/components/ui/Matrix/Matrix.module.css +54 -0
- package/components/ui/Matrix/Matrix.tsx +99 -0
- package/components/ui/Matrix/index.ts +2 -0
- package/components/ui/Messaging/Messaging.module.css +186 -0
- package/components/ui/Messaging/Messaging.tsx +168 -0
- package/components/ui/Messaging/index.ts +2 -0
- package/components/ui/NotFoundPage/NotFoundPage.module.css +270 -0
- package/components/ui/NotFoundPage/NotFoundPage.tsx +158 -0
- package/components/ui/NotFoundPage/index.ts +2 -0
- package/components/ui/Pagination/Pagination.module.css +161 -0
- package/components/ui/Pagination/Pagination.tsx +150 -0
- package/components/ui/Pagination/index.ts +2 -0
- package/components/ui/PieChart/PieChart.module.css +91 -0
- package/components/ui/PieChart/PieChart.tsx +185 -0
- package/components/ui/PieChart/index.ts +2 -0
- package/components/ui/ProgressSteps/ProgressSteps.module.css +232 -0
- package/components/ui/ProgressSteps/ProgressSteps.tsx +134 -0
- package/components/ui/ProgressSteps/index.ts +2 -0
- package/components/ui/RadarChart/RadarChart.module.css +25 -0
- package/components/ui/RadarChart/RadarChart.tsx +140 -0
- package/components/ui/RadarChart/index.ts +2 -0
- package/components/ui/SectionFooter/SectionFooter.module.css +55 -0
- package/components/ui/SectionFooter/SectionFooter.tsx +63 -0
- package/components/ui/SectionFooter/index.ts +2 -0
- package/components/ui/SectionHeader/SectionHeader.module.css +73 -0
- package/components/ui/SectionHeader/SectionHeader.tsx +121 -0
- package/components/ui/SectionHeader/index.ts +2 -0
- package/components/ui/SlideOut/SlideOut.module.css +17 -13
- package/components/ui/VerificationPage/VerificationPage.module.css +252 -0
- package/components/ui/VerificationPage/VerificationPage.tsx +287 -0
- package/components/ui/VerificationPage/index.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A premium glassmorphism design system — dark-first, glass-forward, no compromi
|
|
|
4
4
|
|
|
5
5
|
30+ base components, sidebar navigation, feature cards, 1,000+ icons, and a CLI to scaffold your project with your chosen accent color and theme mode.
|
|
6
6
|
|
|
7
|
-
**[Live Documentation →](https://
|
|
7
|
+
**[Live Documentation →](https://omnira.one)**
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -75,7 +75,7 @@ export default function MyPage() {
|
|
|
75
75
|
|
|
76
76
|
Browse the full library and copy advanced components (Sidebar, Feature Cards, etc.) directly from the docs:
|
|
77
77
|
|
|
78
|
-
**[
|
|
78
|
+
**[omnira.one →](https://omnira.one)**
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -170,4 +170,4 @@ lib/ # Shared utilities
|
|
|
170
170
|
|
|
171
171
|
## License
|
|
172
172
|
|
|
173
|
-
MIT © [Omnira UI](https://
|
|
173
|
+
MIT © [Omnira UI](https://omnira.one)
|
package/cli/omnira-init.mjs
CHANGED
|
@@ -384,7 +384,7 @@ async function main() {
|
|
|
384
384
|
log(` ${MAGENTA}import${RESET} { Button } ${MAGENTA}from${RESET} ${WHITE}"@/components/ui/Button"${RESET};`);
|
|
385
385
|
blank();
|
|
386
386
|
log(` ${DIM}4.${RESET} Browse all components & copy advanced ones:`);
|
|
387
|
-
log(` ${CYAN}https://
|
|
387
|
+
log(` ${CYAN}https://omnira.one${RESET}`);
|
|
388
388
|
blank();
|
|
389
389
|
}
|
|
390
390
|
|
|
@@ -468,6 +468,30 @@ const PAGE_BUNDLES = {
|
|
|
468
468
|
"card": ["Card", "Button", "Badge"],
|
|
469
469
|
// Matrix
|
|
470
470
|
"matrix": ["Card"],
|
|
471
|
+
// ── Base component slug aliases (hyphenated → PascalCase folder) ──
|
|
472
|
+
"app-store-button": ["AppStoreButton"],
|
|
473
|
+
"badge-group": ["BadgeGroup"],
|
|
474
|
+
"button-group": ["ButtonGroup"],
|
|
475
|
+
"credit-card": ["CreditCard"],
|
|
476
|
+
"featured-icon": ["FeaturedIcon"],
|
|
477
|
+
"progress-indicator": ["ProgressBar"],
|
|
478
|
+
"qr-code": ["QRCode"],
|
|
479
|
+
"radio-button": ["RadioButton"],
|
|
480
|
+
"radio-group": ["RadioGroup"],
|
|
481
|
+
"social-button": ["SocialButton"],
|
|
482
|
+
"text-editor": ["TextEditor"],
|
|
483
|
+
"utility": ["ButtonUtility"],
|
|
484
|
+
"verification-code-input": ["PinInput"],
|
|
485
|
+
"video-player": ["VideoPlayer"],
|
|
486
|
+
"agent-thinking": ["AgentThinking"],
|
|
487
|
+
// ── Shared pages bundles ──
|
|
488
|
+
"login": ["AuthPage", "LoginSimple", "LoginSplitImage", "LoginSplitQuote", "LoginCardSeparated", "SocialButton", "Button", "Input", "Checkbox"],
|
|
489
|
+
"sign-up": ["SignUpSimple", "SignUpSplitImage", "SignUpSplitQuote", "SignUpCardSeparated", "SocialButton", "Button", "Input", "Checkbox"],
|
|
490
|
+
"verification": ["VerificationPage", "Button", "PinInput"],
|
|
491
|
+
"forgot-password": ["ForgotPassword", "Button", "Input", "Checkbox"],
|
|
492
|
+
"not-found-page": ["NotFoundPage", "Button"],
|
|
493
|
+
"404": ["NotFoundPage", "Button"],
|
|
494
|
+
"email-template": ["EmailTemplate"],
|
|
471
495
|
};
|
|
472
496
|
|
|
473
497
|
// ── Add command — copy a single component ───────────────────────────
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/* ── Root ── */
|
|
2
|
+
.root {
|
|
3
|
+
display: flex;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.card {
|
|
8
|
+
background: var(--color-bg-card);
|
|
9
|
+
border: 1px solid var(--color-border-standard);
|
|
10
|
+
border-radius: var(--radius-xl);
|
|
11
|
+
padding: 20px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* ── Item ── */
|
|
15
|
+
.item {
|
|
16
|
+
display: flex;
|
|
17
|
+
gap: 10px;
|
|
18
|
+
position: relative;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.default .item + .item {
|
|
22
|
+
margin-top: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.compact .item + .item {
|
|
26
|
+
margin-top: 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* ── Timeline Column ── */
|
|
30
|
+
.timeline {
|
|
31
|
+
display: flex;
|
|
32
|
+
flex-direction: column;
|
|
33
|
+
align-items: center;
|
|
34
|
+
flex-shrink: 0;
|
|
35
|
+
width: 30px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.avatar {
|
|
39
|
+
width: 30px;
|
|
40
|
+
height: 30px;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
object-fit: cover;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.avatarFallback {
|
|
47
|
+
width: 30px;
|
|
48
|
+
height: 30px;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
background: var(--color-bg-elevated);
|
|
51
|
+
border: 1px solid var(--color-border-standard);
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: center;
|
|
55
|
+
font-size: 11px;
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
color: var(--color-text-secondary);
|
|
58
|
+
flex-shrink: 0;
|
|
59
|
+
font-family: var(--font-display);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.iconBubble {
|
|
63
|
+
width: 30px;
|
|
64
|
+
height: 30px;
|
|
65
|
+
border-radius: 50%;
|
|
66
|
+
background: var(--color-bg-lime-subtle);
|
|
67
|
+
display: flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
color: var(--color-lime);
|
|
71
|
+
flex-shrink: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.connector {
|
|
75
|
+
width: 2px;
|
|
76
|
+
flex: 1;
|
|
77
|
+
min-height: 20px;
|
|
78
|
+
background: var(--color-border-standard);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── Compact ── */
|
|
82
|
+
.compact .timeline {
|
|
83
|
+
width: 24px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.compact .avatar,
|
|
87
|
+
.compact .avatarFallback,
|
|
88
|
+
.compact .iconBubble {
|
|
89
|
+
width: 24px;
|
|
90
|
+
height: 24px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.compact .avatarFallback {
|
|
94
|
+
font-size: 10px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.compact .connector {
|
|
98
|
+
min-height: 12px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* ── Content Column ── */
|
|
102
|
+
.content {
|
|
103
|
+
flex: 1;
|
|
104
|
+
min-width: 0;
|
|
105
|
+
padding-bottom: 18px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.compact .content {
|
|
109
|
+
padding-bottom: 12px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.item:last-child .content {
|
|
113
|
+
padding-bottom: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.header {
|
|
117
|
+
display: flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 8px;
|
|
120
|
+
margin-bottom: 4px;
|
|
121
|
+
flex-wrap: wrap;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.userName {
|
|
125
|
+
font-size: 13px;
|
|
126
|
+
font-weight: 500;
|
|
127
|
+
color: var(--color-text-primary);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.timestamp {
|
|
131
|
+
font-size: 12px;
|
|
132
|
+
color: var(--color-text-tertiary);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.body {
|
|
136
|
+
font-size: 13px;
|
|
137
|
+
color: var(--color-text-secondary);
|
|
138
|
+
line-height: 1.5;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.body p {
|
|
142
|
+
margin: 0;
|
|
143
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { forwardRef } from "react";
|
|
4
|
+
import { cn } from "@/lib/cn";
|
|
5
|
+
import styles from "./ActivityFeed.module.css";
|
|
6
|
+
|
|
7
|
+
/* ── Types ── */
|
|
8
|
+
|
|
9
|
+
export interface ActivityFeedItem {
|
|
10
|
+
id: string;
|
|
11
|
+
/** User display name */
|
|
12
|
+
user: string;
|
|
13
|
+
/** Avatar URL (falls back to initials) */
|
|
14
|
+
avatar?: string;
|
|
15
|
+
/** Event content — plain text or ReactNode */
|
|
16
|
+
content: React.ReactNode;
|
|
17
|
+
/** Timestamp label (e.g. "2 hours ago") */
|
|
18
|
+
timestamp: string;
|
|
19
|
+
/** Optional icon (replaces avatar dot) */
|
|
20
|
+
icon?: React.ReactNode;
|
|
21
|
+
/** Icon background color */
|
|
22
|
+
iconBg?: string;
|
|
23
|
+
/** Event type for styling */
|
|
24
|
+
type?: "default" | "comment" | "status" | "assignment" | "commit";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ActivityFeedProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
28
|
+
items: ActivityFeedItem[];
|
|
29
|
+
/** Visual variant */
|
|
30
|
+
variant?: "default" | "compact" | "card";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* ── Helpers ── */
|
|
34
|
+
|
|
35
|
+
function getInitials(name: string) {
|
|
36
|
+
return name
|
|
37
|
+
.split(" ")
|
|
38
|
+
.map((w) => w[0])
|
|
39
|
+
.join("")
|
|
40
|
+
.toUpperCase()
|
|
41
|
+
.slice(0, 2);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ── Component ── */
|
|
45
|
+
|
|
46
|
+
export const ActivityFeed = forwardRef<HTMLDivElement, ActivityFeedProps>(
|
|
47
|
+
({ items, variant = "default", className, ...props }, ref) => {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cn(styles.root, styles[variant], className)}
|
|
52
|
+
{...props}
|
|
53
|
+
>
|
|
54
|
+
{items.map((item, i) => (
|
|
55
|
+
<div key={item.id} className={styles.item}>
|
|
56
|
+
{/* Timeline column */}
|
|
57
|
+
<div className={styles.timeline}>
|
|
58
|
+
{item.icon ? (
|
|
59
|
+
<div
|
|
60
|
+
className={styles.iconBubble}
|
|
61
|
+
style={item.iconBg ? { background: item.iconBg } : undefined}
|
|
62
|
+
>
|
|
63
|
+
{item.icon}
|
|
64
|
+
</div>
|
|
65
|
+
) : item.avatar ? (
|
|
66
|
+
<img
|
|
67
|
+
src={item.avatar}
|
|
68
|
+
alt={item.user}
|
|
69
|
+
className={styles.avatar}
|
|
70
|
+
/>
|
|
71
|
+
) : (
|
|
72
|
+
<div className={styles.avatarFallback}>
|
|
73
|
+
{getInitials(item.user)}
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
{i < items.length - 1 && <div className={styles.connector} />}
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
{/* Content column */}
|
|
80
|
+
<div className={styles.content}>
|
|
81
|
+
<div className={styles.header}>
|
|
82
|
+
<span className={styles.userName}>{item.user}</span>
|
|
83
|
+
<span className={styles.timestamp}>{item.timestamp}</span>
|
|
84
|
+
</div>
|
|
85
|
+
<div className={styles.body}>{item.content}</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
))}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
ActivityFeed.displayName = "ActivityFeed";
|
|
@@ -120,6 +120,8 @@
|
|
|
120
120
|
position: relative;
|
|
121
121
|
flex-shrink: 0;
|
|
122
122
|
user-select: none;
|
|
123
|
+
min-width: 160px;
|
|
124
|
+
height: 42px;
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
.chip:hover {
|
|
@@ -217,6 +219,10 @@
|
|
|
217
219
|
min-width: 0;
|
|
218
220
|
position: relative;
|
|
219
221
|
z-index: 1;
|
|
222
|
+
flex: 1;
|
|
223
|
+
overflow: hidden;
|
|
224
|
+
height: 28px;
|
|
225
|
+
justify-content: center;
|
|
220
226
|
}
|
|
221
227
|
|
|
222
228
|
.chipName {
|
|
@@ -257,6 +263,7 @@
|
|
|
257
263
|
display: flex;
|
|
258
264
|
align-items: center;
|
|
259
265
|
gap: 0;
|
|
266
|
+
height: 14px;
|
|
260
267
|
}
|
|
261
268
|
|
|
262
269
|
.cursor {
|
|
@@ -7,33 +7,39 @@ import type { AgentConfig, AgentActivity, AgentState } from "./types";
|
|
|
7
7
|
import s from "./AgentThinking.module.css";
|
|
8
8
|
|
|
9
9
|
/* ══════════════════════════════════════════════
|
|
10
|
-
|
|
10
|
+
Text cycling hook — fixed-size status rotation
|
|
11
11
|
══════════════════════════════════════════════ */
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
const STATUS_PHRASES = [
|
|
14
|
+
"Analyzing...",
|
|
15
|
+
"Taking action...",
|
|
16
|
+
"Sending emails...",
|
|
17
|
+
"On a phone call...",
|
|
18
|
+
"Reflecting...",
|
|
19
|
+
"Processing data...",
|
|
20
|
+
"Searching...",
|
|
21
|
+
"Composing response...",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function useTextCycler(text: string, isActive: boolean, intervalMs = 2400) {
|
|
25
|
+
const [displayed, setDisplayed] = useState(text || STATUS_PHRASES[0]);
|
|
26
|
+
const idxRef = useRef(0);
|
|
16
27
|
|
|
17
28
|
useEffect(() => {
|
|
18
|
-
if (!isActive
|
|
29
|
+
if (!isActive) {
|
|
19
30
|
setDisplayed("");
|
|
20
|
-
indexRef.current = 0;
|
|
21
31
|
return;
|
|
22
32
|
}
|
|
23
|
-
setDisplayed(
|
|
24
|
-
|
|
33
|
+
setDisplayed(text || STATUS_PHRASES[0]);
|
|
34
|
+
idxRef.current = 0;
|
|
25
35
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
} else {
|
|
31
|
-
clearInterval(interval);
|
|
32
|
-
}
|
|
33
|
-
}, speed);
|
|
36
|
+
const timer = setInterval(() => {
|
|
37
|
+
idxRef.current = (idxRef.current + 1) % STATUS_PHRASES.length;
|
|
38
|
+
setDisplayed(STATUS_PHRASES[idxRef.current]);
|
|
39
|
+
}, intervalMs);
|
|
34
40
|
|
|
35
|
-
return () => clearInterval(
|
|
36
|
-
}, [text, isActive,
|
|
41
|
+
return () => clearInterval(timer);
|
|
42
|
+
}, [text, isActive, intervalMs]);
|
|
37
43
|
|
|
38
44
|
return displayed;
|
|
39
45
|
}
|
|
@@ -101,10 +107,10 @@ interface AgentChipProps {
|
|
|
101
107
|
|
|
102
108
|
function AgentChip({ agent, activity, isPopoverOpen, onTogglePopover }: AgentChipProps) {
|
|
103
109
|
const isAnimating = activity.state === "thinking" || activity.state === "active";
|
|
104
|
-
const
|
|
110
|
+
const statusText = useTextCycler(
|
|
105
111
|
activity.currentAction?.text ?? "",
|
|
106
112
|
isAnimating,
|
|
107
|
-
|
|
113
|
+
2400
|
|
108
114
|
);
|
|
109
115
|
|
|
110
116
|
const chipStyle: React.CSSProperties = {
|
|
@@ -158,7 +164,7 @@ function AgentChip({ agent, activity, isPopoverOpen, onTogglePopover }: AgentChi
|
|
|
158
164
|
</span>
|
|
159
165
|
{isAnimating ? (
|
|
160
166
|
<span className={s.activityText}>
|
|
161
|
-
{
|
|
167
|
+
{statusText}
|
|
162
168
|
<span className={s.cursor} style={{ background: agent.color }} />
|
|
163
169
|
</span>
|
|
164
170
|
) : activity.state === "completed" ? (
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
.primary {
|
|
24
24
|
color: var(--color-lime-text);
|
|
25
25
|
background: var(--color-lime);
|
|
26
|
-
border-radius: var(--radius-
|
|
26
|
+
border-radius: var(--radius-md);
|
|
27
27
|
font-weight: 700;
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
border: 1.5px solid var(--color-border-standard);
|
|
40
40
|
box-shadow: var(--shadow-card-light);
|
|
41
41
|
backdrop-filter: var(--blur-standard);
|
|
42
|
-
border-radius: var(--radius-
|
|
42
|
+
border-radius: var(--radius-md);
|
|
43
43
|
font-weight: 600;
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
color: var(--color-text-secondary);
|
|
55
55
|
background: transparent;
|
|
56
56
|
border: 1.5px solid transparent;
|
|
57
|
-
border-radius: var(--radius-
|
|
57
|
+
border-radius: var(--radius-md);
|
|
58
58
|
font-weight: 600;
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
color: var(--color-text-secondary);
|
|
69
69
|
background: transparent;
|
|
70
70
|
border: 1.5px solid var(--color-border-medium);
|
|
71
|
-
border-radius: var(--radius-
|
|
71
|
+
border-radius: var(--radius-md);
|
|
72
72
|
font-weight: 600;
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
color: var(--color-lime);
|
|
83
83
|
background: var(--color-bg-lime-strong);
|
|
84
84
|
border: 1px solid var(--color-border-lime-medium);
|
|
85
|
-
border-radius: var(--radius-
|
|
85
|
+
border-radius: var(--radius-md);
|
|
86
86
|
font-weight: 600;
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/* ── Group container ── */
|
|
2
|
+
.group {
|
|
3
|
+
display: inline-flex;
|
|
4
|
+
align-items: center;
|
|
5
|
+
border: 1.5px solid var(--color-border-standard);
|
|
6
|
+
border-radius: var(--radius-lg);
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
background: var(--color-bg-card);
|
|
9
|
+
box-shadow: var(--shadow-card-light);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/* ── Sizes ── */
|
|
13
|
+
.sm { height: 36px; }
|
|
14
|
+
.md { height: 40px; }
|
|
15
|
+
.lg { height: 44px; }
|
|
16
|
+
|
|
17
|
+
/* ── Item ── */
|
|
18
|
+
.item {
|
|
19
|
+
display: inline-flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
gap: 6px;
|
|
23
|
+
padding: 0 16px;
|
|
24
|
+
height: 100%;
|
|
25
|
+
font-family: inherit;
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
color: var(--color-text-secondary);
|
|
28
|
+
background: transparent;
|
|
29
|
+
border: none;
|
|
30
|
+
border-right: 1px solid var(--color-border-standard);
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
transition: all 0.15s ease;
|
|
34
|
+
outline: none;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.item:last-child {
|
|
38
|
+
border-right: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.item:hover:not(:disabled) {
|
|
42
|
+
background: var(--color-bg-hover);
|
|
43
|
+
color: var(--color-text-primary);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.item:focus-visible {
|
|
47
|
+
box-shadow: 0 0 0 2px var(--color-lime) inset;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.item:disabled {
|
|
51
|
+
opacity: 0.5;
|
|
52
|
+
cursor: not-allowed;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ── Item sizes ── */
|
|
56
|
+
.item-sm {
|
|
57
|
+
padding: 0 12px;
|
|
58
|
+
font-size: 13px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.item-md {
|
|
62
|
+
padding: 0 16px;
|
|
63
|
+
font-size: 14px;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.item-lg {
|
|
67
|
+
padding: 0 20px;
|
|
68
|
+
font-size: 14px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* ── Selected state ── */
|
|
72
|
+
.selected {
|
|
73
|
+
background: var(--color-bg-elevated);
|
|
74
|
+
color: var(--color-text-primary);
|
|
75
|
+
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.selected:hover:not(:disabled) {
|
|
79
|
+
background: var(--color-bg-elevated);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ── Dot indicator ── */
|
|
83
|
+
.dot {
|
|
84
|
+
width: 8px;
|
|
85
|
+
height: 8px;
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
background: var(--color-lime);
|
|
88
|
+
flex-shrink: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* ── Icon wrapper ── */
|
|
92
|
+
.iconWrapper {
|
|
93
|
+
display: inline-flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
flex-shrink: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* ── Label ── */
|
|
100
|
+
.label {
|
|
101
|
+
display: inline-flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
}
|