@phcdevworks/spectre-ui 0.4.1 → 1.1.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.
@@ -1,6 +1,9 @@
1
1
  @layer components {
2
2
 
3
3
  :root {
4
+ /* structural border width */
5
+ --sp-component-border-width: var(--sp-border-width-base);
6
+
4
7
  /* button roles */
5
8
  --sp-component-button-border-base: var(--sp-component-button-ghost-bg);
6
9
  --sp-component-button-shadow: var(--sp-shadow-sm);
@@ -36,6 +39,21 @@
36
39
  --sp-component-button-success-bg-disabled: var(--sp-button-success-bgdisabled);
37
40
  --sp-component-button-success-text: var(--sp-button-success-text);
38
41
  --sp-component-button-success-text-disabled: var(--sp-button-success-textdisabled);
42
+ /* FLAG: buttons.cta tokens in spectre-tokens v2.x use warning.500 (Gold),
43
+ which violates the Aesthetic Audit guardrails. Remaining on accent palette. */
44
+ --sp-component-button-cta-bg: var(--sp-color-accent-600);
45
+ --sp-component-button-cta-bg-hover: var(--sp-color-accent-700);
46
+ --sp-component-button-cta-bg-active: var(--sp-color-accent-800);
47
+ --sp-component-button-cta-bg-disabled: var(--sp-color-accent-200);
48
+ --sp-component-button-cta-text: var(--sp-color-neutral-50);
49
+ --sp-component-button-cta-text-disabled: var(--sp-color-neutral-400);
50
+ --sp-component-button-cta-shadow: 0 4px 14px 0 var(--sp-color-accent-500) / 0.39;
51
+ --sp-component-button-accent-bg: var(--sp-button-accent-bg);
52
+ --sp-component-button-accent-bg-hover: var(--sp-button-accent-bghover);
53
+ --sp-component-button-accent-bg-active: var(--sp-button-accent-bgactive);
54
+ --sp-component-button-accent-bg-disabled: var(--sp-button-accent-bgdisabled);
55
+ --sp-component-button-accent-text: var(--sp-button-accent-text);
56
+ --sp-component-button-accent-text-disabled: var(--sp-button-accent-textdisabled);
39
57
 
40
58
  /* card roles */
41
59
  --sp-component-card-bg: var(--sp-surface-card);
@@ -77,12 +95,29 @@
77
95
  --sp-component-badge-radius: var(--sp-radius-pill);
78
96
  --sp-component-badge-primary-bg: var(--sp-button-primary-bg);
79
97
  --sp-component-badge-primary-text: var(--sp-button-text-on-primary);
98
+ --sp-component-badge-secondary-bg: var(--sp-button-secondary-bg);
99
+ --sp-component-badge-secondary-text: var(--sp-button-secondary-text);
100
+ --sp-component-badge-secondary-border: var(--sp-button-secondary-border);
80
101
  --sp-component-badge-success-bg: var(--sp-badge-success-bg);
81
102
  --sp-component-badge-success-text: var(--sp-badge-success-text);
82
103
  --sp-component-badge-warning-bg: var(--sp-badge-warning-bg);
83
104
  --sp-component-badge-warning-text: var(--sp-badge-warning-text);
84
105
  --sp-component-badge-danger-bg: var(--sp-badge-danger-bg);
85
106
  --sp-component-badge-danger-text: var(--sp-badge-danger-text);
107
+ --sp-component-badge-neutral-bg: var(--sp-badge-neutral-bg);
108
+ --sp-component-badge-neutral-text: var(--sp-badge-neutral-text);
109
+ --sp-component-badge-info-bg: var(--sp-badge-info-bg);
110
+ --sp-component-badge-info-text: var(--sp-badge-info-text);
111
+
112
+ /* badge hover states — missing from core token exports, mapped to semantic logic */
113
+ --sp-component-badge-primary-bg-hover: var(--sp-button-primary-bghover);
114
+ --sp-component-badge-secondary-bg-hover: var(--sp-button-secondary-bghover);
115
+ --sp-component-badge-success-bg-hover: var(--sp-color-success-200);
116
+ --sp-component-badge-warning-bg-hover: var(--sp-color-warning-200);
117
+ --sp-component-badge-danger-bg-hover: var(--sp-color-error-200);
118
+ --sp-component-badge-neutral-bg-hover: var(--sp-color-neutral-200);
119
+ --sp-component-badge-info-bg-hover: var(--sp-color-info-200);
120
+
86
121
  --sp-component-badge-padding-x-sm: var(--sp-space-8);
87
122
  --sp-component-badge-padding-x-md: var(--sp-space-12);
88
123
  --sp-component-badge-padding-x-lg: var(--sp-space-16);
@@ -105,6 +140,67 @@
105
140
  --sp-component-iconbox-danger-text: var(--sp-icon-box-icon-danger);
106
141
  --sp-component-iconbox-info-bg: var(--sp-color-info-50);
107
142
  --sp-component-iconbox-info-text: var(--sp-badge-info-text);
143
+
144
+ /* testimonial roles */
145
+ --sp-component-testimonial-bg: var(--sp-surface-card);
146
+ --sp-component-testimonial-border: var(--sp-color-neutral-200);
147
+ --sp-component-testimonial-text: var(--sp-color-neutral-700);
148
+ --sp-component-testimonial-author-name: var(--sp-color-neutral-900);
149
+ --sp-component-testimonial-author-title: var(--sp-color-neutral-500);
150
+ --sp-component-testimonial-quote-mark: var(--sp-color-neutral-300);
151
+
152
+ /* pricing card roles */
153
+ --sp-component-pricing-card-bg: var(--sp-surface-card);
154
+ --sp-component-pricing-card-border: var(--sp-color-neutral-200);
155
+ /* FLAG: component.pricingCard.featuredBg in tokens is info.600 (Blue), which clashing
156
+ with the warning.500 (Gold) badge. Remaining on neutral-900 to pass Aesthetic Audit. */
157
+ --sp-component-pricing-card-featured-bg: var(--sp-color-neutral-900);
158
+ --sp-component-pricing-card-featured-text: var(--sp-color-neutral-50);
159
+ --sp-component-pricing-card-featured-badge-bg: var(--sp-color-warning-500);
160
+ --sp-component-pricing-card-featured-badge-text: var(--sp-color-neutral-900);
161
+ --sp-component-pricing-card-price: var(--sp-color-neutral-900);
162
+ --sp-component-pricing-card-featured-price: var(--sp-color-neutral-50);
163
+ --sp-component-pricing-card-price-description: var(--sp-color-neutral-500);
164
+
165
+ /* rating roles */
166
+ --sp-component-rating-star-filled: var(--sp-color-warning-500);
167
+ --sp-component-rating-star-empty: var(--sp-color-neutral-200);
168
+ --sp-component-rating-text: var(--sp-color-neutral-500);
169
+ }
170
+
171
+ /* dark mode overrides for complex component tokens not yet exported by spectre-tokens v2.x */
172
+ :root[data-spectre-theme="dark"] {
173
+ --sp-component-testimonial-bg: var(--sp-color-neutral-800);
174
+ --sp-component-testimonial-border: var(--sp-color-neutral-700);
175
+ --sp-component-testimonial-text: var(--sp-color-neutral-300);
176
+ --sp-component-testimonial-author-name: var(--sp-color-neutral-100);
177
+ --sp-component-testimonial-author-title: var(--sp-color-neutral-400);
178
+ --sp-component-testimonial-quote-mark: var(--sp-color-neutral-600);
179
+
180
+ --sp-component-pricing-card-bg: var(--sp-color-neutral-800);
181
+ --sp-component-pricing-card-border: var(--sp-color-neutral-700);
182
+ --sp-component-pricing-card-price: var(--sp-color-neutral-100);
183
+ --sp-component-pricing-card-price-description: var(--sp-color-neutral-400);
184
+
185
+ --sp-component-rating-star-empty: var(--sp-color-neutral-700);
186
+ --sp-component-rating-text: var(--sp-color-neutral-400);
187
+
188
+ --sp-component-badge-success-bg: var(--sp-color-success-800);
189
+ --sp-component-badge-success-text: var(--sp-color-success-100);
190
+ --sp-component-badge-warning-bg: var(--sp-color-warning-800);
191
+ --sp-component-badge-warning-text: var(--sp-color-warning-100);
192
+ --sp-component-badge-danger-bg: var(--sp-color-error-800);
193
+ --sp-component-badge-danger-text: var(--sp-color-error-100);
194
+ --sp-component-badge-neutral-bg: var(--sp-color-neutral-700);
195
+ --sp-component-badge-neutral-text: var(--sp-color-neutral-100);
196
+ --sp-component-badge-info-bg: var(--sp-color-info-800);
197
+ --sp-component-badge-info-text: var(--sp-color-info-100);
198
+
199
+ --sp-component-badge-success-bg-hover: var(--sp-color-success-700);
200
+ --sp-component-badge-warning-bg-hover: var(--sp-color-warning-700);
201
+ --sp-component-badge-danger-bg-hover: var(--sp-color-error-700);
202
+ --sp-component-badge-neutral-bg-hover: var(--sp-color-neutral-600);
203
+ --sp-component-badge-info-bg-hover: var(--sp-color-info-700);
108
204
  }
109
205
 
110
206
  /* BUTTONS -------------------------------------------------------------- */
@@ -115,7 +211,7 @@
115
211
  gap: var(--sp-space-4);
116
212
  padding: var(--sp-space-4) var(--sp-space-16);
117
213
  border-radius: var(--sp-radius-md);
118
- border: 1px solid var(--sp-component-button-border-base);
214
+ border: var(--sp-component-border-width) solid var(--sp-component-button-border-base);
119
215
  font-family: var(--sp-font-family-sans);
120
216
  font-size: var(--sp-font-md-size);
121
217
  line-height: 1;
@@ -148,6 +244,10 @@
148
244
  width: 100%;
149
245
  }
