@proyecto-viviana/ui 0.3.1 → 0.3.3
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/dist/components.css +1077 -1077
- package/dist/index.js +236 -249
- package/dist/index.js.map +3 -3
- package/dist/index.ssr.js +78 -81
- package/dist/index.ssr.js.map +3 -3
- package/dist/radio/index.d.ts +12 -27
- package/dist/radio/index.d.ts.map +1 -1
- package/dist/test-utils/index.d.ts +2 -2
- package/dist/test-utils/index.d.ts.map +1 -1
- package/package.json +13 -12
- package/src/alert/index.tsx +48 -0
- package/src/assets/favicon.png +0 -0
- package/src/assets/fire.gif +0 -0
- package/src/autocomplete/index.tsx +313 -0
- package/src/avatar/index.tsx +75 -0
- package/src/badge/index.tsx +43 -0
- package/src/breadcrumbs/index.tsx +207 -0
- package/src/button/Button.tsx +74 -0
- package/src/button/index.ts +2 -0
- package/src/button/types.ts +24 -0
- package/src/calendar/DateField.tsx +200 -0
- package/src/calendar/DatePicker.tsx +298 -0
- package/src/calendar/RangeCalendar.tsx +236 -0
- package/src/calendar/TimeField.tsx +196 -0
- package/src/calendar/index.tsx +223 -0
- package/src/checkbox/index.tsx +257 -0
- package/src/color/index.tsx +687 -0
- package/src/combobox/index.tsx +383 -0
- package/src/components.css +1077 -0
- package/src/custom/calendar-card/index.tsx +66 -0
- package/src/custom/chip/index.tsx +46 -0
- package/src/custom/conversation/index.tsx +105 -0
- package/src/custom/event-card/index.tsx +132 -0
- package/src/custom/header/index.tsx +33 -0
- package/src/custom/lateral-nav/index.tsx +88 -0
- package/src/custom/logo/index.tsx +58 -0
- package/src/custom/nav-header/index.tsx +42 -0
- package/src/custom/page-layout/index.tsx +29 -0
- package/src/custom/profile-card/index.tsx +64 -0
- package/src/custom/project-card/index.tsx +59 -0
- package/src/custom/timeline-item/index.tsx +105 -0
- package/src/dialog/Dialog.tsx +260 -0
- package/src/dialog/index.tsx +3 -0
- package/src/disclosure/index.tsx +307 -0
- package/src/gridlist/index.tsx +403 -0
- package/src/icon/icons/GitHubIcon.tsx +20 -0
- package/src/icon/index.tsx +48 -0
- package/src/index.ts +322 -0
- package/src/landmark/index.tsx +231 -0
- package/src/link/index.tsx +130 -0
- package/src/listbox/index.tsx +231 -0
- package/src/menu/index.tsx +297 -0
- package/src/meter/index.tsx +163 -0
- package/src/numberfield/index.tsx +482 -0
- package/src/popover/index.tsx +260 -0
- package/src/progress-bar/index.tsx +169 -0
- package/src/radio/index.tsx +173 -0
- package/src/searchfield/index.tsx +453 -0
- package/src/select/index.tsx +349 -0
- package/src/separator/index.tsx +141 -0
- package/src/slider/index.tsx +382 -0
- package/src/styles.css +450 -0
- package/src/switch/ToggleSwitch.tsx +112 -0
- package/src/switch/index.tsx +90 -0
- package/src/table/index.tsx +531 -0
- package/src/tabs/index.tsx +273 -0
- package/src/tag-group/index.tsx +240 -0
- package/src/test-utils/index.ts +40 -0
- package/src/textfield/index.tsx +211 -0
- package/src/theme.css +101 -0
- package/src/toast/index.tsx +324 -0
- package/src/toolbar/index.tsx +108 -0
- package/src/tooltip/index.tsx +197 -0
- package/src/tree/index.tsx +494 -0
package/src/styles.css
ADDED
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Viviana UI Complete Styles (Theme + Components)
|
|
3
|
+
*
|
|
4
|
+
* WARNING: This file contains @theme which cannot be @imported in Tailwind v4.
|
|
5
|
+
* Use components.css instead and copy the @theme block from theme.css.
|
|
6
|
+
*
|
|
7
|
+
* For proper usage, see theme.css documentation.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/* ===== THEME ===== */
|
|
11
|
+
@theme {
|
|
12
|
+
/* Breakpoints */
|
|
13
|
+
--breakpoint-xxs: 320px;
|
|
14
|
+
--breakpoint-xs: 475px;
|
|
15
|
+
|
|
16
|
+
/* Background - Dark blue-gray */
|
|
17
|
+
--color-bg-100: #3B5260;
|
|
18
|
+
--color-bg-200: #293E4B;
|
|
19
|
+
--color-bg-300: #24313a;
|
|
20
|
+
--color-bg-400: #1D272E;
|
|
21
|
+
--color-bg-light: #515151;
|
|
22
|
+
|
|
23
|
+
/* Accent - Pink */
|
|
24
|
+
--color-accent: #DF5C9A;
|
|
25
|
+
--color-accent-200: #FFB2D7;
|
|
26
|
+
--color-accent-300: #FF88C0;
|
|
27
|
+
--color-accent-500: #DF5C9A;
|
|
28
|
+
--color-accent-highlight: #e2a2be;
|
|
29
|
+
|
|
30
|
+
/* Primary - Cyan/Blue */
|
|
31
|
+
--color-primary-100: #D9F2FF;
|
|
32
|
+
--color-primary-200: #D0E9F5;
|
|
33
|
+
--color-primary-300: #ADCCDC;
|
|
34
|
+
--color-primary-400: #B8DFFF;
|
|
35
|
+
--color-primary-500: #75ABC7;
|
|
36
|
+
--color-primary-600: #58748B;
|
|
37
|
+
--color-primary-700: #4F6D85;
|
|
38
|
+
--color-primary-800: #4C6477;
|
|
39
|
+
|
|
40
|
+
/* Success - Green */
|
|
41
|
+
--color-success-100: #E5FFF3;
|
|
42
|
+
--color-success-400: #C2FFC8;
|
|
43
|
+
--color-success-600: #559D87;
|
|
44
|
+
|
|
45
|
+
/* Warning - Yellow */
|
|
46
|
+
--color-warning-100: #FFFBE5;
|
|
47
|
+
--color-warning-400: #FFDD87;
|
|
48
|
+
--color-warning-600: #9D8D55;
|
|
49
|
+
|
|
50
|
+
/* Danger - Red */
|
|
51
|
+
--color-danger-100: #FFE5E5;
|
|
52
|
+
--color-danger-400: #FF8787;
|
|
53
|
+
--color-danger-600: #9D5555;
|
|
54
|
+
|
|
55
|
+
/* Cards */
|
|
56
|
+
--color-cards-bg: #373737;
|
|
57
|
+
--color-cards-bg-load: #484848;
|
|
58
|
+
--color-correct: #83f1a7;
|
|
59
|
+
--color-incorrect: #e74c3c;
|
|
60
|
+
|
|
61
|
+
/* Typography */
|
|
62
|
+
--font-sen: 'Sen', sans-serif;
|
|
63
|
+
--font-jost: 'Jost', sans-serif;
|
|
64
|
+
--font-sans: 'Sen', sans-serif;
|
|
65
|
+
--font-mono: 'JetBrains Mono', monospace;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ===== FONT UTILITIES ===== */
|
|
69
|
+
.font-sen {
|
|
70
|
+
font-family: 'Sen', sans-serif;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.font-jost {
|
|
74
|
+
font-family: 'Jost', sans-serif;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* ===== CUSTOM SHADOWS ===== */
|
|
78
|
+
.drop-shadow-title-card {
|
|
79
|
+
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.drop-shadow-logo {
|
|
83
|
+
filter: drop-shadow(0 0 10px rgba(223, 92, 154, 0.8));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.shadow-primary-chip {
|
|
87
|
+
box-shadow: 0 2px 8px rgba(79, 109, 133, 0.4);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* ===== BUTTON COMPONENT ===== */
|
|
91
|
+
.vui-button {
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
gap: 0.5rem;
|
|
96
|
+
padding: 0.5rem 1rem;
|
|
97
|
+
font-size: 1rem;
|
|
98
|
+
font-weight: 500;
|
|
99
|
+
border-radius: 0.5rem;
|
|
100
|
+
transition: all 0.2s ease;
|
|
101
|
+
cursor: pointer;
|
|
102
|
+
border: none;
|
|
103
|
+
outline: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.vui-button:focus-visible {
|
|
107
|
+
outline: none;
|
|
108
|
+
box-shadow: 0 0 0 2px var(--color-bg-400), 0 0 0 4px var(--color-accent-300);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.vui-button:disabled {
|
|
112
|
+
opacity: 0.5;
|
|
113
|
+
cursor: not-allowed;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.vui-button.is-pressed {
|
|
117
|
+
transform: scale(0.98);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Fill variants - pokeforos style */
|
|
121
|
+
/* Primary = Pink accent (main CTA) */
|
|
122
|
+
.vui-button--fill.vui-button--primary {
|
|
123
|
+
background: var(--color-accent);
|
|
124
|
+
color: white;
|
|
125
|
+
}
|
|
126
|
+
.vui-button--fill.vui-button--primary:hover:not(:disabled) {
|
|
127
|
+
background: var(--color-accent-300);
|
|
128
|
+
}
|
|
129
|
+
.vui-button--fill.vui-button--primary:active:not(:disabled) {
|
|
130
|
+
background: var(--color-accent-500);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* Secondary = Cyan primary */
|
|
134
|
+
.vui-button--fill.vui-button--secondary {
|
|
135
|
+
background: var(--color-primary-500);
|
|
136
|
+
color: white;
|
|
137
|
+
}
|
|
138
|
+
.vui-button--fill.vui-button--secondary:hover:not(:disabled) {
|
|
139
|
+
background: var(--color-primary-400);
|
|
140
|
+
}
|
|
141
|
+
.vui-button--fill.vui-button--secondary:active:not(:disabled) {
|
|
142
|
+
background: var(--color-primary-600);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Accent = Also pink (alias for primary look) */
|
|
146
|
+
.vui-button--fill.vui-button--accent {
|
|
147
|
+
background: var(--color-accent);
|
|
148
|
+
color: white;
|
|
149
|
+
}
|
|
150
|
+
.vui-button--fill.vui-button--accent:hover:not(:disabled) {
|
|
151
|
+
background: var(--color-accent-300);
|
|
152
|
+
}
|
|
153
|
+
.vui-button--fill.vui-button--accent:active:not(:disabled) {
|
|
154
|
+
background: var(--color-accent-500);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/* Negative = Danger red */
|
|
158
|
+
.vui-button--fill.vui-button--negative {
|
|
159
|
+
background: var(--color-danger-400);
|
|
160
|
+
color: white;
|
|
161
|
+
}
|
|
162
|
+
.vui-button--fill.vui-button--negative:hover:not(:disabled) {
|
|
163
|
+
background: var(--color-danger-600);
|
|
164
|
+
}
|
|
165
|
+
.vui-button--fill.vui-button--negative:active:not(:disabled) {
|
|
166
|
+
background: var(--color-danger-400);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Outline variants */
|
|
170
|
+
.vui-button--outline.vui-button--primary {
|
|
171
|
+
border: 2px solid var(--color-accent);
|
|
172
|
+
color: var(--color-accent-200);
|
|
173
|
+
background: transparent;
|
|
174
|
+
}
|
|
175
|
+
.vui-button--outline.vui-button--primary:hover:not(:disabled) {
|
|
176
|
+
background: color-mix(in srgb, var(--color-accent) 15%, transparent);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.vui-button--outline.vui-button--secondary {
|
|
180
|
+
border: 2px solid var(--color-primary-500);
|
|
181
|
+
color: var(--color-primary-300);
|
|
182
|
+
background: transparent;
|
|
183
|
+
}
|
|
184
|
+
.vui-button--outline.vui-button--secondary:hover:not(:disabled) {
|
|
185
|
+
background: color-mix(in srgb, var(--color-primary-500) 15%, transparent);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.vui-button--outline.vui-button--accent {
|
|
189
|
+
border: 2px solid var(--color-accent);
|
|
190
|
+
color: var(--color-accent-200);
|
|
191
|
+
background: transparent;
|
|
192
|
+
}
|
|
193
|
+
.vui-button--outline.vui-button--accent:hover:not(:disabled) {
|
|
194
|
+
background: color-mix(in srgb, var(--color-accent) 15%, transparent);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.vui-button--outline.vui-button--negative {
|
|
198
|
+
border: 2px solid var(--color-danger-400);
|
|
199
|
+
color: var(--color-danger-100);
|
|
200
|
+
background: transparent;
|
|
201
|
+
}
|
|
202
|
+
.vui-button--outline.vui-button--negative:hover:not(:disabled) {
|
|
203
|
+
background: color-mix(in srgb, var(--color-danger-400) 15%, transparent);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/* ===== CHIP COMPONENT ===== */
|
|
207
|
+
.vui-chip {
|
|
208
|
+
display: inline-flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
justify-content: center;
|
|
211
|
+
padding: 0.125rem 0.5rem;
|
|
212
|
+
font-size: 0.75rem;
|
|
213
|
+
font-weight: 600;
|
|
214
|
+
border-radius: 9999px;
|
|
215
|
+
text-transform: uppercase;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.vui-chip--primary {
|
|
219
|
+
background: var(--color-primary-700);
|
|
220
|
+
color: var(--color-primary-100);
|
|
221
|
+
box-shadow: 0 2px 8px rgba(79, 109, 133, 0.4);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.vui-chip--accent {
|
|
225
|
+
background: var(--color-accent);
|
|
226
|
+
color: white;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.vui-chip--success {
|
|
230
|
+
background: var(--color-success-600);
|
|
231
|
+
color: var(--color-success-100);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.vui-chip--warning {
|
|
235
|
+
background: var(--color-warning-600);
|
|
236
|
+
color: var(--color-warning-100);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.vui-chip--danger {
|
|
240
|
+
background: var(--color-danger-600);
|
|
241
|
+
color: var(--color-danger-100);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* ===== BADGE COMPONENT ===== */
|
|
245
|
+
.vui-badge {
|
|
246
|
+
display: inline-flex;
|
|
247
|
+
align-items: center;
|
|
248
|
+
justify-content: center;
|
|
249
|
+
padding: 0.25rem 0.75rem;
|
|
250
|
+
font-size: 0.875rem;
|
|
251
|
+
font-weight: 500;
|
|
252
|
+
border-radius: 0.375rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.vui-badge--primary {
|
|
256
|
+
background: var(--color-primary-700);
|
|
257
|
+
color: var(--color-primary-100);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.vui-badge--accent {
|
|
261
|
+
background: var(--color-accent);
|
|
262
|
+
color: white;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.vui-badge--success {
|
|
266
|
+
background: var(--color-success-600);
|
|
267
|
+
color: var(--color-success-100);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.vui-badge--warning {
|
|
271
|
+
background: var(--color-warning-600);
|
|
272
|
+
color: var(--color-warning-100);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.vui-badge--danger {
|
|
276
|
+
background: var(--color-danger-600);
|
|
277
|
+
color: var(--color-danger-100);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* ===== ALERT COMPONENT ===== */
|
|
281
|
+
.vui-alert {
|
|
282
|
+
display: flex;
|
|
283
|
+
align-items: flex-start;
|
|
284
|
+
gap: 0.75rem;
|
|
285
|
+
padding: 1rem;
|
|
286
|
+
border-radius: 0.5rem;
|
|
287
|
+
border-width: 1px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.vui-alert--info {
|
|
291
|
+
background: color-mix(in srgb, var(--color-primary-700) 20%, transparent);
|
|
292
|
+
border-color: var(--color-primary-600);
|
|
293
|
+
color: var(--color-primary-200);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.vui-alert--success {
|
|
297
|
+
background: color-mix(in srgb, var(--color-success-600) 20%, transparent);
|
|
298
|
+
border-color: var(--color-success-600);
|
|
299
|
+
color: var(--color-success-100);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.vui-alert--warning {
|
|
303
|
+
background: color-mix(in srgb, var(--color-warning-600) 20%, transparent);
|
|
304
|
+
border-color: var(--color-warning-600);
|
|
305
|
+
color: var(--color-warning-100);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.vui-alert--error {
|
|
309
|
+
background: color-mix(in srgb, var(--color-danger-600) 20%, transparent);
|
|
310
|
+
border-color: var(--color-danger-400);
|
|
311
|
+
color: var(--color-danger-100);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/* ===== AVATAR COMPONENT ===== */
|
|
315
|
+
.vui-avatar {
|
|
316
|
+
display: inline-flex;
|
|
317
|
+
align-items: center;
|
|
318
|
+
justify-content: center;
|
|
319
|
+
border-radius: 9999px;
|
|
320
|
+
overflow: hidden;
|
|
321
|
+
background: var(--color-bg-300);
|
|
322
|
+
color: var(--color-primary-300);
|
|
323
|
+
font-weight: 600;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.vui-avatar--sm {
|
|
327
|
+
width: 2rem;
|
|
328
|
+
height: 2rem;
|
|
329
|
+
font-size: 0.75rem;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.vui-avatar--md {
|
|
333
|
+
width: 2.5rem;
|
|
334
|
+
height: 2.5rem;
|
|
335
|
+
font-size: 0.875rem;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.vui-avatar--lg {
|
|
339
|
+
width: 3rem;
|
|
340
|
+
height: 3rem;
|
|
341
|
+
font-size: 1rem;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
.vui-avatar--xl {
|
|
345
|
+
width: 4rem;
|
|
346
|
+
height: 4rem;
|
|
347
|
+
font-size: 1.25rem;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* ===== CARD COMPONENT ===== */
|
|
351
|
+
.vui-card {
|
|
352
|
+
background: var(--color-bg-300);
|
|
353
|
+
border: 1px solid var(--color-primary-600);
|
|
354
|
+
border-radius: 0.75rem;
|
|
355
|
+
overflow: hidden;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.vui-card--accent-border {
|
|
359
|
+
border-bottom-color: var(--color-accent-500);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/* ===== GRADIENTS ===== */
|
|
363
|
+
.hero-gradient {
|
|
364
|
+
background: linear-gradient(135deg, var(--color-bg-300) 0%, var(--color-bg-400) 100%);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.gradient-text {
|
|
368
|
+
background: linear-gradient(135deg, var(--color-primary-300), var(--color-accent-300));
|
|
369
|
+
-webkit-background-clip: text;
|
|
370
|
+
-webkit-text-fill-color: transparent;
|
|
371
|
+
background-clip: text;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* ===== PROSE/DOCS ===== */
|
|
375
|
+
.prose {
|
|
376
|
+
max-width: 65ch;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.prose h1 {
|
|
380
|
+
font-size: 2.25rem;
|
|
381
|
+
font-weight: 700;
|
|
382
|
+
margin-bottom: 1rem;
|
|
383
|
+
color: var(--color-primary-100);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
.prose h2 {
|
|
387
|
+
font-size: 1.5rem;
|
|
388
|
+
font-weight: 600;
|
|
389
|
+
margin-top: 2rem;
|
|
390
|
+
margin-bottom: 0.75rem;
|
|
391
|
+
color: var(--color-primary-200);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.prose h3 {
|
|
395
|
+
font-size: 1.25rem;
|
|
396
|
+
font-weight: 600;
|
|
397
|
+
margin-top: 1.5rem;
|
|
398
|
+
margin-bottom: 0.5rem;
|
|
399
|
+
color: var(--color-primary-200);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.prose p {
|
|
403
|
+
margin-bottom: 1rem;
|
|
404
|
+
line-height: 1.75;
|
|
405
|
+
color: var(--color-primary-300);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.prose code {
|
|
409
|
+
background: var(--color-bg-300);
|
|
410
|
+
padding: 0.125rem 0.375rem;
|
|
411
|
+
border-radius: 0.25rem;
|
|
412
|
+
font-family: var(--font-mono);
|
|
413
|
+
font-size: 0.875em;
|
|
414
|
+
color: var(--color-accent-200);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.prose pre {
|
|
418
|
+
background: var(--color-bg-400);
|
|
419
|
+
color: var(--color-primary-100);
|
|
420
|
+
padding: 1rem;
|
|
421
|
+
border-radius: 0.5rem;
|
|
422
|
+
overflow-x: auto;
|
|
423
|
+
margin: 1rem 0;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.prose pre code {
|
|
427
|
+
background: transparent;
|
|
428
|
+
padding: 0;
|
|
429
|
+
color: inherit;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/* ===== SIDEBAR ===== */
|
|
433
|
+
.sidebar-link {
|
|
434
|
+
display: block;
|
|
435
|
+
padding: 0.5rem 1rem;
|
|
436
|
+
border-radius: 0.375rem;
|
|
437
|
+
color: var(--color-primary-300);
|
|
438
|
+
transition: all 0.15s;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
.sidebar-link:hover {
|
|
442
|
+
background: var(--color-bg-300);
|
|
443
|
+
color: var(--color-primary-100);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.sidebar-link.active {
|
|
447
|
+
background: var(--color-primary-700);
|
|
448
|
+
color: var(--color-primary-100);
|
|
449
|
+
font-weight: 500;
|
|
450
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToggleSwitch component for proyecto-viviana-ui
|
|
3
|
+
*
|
|
4
|
+
* A styled switch component built on top of solidaria-components.
|
|
5
|
+
* This component only handles styling - all behavior and accessibility
|
|
6
|
+
* is provided by the headless Switch from solidaria-components.
|
|
7
|
+
*
|
|
8
|
+
* Named "ToggleSwitch" to avoid conflict with SolidJS's built-in Switch component.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { type JSX, splitProps, mergeProps as solidMergeProps } from 'solid-js';
|
|
12
|
+
import { ToggleSwitch as HeadlessToggleSwitch, type ToggleSwitchProps as HeadlessToggleSwitchProps, type ToggleSwitchRenderProps } from '@proyecto-viviana/solidaria-components';
|
|
13
|
+
|
|
14
|
+
// ============================================
|
|
15
|
+
// TYPES
|
|
16
|
+
// ============================================
|
|
17
|
+
|
|
18
|
+
export type SwitchSize = 'sm' | 'md' | 'lg';
|
|
19
|
+
|
|
20
|
+
export interface ToggleSwitchProps extends Omit<HeadlessToggleSwitchProps, 'class' | 'children'> {
|
|
21
|
+
/** The size of the switch. */
|
|
22
|
+
size?: SwitchSize;
|
|
23
|
+
/** Additional CSS class name. */
|
|
24
|
+
class?: string;
|
|
25
|
+
/** Label text for the switch. */
|
|
26
|
+
children?: JSX.Element;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ============================================
|
|
30
|
+
// STYLES
|
|
31
|
+
// ============================================
|
|
32
|
+
|
|
33
|
+
const sizeStyles = {
|
|
34
|
+
sm: {
|
|
35
|
+
track: 'h-5 w-9',
|
|
36
|
+
thumb: 'h-4 w-4',
|
|
37
|
+
translate: 'translate-x-4',
|
|
38
|
+
},
|
|
39
|
+
md: {
|
|
40
|
+
track: 'h-6 w-11',
|
|
41
|
+
thumb: 'h-5 w-5',
|
|
42
|
+
translate: 'translate-x-5',
|
|
43
|
+
},
|
|
44
|
+
lg: {
|
|
45
|
+
track: 'h-7 w-14',
|
|
46
|
+
thumb: 'h-6 w-6',
|
|
47
|
+
translate: 'translate-x-7',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// ============================================
|
|
52
|
+
// COMPONENT
|
|
53
|
+
// ============================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A switch allows users to toggle between two mutually exclusive states.
|
|
57
|
+
*
|
|
58
|
+
* Built on solidaria-components Switch for full accessibility support.
|
|
59
|
+
* Named "ToggleSwitch" to avoid conflict with SolidJS's built-in Switch component.
|
|
60
|
+
*/
|
|
61
|
+
export function ToggleSwitch(props: ToggleSwitchProps): JSX.Element {
|
|
62
|
+
const defaultProps: Partial<ToggleSwitchProps> = {
|
|
63
|
+
size: 'md',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const merged = solidMergeProps(defaultProps, props);
|
|
67
|
+
|
|
68
|
+
const [local, headlessProps] = splitProps(merged, [
|
|
69
|
+
'size',
|
|
70
|
+
'class',
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const size = () => sizeStyles[local.size!];
|
|
74
|
+
|
|
75
|
+
// Generate class based on render props
|
|
76
|
+
const getClassName = (renderProps: ToggleSwitchRenderProps): string => {
|
|
77
|
+
const base = 'inline-flex items-center gap-2 cursor-pointer';
|
|
78
|
+
const disabledClass = renderProps.isDisabled ? 'cursor-not-allowed opacity-50' : '';
|
|
79
|
+
const custom = local.class || '';
|
|
80
|
+
return [base, disabledClass, custom].filter(Boolean).join(' ');
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<HeadlessToggleSwitch
|
|
85
|
+
{...headlessProps}
|
|
86
|
+
class={getClassName}
|
|
87
|
+
>
|
|
88
|
+
{(renderProps: ToggleSwitchRenderProps) => (
|
|
89
|
+
<>
|
|
90
|
+
<span
|
|
91
|
+
class={[
|
|
92
|
+
'relative rounded-full transition-colors duration-200',
|
|
93
|
+
'focus-within:ring-2 focus-within:ring-accent-300 focus-within:ring-offset-2 focus-within:ring-offset-bg-400',
|
|
94
|
+
size().track,
|
|
95
|
+
renderProps.isSelected ? 'bg-accent' : 'bg-bg-300',
|
|
96
|
+
renderProps.isDisabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
97
|
+
].join(' ')}
|
|
98
|
+
>
|
|
99
|
+
<span
|
|
100
|
+
class={[
|
|
101
|
+
'absolute top-0.5 left-0.5 rounded-full bg-white shadow transition-transform duration-200',
|
|
102
|
+
size().thumb,
|
|
103
|
+
renderProps.isSelected ? size().translate : 'translate-x-0',
|
|
104
|
+
].join(' ')}
|
|
105
|
+
/>
|
|
106
|
+
</span>
|
|
107
|
+
{props.children && <span class="text-primary-200">{props.children}</span>}
|
|
108
|
+
</>
|
|
109
|
+
)}
|
|
110
|
+
</HeadlessToggleSwitch>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Switch components for proyecto-viviana-ui
|
|
3
|
+
*
|
|
4
|
+
* This file exports:
|
|
5
|
+
* - ToggleSwitch: The primary switch component built on solidaria-components
|
|
6
|
+
* (named to avoid conflict with SolidJS's built-in Switch)
|
|
7
|
+
* - TabSwitch: A custom two-option tab selector
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { type JSX, createSignal, createEffect } from 'solid-js'
|
|
11
|
+
|
|
12
|
+
// Re-export ToggleSwitch (the solidaria-components based switch)
|
|
13
|
+
export { ToggleSwitch, type ToggleSwitchProps, type SwitchSize } from './ToggleSwitch'
|
|
14
|
+
|
|
15
|
+
// ============================================
|
|
16
|
+
// TAB SWITCH (Two-option selector)
|
|
17
|
+
// ============================================
|
|
18
|
+
|
|
19
|
+
interface SwitchOption {
|
|
20
|
+
label: string
|
|
21
|
+
value: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface TabSwitchProps {
|
|
25
|
+
options: SwitchOption[]
|
|
26
|
+
value?: string
|
|
27
|
+
onChange?: (value: string) => void
|
|
28
|
+
class?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A tab-style switch that allows users to select between two options.
|
|
33
|
+
* This is a custom component, not based on solidaria/react-aria.
|
|
34
|
+
*/
|
|
35
|
+
export function TabSwitch(props: TabSwitchProps): JSX.Element {
|
|
36
|
+
const [leftSelected, setLeftSelected] = createSignal(
|
|
37
|
+
props.value ? props.value === props.options[0]?.value : true
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
createEffect(() => {
|
|
41
|
+
if (props.value !== undefined) {
|
|
42
|
+
setLeftSelected(props.value === props.options[0]?.value)
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const toggle = () => {
|
|
47
|
+
const newLeftSelected = !leftSelected()
|
|
48
|
+
setLeftSelected(newLeftSelected)
|
|
49
|
+
const newValue = newLeftSelected ? props.options[0]?.value : props.options[1]?.value
|
|
50
|
+
if (newValue) {
|
|
51
|
+
props.onChange?.(newValue)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const leftSelectedStyle = 'left-0 w-[142px] border-l-2'
|
|
56
|
+
const rightSelectedStyle = 'left-[142px] w-[108px] border-r-2'
|
|
57
|
+
const textSelected = 'font-extrabold text-primary-300'
|
|
58
|
+
const textUnselected = 'font-medium text-primary-600 tracking-wider'
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<div
|
|
62
|
+
onClick={toggle}
|
|
63
|
+
class={`relative bg-bg-400 rounded-full w-[250px] cursor-pointer ${props.class ?? ''}`}
|
|
64
|
+
>
|
|
65
|
+
<div
|
|
66
|
+
class={`${
|
|
67
|
+
leftSelected() ? leftSelectedStyle : rightSelectedStyle
|
|
68
|
+
} transition-all duration-500 ease-in-out z-0 absolute bg-primary-600 rounded-full h-8 border-accent-300`}
|
|
69
|
+
/>
|
|
70
|
+
<div class="flex z-10 h-8 justify-around">
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
class={`${
|
|
74
|
+
leftSelected() ? textSelected : textUnselected
|
|
75
|
+
} transition-all ease-in-out duration-500 z-10 text-lg flex justify-center items-center pointer-events-none`}
|
|
76
|
+
>
|
|
77
|
+
<span>{props.options[0]?.label ?? 'TENDENCIAS'}</span>
|
|
78
|
+
</button>
|
|
79
|
+
<button
|
|
80
|
+
type="button"
|
|
81
|
+
class={`${
|
|
82
|
+
leftSelected() ? textUnselected : textSelected
|
|
83
|
+
} transition-all ease-in-out duration-500 z-10 text-lg flex justify-center items-center pointer-events-none`}
|
|
84
|
+
>
|
|
85
|
+
<span>{props.options[1]?.label ?? 'ÚLTIMOS'}</span>
|
|
86
|
+
</button>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
)
|
|
90
|
+
}
|