@voltro/ui-shadcn 0.66.0 → 0.67.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/CHANGELOG.md +52 -0
- package/THIRD-PARTY-NOTICES.md +6 -6
- package/dist/brand.d.ts +5 -1
- package/dist/brand.js +3 -177
- package/dist/index.d.ts +80 -5
- package/dist/index.js +1316 -882
- package/dist/signal.css +223 -0
- package/dist/voltroLogo-CSnSpQhz.js +207 -0
- package/package.json +7 -6
- package/src/brand/voltroLogo.tsx +13 -4
- package/src/compositions/appShell.tsx +7 -9
- package/src/compositions/codeCompare.tsx +2 -3
- package/src/compositions/docsLayout.tsx +56 -35
- package/src/compositions/profileMenu.tsx +12 -9
- package/src/compositions/signalControls.tsx +43 -0
- package/src/compositions/signalField.tsx +75 -0
- package/src/compositions/signalHeader.tsx +96 -0
- package/src/compositions/signalMotion.ts +68 -0
- package/src/compositions/themeToggle.tsx +6 -3
- package/src/cookies.ts +3 -0
- package/src/index.ts +5 -1
- package/src/primitives/codeBlock.tsx +4 -4
- package/src/primitives/highlightedCode.tsx +2 -0
- package/src/primitives/searchModal.tsx +16 -2
- package/src/signal.css +223 -0
package/dist/signal.css
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/* Voltro Signal: opt-in brand theme. Import after tokens.css. */
|
|
2
|
+
:root {
|
|
3
|
+
--signal-violet: #7c3aed;
|
|
4
|
+
--signal-header-height: 112px;
|
|
5
|
+
--signal-light: #6d28d9;
|
|
6
|
+
--signal-ease: cubic-bezier(.16,1,.3,1);
|
|
7
|
+
--background: #faf9fc;
|
|
8
|
+
--foreground: #21192d;
|
|
9
|
+
--card: #ffffff;
|
|
10
|
+
--card-foreground: #21192d;
|
|
11
|
+
--popover: #ffffff;
|
|
12
|
+
--popover-foreground: #21192d;
|
|
13
|
+
--primary: #7c3aed;
|
|
14
|
+
--primary-foreground: #ffffff;
|
|
15
|
+
--secondary: #eee9f4;
|
|
16
|
+
--secondary-foreground: #38264e;
|
|
17
|
+
--muted: #f2eef7;
|
|
18
|
+
--muted-foreground: #6b5c7c;
|
|
19
|
+
--accent: #eee6fc;
|
|
20
|
+
--accent-foreground: #5b21b6;
|
|
21
|
+
--border: #ded6e9;
|
|
22
|
+
--input: #d0c4df;
|
|
23
|
+
--ring: #7c3aed;
|
|
24
|
+
--sidebar: #f3eff8;
|
|
25
|
+
--sidebar-foreground: #38264e;
|
|
26
|
+
--sidebar-primary: #7c3aed;
|
|
27
|
+
--sidebar-primary-foreground: #fff;
|
|
28
|
+
--sidebar-accent: #e7ddf5;
|
|
29
|
+
--sidebar-accent-foreground: #5b21b6;
|
|
30
|
+
--sidebar-border: #ded6e9;
|
|
31
|
+
--sidebar-ring: #7c3aed;
|
|
32
|
+
--radius: .375rem;
|
|
33
|
+
--signal-accent-ink: #6d28d9;
|
|
34
|
+
--signal-ground: #f4effa;
|
|
35
|
+
--signal-ink: #21192d;
|
|
36
|
+
--signal-muted: #6b5c7c;
|
|
37
|
+
--signal-line: #d4c7e5;
|
|
38
|
+
--signal-detail: #735094;
|
|
39
|
+
--signal-field-a: #e4d5f5;
|
|
40
|
+
--signal-field-b: #efe5fb;
|
|
41
|
+
--signal-field-base: #faf9fc;
|
|
42
|
+
--signal-field-floor: #faf9fc;
|
|
43
|
+
}
|
|
44
|
+
.dark {
|
|
45
|
+
--signal-light: #a874ff;
|
|
46
|
+
--signal-ground: #0b0911;
|
|
47
|
+
--signal-ink: #f5f3fa;
|
|
48
|
+
--signal-muted: #b9afc9;
|
|
49
|
+
--signal-line: #342b43;
|
|
50
|
+
--signal-detail: #c2a1e8;
|
|
51
|
+
--signal-field-a: #29193d;
|
|
52
|
+
--signal-field-b: #1b1430;
|
|
53
|
+
--signal-field-base: #100c19;
|
|
54
|
+
--signal-field-floor: linear-gradient(145deg,#100c18 12%,#110c1e 55%,#0e0b15 100%);
|
|
55
|
+
--background: #100c19;
|
|
56
|
+
--foreground: #f5f3fa;
|
|
57
|
+
--card: #17111f;
|
|
58
|
+
--card-foreground: #f5f3fa;
|
|
59
|
+
--popover: #1c1427;
|
|
60
|
+
--popover-foreground: #f5f3fa;
|
|
61
|
+
--primary: #7c3aed;
|
|
62
|
+
--primary-foreground: #ffffff;
|
|
63
|
+
--secondary: #251b33;
|
|
64
|
+
--secondary-foreground: #e7dbf7;
|
|
65
|
+
--muted: #201828;
|
|
66
|
+
--muted-foreground: #b9afc9;
|
|
67
|
+
--accent: #2c1d40;
|
|
68
|
+
--accent-foreground: #d9bcff;
|
|
69
|
+
--border: #342b43;
|
|
70
|
+
--input: #584566;
|
|
71
|
+
--ring: #b995ff;
|
|
72
|
+
--sidebar: #140f1d;
|
|
73
|
+
--sidebar-foreground: #d5c9e4;
|
|
74
|
+
--sidebar-primary: #a874ff;
|
|
75
|
+
--sidebar-primary-foreground: #170c29;
|
|
76
|
+
--sidebar-accent: #2b1e3c;
|
|
77
|
+
--sidebar-accent-foreground: #e2ccff;
|
|
78
|
+
--sidebar-border: #342b43;
|
|
79
|
+
--sidebar-ring: #b995ff;
|
|
80
|
+
--signal-accent-ink: #c19aff;
|
|
81
|
+
}
|
|
82
|
+
@layer components {
|
|
83
|
+
:where(a, button, input, textarea, select, summary):focus-visible {
|
|
84
|
+
outline: 2px solid var(--ring);
|
|
85
|
+
outline-offset: 4px;
|
|
86
|
+
}
|
|
87
|
+
:where(input, textarea) { caret-color: var(--signal-accent-ink); }
|
|
88
|
+
::selection { background: #6530ba; color: #fff; }
|
|
89
|
+
:where(table, [role="table"]) { font-variant-numeric: tabular-nums; }
|
|
90
|
+
}
|
|
91
|
+
.signal-stage { position: relative; isolation: isolate; }
|
|
92
|
+
.signal-atmosphere{position:absolute;inset:0;z-index:-1;overflow:hidden;pointer-events:none;background:radial-gradient(ellipse at 89% 22%,var(--signal-field-a) 0%,transparent 48%),radial-gradient(ellipse at 8% 76%,var(--signal-field-b) 0%,transparent 44%),var(--signal-field-floor)}
|
|
93
|
+
.field-contours{position:absolute;width:max(100%,1400px);height:auto;top:0;right:0;max-width:none}
|
|
94
|
+
.field-light{position:absolute;inset:20% 0 8% 0;background:radial-gradient(ellipse at 66% 49%,#7c3aed26 0%,#a874ff0b 31%,transparent 65%);opacity:.45;transition:opacity 650ms ease-out}
|
|
95
|
+
.signal-stage:has(.signal-demo[data-state=running]) .field-light{opacity:1}
|
|
96
|
+
.field-highlight{stroke-dasharray:7 93;stroke-dashoffset:-34;opacity:.22}
|
|
97
|
+
.signal-stage:has(.signal-demo[data-state=running]) .field-highlight{animation:field-response 2900ms ease-out 1}
|
|
98
|
+
@keyframes field-response{0%{stroke-dashoffset:-34;opacity:.22}40%{opacity:.55}100%{stroke-dashoffset:-78;opacity:0}}
|
|
99
|
+
.field-ambient-trace{stroke-dasharray:7 93;opacity:0;animation:field-travel 14s linear infinite;animation-play-state:paused}
|
|
100
|
+
.trace-1{animation-delay:-3s}.trace-2{animation-delay:-6s}.trace-3{animation-delay:-9s}.trace-4{animation-delay:-11s;animation-duration:17s}
|
|
101
|
+
.signal-atmosphere[data-motion=running] .field-ambient-trace{animation-play-state:running}
|
|
102
|
+
@keyframes field-travel{0%{stroke-dashoffset:3;opacity:0}10%{opacity:.32}78%{opacity:.32}100%{stroke-dashoffset:-100;opacity:0}}
|
|
103
|
+
|
|
104
|
+
.signal-stage .signal-atmosphere { mask-image: linear-gradient(#000 0%, #000 85%, transparent 100%); }
|
|
105
|
+
.signal-shell { width: min(100% - 88px, 1536px); margin-inline: auto; }
|
|
106
|
+
.signal-primary {
|
|
107
|
+
display: inline-flex; align-items: stretch; min-height: 54px; width: fit-content;
|
|
108
|
+
background: #7c3aed linear-gradient(115deg, #6d28d9, #7c3aed 48%, #8a49ed);
|
|
109
|
+
background-size: 140% 100%; color: #fff; border-radius: 4px;
|
|
110
|
+
box-shadow: 0 5px 20px -9px #7c3aed66; overflow: hidden;
|
|
111
|
+
font-size: 1rem; font-weight: 500; text-decoration: none;
|
|
112
|
+
transition: background-position 280ms var(--signal-ease), box-shadow 240ms var(--signal-ease);
|
|
113
|
+
}
|
|
114
|
+
.signal-primary > span:first-child { padding: 14px 23px; display: flex; align-items: center; }
|
|
115
|
+
.signal-primary .signal-arrow { width: 55px; border-left: 1px solid #a57bdd; display: grid; place-items: center; }
|
|
116
|
+
.signal-primary svg { width: 22px; height: 22px; transition: transform 220ms var(--signal-ease); }
|
|
117
|
+
.signal-primary:hover, .signal-primary:focus-visible { background-position: 100% 50%; box-shadow: 0 8px 30px -8px #7c3aed7a; }
|
|
118
|
+
.signal-primary:hover svg, .signal-primary:focus-visible svg { transform: translateX(4px); }
|
|
119
|
+
.signal-text-link { display: inline-flex; gap: 10px; align-items: center; min-height: 44px; text-underline-offset: 8px; text-decoration-color: var(--signal-light); }
|
|
120
|
+
.signal-text-link:hover, .signal-text-link:focus-visible { text-decoration-line: underline; }
|
|
121
|
+
.signal-text-link svg { width: 16px; height: 16px; color: var(--signal-accent-ink); }
|
|
122
|
+
.signal-motion-toggle { display: inline-flex; align-items: center; gap: 7px; min-height: 44px; color: var(--muted-foreground); font-size: 12px; background: none; border: 0; cursor: pointer; }
|
|
123
|
+
.signal-motion-toggle svg { width: 16px; height: 16px; }
|
|
124
|
+
.signal-motion-toggle:hover { color: var(--signal-accent-ink); }
|
|
125
|
+
@media (max-width: 1150px) { .signal-shell { width: calc(100% - 56px); } }
|
|
126
|
+
@media (max-width: 760px) {
|
|
127
|
+
.signal-shell { width: calc(100% - 40px); }
|
|
128
|
+
.field-contours { width: 1000px; right: -390px; top: 50px; }
|
|
129
|
+
.signal-atmosphere { background: radial-gradient(ellipse at 100% 24%, var(--signal-field-a), transparent 55%), radial-gradient(ellipse at 0% 80%, var(--signal-field-b), transparent 48%), var(--signal-field-base); }
|
|
130
|
+
.signal-primary { min-height: 50px; font-size: 14px; }
|
|
131
|
+
.signal-primary > span:first-child { padding-inline: 18px; }
|
|
132
|
+
.signal-primary .signal-arrow { width: 44px; }
|
|
133
|
+
}
|
|
134
|
+
@media (prefers-reduced-motion: reduce) {
|
|
135
|
+
.field-ambient-trace { animation: none; }
|
|
136
|
+
.signal-primary, .signal-primary svg { transition: none; }
|
|
137
|
+
.signal-motion-toggle { display: none; }
|
|
138
|
+
html { scroll-behavior: auto; }
|
|
139
|
+
}
|
|
140
|
+
@media (forced-colors: active) {
|
|
141
|
+
.signal-atmosphere { display: none; }
|
|
142
|
+
.signal-primary { border: 1px solid ButtonText; }
|
|
143
|
+
}
|
|
144
|
+
.signal-masthead { position: relative; z-index: 40; color: var(--foreground); background: transparent; transition: background-color 180ms var(--signal-ease); }
|
|
145
|
+
.signal-masthead-sticky { position: sticky; top: 0; }
|
|
146
|
+
.signal-masthead[data-scrolled=true] { background: var(--background); }
|
|
147
|
+
.signal-header { min-height: var(--signal-header-height); display: flex; align-items: center; justify-content: space-between; position: relative; z-index: 20; gap: 24px; }
|
|
148
|
+
.signal-brand { flex: none; }
|
|
149
|
+
.signal-brand .voltro-wordmark { --voltro-wordmark-size: 42px; }
|
|
150
|
+
.signal-brand > a { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; }
|
|
151
|
+
.signal-brand svg { flex: none; }
|
|
152
|
+
.signal-navigation-area { display: flex; align-items: center; gap: 24px; }
|
|
153
|
+
.signal-navigation { position: relative; display: flex; align-items: center; padding: 5px; gap: 5px; border: 1px solid var(--border); border-radius: 7px; background: var(--background); }
|
|
154
|
+
.signal-nav-marker { position: absolute; inset-block: 5px; left: 5px; width: 100px; border-radius: 2px; background: var(--secondary); transform-origin: left; transition: transform 240ms var(--signal-ease); pointer-events: none; }
|
|
155
|
+
.signal-nav-item { border: 0; background: none; position: relative; display: flex; align-items: center; gap: 10px; padding: 11px 17px; font-size: 14px; font-weight: 500; min-height: 44px; white-space: nowrap; color: var(--foreground); }
|
|
156
|
+
.signal-nav-dot { width: 5px; height: 5px; background: var(--signal-light); flex: none; }
|
|
157
|
+
.signal-header svg:not(.voltro-logo) { stroke-linecap: round; stroke-linejoin: round; }
|
|
158
|
+
.signal-nav-item > svg, .signal-menu-links svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.5; color: var(--muted-foreground); transition: transform 180ms var(--signal-ease); }
|
|
159
|
+
.signal-nav-item[aria-expanded=true] > svg { transform: rotate(180deg); }
|
|
160
|
+
.signal-nav-item[href]:hover > svg { transform: translate(2px, -2px); }
|
|
161
|
+
.signal-header-utilities { display: flex; align-items: center; gap: 12px; }
|
|
162
|
+
.signal-control { display: inline-flex; flex: none; align-items: center; justify-content: center; gap: 10px; min-height: 56px; padding: 0 16px; border: 1px solid var(--border); border-radius: 7px; background: var(--background); color: var(--foreground); font-size: 14px; font-weight: 500; line-height: 1.4; white-space: nowrap; cursor: pointer; text-decoration: none; transition: color 180ms var(--signal-ease), border-color 180ms var(--signal-ease), background-color 180ms var(--signal-ease); }
|
|
163
|
+
.signal-control > svg { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
|
|
164
|
+
.signal-control:hover, .signal-control[data-state=open] { border-color: var(--input); background: var(--secondary); }
|
|
165
|
+
.signal-preferences { padding-inline: 12px; border-color: transparent; background: transparent; color: var(--muted-foreground); font-size: 12px; }
|
|
166
|
+
.signal-preferences:hover, .signal-preferences[data-state=open] { color: var(--foreground); }
|
|
167
|
+
.signal-header-action { border-color: var(--input); }
|
|
168
|
+
.signal-header-action > svg { color: var(--signal-accent-ink); transition: transform 180ms var(--signal-ease); }
|
|
169
|
+
.signal-header-action:hover > svg { transform: translateX(3px); }
|
|
170
|
+
.signal-search { width: 224px; justify-content: flex-start; color: var(--muted-foreground); font-weight: 400; }
|
|
171
|
+
.signal-search kbd { margin-left: auto; padding: 2px 5px; border: 1px solid var(--border); border-radius: 3px; font-family: inherit; font-size: 11px; line-height: 1.4; }
|
|
172
|
+
.signal-search:hover { color: var(--foreground); }
|
|
173
|
+
@media(max-width:1250px) { .signal-search { width: 56px; padding: 0; justify-content: center; } .signal-search > span, .signal-search kbd { display: none; } }
|
|
174
|
+
.signal-menu { position: absolute; right: 100px; top: calc(100% - 16px); width: 570px; padding: 26px; display: grid; grid-template-columns: 1fr 1.4fr; gap: 28px; background: var(--popover); color: var(--popover-foreground); border: 1px solid var(--input); border-radius: 7px; }
|
|
175
|
+
.signal-menu[hidden] { display: none; }
|
|
176
|
+
.signal-menu-intro { font-size: 22px; font-weight: 500; line-height: 1.25; letter-spacing: -.025em; }
|
|
177
|
+
.signal-menu-links { display: flex; flex-direction: column; }
|
|
178
|
+
.signal-menu-links a { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 13px 0; border-bottom: 1px solid var(--border); font-size: 14px; }
|
|
179
|
+
.signal-menu-links a:first-child { padding-top: 0; }
|
|
180
|
+
.signal-menu-links a:last-child { border: 0; padding-bottom: 0; }
|
|
181
|
+
.signal-menu-links a:hover { color: var(--signal-accent-ink); }
|
|
182
|
+
.signal-menu-links small { display: block; font-size: 12px; color: var(--muted-foreground); margin-top: 5px; }
|
|
183
|
+
@media(max-width:1150px) { :root { --signal-header-height: 96px; } .signal-navigation-area { gap: 24px; } .signal-nav-item { padding-inline: 12px; } }
|
|
184
|
+
@media(max-width:900px) {
|
|
185
|
+
:root { --signal-header-height: 158px; }
|
|
186
|
+
.signal-header { padding-block: 18px; align-items: center; flex-wrap: wrap; gap: 16px; }
|
|
187
|
+
.signal-brand .voltro-wordmark { --voltro-wordmark-size: 32px; display: grid; grid-template-columns: auto auto; row-gap: 5px; }
|
|
188
|
+
.signal-brand .voltro-wordmark > svg { grid-row: 1 / 3; }
|
|
189
|
+
.signal-brand .voltro-wordmark-label, .signal-brand .voltro-product-badge { grid-column: 2; justify-self: start; }
|
|
190
|
+
.signal-navigation-area { display: contents; }
|
|
191
|
+
.signal-navigation { order: 3; width: 100%; gap: 3px; }
|
|
192
|
+
.signal-nav-item { flex: 1; justify-content: center; padding: 7px; font-size: 12px; gap: 7px; }
|
|
193
|
+
.signal-header-utilities { margin-left: auto; }
|
|
194
|
+
.signal-control { min-height: 44px; font-size: 12px; padding-inline: 12px; border-radius: 5px; }
|
|
195
|
+
.signal-search, .signal-preferences { width: 44px; padding: 0; }
|
|
196
|
+
.signal-preferences > span { display: none; }
|
|
197
|
+
.signal-menu { top: 100%; right: 0; width: 100%; grid-template-columns: 1fr; padding: 20px; gap: 21px; }
|
|
198
|
+
.signal-menu-intro { font-size: 20px; }
|
|
199
|
+
.signal-menu-links a { min-height: 55px; }
|
|
200
|
+
}
|
|
201
|
+
@media(prefers-reduced-motion:reduce) { .signal-masthead, .signal-nav-marker, .signal-nav-item > svg, .signal-control, .signal-header-action > svg { transition: none; } }
|
|
202
|
+
|
|
203
|
+
.signal-skip { position: fixed; top: 10px; left: 20px; padding: 12px 20px; background: var(--foreground); color: var(--background); z-index: 100; transform: translateY(-160%); }
|
|
204
|
+
.signal-skip:focus { transform: none; }
|
|
205
|
+
|
|
206
|
+
.signal-operate h1 { letter-spacing: -.03em; }
|
|
207
|
+
.signal-operate h2 { letter-spacing: -.02em; }
|
|
208
|
+
.signal-operate [data-sidebar="sidebar"], .signal-operate aside { background-color: var(--sidebar); }
|
|
209
|
+
.signal-operate [aria-current="page"], .signal-operate [data-active="true"] { color: var(--sidebar-accent-foreground); background-color: var(--sidebar-accent); }
|
|
210
|
+
.signal-operate [role="tab"][aria-selected="true"] { color: var(--signal-accent-ink); }
|
|
211
|
+
.signal-operate :where(td, th) { padding-block: .8rem; }
|
|
212
|
+
.signal-operate :where(tbody tr) { transition: background-color 140ms; }
|
|
213
|
+
.signal-operate :where(tbody tr):hover { background-color: var(--muted); }
|
|
214
|
+
.signal-operate :where(input, select, textarea) { border-radius: 4px; }
|
|
215
|
+
@media(prefers-reduced-motion:reduce) { .signal-operate :where(tbody tr) { transition: none; } }
|
|
216
|
+
|
|
217
|
+
.text-primary { color: var(--signal-accent-ink); }
|
|
218
|
+
|
|
219
|
+
/* The marketing close repeats the hero's violet action and plum surface. */
|
|
220
|
+
.signal-marketing-close { background: var(--signal-ground); backdrop-filter: none; }
|
|
221
|
+
.signal-marketing-close::before { background: radial-gradient(ellipse at 20% 30%, #7c3aed29, transparent 65%); }
|
|
222
|
+
.signal-marketing-close .group { background: linear-gradient(115deg, #6d28d9, #7c3aed 48%, #8a49ed); color: #fff; border-radius: 4px; box-shadow: 0 5px 20px -9px #7c3aed66; }
|
|
223
|
+
@media(max-width:760px) { .signal-marketing-close { padding: 40px 24px; } }
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { cn as e } from "./cn.js";
|
|
2
|
+
import { useId as t } from "react";
|
|
3
|
+
import { Fragment as n, jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
+
import { cva as a } from "class-variance-authority";
|
|
5
|
+
//#region src/primitives/badge.tsx
|
|
6
|
+
var o = a("inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 [&>svg]:pointer-events-none gap-1 transition-[color,box-shadow] overflow-hidden focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
|
|
7
|
+
variants: { variant: {
|
|
8
|
+
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
9
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
10
|
+
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90",
|
|
11
|
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
12
|
+
} },
|
|
13
|
+
defaultVariants: { variant: "default" }
|
|
14
|
+
}), s = ({ className: t, variant: n, children: i, ...a }) => /* @__PURE__ */ r("span", {
|
|
15
|
+
"data-slot": "badge",
|
|
16
|
+
className: e(o({ variant: n }), t),
|
|
17
|
+
...a,
|
|
18
|
+
children: i
|
|
19
|
+
}), c = "M28 5 13 27 22 26 20 43 35 21 26 22Z", l = "M28 5 13 27 22 26 20 43Z", u = "M28 5 20 43 35 21 26 22Z", d = "#7C3AED", f = ({ size: a = 32, variant: o = "gradient", title: s, className: d, ...f }) => {
|
|
20
|
+
let p = t(), m = `vmF-${p}`, h = `vmB-${p}`;
|
|
21
|
+
return /* @__PURE__ */ r("svg", {
|
|
22
|
+
width: a,
|
|
23
|
+
height: a,
|
|
24
|
+
viewBox: "0 0 48 48",
|
|
25
|
+
fill: "none",
|
|
26
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
27
|
+
...s === void 0 ? { "aria-hidden": !0 } : {
|
|
28
|
+
role: "img",
|
|
29
|
+
"aria-label": s
|
|
30
|
+
},
|
|
31
|
+
className: e("inline-block shrink-0", d),
|
|
32
|
+
...f,
|
|
33
|
+
children: o === "gradient" ? /* @__PURE__ */ i(n, { children: [
|
|
34
|
+
/* @__PURE__ */ i("defs", { children: [/* @__PURE__ */ i("linearGradient", {
|
|
35
|
+
id: m,
|
|
36
|
+
x1: "13",
|
|
37
|
+
y1: "5",
|
|
38
|
+
x2: "33",
|
|
39
|
+
y2: "43",
|
|
40
|
+
gradientUnits: "userSpaceOnUse",
|
|
41
|
+
children: [/* @__PURE__ */ r("stop", { stopColor: "#A874FF" }), /* @__PURE__ */ r("stop", {
|
|
42
|
+
offset: "1",
|
|
43
|
+
stopColor: "#7C3AED"
|
|
44
|
+
})]
|
|
45
|
+
}), /* @__PURE__ */ i("linearGradient", {
|
|
46
|
+
id: h,
|
|
47
|
+
x1: "22",
|
|
48
|
+
y1: "5",
|
|
49
|
+
x2: "35",
|
|
50
|
+
y2: "43",
|
|
51
|
+
gradientUnits: "userSpaceOnUse",
|
|
52
|
+
children: [/* @__PURE__ */ r("stop", { stopColor: "#6D28D9" }), /* @__PURE__ */ r("stop", {
|
|
53
|
+
offset: "1",
|
|
54
|
+
stopColor: "#4C1D95"
|
|
55
|
+
})]
|
|
56
|
+
})] }),
|
|
57
|
+
/* @__PURE__ */ r("path", {
|
|
58
|
+
d: l,
|
|
59
|
+
fill: `url(#${m})`
|
|
60
|
+
}),
|
|
61
|
+
/* @__PURE__ */ r("path", {
|
|
62
|
+
d: u,
|
|
63
|
+
fill: `url(#${h})`
|
|
64
|
+
})
|
|
65
|
+
] }) : /* @__PURE__ */ r("path", {
|
|
66
|
+
d: c,
|
|
67
|
+
fill: o === "white" ? "#FFFFFF" : "currentColor"
|
|
68
|
+
})
|
|
69
|
+
});
|
|
70
|
+
}, p = ({ size: a = 40, tone: o = "brand", radius: s = .225, title: c = "Voltro", className: d, style: f }) => {
|
|
71
|
+
let p = t(), m = `viBg-${p}`, h = `viGlow-${p}`, g = `viF-${p}`, _ = `viB-${p}`, v = (64 * s).toFixed(2);
|
|
72
|
+
return /* @__PURE__ */ i("svg", {
|
|
73
|
+
width: a,
|
|
74
|
+
height: a,
|
|
75
|
+
viewBox: "0 0 64 64",
|
|
76
|
+
fill: "none",
|
|
77
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
78
|
+
role: "img",
|
|
79
|
+
"aria-label": c,
|
|
80
|
+
className: e("inline-block shrink-0", d),
|
|
81
|
+
style: f,
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ i("defs", { children: [
|
|
84
|
+
/* @__PURE__ */ r("linearGradient", {
|
|
85
|
+
id: m,
|
|
86
|
+
x1: "0",
|
|
87
|
+
y1: "0",
|
|
88
|
+
x2: "64",
|
|
89
|
+
y2: "64",
|
|
90
|
+
gradientUnits: "userSpaceOnUse",
|
|
91
|
+
children: o === "brand" ? /* @__PURE__ */ i(n, { children: [/* @__PURE__ */ r("stop", { stopColor: "#8B5CFF" }), /* @__PURE__ */ r("stop", {
|
|
92
|
+
offset: "1",
|
|
93
|
+
stopColor: "#6D28D9"
|
|
94
|
+
})] }) : /* @__PURE__ */ i(n, { children: [/* @__PURE__ */ r("stop", { stopColor: "#1B1726" }), /* @__PURE__ */ r("stop", {
|
|
95
|
+
offset: "1",
|
|
96
|
+
stopColor: "#120F1A"
|
|
97
|
+
})] })
|
|
98
|
+
}),
|
|
99
|
+
o === "dark" ? /* @__PURE__ */ i("radialGradient", {
|
|
100
|
+
id: h,
|
|
101
|
+
cx: "0.5",
|
|
102
|
+
cy: "0.46",
|
|
103
|
+
r: "0.5",
|
|
104
|
+
children: [/* @__PURE__ */ r("stop", {
|
|
105
|
+
stopColor: "#7C3AED",
|
|
106
|
+
stopOpacity: "0.55"
|
|
107
|
+
}), /* @__PURE__ */ r("stop", {
|
|
108
|
+
offset: "1",
|
|
109
|
+
stopColor: "#7C3AED",
|
|
110
|
+
stopOpacity: "0"
|
|
111
|
+
})]
|
|
112
|
+
}) : null,
|
|
113
|
+
/* @__PURE__ */ i("linearGradient", {
|
|
114
|
+
id: g,
|
|
115
|
+
x1: "13",
|
|
116
|
+
y1: "5",
|
|
117
|
+
x2: "33",
|
|
118
|
+
y2: "43",
|
|
119
|
+
gradientUnits: "userSpaceOnUse",
|
|
120
|
+
children: [/* @__PURE__ */ r("stop", { stopColor: "#C4A6FF" }), /* @__PURE__ */ r("stop", {
|
|
121
|
+
offset: "1",
|
|
122
|
+
stopColor: "#9D5BFF"
|
|
123
|
+
})]
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ i("linearGradient", {
|
|
126
|
+
id: _,
|
|
127
|
+
x1: "22",
|
|
128
|
+
y1: "5",
|
|
129
|
+
x2: "35",
|
|
130
|
+
y2: "43",
|
|
131
|
+
gradientUnits: "userSpaceOnUse",
|
|
132
|
+
children: [/* @__PURE__ */ r("stop", { stopColor: "#A874FF" }), /* @__PURE__ */ r("stop", {
|
|
133
|
+
offset: "1",
|
|
134
|
+
stopColor: "#7C3AED"
|
|
135
|
+
})]
|
|
136
|
+
})
|
|
137
|
+
] }),
|
|
138
|
+
/* @__PURE__ */ r("rect", {
|
|
139
|
+
width: "64",
|
|
140
|
+
height: "64",
|
|
141
|
+
rx: v,
|
|
142
|
+
fill: `url(#${m})`
|
|
143
|
+
}),
|
|
144
|
+
o === "brand" ? /* @__PURE__ */ i(n, { children: [/* @__PURE__ */ r("path", {
|
|
145
|
+
transform: "translate(8 8)",
|
|
146
|
+
d: l,
|
|
147
|
+
fill: "#FFFFFF"
|
|
148
|
+
}), /* @__PURE__ */ r("path", {
|
|
149
|
+
transform: "translate(8 8)",
|
|
150
|
+
d: u,
|
|
151
|
+
fill: "#D7C4FF"
|
|
152
|
+
})] }) : /* @__PURE__ */ i(n, { children: [
|
|
153
|
+
/* @__PURE__ */ r("ellipse", {
|
|
154
|
+
cx: "32",
|
|
155
|
+
cy: "30",
|
|
156
|
+
rx: "26",
|
|
157
|
+
ry: "26",
|
|
158
|
+
fill: `url(#${h})`
|
|
159
|
+
}),
|
|
160
|
+
/* @__PURE__ */ r("path", {
|
|
161
|
+
transform: "translate(8 8)",
|
|
162
|
+
d: l,
|
|
163
|
+
fill: `url(#${g})`
|
|
164
|
+
}),
|
|
165
|
+
/* @__PURE__ */ r("path", {
|
|
166
|
+
transform: "translate(8 8)",
|
|
167
|
+
d: u,
|
|
168
|
+
fill: `url(#${_})`
|
|
169
|
+
})
|
|
170
|
+
] })
|
|
171
|
+
]
|
|
172
|
+
});
|
|
173
|
+
}, m = ({ size: t = 28, markVariant: n = "gradient", label: a = "Voltro", product: o, productTone: c = "brand", className: l, style: u }) => /* @__PURE__ */ i("span", {
|
|
174
|
+
className: e("voltro-wordmark inline-flex items-center font-semibold tracking-tight leading-none", l),
|
|
175
|
+
style: {
|
|
176
|
+
columnGap: `calc(var(--voltro-wordmark-size, ${t}px) * .28)`,
|
|
177
|
+
fontSize: `calc(var(--voltro-wordmark-size, ${t}px) * .74)`,
|
|
178
|
+
...u
|
|
179
|
+
},
|
|
180
|
+
children: [
|
|
181
|
+
/* @__PURE__ */ r(f, {
|
|
182
|
+
size: Math.round(t * 1.18),
|
|
183
|
+
variant: n,
|
|
184
|
+
"aria-hidden": !0,
|
|
185
|
+
style: {
|
|
186
|
+
width: `calc(var(--voltro-wordmark-size, ${t}px) * 1.18)`,
|
|
187
|
+
height: `calc(var(--voltro-wordmark-size, ${t}px) * 1.18)`,
|
|
188
|
+
flexShrink: 0
|
|
189
|
+
}
|
|
190
|
+
}),
|
|
191
|
+
/* @__PURE__ */ r("span", {
|
|
192
|
+
className: "voltro-wordmark-label",
|
|
193
|
+
children: a
|
|
194
|
+
}),
|
|
195
|
+
o ? /* @__PURE__ */ r(s, {
|
|
196
|
+
variant: "outline",
|
|
197
|
+
className: e("voltro-product-badge shrink-0 rounded px-1.5 py-1 text-[10px] font-medium leading-none uppercase tracking-[.08em]", c === "warning" ? "border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-200" : "border-primary/30 bg-primary/10 text-accent-foreground"),
|
|
198
|
+
children: o
|
|
199
|
+
}) : null
|
|
200
|
+
]
|
|
201
|
+
}), h = {
|
|
202
|
+
full: c,
|
|
203
|
+
front: l,
|
|
204
|
+
back: u
|
|
205
|
+
};
|
|
206
|
+
//#endregion
|
|
207
|
+
export { m as a, f as i, d as n, s as o, p as r, o as s, h as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/ui-shadcn",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.67.0",
|
|
4
4
|
"description": "Voltro's first-party shadcn/ui kit: Tailwind v4 design tokens (light + dark), 30+ primitives, layout compositions, styled widgets for the @voltro/ui seam, and the canonical theme/language preference-cookie helpers.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"default": "./dist/brand.js"
|
|
35
35
|
},
|
|
36
36
|
"./tokens.css": "./dist/tokens.css",
|
|
37
|
-
"./package.json": "./package.json"
|
|
37
|
+
"./package.json": "./package.json",
|
|
38
|
+
"./signal.css": "./dist/signal.css"
|
|
38
39
|
},
|
|
39
40
|
"main": "./dist/index.js",
|
|
40
41
|
"module": "./dist/index.js",
|
|
@@ -49,15 +50,15 @@
|
|
|
49
50
|
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
|
50
51
|
"@radix-ui/react-toggle": "^1.1.18",
|
|
51
52
|
"@radix-ui/react-toggle-group": "^1.1.19",
|
|
52
|
-
"@
|
|
53
|
+
"@shikijs/langs": "^4.4.3",
|
|
54
|
+
"@shikijs/themes": "^4.4.3",
|
|
55
|
+
"@voltro/ui": "0.67.0",
|
|
53
56
|
"class-variance-authority": "^0.7.1",
|
|
54
57
|
"clsx": "^2.1.1",
|
|
55
58
|
"shiki": "^4.4.3",
|
|
56
59
|
"tailwind-merge": "^3.6.0",
|
|
57
60
|
"tailwindcss": "^4.3.3",
|
|
58
|
-
"tw-animate-css": "^1.2.5"
|
|
59
|
-
"@shikijs/langs": "^4.4.3",
|
|
60
|
-
"@shikijs/themes": "^4.4.3"
|
|
61
|
+
"tw-animate-css": "^1.2.5"
|
|
61
62
|
},
|
|
62
63
|
"peerDependencies": {
|
|
63
64
|
"react": "^19.0.0"
|
package/src/brand/voltroLogo.tsx
CHANGED
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import type { CSSProperties, ReactNode, SVGProps } from 'react'
|
|
21
21
|
import { useId } from 'react'
|
|
22
22
|
import { cn } from '../cn'
|
|
23
|
+
import { Badge } from '../primitives/badge'
|
|
23
24
|
|
|
24
25
|
// The bolt geometry, authored once in a 48×48 box and reused everywhere.
|
|
25
26
|
// Sharp joins read as "electric"; the facets share the crease T→C.
|
|
@@ -213,6 +214,10 @@ export interface VoltroWordmarkProps {
|
|
|
213
214
|
readonly markVariant?: VoltroMarkVariant
|
|
214
215
|
/** Wordmark label. Default "Voltro". */
|
|
215
216
|
readonly label?: string
|
|
217
|
+
/** Product badge beside the shared wordmark, e.g. Framework or Cloud. */
|
|
218
|
+
readonly product?: ReactNode
|
|
219
|
+
/** Warning tone for an operator surface; proportions stay shared. */
|
|
220
|
+
readonly productTone?: 'brand' | 'warning'
|
|
216
221
|
readonly className?: string
|
|
217
222
|
readonly style?: CSSProperties
|
|
218
223
|
}
|
|
@@ -226,17 +231,21 @@ export const VoltroWordmark = ({
|
|
|
226
231
|
size = 28,
|
|
227
232
|
markVariant = 'gradient',
|
|
228
233
|
label = 'Voltro',
|
|
234
|
+
product,
|
|
235
|
+
productTone = 'brand',
|
|
229
236
|
className,
|
|
230
237
|
style,
|
|
231
238
|
}: VoltroWordmarkProps): ReactNode => (
|
|
232
239
|
<span
|
|
233
|
-
className={cn('inline-flex items-center font-semibold tracking-tight leading-none', className)}
|
|
234
|
-
style={{
|
|
240
|
+
className={cn('voltro-wordmark inline-flex items-center font-semibold tracking-tight leading-none', className)}
|
|
241
|
+
style={{ columnGap: `calc(var(--voltro-wordmark-size, ${size}px) * .28)`, fontSize: `calc(var(--voltro-wordmark-size, ${size}px) * .74)`, ...style }}
|
|
235
242
|
>
|
|
236
243
|
{/* Mark rendered larger than the cap height so the bolt reads as the
|
|
237
244
|
lead element, not a small adornment beside the wordmark. */}
|
|
238
|
-
<VoltroMark size={Math.round(size * 1.18)} variant={markVariant} aria-hidden
|
|
239
|
-
|
|
245
|
+
<VoltroMark size={Math.round(size * 1.18)} variant={markVariant} aria-hidden
|
|
246
|
+
style={{ width: `calc(var(--voltro-wordmark-size, ${size}px) * 1.18)`, height: `calc(var(--voltro-wordmark-size, ${size}px) * 1.18)`, flexShrink: 0 }} />
|
|
247
|
+
<span className="voltro-wordmark-label">{label}</span>
|
|
248
|
+
{product ? <Badge variant="outline" className={cn('voltro-product-badge shrink-0 rounded px-1.5 py-1 text-[10px] font-medium leading-none uppercase tracking-[.08em]', productTone === 'warning' ? 'border-rose-500/30 bg-rose-500/10 text-rose-700 dark:text-rose-200' : 'border-primary/30 bg-primary/10 text-accent-foreground')}>{product}</Badge> : null}
|
|
240
249
|
</span>
|
|
241
250
|
)
|
|
242
251
|
|
|
@@ -8,11 +8,8 @@
|
|
|
8
8
|
// page reloads. Default is plain `<a>` so the kit stays
|
|
9
9
|
// router-agnostic.
|
|
10
10
|
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// landing / marketplace pages directly. That's the single visual
|
|
14
|
-
// source of truth across the four sibling apps; do not duplicate
|
|
15
|
-
// the header treatment here.
|
|
11
|
+
// PageHeader supplies the default compact top bar. The header slot accepts
|
|
12
|
+
// a shared product masthead while leaving task content and auth to the app.
|
|
16
13
|
|
|
17
14
|
import type { ComponentType, ReactNode } from 'react'
|
|
18
15
|
import { cn } from '../cn'
|
|
@@ -26,6 +23,8 @@ interface NavLink {
|
|
|
26
23
|
|
|
27
24
|
interface AppShellProps {
|
|
28
25
|
readonly brand: ReactNode
|
|
26
|
+
/** Custom top navigation using the app's own shared header composition. */
|
|
27
|
+
readonly header?: ReactNode
|
|
29
28
|
readonly nav?: ReadonlyArray<NavLink>
|
|
30
29
|
readonly right?: ReactNode
|
|
31
30
|
readonly children: ReactNode
|
|
@@ -38,13 +37,13 @@ const PlainLink = ({ to, className, children }: ShellLinkProps): ReactNode => (
|
|
|
38
37
|
)
|
|
39
38
|
|
|
40
39
|
export const AppShell = ({
|
|
41
|
-
brand, nav, right, children, className,
|
|
40
|
+
brand, header, nav, right, children, className,
|
|
42
41
|
LinkComponent = PlainLink,
|
|
43
42
|
}: AppShellProps): ReactNode => {
|
|
44
43
|
const Link = LinkComponent
|
|
45
44
|
return (
|
|
46
45
|
<div className={cn('min-h-screen flex flex-col bg-background text-foreground', className)}>
|
|
47
|
-
<PageHeader>
|
|
46
|
+
{header ?? <PageHeader>
|
|
48
47
|
<div className="font-semibold flex items-center gap-2">{brand}</div>
|
|
49
48
|
<div className="flex items-center gap-6">
|
|
50
49
|
{nav && nav.length > 0 ? (
|
|
@@ -63,10 +62,9 @@ export const AppShell = ({
|
|
|
63
62
|
) : null}
|
|
64
63
|
{right ? <div>{right}</div> : null}
|
|
65
64
|
</div>
|
|
66
|
-
</PageHeader>
|
|
65
|
+
</PageHeader>}
|
|
67
66
|
<main className="flex-1">{children}</main>
|
|
68
67
|
</div>
|
|
69
68
|
)
|
|
70
69
|
}
|
|
71
70
|
|
|
72
|
-
|
|
@@ -21,7 +21,7 @@ interface CodeComparePanelProps {
|
|
|
21
21
|
readonly code?: string
|
|
22
22
|
/** Shiki language. Triggers syntax highlighting on `code`. */
|
|
23
23
|
readonly lang?: ShikiLang
|
|
24
|
-
/** Visual treatment — `'muted'`
|
|
24
|
+
/** Visual treatment — `'muted'` uses a neutral border (the "before"),
|
|
25
25
|
* `'highlight'` keeps the full styling + adds a primary border. */
|
|
26
26
|
readonly tone?: 'muted' | 'highlight'
|
|
27
27
|
/** The corner tag. Pass a translated string on a localised page. */
|
|
@@ -48,7 +48,7 @@ const Panel = ({ label, html, code, lang, tone = 'muted', eyebrow }: CodeCompare
|
|
|
48
48
|
<span
|
|
49
49
|
className={cn(
|
|
50
50
|
'text-[0.65rem] uppercase tracking-[0.08em] font-semibold',
|
|
51
|
-
tone === 'highlight' ? 'text-primary' : 'text-muted-foreground
|
|
51
|
+
tone === 'highlight' ? 'text-primary' : 'text-muted-foreground',
|
|
52
52
|
)}
|
|
53
53
|
>
|
|
54
54
|
{eyebrow ?? (tone === 'highlight' ? 'With Voltro' : 'Before')}
|
|
@@ -57,7 +57,6 @@ const Panel = ({ label, html, code, lang, tone = 'muted', eyebrow }: CodeCompare
|
|
|
57
57
|
<div
|
|
58
58
|
className={cn(
|
|
59
59
|
'text-sm leading-relaxed [&_pre]:!m-0 [&_pre]:!bg-transparent [&_pre]:p-5 overflow-x-auto',
|
|
60
|
-
tone === 'muted' && 'opacity-60',
|
|
61
60
|
)}
|
|
62
61
|
>
|
|
63
62
|
{html ? (
|