150
246
 
247
+ .sp-btn--pill {
248
+ border-radius: var(--sp-radius-pill);
249
+ }
250
+
151
251
  .sp-btn--icon {
152
252
  padding-inline: var(--sp-space-12);
153
253
  padding-block: var(--sp-space-4);
@@ -172,16 +272,8 @@
172
272
  line-height: var(--sp-font-lg-line-height);
173
273
  }
174
274
 
175
- /* Generic forced-state helpers (safe, variant rules still set actual colors) */
176
- .sp-btn.sp-btn--hover,
177
- .sp-btn.is-hover {
178
- /* no-op here; variant sections below define the actual hover colors */
179
- }
275
+ /* Generic forced-state helpers (actual colors defined in variant sections below) */
180
276
 
181
- .sp-btn.sp-btn--active,
182
- .sp-btn.is-active {
183
- /* no-op here; variant sections below define the actual active colors */
184
- }
185
277
 
186
278
  /* primary */
187
279
  .sp-btn--primary {
@@ -307,6 +399,56 @@
307
399
  color: var(--sp-component-button-success-text-disabled);
308
400
  }
309
401
 
402
+ /* cta */
403
+ .sp-btn--cta {
404
+ background-color: var(--sp-component-button-cta-bg);
405
+ color: var(--sp-component-button-cta-text);
406
+ box-shadow: var(--sp-component-button-cta-shadow);
407
+ }
408
+
409
+ .sp-btn--cta.sp-btn--hover,
410
+ .sp-btn--cta.is-hover,
411
+ .sp-btn--cta:hover {
412
+ background-color: var(--sp-component-button-cta-bg-hover);
413
+ }
414
+
415
+ .sp-btn--cta.sp-btn--active,
416
+ .sp-btn--cta.is-active,
417
+ .sp-btn--cta:active {
418
+ background-color: var(--sp-component-button-cta-bg-active);
419
+ }
420
+
421
+ .sp-btn--cta.sp-btn--disabled,
422
+ .sp-btn--cta:disabled {
423
+ background-color: var(--sp-component-button-cta-bg-disabled);
424
+ color: var(--sp-component-button-cta-text-disabled);
425
+ box-shadow: none;
426
+ }
427
+
428
+ /* accent */
429
+ .sp-btn--accent {
430
+ background-color: var(--sp-component-button-accent-bg);
431
+ color: var(--sp-component-button-accent-text);
432
+ }
433
+
434
+ .sp-btn--accent.sp-btn--hover,
435
+ .sp-btn--accent.is-hover,
436
+ .sp-btn--accent:hover {
437
+ background-color: var(--sp-component-button-accent-bg-hover);
438
+ }
439
+
440
+ .sp-btn--accent.sp-btn--active,
441
+ .sp-btn--accent.is-active,
442
+ .sp-btn--accent:active {
443
+ background-color: var(--sp-component-button-accent-bg-active);
444
+ }
445
+
446
+ .sp-btn--accent.sp-btn--disabled,
447
+ .sp-btn--accent:disabled {
448
+ background-color: var(--sp-component-button-accent-bg-disabled);
449
+ color: var(--sp-component-button-accent-text-disabled);
450
+ }
451
+
310
452
  /* INPUTS --------------------------------------------------------------- */
