@protolabsai/ui 0.2.0 → 0.4.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
@@ -25,7 +25,7 @@
25
25
  .pl-btn:hover {
26
26
  border-color: var(--pl-color-fg);
27
27
  }
28
- /* Primary ships as a stronger border, not a violet fill — brand restraint. */
28
+ /* Primary ships as a stronger border, not a lavender fill — brand restraint. */
29
29
  .pl-btn--primary {
30
30
  border-color: var(--pl-color-fg);
31
31
  }
@@ -464,3 +464,645 @@ a.pl-row:hover {
464
464
  .pl-link:hover {
465
465
  text-decoration-color: var(--pl-color-fg);
466
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
+ background: none;
476
+ border: none;
477
+ border-bottom: 2px solid transparent;
478
+ color: var(--pl-color-fg-muted);
479
+ font: inherit;
480
+ font-family: var(--pl-font-sans);
481
+ padding: 8px 14px;
482
+ cursor: pointer;
483
+ border-radius: var(--pl-radius) var(--pl-radius) 0 0;
484
+ }
485
+ .pl-tab:hover:not(:disabled) {
486
+ color: var(--pl-color-fg);
487
+ }
488
+ .pl-tab--active {
489
+ color: var(--pl-color-fg);
490
+ border-bottom-color: var(--pl-color-fg);
491
+ }
492
+ .pl-tab:disabled {
493
+ opacity: 0.35;
494
+ cursor: not-allowed;
495
+ }
496
+ .pl-tab__lock {
497
+ margin-left: 5px;
498
+ opacity: 0.6;
499
+ }
500
+
501
+ /* ── Board (kanban) ────────────────────────────────────────────────────────── */
502
+ .pl-board {
503
+ display: flex;
504
+ gap: 12px;
505
+ overflow-x: auto;
506
+ align-items: flex-start;
507
+ }
508
+ .pl-board-col {
509
+ flex: 1 0 200px;
510
+ min-width: 200px;
511
+ background: var(--pl-color-bg-raised);
512
+ border: var(--pl-border-width) solid var(--pl-color-border);
513
+ border-radius: var(--pl-radius);
514
+ display: flex;
515
+ flex-direction: column;
516
+ }
517
+ .pl-board-col__head {
518
+ display: flex;
519
+ align-items: center;
520
+ justify-content: space-between;
521
+ padding: 10px 12px;
522
+ font-size: 12px;
523
+ font-weight: 600;
524
+ border-bottom: var(--pl-border-width) solid var(--pl-color-border);
525
+ }
526
+ .pl-board-col__count {
527
+ color: var(--pl-color-fg-muted);
528
+ font-family: var(--pl-font-mono);
529
+ }
530
+ .pl-board-col__body {
531
+ padding: 8px;
532
+ display: flex;
533
+ flex-direction: column;
534
+ gap: 8px;
535
+ min-height: 40px;
536
+ }
537
+ .pl-board-card {
538
+ text-align: left;
539
+ background: var(--pl-color-bg);
540
+ border: var(--pl-border-width) solid var(--pl-color-border);
541
+ border-radius: var(--pl-radius);
542
+ color: var(--pl-color-fg);
543
+ padding: 10px 12px;
544
+ cursor: pointer;
545
+ display: flex;
546
+ flex-direction: column;
547
+ gap: 6px;
548
+ font: inherit;
549
+ }
550
+ .pl-board-card:hover {
551
+ border-color: var(--pl-color-fg);
552
+ }
553
+
554
+ /* ── Field ─────────────────────────────────────────────────────────────────── */
555
+ .pl-field {
556
+ display: block;
557
+ }
558
+ .pl-field__label {
559
+ display: block;
560
+ font-size: 11px;
561
+ text-transform: uppercase;
562
+ letter-spacing: 0.05em;
563
+ color: var(--pl-color-fg-muted);
564
+ margin-bottom: 6px;
565
+ }
566
+ .pl-field__input {
567
+ width: 100%;
568
+ background: var(--pl-color-bg-raised);
569
+ border: var(--pl-border-width) solid var(--pl-color-border);
570
+ color: var(--pl-color-fg);
571
+ border-radius: var(--pl-radius);
572
+ padding: 9px 11px;
573
+ font: inherit;
574
+ font-family: var(--pl-font-sans);
575
+ resize: vertical;
576
+ }
577
+ .pl-field__input:focus {
578
+ outline: none;
579
+ border-color: var(--pl-color-fg);
580
+ }
581
+
582
+ /* ── Overlay scrim (Dialog + Drawer) ─────────────────────────────────────────── */
583
+ .pl-overlay {
584
+ position: fixed;
585
+ inset: 0;
586
+ z-index: 1000;
587
+ display: flex;
588
+ align-items: center;
589
+ justify-content: center;
590
+ padding: var(--pl-space-4);
591
+ background: var(--pl-color-overlay);
592
+ }
593
+ .pl-overlay--drawer {
594
+ padding: 0;
595
+ }
596
+
597
+ /* ── Dialog / Modal ──────────────────────────────────────────────────────────── */
598
+ .pl-dialog {
599
+ display: flex;
600
+ flex-direction: column;
601
+ width: 480px;
602
+ max-width: 100%;
603
+ max-height: calc(100vh - 2 * var(--pl-space-4));
604
+ background: var(--pl-color-bg-raised);
605
+ border: var(--pl-border-width) solid var(--pl-color-border-strong);
606
+ border-radius: var(--pl-radius);
607
+ box-shadow: var(--pl-shadow-popover);
608
+ }
609
+ .pl-dialog:focus {
610
+ outline: none;
611
+ }
612
+ .pl-dialog__head {
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-dialog__title {
621
+ font-size: 14px;
622
+ font-weight: var(--pl-font-weight-medium);
623
+ color: var(--pl-color-fg);
624
+ }
625
+ .pl-dialog__close {
626
+ display: inline-flex;
627
+ align-items: center;
628
+ justify-content: center;
629
+ width: 24px;
630
+ height: 24px;
631
+ font-size: 18px;
632
+ line-height: 1;
633
+ color: var(--pl-color-fg-muted);
634
+ background: transparent;
635
+ border: none;
636
+ border-radius: var(--pl-radius);
637
+ cursor: pointer;
638
+ transition:
639
+ color var(--pl-motion-fast) var(--pl-motion-ease),
640
+ background var(--pl-motion-fast) var(--pl-motion-ease);
641
+ }
642
+ .pl-dialog__close:hover {
643
+ color: var(--pl-color-fg);
644
+ background: var(--pl-color-bg-hover);
645
+ }
646
+ .pl-dialog__body {
647
+ padding: var(--pl-space-4);
648
+ overflow-y: auto;
649
+ font-size: 14px;
650
+ line-height: 1.6;
651
+ color: var(--pl-color-fg-muted);
652
+ }
653
+ .pl-dialog__foot {
654
+ display: flex;
655
+ justify-content: flex-end;
656
+ gap: var(--pl-space-2);
657
+ padding: var(--pl-space-3) var(--pl-space-4);
658
+ border-top: var(--pl-border-width) solid var(--pl-color-border);
659
+ }
660
+
661
+ /* Destructive confirm — error-toned border, fills error on hover. */
662
+ .pl-btn--danger {
663
+ border-color: color-mix(in oklch, var(--pl-color-status-error) 60%, transparent);
664
+ color: var(--pl-color-status-error);
665
+ }
666
+ .pl-btn--danger:hover {
667
+ background: var(--pl-color-status-error);
668
+ border-color: var(--pl-color-status-error);
669
+ color: var(--pl-color-bg);
670
+ }
671
+
672
+ /* ── Drawer (slide-in sheet) ─────────────────────────────────────────────────── */
673
+ .pl-drawer {
674
+ display: flex;
675
+ flex-direction: column;
676
+ width: 420px;
677
+ max-width: 100%;
678
+ height: 100%;
679
+ background: var(--pl-color-bg-raised);
680
+ box-shadow: var(--pl-shadow-popover);
681
+ animation: pl-drawer-in var(--pl-motion-base) var(--pl-motion-ease);
682
+ }
683
+ .pl-drawer:focus {
684
+ outline: none;
685
+ }
686
+ .pl-drawer--right {
687
+ margin-left: auto;
688
+ border-left: var(--pl-border-width) solid var(--pl-color-border-strong);
689
+ }
690
+ .pl-drawer--left {
691
+ margin-right: auto;
692
+ border-right: var(--pl-border-width) solid var(--pl-color-border-strong);
693
+ animation-name: pl-drawer-in-left;
694
+ }
695
+ .pl-overlay--drawer:has(.pl-drawer--left) {
696
+ justify-content: flex-start;
697
+ }
698
+ @keyframes pl-drawer-in {
699
+ from {
700
+ transform: translateX(100%);
701
+ }
702
+ }
703
+ @keyframes pl-drawer-in-left {
704
+ from {
705
+ transform: translateX(-100%);
706
+ }
707
+ }
708
+ .pl-drawer__head {
709
+ display: flex;
710
+ align-items: center;
711
+ justify-content: space-between;
712
+ gap: var(--pl-space-3);
713
+ padding: var(--pl-space-3) var(--pl-space-4);
714
+ border-bottom: var(--pl-border-width) solid var(--pl-color-border);
715
+ }
716
+ .pl-drawer__title {
717
+ font-size: 14px;
718
+ font-weight: var(--pl-font-weight-medium);
719
+ color: var(--pl-color-fg);
720
+ }
721
+ .pl-drawer__body {
722
+ flex: 1;
723
+ padding: var(--pl-space-4);
724
+ overflow-y: auto;
725
+ font-size: 14px;
726
+ line-height: 1.6;
727
+ color: var(--pl-color-fg-muted);
728
+ }
729
+ .pl-drawer__foot {
730
+ display: flex;
731
+ justify-content: flex-end;
732
+ gap: var(--pl-space-2);
733
+ padding: var(--pl-space-3) var(--pl-space-4);
734
+ border-top: var(--pl-border-width) solid var(--pl-color-border);
735
+ }
736
+
737
+ /* ── Toast ───────────────────────────────────────────────────────────────────── */
738
+ .pl-toast-stack {
739
+ position: fixed;
740
+ bottom: var(--pl-space-4);
741
+ right: var(--pl-space-4);
742
+ z-index: 1100;
743
+ display: flex;
744
+ flex-direction: column;
745
+ gap: var(--pl-space-2);
746
+ max-width: min(360px, calc(100vw - 2 * var(--pl-space-4)));
747
+ }
748
+ .pl-toast {
749
+ display: flex;
750
+ align-items: flex-start;
751
+ gap: var(--pl-space-3);
752
+ padding: var(--pl-space-3);
753
+ background: var(--pl-color-bg-raised);
754
+ border: var(--pl-border-width) solid var(--pl-color-border);
755
+ border-left-width: 2px;
756
+ border-radius: var(--pl-radius);
757
+ box-shadow: var(--pl-shadow-popover);
758
+ animation: pl-toast-in var(--pl-motion-base) var(--pl-motion-ease);
759
+ }
760
+ @keyframes pl-toast-in {
761
+ from {
762
+ opacity: 0;
763
+ transform: translateY(6px);
764
+ }
765
+ }
766
+ .pl-toast--success {
767
+ border-left-color: var(--pl-color-status-success);
768
+ }
769
+ .pl-toast--warning {
770
+ border-left-color: var(--pl-color-status-warning);
771
+ }
772
+ .pl-toast--error {
773
+ border-left-color: var(--pl-color-status-error);
774
+ }
775
+ .pl-toast--info {
776
+ border-left-color: var(--pl-color-status-info);
777
+ }
778
+ .pl-toast__body {
779
+ flex: 1;
780
+ min-width: 0;
781
+ }
782
+ .pl-toast__title {
783
+ font-family: var(--pl-font-mono);
784
+ font-size: 12px;
785
+ color: var(--pl-color-fg);
786
+ margin-bottom: 0.2rem;
787
+ }
788
+ .pl-toast__msg {
789
+ font-size: 13px;
790
+ line-height: 1.5;
791
+ color: var(--pl-color-fg-muted);
792
+ }
793
+ .pl-toast__close {
794
+ flex-shrink: 0;
795
+ font-size: 16px;
796
+ line-height: 1;
797
+ color: var(--pl-color-fg-muted);
798
+ background: transparent;
799
+ border: none;
800
+ cursor: pointer;
801
+ }
802
+ .pl-toast__close:hover {
803
+ color: var(--pl-color-fg);
804
+ }
805
+
806
+ /* ── Tooltip (CSS-only) ──────────────────────────────────────────────────────── */
807
+ .pl-tip-wrap {
808
+ position: relative;
809
+ display: inline-flex;
810
+ }
811
+ .pl-tip {
812
+ position: absolute;
813
+ z-index: 1200;
814
+ pointer-events: none;
815
+ white-space: nowrap;
816
+ padding: 0.25rem 0.5rem;
817
+ font-family: var(--pl-font-mono);
818
+ font-size: 11px;
819
+ color: var(--pl-color-fg);
820
+ background: var(--pl-color-bg-raised);
821
+ border: var(--pl-border-width) solid var(--pl-color-border-strong);
822
+ border-radius: var(--pl-radius);
823
+ box-shadow: var(--pl-shadow-popover);
824
+ opacity: 0;
825
+ transition: opacity var(--pl-motion-fast) var(--pl-motion-ease);
826
+ }
827
+ .pl-tip-wrap:hover .pl-tip,
828
+ .pl-tip-wrap:focus-within .pl-tip {
829
+ opacity: 1;
830
+ }
831
+ .pl-tip--top {
832
+ bottom: calc(100% + 6px);
833
+ left: 50%;
834
+ transform: translateX(-50%);
835
+ }
836
+ .pl-tip--bottom {
837
+ top: calc(100% + 6px);
838
+ left: 50%;
839
+ transform: translateX(-50%);
840
+ }
841
+ .pl-tip--left {
842
+ right: calc(100% + 6px);
843
+ top: 50%;
844
+ transform: translateY(-50%);
845
+ }
846
+ .pl-tip--right {
847
+ left: calc(100% + 6px);
848
+ top: 50%;
849
+ transform: translateY(-50%);
850
+ }
851
+
852
+ /* ── Table (dense data) ──────────────────────────────────────────────────────── */
853
+ .pl-table {
854
+ width: 100%;
855
+ border-collapse: collapse;
856
+ font-size: 13px;
857
+ }
858
+ .pl-table th {
859
+ text-align: left;
860
+ font-family: var(--pl-font-mono);
861
+ font-size: 11px;
862
+ font-weight: var(--pl-font-weight-medium);
863
+ text-transform: uppercase;
864
+ letter-spacing: 0.04em;
865
+ color: var(--pl-color-fg-muted);
866
+ padding: var(--pl-space-2) var(--pl-space-3);
867
+ border-bottom: var(--pl-border-width) solid var(--pl-color-border);
868
+ }
869
+ .pl-table td {
870
+ padding: var(--pl-space-2) var(--pl-space-3);
871
+ color: var(--pl-color-fg);
872
+ border-bottom: var(--pl-border-width) solid var(--pl-color-border);
873
+ }
874
+ .pl-table tbody tr.pl-tr--interactive {
875
+ cursor: pointer;
876
+ transition: background var(--pl-motion-fast) var(--pl-motion-ease);
877
+ }
878
+ .pl-table tbody tr.pl-tr--interactive:hover {
879
+ background: var(--pl-color-bg-hover);
880
+ }
881
+ .pl-table tbody tr.pl-tr--selected {
882
+ background: var(--pl-color-bg-subtle);
883
+ }
884
+
885
+ /* ── Status dot ──────────────────────────────────────────────────────────────── */
886
+ .pl-dot {
887
+ display: inline-block;
888
+ width: 8px;
889
+ height: 8px;
890
+ border-radius: 50%;
891
+ background: var(--pl-color-fg-muted);
892
+ }
893
+ .pl-dot--success {
894
+ background: var(--pl-color-status-success);
895
+ }
896
+ .pl-dot--warning {
897
+ background: var(--pl-color-status-warning);
898
+ }
899
+ .pl-dot--error {
900
+ background: var(--pl-color-status-error);
901
+ }
902
+ .pl-dot--info {
903
+ background: var(--pl-color-status-info);
904
+ }
905
+ .pl-dot--pulse {
906
+ animation: pl-dot-pulse var(--pl-motion-status) var(--pl-motion-ease-in-out) infinite;
907
+ }
908
+ @keyframes pl-dot-pulse {
909
+ 0%,
910
+ 100% {
911
+ opacity: 1;
912
+ }
913
+ 50% {
914
+ opacity: 0.35;
915
+ }
916
+ }
917
+ .pl-dot-row {
918
+ display: inline-flex;
919
+ align-items: center;
920
+ gap: 0.4rem;
921
+ }
922
+ .pl-dot-row__label {
923
+ font-size: 12px;
924
+ color: var(--pl-color-fg-muted);
925
+ }
926
+
927
+ /* ── Spinner ─────────────────────────────────────────────────────────────────── */
928
+ .pl-spinner {
929
+ display: inline-block;
930
+ border: 2px solid var(--pl-color-border-strong);
931
+ border-top-color: var(--pl-color-fg);
932
+ border-radius: 50%;
933
+ animation: pl-spin var(--pl-motion-loading) var(--pl-motion-linear) infinite;
934
+ }
935
+ @keyframes pl-spin {
936
+ to {
937
+ transform: rotate(360deg);
938
+ }
939
+ }
940
+
941
+ /* ── ScrollArea (thin brand scrollbars) ──────────────────────────────────────── */
942
+ .pl-scroll {
943
+ overflow: auto;
944
+ scrollbar-width: thin;
945
+ scrollbar-color: var(--pl-color-border-strong) transparent;
946
+ }
947
+ .pl-scroll::-webkit-scrollbar {
948
+ width: 8px;
949
+ height: 8px;
950
+ }
951
+ .pl-scroll::-webkit-scrollbar-thumb {
952
+ background: var(--pl-color-border-strong);
953
+ border-radius: var(--pl-radius);
954
+ }
955
+ .pl-scroll::-webkit-scrollbar-track {
956
+ background: transparent;
957
+ }
958
+
959
+ /* ── Form controls ───────────────────────────────────────────────────────────── */
960
+ .pl-input {
961
+ width: 100%;
962
+ background: var(--pl-color-bg-raised);
963
+ border: var(--pl-border-width) solid var(--pl-color-border);
964
+ color: var(--pl-color-fg);
965
+ border-radius: var(--pl-radius);
966
+ padding: 9px 11px;
967
+ font: inherit;
968
+ font-family: var(--pl-font-sans);
969
+ font-size: 13px;
970
+ }
971
+ .pl-input::placeholder {
972
+ color: var(--pl-color-fg-muted);
973
+ }
974
+ .pl-input:focus {
975
+ outline: none;
976
+ border-color: var(--pl-color-border-strong);
977
+ }
978
+ .pl-input:disabled {
979
+ opacity: 0.5;
980
+ cursor: not-allowed;
981
+ }
982
+ .pl-textarea {
983
+ resize: vertical;
984
+ min-height: 72px;
985
+ line-height: 1.5;
986
+ }
987
+ .pl-select {
988
+ cursor: pointer;
989
+ }
990
+
991
+ /* Switch */
992
+ .pl-switch {
993
+ display: inline-flex;
994
+ align-items: center;
995
+ gap: 0.5rem;
996
+ cursor: pointer;
997
+ }
998
+ .pl-switch--disabled {
999
+ opacity: 0.5;
1000
+ cursor: not-allowed;
1001
+ }
1002
+ .pl-switch__input {
1003
+ position: absolute;
1004
+ opacity: 0;
1005
+ width: 0;
1006
+ height: 0;
1007
+ }
1008
+ .pl-switch__track {
1009
+ position: relative;
1010
+ display: inline-block;
1011
+ width: 32px;
1012
+ height: 18px;
1013
+ background: var(--pl-color-bg-subtle);
1014
+ border: var(--pl-border-width) solid var(--pl-color-border-strong);
1015
+ border-radius: 999px;
1016
+ transition: background var(--pl-motion-fast) var(--pl-motion-ease);
1017
+ }
1018
+ .pl-switch__thumb {
1019
+ position: absolute;
1020
+ top: 2px;
1021
+ left: 2px;
1022
+ width: 12px;
1023
+ height: 12px;
1024
+ background: var(--pl-color-fg-muted);
1025
+ border-radius: 50%;
1026
+ transition:
1027
+ transform var(--pl-motion-fast) var(--pl-motion-ease),
1028
+ background var(--pl-motion-fast) var(--pl-motion-ease);
1029
+ }
1030
+ .pl-switch__input:checked + .pl-switch__track {
1031
+ background: var(--pl-color-fg);
1032
+ border-color: var(--pl-color-fg);
1033
+ }
1034
+ .pl-switch__input:checked + .pl-switch__track .pl-switch__thumb {
1035
+ transform: translateX(14px);
1036
+ background: var(--pl-color-bg);
1037
+ }
1038
+ .pl-switch__input:focus-visible + .pl-switch__track {
1039
+ outline: 2px solid var(--pl-color-border-strong);
1040
+ outline-offset: 2px;
1041
+ }
1042
+ .pl-switch__label {
1043
+ font-size: 13px;
1044
+ color: var(--pl-color-fg);
1045
+ }
1046
+
1047
+ /* Checkbox */
1048
+ .pl-checkbox {
1049
+ display: inline-flex;
1050
+ align-items: center;
1051
+ gap: 0.5rem;
1052
+ cursor: pointer;
1053
+ }
1054
+ .pl-checkbox--disabled {
1055
+ opacity: 0.5;
1056
+ cursor: not-allowed;
1057
+ }
1058
+ .pl-checkbox__input {
1059
+ position: absolute;
1060
+ opacity: 0;
1061
+ width: 0;
1062
+ height: 0;
1063
+ }
1064
+ .pl-checkbox__box {
1065
+ position: relative;
1066
+ display: inline-block;
1067
+ width: 16px;
1068
+ height: 16px;
1069
+ background: var(--pl-color-bg-raised);
1070
+ border: var(--pl-border-width) solid var(--pl-color-border-strong);
1071
+ border-radius: var(--pl-radius);
1072
+ transition:
1073
+ background var(--pl-motion-fast) var(--pl-motion-ease),
1074
+ border-color var(--pl-motion-fast) var(--pl-motion-ease);
1075
+ }
1076
+ .pl-checkbox__input:checked + .pl-checkbox__box {
1077
+ background: var(--pl-color-fg);
1078
+ border-color: var(--pl-color-fg);
1079
+ }
1080
+ .pl-checkbox__input:checked + .pl-checkbox__box::after {
1081
+ content: "";
1082
+ position: absolute;
1083
+ left: 5px;
1084
+ top: 2px;
1085
+ width: 4px;
1086
+ height: 8px;
1087
+ border: solid var(--pl-color-bg);
1088
+ border-width: 0 2px 2px 0;
1089
+ transform: rotate(45deg);
1090
+ }
1091
+ .pl-checkbox__input:focus-visible + .pl-checkbox__box {
1092
+ outline: 2px solid var(--pl-color-border-strong);
1093
+ outline-offset: 2px;
1094
+ }
1095
+ .pl-checkbox__label {
1096
+ font-size: 13px;
1097
+ color: var(--pl-color-fg);
1098
+ }
1099
+
1100
+ /* Respect reduced-motion for every animation this package introduces. */
1101
+ @media (prefers-reduced-motion: reduce) {
1102
+ .pl-drawer,
1103
+ .pl-toast,
1104
+ .pl-dot--pulse,
1105
+ .pl-spinner {
1106
+ animation: none;
1107
+ }
1108
+ }