@protolabsai/ui 0.6.0 → 0.8.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/src/styles.css CHANGED
@@ -1,1322 +1,12 @@
1
- /* @protolabsai/ui — component styles, built entirely on @protolabsai/design
2
- * tokens (the --pl-* custom properties). Import once at your app root:
3
- * import "@protolabsai/ui/styles.css";
4
- * Requires @protolabsai/design/css to be imported too (for the tokens). */
5
-
6
- .pl-btn {
7
- display: inline-flex;
8
- align-items: center;
9
- gap: 0.4rem;
10
- padding: 0.5rem 0.9rem;
11
- font-family: var(--pl-font-sans);
12
- font-size: 13px;
13
- font-weight: 400;
14
- color: var(--pl-color-fg);
15
- background: transparent;
16
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
17
- border-radius: var(--pl-radius);
18
- cursor: pointer;
19
- text-decoration: none;
20
- transition:
21
- border-color var(--pl-motion-fast) var(--pl-motion-ease),
22
- color var(--pl-motion-fast) var(--pl-motion-ease),
23
- background var(--pl-motion-fast) var(--pl-motion-ease);
24
- }
25
- .pl-btn:hover {
26
- border-color: var(--pl-color-fg);
27
- }
28
- /* Primary ships as a stronger border, not a lavender fill — brand restraint. */
29
- .pl-btn--primary {
30
- border-color: var(--pl-color-fg);
31
- }
32
- .pl-btn--primary:hover {
33
- background: var(--pl-color-fg);
34
- color: var(--pl-color-bg);
35
- }
36
- .pl-btn:disabled {
37
- opacity: 0.5;
38
- cursor: not-allowed;
39
- }
40
-
41
- .pl-badge {
42
- display: inline-flex;
43
- align-items: center;
44
- gap: 0.35rem;
45
- padding: 0.15rem 0.5rem;
46
- font-family: var(--pl-font-mono);
47
- font-size: 11px;
48
- line-height: 1.4;
49
- text-transform: lowercase;
50
- letter-spacing: 0.02em;
51
- color: var(--pl-color-fg-muted);
52
- background: var(--pl-color-bg-raised);
53
- border: var(--pl-border-width) solid var(--pl-color-border);
54
- border-radius: var(--pl-radius);
55
- }
56
- .pl-badge--success {
57
- color: var(--pl-color-status-success);
58
- border-color: color-mix(in oklch, var(--pl-color-status-success) 35%, transparent);
59
- }
60
- .pl-badge--warning {
61
- color: var(--pl-color-status-warning);
62
- border-color: color-mix(in oklch, var(--pl-color-status-warning) 35%, transparent);
63
- }
64
- .pl-badge--error {
65
- color: var(--pl-color-status-error);
66
- border-color: color-mix(in oklch, var(--pl-color-status-error) 35%, transparent);
67
- }
68
- .pl-badge--info {
69
- color: var(--pl-color-status-info);
70
- border-color: color-mix(in oklch, var(--pl-color-status-info) 35%, transparent);
71
- }
72
-
73
- .pl-card {
74
- background: var(--pl-color-bg-raised);
75
- border: var(--pl-border-width) solid var(--pl-color-border);
76
- border-radius: var(--pl-radius);
77
- padding: var(--pl-space-4);
78
- }
79
-
80
- .pl-eyebrow {
81
- font-family: var(--pl-font-mono);
82
- font-size: 11px;
83
- font-weight: var(--pl-font-weight-medium);
84
- text-transform: uppercase;
85
- letter-spacing: 0.08em;
86
- color: var(--pl-color-fg-muted);
87
- }
88
-
89
- .pl-stat__num {
90
- font-family: var(--pl-font-mono);
91
- font-size: 1.1rem;
92
- color: var(--pl-color-fg);
93
- }
94
- .pl-stat__label {
95
- margin-top: 0.15rem;
96
- font-size: 12px;
97
- color: var(--pl-color-fg-muted);
98
- }
99
-
100
- /* ── layout ── */
101
- .pl-container {
102
- max-width: 880px;
103
- margin: 0 auto;
104
- padding: 0 1.5rem;
105
- }
106
- .pl-section {
107
- padding: 4rem 0;
108
- }
109
-
110
- /* ── stats grid (wraps Stat) ── */
111
- .pl-stats {
112
- display: grid;
113
- grid-template-columns: repeat(2, 1fr);
114
- gap: 1.5rem 2rem;
115
- padding: 1.5rem 0;
116
- border-top: var(--pl-border-width) solid var(--pl-color-border);
117
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
118
- }
119
- @media (min-width: 640px) {
120
- .pl-stats {
121
- grid-template-columns: repeat(4, 1fr);
122
- }
123
- }
124
-
125
- /* ── row (label | body [| status]) ── */
126
- .pl-row {
127
- display: grid;
128
- grid-template-columns: 9rem 1fr;
129
- gap: 1.25rem;
130
- padding: 1rem 0;
131
- border-top: var(--pl-border-width) solid var(--pl-color-border);
132
- text-decoration: none;
133
- color: var(--pl-color-fg);
134
- transition: opacity var(--pl-motion-fast) var(--pl-motion-ease);
135
- }
136
- .pl-row:last-of-type {
137
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
138
- }
139
- a.pl-row:hover {
140
- opacity: 0.7;
141
- }
142
- .pl-row--wide {
143
- grid-template-columns: 9rem 1fr auto;
144
- }
145
- .pl-row__label {
146
- font-family: var(--pl-font-mono);
147
- font-size: 12px;
148
- color: var(--pl-color-fg-muted);
149
- }
150
- .pl-row__name {
151
- font-family: var(--pl-font-mono);
152
- font-size: 13px;
153
- color: var(--pl-color-fg);
154
- margin-bottom: 0.25rem;
155
- }
156
- .pl-row__desc {
157
- font-size: 13px;
158
- line-height: 1.5;
159
- color: var(--pl-color-fg-muted);
160
- }
161
- .pl-row__status {
162
- font-family: var(--pl-font-mono);
163
- font-size: 11px;
164
- text-transform: lowercase;
165
- color: var(--pl-color-fg-muted);
166
- }
167
- @media (max-width: 640px) {
168
- .pl-row,
169
- .pl-row--wide {
170
- grid-template-columns: 1fr;
171
- gap: 0.25rem;
172
- }
173
- }
174
-
175
- /* ── gradient text (the one gradient — tagline word only) ── */
176
- .pl-gradient-text {
177
- background: var(--pl-gradient-brand);
178
- -webkit-background-clip: text;
179
- -webkit-text-fill-color: transparent;
180
- background-clip: text;
181
- font-weight: 700;
182
- letter-spacing: -0.02em;
183
- }
184
-
185
- /* ── hero ── */
186
- .pl-hero {
187
- display: block;
188
- padding: 5rem 0 3rem;
189
- }
190
- .pl-hero h1 {
191
- margin: 0 0 1.25rem;
192
- font-size: clamp(2rem, 4vw, 2.75rem);
193
- font-weight: 500;
194
- line-height: 1.2;
195
- letter-spacing: -0.025em;
196
- }
197
- .pl-hero__cta {
198
- display: flex;
199
- gap: 0.75rem;
200
- flex-wrap: wrap;
201
- }
202
-
203
- /* ── lead + section heading/intro ── */
204
- .pl-lead {
205
- margin: 0 0 1.5rem;
206
- font-size: 1.05rem;
207
- line-height: 1.6;
208
- color: var(--pl-color-fg-muted);
209
- max-width: 60ch;
210
- }
211
- .pl-heading {
212
- margin: 0 0 1rem;
213
- font-size: 1.4rem;
214
- font-weight: 500;
215
- line-height: 1.2;
216
- letter-spacing: -0.01em;
217
- color: var(--pl-color-fg);
218
- }
219
- .pl-section-intro {
220
- margin: 0 0 2rem;
221
- color: var(--pl-color-fg-muted);
222
- max-width: 60ch;
223
- line-height: 1.6;
224
- }
225
-
226
- /* ── steps (numbered process) ── */
227
- .pl-steps {
228
- display: grid;
229
- gap: 1.5rem;
230
- }
231
- .pl-step {
232
- display: grid;
233
- grid-template-columns: 2rem 1fr;
234
- gap: 0.5rem;
235
- align-items: baseline;
236
- }
237
- .pl-step__num {
238
- font-family: var(--pl-font-mono);
239
- font-size: 13px;
240
- color: var(--pl-color-fg-muted);
241
- }
242
- .pl-step__title {
243
- font-family: var(--pl-font-mono);
244
- font-size: 13px;
245
- margin-bottom: 0.4rem;
246
- color: var(--pl-color-fg);
247
- }
248
- .pl-step__body {
249
- color: var(--pl-color-fg-muted);
250
- font-size: 14px;
251
- line-height: 1.55;
252
- }
253
-
254
- /* ── checks (checklist) ── */
255
- .pl-checks {
256
- display: grid;
257
- gap: 0.5rem;
258
- }
259
- .pl-check {
260
- display: grid;
261
- grid-template-columns: 1.2rem 1fr;
262
- gap: 0.5rem;
263
- align-items: baseline;
264
- font-size: 14px;
265
- color: var(--pl-color-fg-muted);
266
- }
267
- .pl-check__mark {
268
- color: var(--pl-color-fg);
269
- font-family: var(--pl-font-mono);
270
- }
271
- .pl-check strong {
272
- color: var(--pl-color-fg);
273
- font-weight: 500;
274
- }
275
-
276
- /* ── deliverables (two-col, left-border cards) ── */
277
- .pl-deliverables {
278
- display: grid;
279
- gap: 1.5rem;
280
- }
281
- @media (min-width: 640px) {
282
- .pl-deliverables {
283
- grid-template-columns: 1fr 1fr;
284
- }
285
- }
286
- .pl-deliverable {
287
- border-left: var(--pl-border-width) solid var(--pl-color-border-strong);
288
- padding-left: 1rem;
289
- }
290
- .pl-deliverable__title {
291
- font-family: var(--pl-font-mono);
292
- font-size: 13px;
293
- margin-bottom: 0.4rem;
294
- color: var(--pl-color-fg);
295
- }
296
- .pl-deliverable__body {
297
- color: var(--pl-color-fg-muted);
298
- font-size: 14px;
299
- line-height: 1.55;
300
- }
301
-
302
- /* ── post list (blog index) ── */
303
- .pl-post-list {
304
- display: grid;
305
- gap: 0;
306
- }
307
- .pl-post-item {
308
- display: block;
309
- padding: 1.25rem 0;
310
- border-top: var(--pl-border-width) solid var(--pl-color-border);
311
- text-decoration: none;
312
- color: var(--pl-color-fg);
313
- transition: opacity var(--pl-motion-fast) var(--pl-motion-ease);
314
- }
315
- .pl-post-item:last-of-type {
316
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
317
- }
318
- .pl-post-item:hover {
319
- opacity: 0.7;
320
- }
321
- .pl-post-item__meta {
322
- font-family: var(--pl-font-mono);
323
- font-size: 11px;
324
- color: var(--pl-color-fg-muted);
325
- text-transform: uppercase;
326
- letter-spacing: 0.05em;
327
- margin-bottom: 0.4rem;
328
- }
329
- .pl-post-item__title {
330
- font-size: 1.05rem;
331
- font-weight: 500;
332
- margin-bottom: 0.4rem;
333
- }
334
- .pl-post-item__excerpt {
335
- color: var(--pl-color-fg-muted);
336
- font-size: 14px;
337
- line-height: 1.55;
338
- }
339
-
340
- /* ── empty state ── */
341
- .pl-empty {
342
- color: var(--pl-color-fg-muted);
343
- font-family: var(--pl-font-mono);
344
- font-size: 13px;
345
- padding: 1rem 0;
346
- }
347
-
348
- /* ── prose (long-form rich text) ── */
349
- .pl-prose {
350
- font-size: 1rem;
351
- line-height: 1.7;
352
- color: var(--pl-color-fg);
353
- }
354
- .pl-prose h2 {
355
- font-size: 1.3rem;
356
- margin-top: 2rem;
357
- margin-bottom: 0.75rem;
358
- }
359
- .pl-prose h3 {
360
- font-size: 1.1rem;
361
- margin-top: 1.5rem;
362
- margin-bottom: 0.5rem;
363
- }
364
- .pl-prose p {
365
- margin: 1rem 0;
366
- }
367
- .pl-prose ul,
368
- .pl-prose ol {
369
- margin: 1rem 0;
370
- padding-left: 1.25rem;
371
- }
372
- .pl-prose li {
373
- margin: 0.3rem 0;
374
- }
375
- .pl-prose code {
376
- background: var(--pl-color-bg-raised);
377
- padding: 0.1rem 0.35rem;
378
- border-radius: var(--pl-radius);
379
- color: var(--pl-color-fg);
380
- font-size: 0.88em;
381
- }
382
- .pl-prose pre {
383
- background: var(--pl-color-bg-raised);
384
- border: var(--pl-border-width) solid var(--pl-color-border);
385
- padding: 1rem;
386
- border-radius: var(--pl-radius);
387
- overflow-x: auto;
388
- margin: 1rem 0;
389
- }
390
- .pl-prose pre code {
391
- background: transparent;
392
- padding: 0;
393
- }
394
- .pl-prose blockquote {
395
- border-left: 2px solid var(--pl-color-border-strong);
396
- padding-left: 1rem;
397
- margin: 1.5rem 0;
398
- color: var(--pl-color-fg-muted);
399
- }
400
-
401
- /* ── divider ── */
402
- .pl-divider {
403
- border: 0;
404
- border-top: var(--pl-border-width) solid var(--pl-color-border);
405
- margin: 2rem 0;
406
- }
407
-
408
- /* ── callout (note block) ── */
409
- .pl-callout {
410
- background: var(--pl-color-bg-raised);
411
- border: var(--pl-border-width) solid var(--pl-color-border);
412
- border-left-width: 2px;
413
- border-radius: var(--pl-radius);
414
- padding: 0.85rem 1rem;
415
- }
416
- .pl-callout__title {
417
- font-family: var(--pl-font-mono);
418
- font-size: 12px;
419
- text-transform: lowercase;
420
- letter-spacing: 0.02em;
421
- color: var(--pl-color-fg);
422
- margin-bottom: 0.35rem;
423
- }
424
- .pl-callout__body {
425
- font-size: 14px;
426
- line-height: 1.6;
427
- color: var(--pl-color-fg-muted);
428
- }
429
- .pl-callout--success {
430
- border-left-color: var(--pl-color-status-success);
431
- }
432
- .pl-callout--warning {
433
- border-left-color: var(--pl-color-status-warning);
434
- }
435
- .pl-callout--error {
436
- border-left-color: var(--pl-color-status-error);
437
- }
438
- .pl-callout--info {
439
- border-left-color: var(--pl-color-status-info);
440
- }
441
-
442
- /* ── kbd / inline token ── */
443
- .pl-kbd {
444
- font-family: var(--pl-font-mono);
445
- font-size: 0.82em;
446
- padding: 0.1rem 0.4rem;
447
- color: var(--pl-color-fg);
448
- background: var(--pl-color-bg-raised);
449
- border: var(--pl-border-width) solid var(--pl-color-border);
450
- border-bottom-width: 2px;
451
- border-radius: var(--pl-radius);
452
- }
453
-
454
- /* ── standalone link ── */
455
- .pl-link {
456
- color: inherit;
457
- text-decoration: underline;
458
- text-underline-offset: 3px;
459
- text-decoration-color: var(--pl-color-border-strong);
460
- transition:
461
- text-decoration-color var(--pl-motion-fast) var(--pl-motion-ease),
462
- color var(--pl-motion-fast) var(--pl-motion-ease);
463
- }
464
- .pl-link:hover {
465
- text-decoration-color: var(--pl-color-fg);
466
- }
467
-
468
- /* ── Tabs ──────────────────────────────────────────────────────────────────── */
469
- .pl-tabs {
470
- display: flex;
471
- gap: 2px;
472
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
473
- }
474
- .pl-tab {
475
- display: inline-flex;
476
- align-items: center;
477
- gap: 6px;
478
- background: none;
479
- border: none;
480
- border-bottom: 2px solid transparent;
481
- color: var(--pl-color-fg-muted);
482
- font: inherit;
483
- font-family: var(--pl-font-sans);
484
- padding: 8px 14px;
485
- cursor: pointer;
486
- border-radius: var(--pl-radius) var(--pl-radius) 0 0;
487
- }
488
- .pl-tab__icon {
489
- display: inline-flex;
490
- align-items: center;
491
- }
492
- .pl-tab__icon svg {
493
- width: 15px;
494
- height: 15px;
495
- }
496
- .pl-tab__badge {
497
- display: inline-flex;
498
- align-items: center;
499
- justify-content: center;
500
- min-width: 16px;
501
- height: 16px;
502
- padding: 0 5px;
503
- font-family: var(--pl-font-mono);
504
- font-size: 10px;
505
- line-height: 1;
506
- color: var(--pl-color-fg-muted);
507
- background: var(--pl-color-bg-subtle);
508
- border: var(--pl-border-width) solid var(--pl-color-border);
509
- border-radius: 999px;
510
- }
511
- .pl-tab--active .pl-tab__badge {
512
- color: var(--pl-color-fg);
513
- }
514
- .pl-tab:hover:not(:disabled) {
515
- color: var(--pl-color-fg);
516
- }
517
- .pl-tab--active {
518
- color: var(--pl-color-fg);
519
- border-bottom-color: var(--pl-color-fg);
520
- }
521
- .pl-tab:disabled {
522
- opacity: 0.35;
523
- cursor: not-allowed;
524
- }
525
- .pl-tab__lock {
526
- margin-left: 5px;
527
- opacity: 0.6;
528
- }
529
-
530
- /* ── Board (kanban) ────────────────────────────────────────────────────────── */
531
- .pl-board {
532
- display: flex;
533
- gap: 12px;
534
- overflow-x: auto;
535
- align-items: flex-start;
536
- }
537
- .pl-board-col {
538
- flex: 1 0 200px;
539
- min-width: 200px;
540
- background: var(--pl-color-bg-raised);
541
- border: var(--pl-border-width) solid var(--pl-color-border);
542
- border-radius: var(--pl-radius);
543
- display: flex;
544
- flex-direction: column;
545
- }
546
- .pl-board-col__head {
547
- display: flex;
548
- align-items: center;
549
- justify-content: space-between;
550
- padding: 10px 12px;
551
- font-size: 12px;
552
- font-weight: 600;
553
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
554
- }
555
- .pl-board-col__count {
556
- color: var(--pl-color-fg-muted);
557
- font-family: var(--pl-font-mono);
558
- }
559
- .pl-board-col__body {
560
- padding: 8px;
561
- display: flex;
562
- flex-direction: column;
563
- gap: 8px;
564
- min-height: 40px;
565
- }
566
- .pl-board-card {
567
- text-align: left;
568
- background: var(--pl-color-bg);
569
- border: var(--pl-border-width) solid var(--pl-color-border);
570
- border-radius: var(--pl-radius);
571
- color: var(--pl-color-fg);
572
- padding: 10px 12px;
573
- cursor: pointer;
574
- display: flex;
575
- flex-direction: column;
576
- gap: 6px;
577
- font: inherit;
578
- }
579
- .pl-board-card:hover {
580
- border-color: var(--pl-color-fg);
581
- }
582
-
583
- /* ── Field ─────────────────────────────────────────────────────────────────── */
584
- .pl-field {
585
- display: block;
586
- }
587
- .pl-field__label {
588
- display: block;
589
- font-size: 11px;
590
- text-transform: uppercase;
591
- letter-spacing: 0.05em;
592
- color: var(--pl-color-fg-muted);
593
- margin-bottom: 6px;
594
- }
595
- .pl-field__input {
596
- width: 100%;
597
- background: var(--pl-color-bg-raised);
598
- border: var(--pl-border-width) solid var(--pl-color-border);
599
- color: var(--pl-color-fg);
600
- border-radius: var(--pl-radius);
601
- padding: 9px 11px;
602
- font: inherit;
603
- font-family: var(--pl-font-sans);
604
- resize: vertical;
605
- }
606
- .pl-field__input:focus {
607
- outline: none;
608
- border-color: var(--pl-color-fg);
609
- }
610
-
611
- /* ── PanelHeader (console panel header) ──────────────────────────────────────── */
612
- .pl-panel-header {
613
- display: flex;
614
- align-items: center;
615
- justify-content: space-between;
616
- gap: var(--pl-space-3);
617
- padding: var(--pl-space-3) var(--pl-space-4);
618
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
619
- }
620
- .pl-panel-header__kicker {
621
- font-family: var(--pl-font-mono);
622
- font-size: 11px;
623
- text-transform: uppercase;
624
- letter-spacing: 0.06em;
625
- color: var(--pl-color-fg-muted);
626
- margin-bottom: 2px;
627
- }
628
- .pl-panel-header__title {
629
- margin: 0;
630
- font-size: 15px;
631
- font-weight: var(--pl-font-weight-medium);
632
- line-height: 1.2;
633
- color: var(--pl-color-fg);
634
- }
635
- .pl-panel-header__actions {
636
- display: flex;
637
- align-items: center;
638
- gap: var(--pl-space-2);
639
- flex-shrink: 0;
640
- }
641
- .pl-panel-header--compact {
642
- padding: var(--pl-space-2) var(--pl-space-3);
643
- }
644
- .pl-panel-header--compact .pl-panel-header__title {
645
- font-size: 13px;
646
- }
647
-
648
- /* ── Overlay scrim (Dialog + Drawer) ─────────────────────────────────────────── */
649
- .pl-overlay {
650
- position: fixed;
651
- inset: 0;
652
- z-index: 1000;
653
- display: flex;
654
- align-items: center;
655
- justify-content: center;
656
- padding: var(--pl-space-4);
657
- background: var(--pl-color-overlay);
658
- }
659
- .pl-overlay--drawer {
660
- padding: 0;
661
- }
662
-
663
- /* ── Dialog / Modal ──────────────────────────────────────────────────────────── */
664
- .pl-dialog {
665
- display: flex;
666
- flex-direction: column;
667
- width: 480px;
668
- max-width: 100%;
669
- max-height: calc(100vh - 2 * var(--pl-space-4));
670
- background: var(--pl-color-bg-raised);
671
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
672
- border-radius: var(--pl-radius);
673
- box-shadow: var(--pl-shadow-popover);
674
- }
675
- .pl-dialog:focus {
676
- outline: none;
677
- }
678
- .pl-dialog__head {
679
- display: flex;
680
- align-items: center;
681
- justify-content: space-between;
682
- gap: var(--pl-space-3);
683
- padding: var(--pl-space-3) var(--pl-space-4);
684
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
685
- }
686
- .pl-dialog__title {
687
- font-size: 14px;
688
- font-weight: var(--pl-font-weight-medium);
689
- color: var(--pl-color-fg);
690
- }
691
- .pl-dialog__close {
692
- display: inline-flex;
693
- align-items: center;
694
- justify-content: center;
695
- width: 24px;
696
- height: 24px;
697
- font-size: 18px;
698
- line-height: 1;
699
- color: var(--pl-color-fg-muted);
700
- background: transparent;
701
- border: none;
702
- border-radius: var(--pl-radius);
703
- cursor: pointer;
704
- transition:
705
- color var(--pl-motion-fast) var(--pl-motion-ease),
706
- background var(--pl-motion-fast) var(--pl-motion-ease);
707
- }
708
- .pl-dialog__close:hover {
709
- color: var(--pl-color-fg);
710
- background: var(--pl-color-bg-hover);
711
- }
712
- .pl-dialog__body {
713
- padding: var(--pl-space-4);
714
- overflow-y: auto;
715
- font-size: 14px;
716
- line-height: 1.6;
717
- color: var(--pl-color-fg-muted);
718
- }
719
- .pl-dialog__foot {
720
- display: flex;
721
- justify-content: flex-end;
722
- gap: var(--pl-space-2);
723
- padding: var(--pl-space-3) var(--pl-space-4);
724
- border-top: var(--pl-border-width) solid var(--pl-color-border);
725
- }
726
-
727
- /* Destructive confirm — error-toned border, fills error on hover. */
728
- .pl-btn--danger {
729
- border-color: color-mix(in oklch, var(--pl-color-status-error) 60%, transparent);
730
- color: var(--pl-color-status-error);
731
- }
732
- .pl-btn--danger:hover {
733
- background: var(--pl-color-status-error);
734
- border-color: var(--pl-color-status-error);
735
- color: var(--pl-color-bg);
736
- }
737
- /* Ghost — transparent until hover, for toolbars / inline actions. */
738
- .pl-btn--ghost {
739
- border-color: transparent;
740
- }
741
- .pl-btn--ghost:hover {
742
- border-color: var(--pl-color-border-strong);
743
- background: var(--pl-color-bg-hover);
744
- }
745
- .pl-btn--sm {
746
- padding: 0.3rem 0.6rem;
747
- font-size: 12px;
748
- }
749
- /* Icon-only — square, centered glyph. */
750
- .pl-btn--icon {
751
- padding: 0;
752
- width: 30px;
753
- height: 30px;
754
- justify-content: center;
755
- }
756
- .pl-btn--icon.pl-btn--sm {
757
- width: 26px;
758
- height: 26px;
759
- }
760
- .pl-btn--icon svg {
761
- width: 16px;
762
- height: 16px;
763
- }
764
-
765
- /* ── Drawer (slide-in sheet) ─────────────────────────────────────────────────── */
766
- .pl-drawer {
767
- display: flex;
768
- flex-direction: column;
769
- width: 420px;
770
- max-width: 100%;
771
- height: 100%;
772
- background: var(--pl-color-bg-raised);
773
- box-shadow: var(--pl-shadow-popover);
774
- animation: pl-drawer-in var(--pl-motion-base) var(--pl-motion-ease);
775
- }
776
- .pl-drawer:focus {
777
- outline: none;
778
- }
779
- .pl-drawer--right {
780
- margin-left: auto;
781
- border-left: var(--pl-border-width) solid var(--pl-color-border-strong);
782
- }
783
- .pl-drawer--left {
784
- margin-right: auto;
785
- border-right: var(--pl-border-width) solid var(--pl-color-border-strong);
786
- animation-name: pl-drawer-in-left;
787
- }
788
- .pl-overlay--drawer:has(.pl-drawer--left) {
789
- justify-content: flex-start;
790
- }
791
- @keyframes pl-drawer-in {
792
- from {
793
- transform: translateX(100%);
794
- }
795
- }
796
- @keyframes pl-drawer-in-left {
797
- from {
798
- transform: translateX(-100%);
799
- }
800
- }
801
- .pl-drawer__head {
802
- display: flex;
803
- align-items: center;
804
- justify-content: space-between;
805
- gap: var(--pl-space-3);
806
- padding: var(--pl-space-3) var(--pl-space-4);
807
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
808
- }
809
- .pl-drawer__title {
810
- font-size: 14px;
811
- font-weight: var(--pl-font-weight-medium);
812
- color: var(--pl-color-fg);
813
- }
814
- .pl-drawer__body {
815
- flex: 1;
816
- padding: var(--pl-space-4);
817
- overflow-y: auto;
818
- font-size: 14px;
819
- line-height: 1.6;
820
- color: var(--pl-color-fg-muted);
821
- }
822
- .pl-drawer__foot {
823
- display: flex;
824
- justify-content: flex-end;
825
- gap: var(--pl-space-2);
826
- padding: var(--pl-space-3) var(--pl-space-4);
827
- border-top: var(--pl-border-width) solid var(--pl-color-border);
828
- }
829
-
830
- /* ── Toast ───────────────────────────────────────────────────────────────────── */
831
- .pl-toast-stack {
832
- position: fixed;
833
- bottom: var(--pl-space-4);
834
- right: var(--pl-space-4);
835
- z-index: 1100;
836
- display: flex;
837
- flex-direction: column;
838
- gap: var(--pl-space-2);
839
- max-width: min(360px, calc(100vw - 2 * var(--pl-space-4)));
840
- }
841
- .pl-toast {
842
- display: flex;
843
- align-items: flex-start;
844
- gap: var(--pl-space-3);
845
- padding: var(--pl-space-3);
846
- background: var(--pl-color-bg-raised);
847
- border: var(--pl-border-width) solid var(--pl-color-border);
848
- border-left-width: 2px;
849
- border-radius: var(--pl-radius);
850
- box-shadow: var(--pl-shadow-popover);
851
- animation: pl-toast-in var(--pl-motion-base) var(--pl-motion-ease);
852
- }
853
- @keyframes pl-toast-in {
854
- from {
855
- opacity: 0;
856
- transform: translateY(6px);
857
- }
858
- }
859
- .pl-toast--success {
860
- border-left-color: var(--pl-color-status-success);
861
- }
862
- .pl-toast--warning {
863
- border-left-color: var(--pl-color-status-warning);
864
- }
865
- .pl-toast--error {
866
- border-left-color: var(--pl-color-status-error);
867
- }
868
- .pl-toast--info {
869
- border-left-color: var(--pl-color-status-info);
870
- }
871
- .pl-toast__body {
872
- flex: 1;
873
- min-width: 0;
874
- }
875
- .pl-toast__title {
876
- font-family: var(--pl-font-mono);
877
- font-size: 12px;
878
- color: var(--pl-color-fg);
879
- margin-bottom: 0.2rem;
880
- }
881
- .pl-toast__msg {
882
- font-size: 13px;
883
- line-height: 1.5;
884
- color: var(--pl-color-fg-muted);
885
- }
886
- .pl-toast__close {
887
- flex-shrink: 0;
888
- font-size: 16px;
889
- line-height: 1;
890
- color: var(--pl-color-fg-muted);
891
- background: transparent;
892
- border: none;
893
- cursor: pointer;
894
- }
895
- .pl-toast__close:hover {
896
- color: var(--pl-color-fg);
897
- }
898
-
899
- /* ── Tooltip (CSS-only) ──────────────────────────────────────────────────────── */
900
- .pl-tip-wrap {
901
- position: relative;
902
- display: inline-flex;
903
- }
904
- .pl-tip {
905
- position: absolute;
906
- z-index: 1200;
907
- pointer-events: none;
908
- white-space: nowrap;
909
- padding: 0.25rem 0.5rem;
910
- font-family: var(--pl-font-mono);
911
- font-size: 11px;
912
- color: var(--pl-color-fg);
913
- background: var(--pl-color-bg-raised);
914
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
915
- border-radius: var(--pl-radius);
916
- box-shadow: var(--pl-shadow-popover);
917
- opacity: 0;
918
- transition: opacity var(--pl-motion-fast) var(--pl-motion-ease);
919
- }
920
- .pl-tip-wrap:hover .pl-tip,
921
- .pl-tip-wrap:focus-within .pl-tip {
922
- opacity: 1;
923
- }
924
- .pl-tip--top {
925
- bottom: calc(100% + 6px);
926
- left: 50%;
927
- transform: translateX(-50%);
928
- }
929
- .pl-tip--bottom {
930
- top: calc(100% + 6px);
931
- left: 50%;
932
- transform: translateX(-50%);
933
- }
934
- .pl-tip--left {
935
- right: calc(100% + 6px);
936
- top: 50%;
937
- transform: translateY(-50%);
938
- }
939
- .pl-tip--right {
940
- left: calc(100% + 6px);
941
- top: 50%;
942
- transform: translateY(-50%);
943
- }
944
-
945
- /* ── Table (dense data) ──────────────────────────────────────────────────────── */
946
- .pl-table {
947
- width: 100%;
948
- border-collapse: collapse;
949
- font-size: 13px;
950
- }
951
- .pl-table th {
952
- text-align: left;
953
- font-family: var(--pl-font-mono);
954
- font-size: 11px;
955
- font-weight: var(--pl-font-weight-medium);
956
- text-transform: uppercase;
957
- letter-spacing: 0.04em;
958
- color: var(--pl-color-fg-muted);
959
- padding: var(--pl-space-2) var(--pl-space-3);
960
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
961
- }
962
- .pl-table td {
963
- padding: var(--pl-space-2) var(--pl-space-3);
964
- color: var(--pl-color-fg);
965
- border-bottom: var(--pl-border-width) solid var(--pl-color-border);
966
- }
967
- .pl-table tbody tr.pl-tr--interactive {
968
- cursor: pointer;
969
- transition: background var(--pl-motion-fast) var(--pl-motion-ease);
970
- }
971
- .pl-table tbody tr.pl-tr--interactive:hover {
972
- background: var(--pl-color-bg-hover);
973
- }
974
- .pl-table tbody tr.pl-tr--selected {
975
- background: var(--pl-color-bg-subtle);
976
- }
977
-
978
- /* ── Status dot ──────────────────────────────────────────────────────────────── */
979
- .pl-dot {
980
- display: inline-block;
981
- width: 8px;
982
- height: 8px;
983
- border-radius: 50%;
984
- background: var(--pl-color-fg-muted);
985
- }
986
- .pl-dot--success {
987
- background: var(--pl-color-status-success);
988
- }
989
- .pl-dot--warning {
990
- background: var(--pl-color-status-warning);
991
- }
992
- .pl-dot--error {
993
- background: var(--pl-color-status-error);
994
- }
995
- .pl-dot--info {
996
- background: var(--pl-color-status-info);
997
- }
998
- .pl-dot--pulse {
999
- animation: pl-dot-pulse var(--pl-motion-status) var(--pl-motion-ease-in-out) infinite;
1000
- }
1001
- @keyframes pl-dot-pulse {
1002
- 0%,
1003
- 100% {
1004
- opacity: 1;
1005
- }
1006
- 50% {
1007
- opacity: 0.35;
1008
- }
1009
- }
1010
- .pl-dot-row {
1011
- display: inline-flex;
1012
- align-items: center;
1013
- gap: 0.4rem;
1014
- }
1015
- .pl-dot-row__label {
1016
- font-size: 12px;
1017
- color: var(--pl-color-fg-muted);
1018
- }
1019
-
1020
- /* ── Spinner ─────────────────────────────────────────────────────────────────── */
1021
- .pl-spinner {
1022
- display: inline-block;
1023
- border: 2px solid var(--pl-color-border-strong);
1024
- border-top-color: var(--pl-color-fg);
1025
- border-radius: 50%;
1026
- animation: pl-spin var(--pl-motion-loading) var(--pl-motion-linear) infinite;
1027
- }
1028
- @keyframes pl-spin {
1029
- to {
1030
- transform: rotate(360deg);
1031
- }
1032
- }
1033
-
1034
- /* ── ScrollArea (thin brand scrollbars) ──────────────────────────────────────── */
1035
- .pl-scroll {
1036
- overflow: auto;
1037
- /* min-height:0 lets the region actually scroll inside a flex/grid parent
1038
- (the classic min-size trap) instead of overflowing it. */
1039
- min-height: 0;
1040
- overscroll-behavior: contain;
1041
- scrollbar-gutter: stable;
1042
- scrollbar-width: thin;
1043
- scrollbar-color: var(--pl-color-border-strong) transparent;
1044
- }
1045
- .pl-scroll:focus-visible {
1046
- outline: 1px solid var(--pl-color-fg);
1047
- outline-offset: -2px;
1048
- }
1049
- .pl-scroll::-webkit-scrollbar {
1050
- width: 8px;
1051
- height: 8px;
1052
- }
1053
- .pl-scroll::-webkit-scrollbar-thumb {
1054
- background: var(--pl-color-border-strong);
1055
- border-radius: var(--pl-radius);
1056
- }
1057
- .pl-scroll::-webkit-scrollbar-track {
1058
- background: transparent;
1059
- }
1060
-
1061
- /* ── Form controls ───────────────────────────────────────────────────────────── */
1062
- .pl-input {
1063
- width: 100%;
1064
- background: var(--pl-color-bg-raised);
1065
- border: var(--pl-border-width) solid var(--pl-color-border);
1066
- color: var(--pl-color-fg);
1067
- border-radius: var(--pl-radius);
1068
- padding: 9px 11px;
1069
- font: inherit;
1070
- font-family: var(--pl-font-sans);
1071
- font-size: 13px;
1072
- }
1073
- .pl-input::placeholder {
1074
- color: var(--pl-color-fg-muted);
1075
- }
1076
- .pl-input:focus {
1077
- outline: none;
1078
- border-color: var(--pl-color-border-strong);
1079
- }
1080
- .pl-input:disabled {
1081
- opacity: 0.5;
1082
- cursor: not-allowed;
1083
- }
1084
- .pl-textarea {
1085
- resize: vertical;
1086
- min-height: 72px;
1087
- line-height: 1.5;
1088
- }
1089
- .pl-select {
1090
- cursor: pointer;
1091
- }
1092
-
1093
- /* Switch */
1094
- .pl-switch {
1095
- display: inline-flex;
1096
- align-items: center;
1097
- gap: 0.5rem;
1098
- cursor: pointer;
1099
- }
1100
- .pl-switch--disabled {
1101
- opacity: 0.5;
1102
- cursor: not-allowed;
1103
- }
1104
- .pl-switch__input {
1105
- position: absolute;
1106
- opacity: 0;
1107
- width: 0;
1108
- height: 0;
1109
- }
1110
- .pl-switch__track {
1111
- position: relative;
1112
- display: inline-block;
1113
- width: 32px;
1114
- height: 18px;
1115
- background: var(--pl-color-bg-subtle);
1116
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
1117
- border-radius: 999px;
1118
- transition: background var(--pl-motion-fast) var(--pl-motion-ease);
1119
- }
1120
- .pl-switch__thumb {
1121
- position: absolute;
1122
- top: 2px;
1123
- left: 2px;
1124
- width: 12px;
1125
- height: 12px;
1126
- background: var(--pl-color-fg-muted);
1127
- border-radius: 50%;
1128
- transition:
1129
- transform var(--pl-motion-fast) var(--pl-motion-ease),
1130
- background var(--pl-motion-fast) var(--pl-motion-ease);
1131
- }
1132
- .pl-switch__input:checked + .pl-switch__track {
1133
- background: var(--pl-color-fg);
1134
- border-color: var(--pl-color-fg);
1135
- }
1136
- .pl-switch__input:checked + .pl-switch__track .pl-switch__thumb {
1137
- transform: translateX(14px);
1138
- background: var(--pl-color-bg);
1139
- }
1140
- .pl-switch__input:focus-visible + .pl-switch__track {
1141
- outline: 2px solid var(--pl-color-border-strong);
1142
- outline-offset: 2px;
1143
- }
1144
- .pl-switch__label {
1145
- font-size: 13px;
1146
- color: var(--pl-color-fg);
1147
- }
1148
-
1149
- /* Checkbox */
1150
- .pl-checkbox {
1151
- display: inline-flex;
1152
- align-items: center;
1153
- gap: 0.5rem;
1154
- cursor: pointer;
1155
- }
1156
- .pl-checkbox--disabled {
1157
- opacity: 0.5;
1158
- cursor: not-allowed;
1159
- }
1160
- .pl-checkbox__input {
1161
- position: absolute;
1162
- opacity: 0;
1163
- width: 0;
1164
- height: 0;
1165
- }
1166
- .pl-checkbox__box {
1167
- position: relative;
1168
- display: inline-block;
1169
- width: 16px;
1170
- height: 16px;
1171
- background: var(--pl-color-bg-raised);
1172
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
1173
- border-radius: var(--pl-radius);
1174
- transition:
1175
- background var(--pl-motion-fast) var(--pl-motion-ease),
1176
- border-color var(--pl-motion-fast) var(--pl-motion-ease);
1177
- }
1178
- .pl-checkbox__input:checked + .pl-checkbox__box {
1179
- background: var(--pl-color-fg);
1180
- border-color: var(--pl-color-fg);
1181
- }
1182
- .pl-checkbox__input:checked + .pl-checkbox__box::after {
1183
- content: "";
1184
- position: absolute;
1185
- left: 5px;
1186
- top: 2px;
1187
- width: 4px;
1188
- height: 8px;
1189
- border: solid var(--pl-color-bg);
1190
- border-width: 0 2px 2px 0;
1191
- transform: rotate(45deg);
1192
- }
1193
- .pl-checkbox__input:focus-visible + .pl-checkbox__box {
1194
- outline: 2px solid var(--pl-color-border-strong);
1195
- outline-offset: 2px;
1196
- }
1197
- .pl-checkbox__label {
1198
- font-size: 13px;
1199
- color: var(--pl-color-fg);
1200
- }
1201
-
1202
- /* ── Menu / DropdownMenu (Radix-backed) ──────────────────────────────────────── */
1203
- .pl-menu__anchor {
1204
- width: 0;
1205
- height: 0;
1206
- pointer-events: none;
1207
- }
1208
- .pl-menu {
1209
- min-width: 180px;
1210
- padding: 4px;
1211
- background: var(--pl-color-bg-raised);
1212
- border: var(--pl-border-width) solid var(--pl-color-border-strong);
1213
- border-radius: var(--pl-radius);
1214
- box-shadow: var(--pl-shadow-popover);
1215
- z-index: 1200;
1216
- }
1217
- .pl-menu__item {
1218
- display: flex;
1219
- align-items: center;
1220
- gap: 8px;
1221
- padding: 6px 8px;
1222
- font-size: 13px;
1223
- color: var(--pl-color-fg);
1224
- border-radius: calc(var(--pl-radius) - 1px);
1225
- cursor: pointer;
1226
- outline: none;
1227
- user-select: none;
1228
- }
1229
- /* Radix sets data-highlighted on the keyboard/pointer-focused item. */
1230
- .pl-menu__item[data-highlighted] {
1231
- background: var(--pl-color-bg-hover);
1232
- }
1233
- .pl-menu__item[data-disabled] {
1234
- color: var(--pl-color-fg-muted);
1235
- opacity: 0.5;
1236
- pointer-events: none;
1237
- }
1238
- .pl-menu__item--destructive {
1239
- color: var(--pl-color-status-error);
1240
- }
1241
- .pl-menu__item--destructive[data-highlighted] {
1242
- background: color-mix(in oklch, var(--pl-color-status-error) 16%, transparent);
1243
- }
1244
- .pl-menu__icon {
1245
- display: inline-flex;
1246
- align-items: center;
1247
- color: var(--pl-color-fg-muted);
1248
- }
1249
- .pl-menu__icon svg {
1250
- width: 15px;
1251
- height: 15px;
1252
- }
1253
- .pl-menu__item--destructive .pl-menu__icon {
1254
- color: var(--pl-color-status-error);
1255
- }
1256
- .pl-menu__label {
1257
- flex: 1;
1258
- }
1259
- .pl-menu__subarrow {
1260
- color: var(--pl-color-fg-muted);
1261
- font-size: 14px;
1262
- line-height: 1;
1263
- }
1264
- .pl-menu__sep {
1265
- height: 1px;
1266
- margin: 4px 0;
1267
- background: var(--pl-color-border);
1268
- }
1269
- .pl-menu__group-label {
1270
- padding: 4px 8px;
1271
- font-family: var(--pl-font-mono);
1272
- font-size: 10px;
1273
- text-transform: uppercase;
1274
- letter-spacing: 0.06em;
1275
- color: var(--pl-color-fg-muted);
1276
- }
1277
-
1278
- /* ── Skeleton (loading placeholder) ──────────────────────────────────────────── */
1279
- .pl-skel {
1280
- display: block;
1281
- border-radius: var(--pl-radius);
1282
- background-color: var(--pl-color-bg-subtle);
1283
- background-image: linear-gradient(
1284
- 90deg,
1285
- var(--pl-color-bg-subtle) 25%,
1286
- var(--pl-color-bg-hover) 50%,
1287
- var(--pl-color-bg-subtle) 75%
1288
- );
1289
- background-size: 200% 100%;
1290
- animation: pl-skel-shimmer 1.4s var(--pl-motion-ease-in-out) infinite;
1291
- }
1292
- @keyframes pl-skel-shimmer {
1293
- from {
1294
- background-position: 200% 0;
1295
- }
1296
- to {
1297
- background-position: -200% 0;
1298
- }
1299
- }
1300
- .pl-skel-lines {
1301
- display: grid;
1302
- gap: 8px;
1303
- }
1304
- .pl-skel-group {
1305
- display: grid;
1306
- gap: var(--pl-space-3);
1307
- }
1308
-
1309
- /* Respect reduced-motion for every animation this package introduces. */
1310
- @media (prefers-reduced-motion: reduce) {
1311
- .pl-drawer,
1312
- .pl-toast,
1313
- .pl-dot--pulse,
1314
- .pl-spinner {
1315
- animation: none;
1316
- }
1317
- /* Skeletons go static (solid fill, no shimmer). */
1318
- .pl-skel {
1319
- animation: none;
1320
- background-image: none;
1321
- }
1322
- }
1
+ /* @protolabsai/ui — style barrel. Import once: `import "@protolabsai/ui/styles.css"`.
2
+ * Requires @protolabsai/design/css for the --pl-* tokens. Partials live in ./styles/. */
3
+
4
+ @import "./styles/primitives.css";
5
+ @import "./styles/layout.css";
6
+ @import "./styles/marketing.css";
7
+ @import "./styles/navigation.css";
8
+ @import "./styles/forms.css";
9
+ @import "./styles/overlays.css";
10
+ @import "./styles/data.css";
11
+ @import "./styles/menu.css";
12
+ @import "./styles/app-shell.css";