311
453
 
312
454
  .sp-input-wrapper {
@@ -340,7 +482,7 @@
340
482
  appearance: none;
341
483
  padding: var(--sp-space-4) var(--sp-space-16);
342
484
  border-radius: var(--sp-radius-md);
343
- border: 1px solid var(--sp-component-input-role-border);
485
+ border: var(--sp-component-border-width) solid var(--sp-component-input-role-border);
344
486
  background-color: var(--sp-component-input-role-bg);
345
487
  color: var(--sp-component-input-role-text);
346
488
  font-family: var(--sp-font-family-sans);
@@ -378,10 +520,14 @@
378
520
  width: 100%;
379
521
  }
380
522
 
523
+ .sp-input--pill {
524
+ border-radius: var(--sp-radius-pill);
525
+ }
526
+
381
527
  .sp-input:focus,
382
528
  .sp-input--focus {
383
529
  border-color: var(--sp-component-input-role-border-focus);
384
- box-shadow: 0 0 0 calc(var(--sp-focus-ring-width) + 1px) var(--sp-component-input-role-ring);
530
+ box-shadow: 0 0 0 calc(var(--sp-focus-ring-width) + var(--sp-component-border-width)) var(--sp-component-input-role-ring);
385
531
  outline: none;
386
532
  }
