brainzlab-ui 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/LICENSE +7 -17
- data/README.md +92 -14
- data/app/assets/stylesheets/brainzlab_ui/animations.css +11 -2
- data/app/assets/stylesheets/brainzlab_ui/base.css +3 -0
- data/app/assets/stylesheets/brainzlab_ui/components.css +504 -11
- data/app/assets/stylesheets/brainzlab_ui/dark-mode.css +317 -0
- data/app/assets/stylesheets/brainzlab_ui/tokens.css +170 -19
- data/app/assets/stylesheets/brainzlab_ui/utilities.css +319 -4
- data/lib/brainzlab/components/alert.rb +6 -6
- data/lib/brainzlab/components/avatar.rb +10 -9
- data/lib/brainzlab/components/badge.rb +7 -7
- data/lib/brainzlab/components/base.rb +2 -2
- data/lib/brainzlab/components/button.rb +8 -8
- data/lib/brainzlab/components/card.rb +6 -6
- data/lib/brainzlab/components/empty_state.rb +5 -11
- data/lib/brainzlab/components/input.rb +8 -8
- data/lib/brainzlab/components/modal.rb +10 -10
- data/lib/brainzlab/components/nav_item.rb +3 -3
- data/lib/brainzlab/components/stat_card.rb +7 -9
- data/lib/brainzlab/components/table.rb +2 -2
- data/lib/brainzlab/ui/engine.rb +4 -4
- data/lib/brainzlab/ui/version.rb +1 -1
- data/lib/brainzlab/ui.rb +15 -15
- data/lib/brainzlab-ui.rb +1 -1
- data/lib/brainzlab_ui.rb +1 -1
- metadata +3 -1
|
@@ -116,16 +116,24 @@
|
|
|
116
116
|
white-space: nowrap;
|
|
117
117
|
opacity: 0;
|
|
118
118
|
visibility: hidden;
|
|
119
|
-
transition: all
|
|
119
|
+
transition: all var(--duration-fast) var(--ease-out);
|
|
120
120
|
margin-bottom: 0.5rem;
|
|
121
121
|
z-index: 50;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
.tooltip:hover .tooltip-content
|
|
124
|
+
.tooltip:hover .tooltip-content,
|
|
125
|
+
.tooltip:focus-within .tooltip-content {
|
|
125
126
|
opacity: 1;
|
|
126
127
|
visibility: visible;
|
|
127
128
|
}
|
|
128
129
|
|
|
130
|
+
/* Tooltip focus indicator */
|
|
131
|
+
.tooltip:focus-visible {
|
|
132
|
+
outline: 2px solid var(--color-primary-500);
|
|
133
|
+
outline-offset: 2px;
|
|
134
|
+
border-radius: 2px;
|
|
135
|
+
}
|
|
136
|
+
|
|
129
137
|
/* ----------------------------------------
|
|
130
138
|
SKELETON LOADING
|
|
131
139
|
---------------------------------------- */
|
|
@@ -207,7 +215,7 @@
|
|
|
207
215
|
opacity: 0;
|
|
208
216
|
visibility: hidden;
|
|
209
217
|
transform: translateY(-8px);
|
|
210
|
-
transition: all
|
|
218
|
+
transition: all var(--duration-fast) var(--ease-out);
|
|
211
219
|
}
|
|
212
220
|
|
|
213
221
|
.dropdown.open .dropdown-menu,
|
|
@@ -224,7 +232,7 @@
|
|
|
224
232
|
padding: 0.625rem 1rem;
|
|
225
233
|
font-size: 0.875rem;
|
|
226
234
|
color: var(--color-ink-700);
|
|
227
|
-
transition: all
|
|
235
|
+
transition: all var(--duration-fast) var(--ease-out);
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
.dropdown-item:hover {
|
|
@@ -232,6 +240,13 @@
|
|
|
232
240
|
color: var(--color-ink-900);
|
|
233
241
|
}
|
|
234
242
|
|
|
243
|
+
.dropdown-item:focus-visible {
|
|
244
|
+
outline: 2px solid var(--color-primary-500);
|
|
245
|
+
outline-offset: -2px;
|
|
246
|
+
background: var(--color-cream-50);
|
|
247
|
+
color: var(--color-ink-900);
|
|
248
|
+
}
|
|
249
|
+
|
|
235
250
|
.dropdown-item:first-child { border-radius: 0.75rem 0.75rem 0 0; }
|
|
236
251
|
.dropdown-item:last-child { border-radius: 0 0 0.75rem 0.75rem; }
|
|
237
252
|
|
|
@@ -260,3 +275,303 @@
|
|
|
260
275
|
.text-warning { color: var(--color-warning-600); }
|
|
261
276
|
.text-info { color: var(--color-info-600); }
|
|
262
277
|
.text-muted { color: var(--color-ink-500); }
|
|
278
|
+
|
|
279
|
+
/* ----------------------------------------
|
|
280
|
+
TYPOGRAPHY SCALE
|
|
281
|
+
---------------------------------------- */
|
|
282
|
+
.text-xs { font-size: var(--text-xs); }
|
|
283
|
+
.text-sm { font-size: var(--text-sm); }
|
|
284
|
+
.text-base { font-size: var(--text-base); }
|
|
285
|
+
.text-lg { font-size: var(--text-lg); }
|
|
286
|
+
.text-xl { font-size: var(--text-xl); }
|
|
287
|
+
.text-2xl { font-size: var(--text-2xl); }
|
|
288
|
+
.text-3xl { font-size: var(--text-3xl); }
|
|
289
|
+
.text-4xl { font-size: var(--text-4xl); }
|
|
290
|
+
.text-5xl { font-size: var(--text-5xl); }
|
|
291
|
+
.text-6xl { font-size: var(--text-6xl); }
|
|
292
|
+
.text-7xl { font-size: var(--text-7xl); }
|
|
293
|
+
|
|
294
|
+
/* ----------------------------------------
|
|
295
|
+
LINE HEIGHTS
|
|
296
|
+
---------------------------------------- */
|
|
297
|
+
.leading-none { line-height: var(--leading-none); }
|
|
298
|
+
.leading-tight { line-height: var(--leading-tight); }
|
|
299
|
+
.leading-snug { line-height: var(--leading-snug); }
|
|
300
|
+
.leading-normal { line-height: var(--leading-normal); }
|
|
301
|
+
.leading-relaxed { line-height: var(--leading-relaxed); }
|
|
302
|
+
.leading-loose { line-height: var(--leading-loose); }
|
|
303
|
+
|
|
304
|
+
/* ----------------------------------------
|
|
305
|
+
LETTER SPACING
|
|
306
|
+
---------------------------------------- */
|
|
307
|
+
.tracking-tighter { letter-spacing: var(--tracking-tighter); }
|
|
308
|
+
.tracking-tight { letter-spacing: var(--tracking-tight); }
|
|
309
|
+
.tracking-normal { letter-spacing: var(--tracking-normal); }
|
|
310
|
+
.tracking-wide { letter-spacing: var(--tracking-wide); }
|
|
311
|
+
.tracking-wider { letter-spacing: var(--tracking-wider); }
|
|
312
|
+
|
|
313
|
+
/* ----------------------------------------
|
|
314
|
+
FONT WEIGHTS
|
|
315
|
+
---------------------------------------- */
|
|
316
|
+
.font-thin { font-weight: var(--font-thin); }
|
|
317
|
+
.font-light { font-weight: var(--font-light); }
|
|
318
|
+
.font-normal { font-weight: var(--font-normal); }
|
|
319
|
+
.font-medium { font-weight: var(--font-medium); }
|
|
320
|
+
.font-semibold { font-weight: var(--font-semibold); }
|
|
321
|
+
.font-bold { font-weight: var(--font-bold); }
|
|
322
|
+
.font-extrabold { font-weight: var(--font-extrabold); }
|
|
323
|
+
|
|
324
|
+
/* ----------------------------------------
|
|
325
|
+
FONT FAMILIES
|
|
326
|
+
---------------------------------------- */
|
|
327
|
+
.font-sans { font-family: var(--font-sans); }
|
|
328
|
+
.font-serif { font-family: var(--font-serif); }
|
|
329
|
+
.font-mono { font-family: var(--font-mono); }
|
|
330
|
+
|
|
331
|
+
/* ----------------------------------------
|
|
332
|
+
SCREEN READER UTILITIES
|
|
333
|
+
---------------------------------------- */
|
|
334
|
+
|
|
335
|
+
/* Visually hide content but keep it accessible to screen readers */
|
|
336
|
+
.sr-only {
|
|
337
|
+
position: absolute;
|
|
338
|
+
width: 1px;
|
|
339
|
+
height: 1px;
|
|
340
|
+
padding: 0;
|
|
341
|
+
margin: -1px;
|
|
342
|
+
overflow: hidden;
|
|
343
|
+
clip: rect(0, 0, 0, 0);
|
|
344
|
+
white-space: nowrap;
|
|
345
|
+
border-width: 0;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* Undo sr-only, making content visible again */
|
|
349
|
+
.not-sr-only {
|
|
350
|
+
position: static;
|
|
351
|
+
width: auto;
|
|
352
|
+
height: auto;
|
|
353
|
+
padding: 0;
|
|
354
|
+
margin: 0;
|
|
355
|
+
overflow: visible;
|
|
356
|
+
clip: auto;
|
|
357
|
+
white-space: normal;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/* Focusable sr-only - becomes visible when focused */
|
|
361
|
+
.sr-only-focusable:not(:focus):not(:focus-within) {
|
|
362
|
+
position: absolute;
|
|
363
|
+
width: 1px;
|
|
364
|
+
height: 1px;
|
|
365
|
+
padding: 0;
|
|
366
|
+
margin: -1px;
|
|
367
|
+
overflow: hidden;
|
|
368
|
+
clip: rect(0, 0, 0, 0);
|
|
369
|
+
white-space: nowrap;
|
|
370
|
+
border-width: 0;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/* ----------------------------------------
|
|
374
|
+
REDUCED MOTION
|
|
375
|
+
---------------------------------------- */
|
|
376
|
+
|
|
377
|
+
/* Respect user's motion preferences */
|
|
378
|
+
@media (prefers-reduced-motion: reduce) {
|
|
379
|
+
*,
|
|
380
|
+
*::before,
|
|
381
|
+
*::after {
|
|
382
|
+
animation-duration: 0.01ms !important;
|
|
383
|
+
animation-iteration-count: 1 !important;
|
|
384
|
+
transition-duration: 0.01ms !important;
|
|
385
|
+
scroll-behavior: auto !important;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* ----------------------------------------
|
|
390
|
+
HIGH CONTRAST MODE
|
|
391
|
+
---------------------------------------- */
|
|
392
|
+
|
|
393
|
+
/* Enhanced focus for high contrast mode */
|
|
394
|
+
@media (prefers-contrast: more) {
|
|
395
|
+
:focus-visible {
|
|
396
|
+
outline: 3px solid currentColor !important;
|
|
397
|
+
outline-offset: 3px !important;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.btn-primary,
|
|
401
|
+
.btn-secondary,
|
|
402
|
+
.btn-ghost,
|
|
403
|
+
.btn-danger {
|
|
404
|
+
border: 2px solid currentColor;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/* ----------------------------------------
|
|
409
|
+
FOCUS WITHIN UTILITIES
|
|
410
|
+
---------------------------------------- */
|
|
411
|
+
|
|
412
|
+
/* Show child elements when parent has focus within */
|
|
413
|
+
.focus-within-show:focus-within .focus-within-target {
|
|
414
|
+
opacity: 1;
|
|
415
|
+
visibility: visible;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* Hide by default, show on focus within */
|
|
419
|
+
.focus-within-target {
|
|
420
|
+
opacity: 0;
|
|
421
|
+
visibility: hidden;
|
|
422
|
+
transition: opacity var(--duration-fast) var(--ease-out), visibility var(--duration-fast) var(--ease-out);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* ----------------------------------------
|
|
426
|
+
KEYBOARD NAVIGATION UTILITIES
|
|
427
|
+
---------------------------------------- */
|
|
428
|
+
|
|
429
|
+
/* Visible focus indicator for keyboard users only */
|
|
430
|
+
.focus-visible-only:focus:not(:focus-visible) {
|
|
431
|
+
outline: none;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.focus-visible-only:focus-visible {
|
|
435
|
+
outline: 2px solid var(--color-primary-500);
|
|
436
|
+
outline-offset: 2px;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/* ----------------------------------------
|
|
440
|
+
TRANSITION UTILITIES
|
|
441
|
+
---------------------------------------- */
|
|
442
|
+
.transition-none { transition: none; }
|
|
443
|
+
.transition-all { transition: all var(--duration-normal) var(--ease-out); }
|
|
444
|
+
.transition-colors { transition: color var(--duration-fast) var(--ease-out), background-color var(--duration-fast) var(--ease-out), border-color var(--duration-fast) var(--ease-out); }
|
|
445
|
+
.transition-opacity { transition: opacity var(--duration-normal) var(--ease-out); }
|
|
446
|
+
.transition-transform { transition: transform var(--duration-normal) var(--ease-out-expo); }
|
|
447
|
+
.transition-shadow { transition: box-shadow var(--duration-normal) var(--ease-out); }
|
|
448
|
+
|
|
449
|
+
/* Duration modifiers */
|
|
450
|
+
.duration-fast { transition-duration: var(--duration-fast); }
|
|
451
|
+
.duration-normal { transition-duration: var(--duration-normal); }
|
|
452
|
+
.duration-slow { transition-duration: var(--duration-slow); }
|
|
453
|
+
.duration-slower { transition-duration: var(--duration-slower); }
|
|
454
|
+
|
|
455
|
+
/* Easing modifiers */
|
|
456
|
+
.ease-linear { transition-timing-function: var(--ease-linear); }
|
|
457
|
+
.ease-in { transition-timing-function: var(--ease-in); }
|
|
458
|
+
.ease-out { transition-timing-function: var(--ease-out); }
|
|
459
|
+
.ease-in-out { transition-timing-function: var(--ease-in-out); }
|
|
460
|
+
.ease-bounce { transition-timing-function: var(--ease-bounce); }
|
|
461
|
+
|
|
462
|
+
/* ============================================
|
|
463
|
+
DARK MODE UTILITY VARIANTS
|
|
464
|
+
============================================ */
|
|
465
|
+
|
|
466
|
+
/* ----------------------------------------
|
|
467
|
+
DARK MODE - FOCUS RING
|
|
468
|
+
---------------------------------------- */
|
|
469
|
+
.dark .focus-ring:focus-visible {
|
|
470
|
+
outline-color: var(--color-primary-400);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/* ----------------------------------------
|
|
474
|
+
DARK MODE - GRADIENTS
|
|
475
|
+
---------------------------------------- */
|
|
476
|
+
.dark .bg-gradient-warm {
|
|
477
|
+
background: linear-gradient(135deg, var(--color-dark-surface) 0%, var(--color-dark-surface-light) 100%);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.dark .gradient-blob {
|
|
481
|
+
opacity: 0.3;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/* ----------------------------------------
|
|
485
|
+
DARK MODE - TERMINAL (already dark-themed)
|
|
486
|
+
---------------------------------------- */
|
|
487
|
+
.dark .terminal {
|
|
488
|
+
border: 1px solid var(--color-dark-border);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/* ----------------------------------------
|
|
492
|
+
DARK MODE - TOOLTIPS
|
|
493
|
+
---------------------------------------- */
|
|
494
|
+
.dark .tooltip-content {
|
|
495
|
+
background: var(--color-dark-surface-light);
|
|
496
|
+
color: var(--color-dark-text);
|
|
497
|
+
border: 1px solid var(--color-dark-border);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.dark .tooltip:focus-visible {
|
|
501
|
+
outline-color: var(--color-primary-400);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
/* ----------------------------------------
|
|
505
|
+
DARK MODE - SKELETON LOADING
|
|
506
|
+
---------------------------------------- */
|
|
507
|
+
.dark .skeleton {
|
|
508
|
+
background: linear-gradient(90deg, var(--color-dark-surface) 25%, var(--color-dark-surface-light) 50%, var(--color-dark-surface) 75%);
|
|
509
|
+
background-size: 200% 100%;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/* ----------------------------------------
|
|
513
|
+
DARK MODE - MODAL OVERLAY
|
|
514
|
+
---------------------------------------- */
|
|
515
|
+
.dark .modal-overlay {
|
|
516
|
+
background: rgba(0, 0, 0, 0.7);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.dark .modal {
|
|
520
|
+
background: var(--color-dark-surface);
|
|
521
|
+
box-shadow: var(--shadow-dark-large);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.dark .modal-header {
|
|
525
|
+
border-bottom-color: var(--color-dark-border);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.dark .modal-footer {
|
|
529
|
+
border-top-color: var(--color-dark-border);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* ----------------------------------------
|
|
533
|
+
DARK MODE - DROPDOWN
|
|
534
|
+
---------------------------------------- */
|
|
535
|
+
.dark .dropdown-menu {
|
|
536
|
+
background: var(--color-dark-surface);
|
|
537
|
+
border-color: var(--color-dark-border);
|
|
538
|
+
box-shadow: var(--shadow-dark-medium);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.dark .dropdown-item {
|
|
542
|
+
color: var(--color-dark-text-muted);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.dark .dropdown-item:hover {
|
|
546
|
+
background: var(--color-dark-surface-light);
|
|
547
|
+
color: var(--color-dark-text);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.dark .dropdown-item:focus-visible {
|
|
551
|
+
outline-color: var(--color-primary-400);
|
|
552
|
+
background: var(--color-dark-surface-light);
|
|
553
|
+
color: var(--color-dark-text);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.dark .dropdown-divider {
|
|
557
|
+
background: var(--color-dark-border);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/* ----------------------------------------
|
|
561
|
+
DARK MODE - TEXT UTILITIES
|
|
562
|
+
---------------------------------------- */
|
|
563
|
+
.dark .text-primary { color: var(--color-primary-300); }
|
|
564
|
+
.dark .text-success { color: var(--color-success-400); }
|
|
565
|
+
.dark .text-error { color: var(--color-error-400); }
|
|
566
|
+
.dark .text-warning { color: var(--color-warning-400); }
|
|
567
|
+
.dark .text-info { color: var(--color-info-400); }
|
|
568
|
+
.dark .text-muted { color: var(--color-dark-text-muted); }
|
|
569
|
+
|
|
570
|
+
/* ----------------------------------------
|
|
571
|
+
DARK MODE - HIGH CONTRAST
|
|
572
|
+
---------------------------------------- */
|
|
573
|
+
@media (prefers-contrast: more) {
|
|
574
|
+
.dark :focus-visible {
|
|
575
|
+
outline-color: var(--color-cream-200) !important;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
@@ -4,10 +4,10 @@ module Brainzlab
|
|
|
4
4
|
module Components
|
|
5
5
|
class Alert < Base
|
|
6
6
|
TYPES = {
|
|
7
|
-
success:
|
|
8
|
-
error:
|
|
9
|
-
warning:
|
|
10
|
-
info:
|
|
7
|
+
success: 'alert-success',
|
|
8
|
+
error: 'alert-error',
|
|
9
|
+
warning: 'alert-warning',
|
|
10
|
+
info: 'alert-info'
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
13
|
def initialize(type: :info, **attrs)
|
|
@@ -16,13 +16,13 @@ module Brainzlab
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def view_template(&)
|
|
19
|
-
div(class: alert_classes, role:
|
|
19
|
+
div(class: alert_classes, role: 'alert', **@attrs, &)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def alert_classes
|
|
25
|
-
classes(
|
|
25
|
+
classes('alert', TYPES[@type], @attrs[:class])
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
@@ -4,15 +4,15 @@ module Brainzlab
|
|
|
4
4
|
module Components
|
|
5
5
|
class Avatar < Base
|
|
6
6
|
SIZES = {
|
|
7
|
-
sm:
|
|
8
|
-
md:
|
|
9
|
-
lg:
|
|
10
|
-
xl:
|
|
7
|
+
sm: 'avatar-sm',
|
|
8
|
+
md: 'avatar-md',
|
|
9
|
+
lg: 'avatar-lg',
|
|
10
|
+
xl: 'avatar-xl'
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
13
|
VARIANTS = {
|
|
14
|
-
primary:
|
|
15
|
-
neutral:
|
|
14
|
+
primary: 'avatar-primary',
|
|
15
|
+
neutral: 'avatar-neutral'
|
|
16
16
|
}.freeze
|
|
17
17
|
|
|
18
18
|
def initialize(name: nil, src: nil, size: :md, variant: :primary, **attrs)
|
|
@@ -27,7 +27,7 @@ module Brainzlab
|
|
|
27
27
|
if @src
|
|
28
28
|
img(
|
|
29
29
|
src: @src,
|
|
30
|
-
alt: @name ||
|
|
30
|
+
alt: @name || 'Avatar',
|
|
31
31
|
class: avatar_classes
|
|
32
32
|
)
|
|
33
33
|
else
|
|
@@ -40,11 +40,12 @@ module Brainzlab
|
|
|
40
40
|
private
|
|
41
41
|
|
|
42
42
|
def avatar_classes
|
|
43
|
-
classes(
|
|
43
|
+
classes('avatar', SIZES[@size], VARIANTS[@variant], @attrs[:class])
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def initials
|
|
47
|
-
return
|
|
47
|
+
return '' unless @name
|
|
48
|
+
|
|
48
49
|
@name.split.map { |part| part[0] }.take(2).join.upcase
|
|
49
50
|
end
|
|
50
51
|
end
|
|
@@ -4,12 +4,12 @@ module Brainzlab
|
|
|
4
4
|
module Components
|
|
5
5
|
class Badge < Base
|
|
6
6
|
VARIANTS = {
|
|
7
|
-
primary:
|
|
8
|
-
success:
|
|
9
|
-
error:
|
|
10
|
-
warning:
|
|
11
|
-
info:
|
|
12
|
-
neutral:
|
|
7
|
+
primary: 'badge-primary',
|
|
8
|
+
success: 'badge-success',
|
|
9
|
+
error: 'badge-error',
|
|
10
|
+
warning: 'badge-warning',
|
|
11
|
+
info: 'badge-info',
|
|
12
|
+
neutral: 'badge-neutral'
|
|
13
13
|
}.freeze
|
|
14
14
|
|
|
15
15
|
def initialize(variant: :neutral, **attrs)
|
|
@@ -24,7 +24,7 @@ module Brainzlab
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def badge_classes
|
|
27
|
-
classes(
|
|
27
|
+
classes('badge', VARIANTS[@variant], @attrs[:class])
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require 'phlex'
|
|
4
4
|
|
|
5
5
|
module Brainzlab
|
|
6
6
|
module Components
|
|
@@ -8,7 +8,7 @@ module Brainzlab
|
|
|
8
8
|
include Phlex::Rails::Helpers::Routes if defined?(Phlex::Rails::Helpers::Routes)
|
|
9
9
|
|
|
10
10
|
def classes(*args)
|
|
11
|
-
args.flatten.compact.join(
|
|
11
|
+
args.flatten.compact.join(' ')
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
end
|
|
@@ -4,19 +4,19 @@ module Brainzlab
|
|
|
4
4
|
module Components
|
|
5
5
|
class Button < Base
|
|
6
6
|
VARIANTS = {
|
|
7
|
-
primary:
|
|
8
|
-
secondary:
|
|
9
|
-
ghost:
|
|
10
|
-
danger:
|
|
7
|
+
primary: 'btn-primary',
|
|
8
|
+
secondary: 'btn-secondary',
|
|
9
|
+
ghost: 'btn-ghost',
|
|
10
|
+
danger: 'btn-danger'
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
13
|
SIZES = {
|
|
14
|
-
sm:
|
|
14
|
+
sm: 'btn-sm',
|
|
15
15
|
md: nil,
|
|
16
|
-
lg:
|
|
16
|
+
lg: 'btn-lg'
|
|
17
17
|
}.freeze
|
|
18
18
|
|
|
19
|
-
def initialize(variant: :primary, size: :md, lift: false, disabled: false, type:
|
|
19
|
+
def initialize(variant: :primary, size: :md, lift: false, disabled: false, type: 'button', **attrs)
|
|
20
20
|
@variant = variant
|
|
21
21
|
@size = size
|
|
22
22
|
@lift = lift
|
|
@@ -41,7 +41,7 @@ module Brainzlab
|
|
|
41
41
|
classes(
|
|
42
42
|
VARIANTS[@variant],
|
|
43
43
|
SIZES[@size],
|
|
44
|
-
@lift ?
|
|
44
|
+
@lift ? 'btn-lift' : nil,
|
|
45
45
|
@attrs[:class]
|
|
46
46
|
)
|
|
47
47
|
end
|
|
@@ -17,9 +17,9 @@ module Brainzlab
|
|
|
17
17
|
|
|
18
18
|
def card_classes
|
|
19
19
|
classes(
|
|
20
|
-
|
|
21
|
-
@interactive ?
|
|
22
|
-
@lift ?
|
|
20
|
+
'card',
|
|
21
|
+
@interactive ? 'card-interactive' : nil,
|
|
22
|
+
@lift ? 'card-lift' : nil,
|
|
23
23
|
@attrs[:class]
|
|
24
24
|
)
|
|
25
25
|
end
|
|
@@ -31,7 +31,7 @@ module Brainzlab
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def view_template(&)
|
|
34
|
-
div(class: classes(
|
|
34
|
+
div(class: classes('card-header', @attrs[:class]), **@attrs.except(:class), &)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -41,7 +41,7 @@ module Brainzlab
|
|
|
41
41
|
end
|
|
42
42
|
|
|
43
43
|
def view_template(&)
|
|
44
|
-
div(class: classes(
|
|
44
|
+
div(class: classes('card-body', @attrs[:class]), **@attrs.except(:class), &)
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -51,7 +51,7 @@ module Brainzlab
|
|
|
51
51
|
end
|
|
52
52
|
|
|
53
53
|
def view_template(&)
|
|
54
|
-
div(class: classes(
|
|
54
|
+
div(class: classes('card-footer', @attrs[:class]), **@attrs.except(:class), &)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
57
57
|
end
|
|
@@ -11,20 +11,14 @@ module Brainzlab
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def view_template(&)
|
|
14
|
-
div(class: classes(
|
|
15
|
-
if @icon
|
|
16
|
-
div(class: "empty-state-icon") { @icon }
|
|
17
|
-
end
|
|
14
|
+
div(class: classes('empty-state', @attrs[:class]), **@attrs.except(:class)) do
|
|
15
|
+
div(class: 'empty-state-icon') { @icon } if @icon
|
|
18
16
|
|
|
19
|
-
h3(class:
|
|
17
|
+
h3(class: 'empty-state-title') { @title }
|
|
20
18
|
|
|
21
|
-
if @description
|
|
22
|
-
p(class: "empty-state-description") { @description }
|
|
23
|
-
end
|
|
19
|
+
p(class: 'empty-state-description') { @description } if @description
|
|
24
20
|
|
|
25
|
-
if block_given?
|
|
26
|
-
div(class: "mt-4") { yield }
|
|
27
|
-
end
|
|
21
|
+
div(class: 'mt-4', &) if block_given?
|
|
28
22
|
end
|
|
29
23
|
end
|
|
30
24
|
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Brainzlab
|
|
4
4
|
module Components
|
|
5
5
|
class Input < Base
|
|
6
|
-
def initialize(type:
|
|
6
|
+
def initialize(type: 'text', error: false, **attrs)
|
|
7
7
|
@type = type
|
|
8
8
|
@error = error
|
|
9
9
|
@attrs = attrs
|
|
@@ -21,8 +21,8 @@ module Brainzlab
|
|
|
21
21
|
|
|
22
22
|
def input_classes
|
|
23
23
|
classes(
|
|
24
|
-
|
|
25
|
-
@error ?
|
|
24
|
+
'input',
|
|
25
|
+
@error ? 'input-error' : nil,
|
|
26
26
|
@attrs[:class]
|
|
27
27
|
)
|
|
28
28
|
end
|
|
@@ -37,7 +37,7 @@ module Brainzlab
|
|
|
37
37
|
def view_template(&)
|
|
38
38
|
label(
|
|
39
39
|
for: @for_input,
|
|
40
|
-
class: classes(
|
|
40
|
+
class: classes('label', @attrs[:class]),
|
|
41
41
|
**@attrs.except(:class),
|
|
42
42
|
&
|
|
43
43
|
)
|
|
@@ -62,8 +62,8 @@ module Brainzlab
|
|
|
62
62
|
|
|
63
63
|
def select_classes
|
|
64
64
|
classes(
|
|
65
|
-
|
|
66
|
-
@error ?
|
|
65
|
+
'select',
|
|
66
|
+
@error ? 'input-error' : nil,
|
|
67
67
|
@attrs[:class]
|
|
68
68
|
)
|
|
69
69
|
end
|
|
@@ -87,8 +87,8 @@ module Brainzlab
|
|
|
87
87
|
|
|
88
88
|
def textarea_classes
|
|
89
89
|
classes(
|
|
90
|
-
|
|
91
|
-
@error ?
|
|
90
|
+
'textarea',
|
|
91
|
+
@error ? 'input-error' : nil,
|
|
92
92
|
@attrs[:class]
|
|
93
93
|
)
|
|
94
94
|
end
|
|
@@ -4,10 +4,10 @@ module Brainzlab
|
|
|
4
4
|
module Components
|
|
5
5
|
class Modal < Base
|
|
6
6
|
SIZES = {
|
|
7
|
-
sm:
|
|
8
|
-
md:
|
|
9
|
-
lg:
|
|
10
|
-
xl:
|
|
7
|
+
sm: 'modal-sm',
|
|
8
|
+
md: 'modal-md',
|
|
9
|
+
lg: 'modal-lg',
|
|
10
|
+
xl: 'modal-xl'
|
|
11
11
|
}.freeze
|
|
12
12
|
|
|
13
13
|
def initialize(size: :md, **attrs)
|
|
@@ -16,14 +16,14 @@ module Brainzlab
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def view_template(&)
|
|
19
|
-
div(class:
|
|
20
|
-
div(class: modal_classes, role:
|
|
19
|
+
div(class: 'modal-overlay', data: { modal_target: 'overlay' })
|
|
20
|
+
div(class: modal_classes, role: 'dialog', **@attrs, &)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
25
|
def modal_classes
|
|
26
|
-
classes(
|
|
26
|
+
classes('modal', SIZES[@size], @attrs[:class])
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
@@ -33,7 +33,7 @@ module Brainzlab
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def view_template(&)
|
|
36
|
-
div(class: classes(
|
|
36
|
+
div(class: classes('modal-header', @attrs[:class]), **@attrs.except(:class), &)
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
@@ -43,7 +43,7 @@ module Brainzlab
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def view_template(&)
|
|
46
|
-
div(class: classes(
|
|
46
|
+
div(class: classes('modal-body', @attrs[:class]), **@attrs.except(:class), &)
|
|
47
47
|
end
|
|
48
48
|
end
|
|
49
49
|
|
|
@@ -53,7 +53,7 @@ module Brainzlab
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def view_template(&)
|
|
56
|
-
div(class: classes(
|
|
56
|
+
div(class: classes('modal-footer', @attrs[:class]), **@attrs.except(:class), &)
|
|
57
57
|
end
|
|
58
58
|
end
|
|
59
59
|
end
|