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.
Files changed (69) hide show
  1. package/README.md +3 -3
  2. package/cli/omnira-init.mjs +25 -1
  3. package/components/ui/ActivityFeed/ActivityFeed.module.css +143 -0
  4. package/components/ui/ActivityFeed/ActivityFeed.tsx +94 -0
  5. package/components/ui/ActivityFeed/index.ts +2 -0
  6. package/components/ui/AgentThinking/AgentThinking.module.css +7 -0
  7. package/components/ui/AgentThinking/AgentThinking.tsx +27 -21
  8. package/components/ui/Button/Button.module.css +5 -5
  9. package/components/ui/ButtonGroup/ButtonGroup.module.css +103 -0
  10. package/components/ui/ButtonGroup/ButtonGroup.tsx +153 -0
  11. package/components/ui/ButtonGroup/index.ts +2 -0
  12. package/components/ui/Carousel/Carousel.module.css +95 -0
  13. package/components/ui/Carousel/Carousel.tsx +137 -0
  14. package/components/ui/Carousel/index.ts +2 -0
  15. package/components/ui/CodeSnippet/CodeSnippet.module.css +38 -18
  16. package/components/ui/CodeSnippet/CodeSnippet.tsx +84 -2
  17. package/components/ui/CommandMenu/CommandMenu.module.css +187 -0
  18. package/components/ui/CommandMenu/CommandMenu.tsx +205 -0
  19. package/components/ui/CommandMenu/index.ts +2 -0
  20. package/components/ui/EmailTemplate/EmailTemplate.module.css +303 -0
  21. package/components/ui/EmailTemplate/EmailTemplate.tsx +298 -0
  22. package/components/ui/EmailTemplate/index.ts +2 -0
  23. package/components/ui/FeaturedIcon/FeaturedIcon.module.css +212 -0
  24. package/components/ui/FeaturedIcon/FeaturedIcon.tsx +46 -0
  25. package/components/ui/FeaturedIcon/index.ts +2 -0
  26. package/components/ui/ForgotPassword/ForgotPassword.module.css +332 -0
  27. package/components/ui/ForgotPassword/ForgotPassword.tsx +387 -0
  28. package/components/ui/ForgotPassword/index.ts +2 -0
  29. package/components/ui/HeaderNavigation/HeaderNavigation.module.css +99 -0
  30. package/components/ui/HeaderNavigation/HeaderNavigation.tsx +103 -0
  31. package/components/ui/HeaderNavigation/index.ts +2 -0
  32. package/components/ui/InlineCTA/InlineCTA.module.css +101 -0
  33. package/components/ui/InlineCTA/InlineCTA.tsx +59 -0
  34. package/components/ui/InlineCTA/index.ts +2 -0
  35. package/components/ui/LineBarChart/LineBarChart.module.css +41 -0
  36. package/components/ui/LineBarChart/LineBarChart.tsx +191 -0
  37. package/components/ui/LineBarChart/index.ts +2 -0
  38. package/components/ui/Matrix/Matrix.module.css +54 -0
  39. package/components/ui/Matrix/Matrix.tsx +99 -0
  40. package/components/ui/Matrix/index.ts +2 -0
  41. package/components/ui/Messaging/Messaging.module.css +186 -0
  42. package/components/ui/Messaging/Messaging.tsx +168 -0
  43. package/components/ui/Messaging/index.ts +2 -0
  44. package/components/ui/NotFoundPage/NotFoundPage.module.css +270 -0
  45. package/components/ui/NotFoundPage/NotFoundPage.tsx +158 -0
  46. package/components/ui/NotFoundPage/index.ts +2 -0
  47. package/components/ui/Pagination/Pagination.module.css +161 -0
  48. package/components/ui/Pagination/Pagination.tsx +150 -0
  49. package/components/ui/Pagination/index.ts +2 -0
  50. package/components/ui/PieChart/PieChart.module.css +91 -0
  51. package/components/ui/PieChart/PieChart.tsx +185 -0
  52. package/components/ui/PieChart/index.ts +2 -0
  53. package/components/ui/ProgressSteps/ProgressSteps.module.css +232 -0
  54. package/components/ui/ProgressSteps/ProgressSteps.tsx +134 -0
  55. package/components/ui/ProgressSteps/index.ts +2 -0
  56. package/components/ui/RadarChart/RadarChart.module.css +25 -0
  57. package/components/ui/RadarChart/RadarChart.tsx +140 -0
  58. package/components/ui/RadarChart/index.ts +2 -0
  59. package/components/ui/SectionFooter/SectionFooter.module.css +55 -0
  60. package/components/ui/SectionFooter/SectionFooter.tsx +63 -0
  61. package/components/ui/SectionFooter/index.ts +2 -0
  62. package/components/ui/SectionHeader/SectionHeader.module.css +73 -0
  63. package/components/ui/SectionHeader/SectionHeader.tsx +121 -0
  64. package/components/ui/SectionHeader/index.ts +2 -0
  65. package/components/ui/SlideOut/SlideOut.module.css +17 -13
  66. package/components/ui/VerificationPage/VerificationPage.module.css +252 -0
  67. package/components/ui/VerificationPage/VerificationPage.tsx +287 -0
  68. package/components/ui/VerificationPage/index.ts +2 -0
  69. 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://ui.omnira.space)**
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
- **[ui.omnira.space →](https://ui.omnira.space)**
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://ui.omnira.space)
173
+ MIT © [Omnira UI](https://omnira.one)
@@ -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://ui.omnira.space${RESET}`);
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";
@@ -0,0 +1,2 @@
1
+ export { ActivityFeed } from "./ActivityFeed";
2
+ export type { ActivityFeedProps, ActivityFeedItem } from "./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
- Typewriter hook
10
+ Text cycling hook — fixed-size status rotation
11
11
  ══════════════════════════════════════════════ */
12
12
 
13
- function useTypewriter(text: string, isActive: boolean, speed = 30) {
14
- const [displayed, setDisplayed] = useState("");
15
- const indexRef = useRef(0);
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 || !text) {
29
+ if (!isActive) {
19
30
  setDisplayed("");
20
- indexRef.current = 0;
21
31
  return;
22
32
  }
23
- setDisplayed("");
24
- indexRef.current = 0;
33
+ setDisplayed(text || STATUS_PHRASES[0]);
34
+ idxRef.current = 0;
25
35
 
26
- const interval = setInterval(() => {
27
- indexRef.current += 1;
28
- if (indexRef.current <= text.length) {
29
- setDisplayed(text.slice(0, indexRef.current));
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(interval);
36
- }, [text, isActive, speed]);
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 typed = useTypewriter(
110
+ const statusText = useTextCycler(
105
111
  activity.currentAction?.text ?? "",
106
112
  isAnimating,
107
- 28
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
- {typed}
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-full);
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-full);
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-full);
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-full);
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-full);
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
+ }