387
533
 
@@ -422,7 +568,7 @@
422
568
  border-radius: var(--sp-radius-lg);
423
569
  padding: var(--sp-space-24);
424
570
  box-shadow: var(--sp-component-card-shadow);
425
- border: 1px solid var(--sp-component-card-border-base);
571
+ border: var(--sp-component-border-width) solid var(--sp-component-card-border-base);
426
572
  }
427
573
 
428
574
  .sp-card p {
@@ -463,6 +609,11 @@
463
609
  height: 100%;
464
610
  }
465
611
 
612
+ .sp-card--disabled {
613
+ opacity: var(--sp-opacity-disabled);
614
+ pointer-events: none;
615
+ }
616
+
466
617
  .sp-card--interactive {
467
618
  cursor: pointer;
468
619
  transition:
@@ -473,7 +624,7 @@
473
624
  .sp-card--interactive:hover,
474
625
  .sp-card--interactive:focus-visible,
475
626
  .sp-card--interactive:focus-within {
476
- transform: translateY(-1px);
627
+ transform: translateY(calc(var(--sp-component-border-width) * -1));
477
628
  box-shadow: var(--sp-component-card-shadow-elevated);
478
629
  }
479
630
 
@@ -490,7 +641,7 @@
490
641
  padding: var(--sp-component-badge-padding-y-md) var(--sp-component-badge-padding-x-md);
491
642
  font-size: var(--sp-font-sm-size);
492
643
  line-height: var(--sp-font-sm-line-height);
493
- border: 1px solid transparent;
644
+ border: var(--sp-component-border-width) solid transparent;
494
645
  white-space: nowrap;
495
646
  }
496
647
 
@@ -517,21 +668,75 @@
517
668
  color: var(--sp-component-badge-primary-text);
518
669
  }
519
670
 
671
+ .sp-badge--primary.sp-badge--interactive:hover {
672
+ background-color: var(--sp-component-badge-primary-bg-hover);
673
+ }
674
+
675
+ .sp-badge--secondary {
676
+ background-color: var(--sp-component-badge-secondary-bg);
677
+ color: var(--sp-component-badge-secondary-text);
678
+ border-color: var(--sp-component-badge-secondary-border);
679
+ }
680
+
681
+ .sp-badge--secondary.sp-badge--interactive:hover {
682
+ background-color: var(--sp-component-badge-secondary-bg-hover);
683
+ }
684
+
520
685
  .sp-badge--success {
521
686
  background-color: var(--sp-component-badge-success-bg);
522
687
  color: var(--sp-component-badge-success-text);
523
688
  }
524
689
 
690
+ .sp-badge--success.sp-badge--interactive:hover {
691
+ background-color: var(--sp-component-badge-success-bg-hover);
692
+ }
693
+
525
694
  .sp-badge--warning {
526
695
  background-color: var(--sp-component-badge-warning-bg);
527
696
  color: var(--sp-component-badge-warning-text);
528
697
  }
529
698
 
699
+ .sp-badge--warning.sp-badge--interactive:hover {
700
+ background-color: var(--sp-component-badge-warning-bg-hover);
701
+ }
702
+
530
703
  .sp-badge--danger {
531
704
  background-color: var(--sp-component-badge-danger-bg);
532
705
  color: var(--sp-component-badge-danger-text);
533
706
  }
534
707
 
708
+ .sp-badge--danger.sp-badge--interactive:hover {
709
+ background-color: var(--sp-component-badge-danger-bg-hover);
710
+ }
711
+
712
+ .sp-badge--neutral {
713
+ background-color: var(--sp-component-badge-neutral-bg);
714
+ color: var(--sp-component-badge-neutral-text);
715
+ }
716
+
717
+ .sp-badge--neutral.sp-badge--interactive:hover {
718
+ background-color: var(--sp-component-badge-neutral-bg-hover);
719
+ }
720
+
721
+ .sp-badge--info {
722
+ background-color: var(--sp-component-badge-info-bg);
723
+ color: var(--sp-component-badge-info-text);
724
+ }
725
+
726
+ .sp-badge--info.sp-badge--interactive:hover {
727
+ background-color: var(--sp-component-badge-info-bg-hover);
728
+ }
729
+
730
+ .sp-badge--interactive {
731
+ cursor: pointer;
732
+ transition: background-color var(--sp-duration-fast) var(--sp-easing-out);
733
+ }
734
+
735
+ .sp-badge--disabled {
736
+ opacity: var(--sp-opacity-disabled);
737
+ pointer-events: none;
738
+ }
739
+
535
740
  /* ICON BOXES ----------------------------------------------------------- */
536
741
 
537
742
  .sp-iconbox {
@@ -636,4 +841,155 @@
636
841
  background-color: var(--sp-component-iconbox-info-bg);
637
842
  color: var(--sp-component-iconbox-info-text);
638
843
  }
844
+
845
+ .sp-iconbox--disabled {
846
+ opacity: var(--sp-opacity-disabled);
847
+ pointer-events: none;
848
+ }
849
+
850
+ /* TESTIMONIALS --------------------------------------------------------- */
851
+
852
+ .sp-testimonial {
853
+ background-color: var(--sp-component-testimonial-bg);
854
+ border: var(--sp-component-border-width) solid var(--sp-component-testimonial-border);
855
+ border-radius: var(--sp-radius-lg);
856
+ padding: var(--sp-space-32);
857
+ display: flex;
858
+ flex-direction: column;
859
+ gap: var(--sp-space-24);
860
+ }
861
+
862
+ .sp-testimonial-quote {
863
+ color: var(--sp-component-testimonial-text);
864
+ font-size: var(--sp-font-lg-size);
865
+ line-height: var(--sp-font-lg-line-height);
866
+ font-style: italic;
867
+ position: relative;
868
+ }
869
+
870
+ .sp-testimonial-quote::before {
871
+ content: "“";
872
+ color: var(--sp-component-testimonial-quote-mark);
873
+ font-size: var(--sp-space-48);
874
+ position: absolute;
875
+ top: calc(var(--sp-space-24) * -1);
876
+ left: calc(var(--sp-space-16) * -1);
877
+ opacity: var(--sp-opacity-overlay);
878
+ }
879
+
880
+ .sp-testimonial-author {
881
+ display: flex;
882
+ align-items: center;
883
+ gap: var(--sp-space-16);
884
+ }
885
+
886
+ .sp-testimonial-author-info {
887
+ display: flex;
888
+ flex-direction: column;
889
+ }
890
+
891
+ .sp-testimonial-author-name {
892
+ color: var(--sp-component-testimonial-author-name);
893
+ font-weight: var(--sp-font-xl-weight);
894
+ font-size: var(--sp-font-md-size);
895
+ }
896
+
897
+ .sp-testimonial-author-title {
898
+ color: var(--sp-component-testimonial-author-title);
899
+ font-size: var(--sp-font-sm-size);
900
+ }
901
+
902
+ /* PRICING CARDS -------------------------------------------------------- */
903
+
904
+ .sp-pricing-card {
905
+ background-color: var(--sp-component-pricing-card-bg);
906
+ border: var(--sp-component-border-width) solid var(--sp-component-pricing-card-border);
907
+ border-radius: var(--sp-radius-lg);
908
+ padding: var(--sp-space-32);
909
+ display: flex;
910
+ flex-direction: column;
911
+ gap: var(--sp-space-24);
912
+ position: relative;
913
+ transition: transform var(--sp-duration-fast) var(--sp-easing-out);
914
+ }
915
+
916
+ .sp-pricing-card--featured {
917
+ background-color: var(--sp-component-pricing-card-featured-bg);
918
+ color: var(--sp-component-pricing-card-featured-text);
919
+ transform: scale(1.05);
920
+ z-index: 1;
921
+ border: none;
922
+ }
923
+
924
+ .sp-pricing-card--disabled {
925
+ opacity: var(--sp-opacity-disabled);
926
+ pointer-events: none;
927
+ }
928
+
929
+ .sp-pricing-card-badge {
930
+ position: absolute;
931
+ top: var(--sp-space-16);
932
+ right: var(--sp-space-16);
933
+ background-color: var(--sp-component-pricing-card-featured-badge-bg);
934
+ color: var(--sp-component-pricing-card-featured-badge-text);
935
+ padding: var(--sp-space-4) var(--sp-space-12);
936
+ border-radius: var(--sp-radius-pill);
937
+ font-size: var(--sp-font-xs-size);
938
+ font-weight: var(--sp-font-md-weight);
939
+ }
940
+
941
+ .sp-pricing-card-price-container {
942
+ display: flex;
943
+ align-items: baseline;
944
+ gap: var(--sp-space-4);
945
+ }
946
+
947
+ .sp-pricing-card-price {
948
+ font-size: var(--sp-font-2xl-size);
949
+ font-weight: var(--sp-font-2xl-weight);
950
+ color: var(--sp-component-pricing-card-price);
951
+ }
952
+
953
+ .sp-pricing-card--featured .sp-pricing-card-price {
954
+ color: var(--sp-component-pricing-card-featured-price);
955
+ }
956
+
957
+ .sp-pricing-card-description {
958
+ color: var(--sp-component-pricing-card-price-description);
959
+ font-size: var(--sp-font-sm-size);
960
+ }
961
+
962
+ .sp-pricing-card--featured .sp-pricing-card-description {
963
+ color: var(--sp-component-pricing-card-featured-text);
964
+ opacity: 0.8;
965
+ }
966
+
967
+ /* RATING --------------------------------------------------------------- */
968
+
969
+ .sp-rating {
970
+ display: inline-flex;
971
+ align-items: center;
972
+ gap: var(--sp-space-8);
973
+ }
974
+
975
+ .sp-rating-stars {
976
+ display: flex;
977
+ gap: var(--sp-space-4);
978
+ color: var(--sp-component-rating-star-empty);
979
+ }
980
+
981
+ .sp-rating-star {
982
+ display: flex;
983
+ align-items: center;
984
+ justify-content: center;
985
+ }
986
+
987
+ .sp-rating-star--filled {
988
+ color: var(--sp-component-rating-star-filled);
989
+ }
990
+
991
+ .sp-rating-text {
992
+ color: var(--sp-component-rating-text);
993
+ font-size: var(--sp-font-sm-size);
994
+ }
639
995
  }