@webority/theme 0.80.8 → 0.80.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/theme",
3
- "version": "0.80.8",
3
+ "version": "0.80.9",
4
4
  "description": "Webority shared design system — Bootstrap 5.3 SCSS overrides, --wui-* tokens, and shared component CSS. The single source of brand chrome for React portals and Razor sites.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "publishConfig": {
@@ -267,9 +267,17 @@
267
267
  --color-warning-strong: var(--color-warning-text);
268
268
 
269
269
  --color-success-soft: color-mix(in srgb, var(--wui-success) 18%, transparent);
270
+ --color-success-5: color-mix(in srgb, var(--wui-success) 8%, transparent);
271
+ --color-success-10: color-mix(in srgb, var(--wui-success) 12%, transparent);
270
272
  --color-warning-soft: color-mix(in srgb, var(--wui-warning) 18%, transparent);
273
+ --color-warning-5: color-mix(in srgb, var(--wui-warning) 8%, transparent);
274
+ --color-warning-10: color-mix(in srgb, var(--wui-warning) 12%, transparent);
271
275
  --color-danger-soft: color-mix(in srgb, var(--wui-danger) 18%, transparent);
276
+ --color-danger-5: color-mix(in srgb, var(--wui-danger) 8%, transparent);
277
+ --color-danger-10: color-mix(in srgb, var(--wui-danger) 12%, transparent);
272
278
  --color-info-soft: color-mix(in srgb, var(--wui-info) 18%, transparent);
279
+ --color-info-5: color-mix(in srgb, var(--wui-info) 8%, transparent);
280
+ --color-info-10: color-mix(in srgb, var(--wui-info) 12%, transparent);
273
281
  // The -50 border tone: the light hex would glow on a dark page, so it becomes a translucent
274
282
  // mix of the vivid tone that reads as a border on the dark tint.
275
283
  --color-success-50: color-mix(in srgb, var(--wui-success) 45%, transparent);
@@ -68,8 +68,8 @@
68
68
  bottom: 0;
69
69
  display: grid;
70
70
  place-items: center;
71
- width: calc(max(28px, var(--wui-avatar-size) * 0.3));
72
- height: calc(max(28px, var(--wui-avatar-size) * 0.3));
71
+ width: calc(max(22px, calc(var(--wui-avatar-size) * 0.3)));
72
+ height: calc(max(22px, calc(var(--wui-avatar-size) * 0.3)));
73
73
  border: 2px solid var(--color-surface);
74
74
  border-radius: 50%;
75
75
  background: var(--color-primary);
@@ -25,6 +25,10 @@
25
25
  .wui-chart-card .card-header-actions {
26
26
  gap: 4px;
27
27
  }
28
+ .wui-chart-card > .card-footer {
29
+ font-size: 12.5px;
30
+ color: var(--color-text-muted);
31
+ }
28
32
  .wui-chart-card-tool[aria-pressed="true"] {
29
33
  background: var(--color-primary-soft);
30
34
  color: var(--color-primary-ink);
@@ -76,7 +76,7 @@ wui-chat[position="start"] .wui-chat-panel {
76
76
  }
77
77
 
78
78
  // The question box starts one line tall, as tall as Send beside it, and grows with its text
79
- // up to a few lines. It overrides the textarea's 120px minimum and uneven padding.
79
+ // up to a few lines. Its padding is equal top and bottom, so one line of text sits centred in it.
80
80
  .wui-chat-composer .form-control {
81
81
  min-height: var(--wui-control-height);
82
82
  max-height: 9rem;
@@ -38,7 +38,8 @@
38
38
 
39
39
  // A card that cannot change: its input is disabled directly or by a disabled fieldset.
40
40
  .struct-card:has(.struct-card-input:disabled) {
41
- cursor: default;
41
+ opacity: 0.55;
42
+ cursor: not-allowed;
42
43
  }
43
44
  .struct-card:has(.struct-card-input:disabled):hover {
44
45
  border-color: var(--color-border);
@@ -258,7 +259,7 @@
258
259
  cursor: not-allowed;
259
260
  opacity: 0.6;
260
261
  }
261
- .search-select-control:hover:not(:disabled):not(.open):not([aria-invalid="true"]) {
262
+ .search-select-control:hover:not(:disabled):not(.open):not([aria-invalid="true"]):not(:has(.search-select-ac-input:disabled)):not([aria-disabled="true"]) {
262
263
  // Not while open — an open control keeps its active (primary) border, not the grey hover one.
263
264
  // Not while invalid — an errored control (aria-invalid mirrored from the host) holds its red
264
265
  // border on hover rather than reverting to the grey hover one.
@@ -418,7 +418,6 @@
418
418
  .textarea,
419
419
  textarea.form-control {
420
420
  height: auto;
421
- min-height: 120px;
422
421
  padding: 12px 15px 16px;
423
422
  line-height: 1.5;
424
423
  resize: vertical;
@@ -442,7 +441,7 @@ textarea.form-control.autosize {
442
441
  .form-select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
443
442
  .input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"]):not(
444
443
  .phone-input-wrap > .input
445
- ),
444
+ ):not(:has(.search-select-ac-input:disabled)):not([aria-disabled="true"]),
446
445
  .select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
447
446
  .textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error) {
448
447
  background-color: var(--color-field-bg);
@@ -1290,7 +1289,8 @@ wui-select[compact] {
1290
1289
  .field > .file-input,
1291
1290
  .field > .file-preview,
1292
1291
  .field > .field-error,
1293
- .field > .wui-field-message {
1292
+ .field > .wui-field-message,
1293
+ .field > .wui-score-scale {
1294
1294
  align-self: stretch;
1295
1295
  }
1296
1296
  // A file picker fills its column by default (align-self:stretch fills the field on the cross
@@ -1825,7 +1825,8 @@ wui-otp {
1825
1825
  // Invalid — soft danger border on a clean surface, mirroring AppInput's .error (danger
1826
1826
  // at 30%, no ring), not a solid alarm box.
1827
1827
  .field-error ~ .otp .otp-slot,
1828
- .otp.error .otp-slot {
1828
+ .otp.error .otp-slot,
1829
+ wui-otp[aria-invalid="true"] .otp-slot {
1829
1830
  background: var(--color-surface);
1830
1831
  border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
1831
1832
  box-shadow: none;
@@ -1849,11 +1850,19 @@ wui-otp {
1849
1850
  display: flex;
1850
1851
  align-items: center;
1851
1852
  gap: 12px;
1852
- position: relative;
1853
1853
  user-select: none;
1854
1854
  height: 36px;
1855
1855
  min-width: 200px;
1856
1856
  }
1857
+ // The value label sits beside the rail, so the fill and thumbs measure the track alone.
1858
+ .wui-slider-rail {
1859
+ position: relative;
1860
+ flex: 1;
1861
+ display: flex;
1862
+ align-items: center;
1863
+ align-self: stretch;
1864
+ min-width: 0;
1865
+ }
1857
1866
  // One continuous pill: the filled part runs up to the thumb in the primary accent, the
1858
1867
  // rest stays the neutral border tone.
1859
1868
  .slider-track {
@@ -1864,8 +1873,8 @@ wui-otp {
1864
1873
  border-radius: 999px;
1865
1874
  cursor: pointer;
1866
1875
  }
1867
- // The fill and the thumbs are siblings of the track, positioned against .slider, so each
1868
- // centres itself on the track's midline rather than inheriting the container's height.
1876
+ // The fill and the thumbs are positioned against the rail, so each centres itself on the
1877
+ // track's midline rather than inheriting the container's height.
1869
1878
  .slider-fill {
1870
1879
  position: absolute;
1871
1880
  top: 50%;
@@ -811,7 +811,9 @@ a.info-row:hover .info-value {
811
811
  font-size: 12.5px;
812
812
  color: var(--color-text-muted);
813
813
  }
814
- .timeline-at,
814
+ .timeline-at {
815
+ color: var(--color-text-subtle);
816
+ }
815
817
  .timeline-time {
816
818
  color: var(--color-text-subtle);
817
819
  font-variant-numeric: tabular-nums;
@@ -1497,6 +1499,10 @@ a.info-row:hover .info-value {
1497
1499
  .wui-link:hover {
1498
1500
  color: var(--color-primary-ink);
1499
1501
  }
1502
+ .wui-link.wui-link--surface-dark,
1503
+ .wui-link.wui-link--surface-dark:hover {
1504
+ color: var(--color-on-scrim);
1505
+ }
1500
1506
  .wui-link:focus-visible {
1501
1507
  outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
1502
1508
  outline-offset: 3px;
@@ -307,10 +307,10 @@ button.step.done:focus-visible .step-circle {
307
307
  flex: 0 1 auto;
308
308
  }
309
309
  .stepper-journey .step-line {
310
- flex: 1 1 32px;
311
- min-width: 24px;
310
+ flex: 1 1 8px;
311
+ min-width: 8px;
312
312
  height: 2px;
313
- margin: 0 16px;
313
+ margin: 0 8px;
314
314
  border-radius: 999px;
315
315
  background: var(--color-border-strong);
316
316
  }
@@ -1264,6 +1264,35 @@ wui-wizard-step[hidden] {
1264
1264
  .wizard-stepper {
1265
1265
  margin-bottom: 24px;
1266
1266
  }
1267
+ // The rail sits beside the panel and footer, so it stays in view while a long step scrolls.
1268
+ // A hidden step list (hide-stepper) keeps the stacked layout, so the panel never sits beside an empty column.
1269
+ @include media-breakpoint-up(md) {
1270
+ wui-wizard:has(> .stepper-vertical:not([hidden])) {
1271
+ display: grid;
1272
+ grid-template-columns: minmax(200px, 240px) minmax(0, 1fr);
1273
+ column-gap: 32px;
1274
+ align-items: start;
1275
+ }
1276
+ wui-wizard:has(> .stepper-vertical:not([hidden])) > * {
1277
+ grid-column: 2;
1278
+ }
1279
+ wui-wizard:has(> .stepper-vertical:not([hidden])) > .wui-wizard-topbar {
1280
+ grid-column: 1 / -1;
1281
+ }
1282
+ wui-wizard:has(> .stepper-vertical:not([hidden])) > .stepper-vertical {
1283
+ grid-column: 1;
1284
+ grid-row: span 2;
1285
+ margin-bottom: 0;
1286
+ position: sticky;
1287
+ top: 16px;
1288
+ }
1289
+ wui-wizard:has(> .wui-wizard-topbar):has(> .stepper-vertical:not([hidden])) > .stepper-vertical {
1290
+ grid-row: 2 / span 2;
1291
+ }
1292
+ wui-wizard:has(> .wui-wizard-topbar):has(> .stepper-vertical:not([hidden])) > wui-wizard-step {
1293
+ margin-top: 16px;
1294
+ }
1295
+ }
1267
1296
  // The optional bar above the stepper (`top-bar`): the title at the start, then the step count and the
1268
1297
  // close button at the end.
1269
1298
  .wui-wizard-topbar {
@@ -46,11 +46,14 @@
46
46
  .wui-split-button .btn:focus-visible {
47
47
  z-index: 2;
48
48
  }
49
+ .wui-split-button > .btn.btn-text:first-child {
50
+ padding-inline-end: 0.5rem;
51
+ }
49
52
 
50
53
  // ── Input group ──
51
54
  .wui-addon-group {
52
55
  display: flex;
53
- align-items: stretch;
56
+ align-items: flex-start;
54
57
  width: 100%;
55
58
  }
56
59
  .wui-addon-group > * {
@@ -78,15 +81,24 @@
78
81
  white-space: nowrap;
79
82
  }
80
83
  .wui-addon-group-sm .wui-addon {
81
- min-height: 35px;
84
+ min-height: var(--wui-control-height-sm);
82
85
  padding-inline: 0.75rem;
83
86
  font-size: 0.75rem;
84
87
  }
85
88
  .wui-addon-group-lg .wui-addon {
86
- min-height: 55px;
89
+ min-height: var(--wui-control-height-lg);
87
90
  padding-inline: 1.25rem;
88
91
  font-size: 1rem;
89
92
  }
93
+ .wui-addon-group > .btn {
94
+ height: var(--wui-control-height);
95
+ }
96
+ .wui-addon-group-sm > .btn {
97
+ height: var(--wui-control-height-sm);
98
+ }
99
+ .wui-addon-group-lg > .btn {
100
+ height: var(--wui-control-height-lg);
101
+ }
90
102
 
91
103
  // Square the sides that meet, and let the shared border overlap.
92
104
  .wui-addon-group > :not(:first-child),
@@ -25,7 +25,7 @@
25
25
  align-items: center;
26
26
  gap: 6px;
27
27
  min-width: 0;
28
- max-width: 100%;
28
+ max-width: calc(100% + 12px);
29
29
  min-height: 32px;
30
30
  // The text lines up with its neighbours; only the hover tint reaches past it.
31
31
  margin-inline: -6px;
@@ -1056,6 +1056,9 @@
1056
1056
  .set-uploader[aria-busy="true"] {
1057
1057
  cursor: progress;
1058
1058
  }
1059
+ .set-uploader[aria-busy="true"] .set-uploader-logo {
1060
+ visibility: hidden;
1061
+ }
1059
1062
  .set-uploader-hint {
1060
1063
  margin: 12px 0 0;
1061
1064
  max-width: 240px;
@@ -397,6 +397,9 @@
397
397
  flex: 1 1 0;
398
398
  justify-content: center;
399
399
  }
400
+ .app-tabs-wrap > .app-tabs-fitted {
401
+ flex: 1 1 auto;
402
+ }
400
403
 
401
404
  // Wrapper for a self-contained tabs widget (strip + panels), as <app-tabs>
402
405
  // renders server-side. React composes the strip and its panels itself.
@@ -651,7 +654,7 @@
651
654
  .search-field,
652
655
  .search-input {
653
656
  width: 100%;
654
- padding-left: 40px;
657
+ padding-left: calc(13px + var(--wui-search-icon-size, 18px) + 9px);
655
658
  padding-right: 36px;
656
659
  }
657
660
  .search-clear {
@@ -746,7 +749,7 @@
746
749
  // track the height so they stay centred and clear of the text.
747
750
  .search-wrap.search-sm .search-input {
748
751
  height: var(--wui-control-height-sm);
749
- padding-left: 34px;
752
+ padding-left: calc(13px + var(--wui-search-icon-size, 12px) + 9px);
750
753
  padding-right: 32px;
751
754
  font-size: 13px;
752
755
  }
@@ -761,7 +764,7 @@
761
764
  }
762
765
  .search-wrap.search-lg .search-input {
763
766
  height: var(--wui-control-height-lg);
764
- padding-left: 46px;
767
+ padding-left: calc(13px + var(--wui-search-icon-size, 24px) + 9px);
765
768
  padding-right: 40px;
766
769
  font-size: 16px;
767
770
  }
@@ -16,19 +16,19 @@
16
16
  // White on the strong danger fill, ringed in the surface colour so it reads as sitting on the bell.
17
17
  .wui-notification-center-count {
18
18
  position: absolute;
19
- top: 2px;
20
- right: 0;
21
- box-sizing: content-box;
19
+ top: -2px;
20
+ right: -2px;
21
+ box-sizing: border-box;
22
22
  min-width: 18px;
23
23
  height: 18px;
24
- padding: 0 5px;
24
+ padding: 0 3px;
25
25
  border: 2px solid var(--color-surface);
26
26
  border-radius: 999px;
27
27
  background: var(--color-danger-strong);
28
28
  color: var(--color-progress-label);
29
29
  font-size: 11px;
30
30
  font-weight: 700;
31
- line-height: 18px;
31
+ line-height: 14px;
32
32
  text-align: center;
33
33
  pointer-events: none;
34
34
  }
@@ -570,7 +570,7 @@
570
570
  // Fills that carry white text use the AA-cleared -strong tokens; warning stays dark-on-yellow.
571
571
  .tooltip.wui-tooltip.tone-dark {
572
572
  --wui-tooltip-bg: var(--color-text);
573
- --wui-tooltip-color: #fff;
573
+ --wui-tooltip-color: var(--color-bg);
574
574
  --wui-tooltip-border: transparent;
575
575
  }
576
576
  .tooltip.wui-tooltip.tone-primary {
@@ -228,6 +228,12 @@
228
228
  filter: none;
229
229
  opacity: 1;
230
230
  }
231
+ .wui-section-logo-text {
232
+ font-family: inherit;
233
+ font-weight: 600;
234
+ color: var(--color-text-subtle);
235
+ font-size: var(--wui-fs-lg);
236
+ }
231
237
 
232
238
  // ── Testimonials ──
233
239
  .wui-section-testimonials-list {
@@ -244,19 +244,19 @@
244
244
  // reads as sitting on the bell rather than touching it.
245
245
  .wui-bell-count {
246
246
  position: absolute;
247
- top: 2px;
248
- right: 0;
249
- box-sizing: content-box;
247
+ top: -2px;
248
+ right: -2px;
249
+ box-sizing: border-box;
250
250
  min-width: 18px;
251
251
  height: 18px;
252
- padding: 0 5px;
252
+ padding: 0 3px;
253
253
  border: 2px solid var(--color-surface);
254
254
  border-radius: 999px;
255
255
  background: var(--color-danger-strong);
256
256
  color: var(--color-progress-label);
257
257
  font-size: 11px;
258
258
  font-weight: 700;
259
- line-height: 18px;
259
+ line-height: 14px;
260
260
  text-align: center;
261
261
  }
262
262
  .wui-bell-count[hidden] {
@@ -797,21 +797,31 @@
797
797
  [data-density="compact"] .app-content {
798
798
  --app-content-padding-top: 12px;
799
799
  }
800
- // The skip link is the shell's first stop. It stays off screen until it takes focus, and being
800
+ // The skip link is the shell's first stop. It stays visually hidden until it takes focus, and being
801
801
  // absolutely placed it takes no cell of the shell's grid.
802
802
  .wui-skip-link {
803
803
  position: absolute;
804
804
  top: 8px;
805
805
  left: 8px;
806
806
  z-index: var(--wui-z-fixed);
807
+ width: 1px;
808
+ height: 1px;
809
+ overflow: hidden;
810
+ clip-path: inset(50%);
811
+ white-space: nowrap;
807
812
  padding: 8px 12px;
808
813
  border-radius: var(--wui-radius);
809
814
  background: var(--color-surface);
810
815
  color: var(--color-text);
811
- transform: translateY(-200%);
816
+ }
817
+ .wui-skip-link:focus,
818
+ .wui-skip-link:focus-visible {
819
+ width: auto;
820
+ height: auto;
821
+ clip-path: none;
822
+ overflow: visible;
812
823
  }
813
824
  .wui-skip-link:focus-visible {
814
- transform: none;
815
825
  outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
816
826
  outline-offset: var(--wui-focus-ring-offset);
817
827
  }
@@ -301,6 +301,18 @@
301
301
  cursor: text;
302
302
  padding-right: 8px;
303
303
  }
304
+ .search-select-ac:has(.search-select-ac-input:disabled) {
305
+ background: var(--color-border);
306
+ border-color: transparent;
307
+ color: var(--color-text-subtle);
308
+ cursor: not-allowed;
309
+ }
310
+ .search-select-multi[aria-disabled="true"] {
311
+ background: var(--color-border);
312
+ border-color: transparent;
313
+ color: var(--color-text-subtle);
314
+ cursor: not-allowed;
315
+ }
304
316
  .search-select-ac-input {
305
317
  flex: 1 1 auto;
306
318
  min-width: 0;
@@ -693,6 +693,17 @@
693
693
  }
694
694
  }
695
695
 
696
+ .wui-progress-labelled {
697
+ display: flex;
698
+ flex-direction: column;
699
+ gap: 4px;
700
+ }
701
+ .wui-progress-label {
702
+ font-size: var(--wui-fs-sm);
703
+ color: var(--color-text-muted);
704
+ line-height: 1.3;
705
+ }
706
+
696
707
  // ── Spinner / shimmer ──
697
708
  .wui-spinner {
698
709
  width: 18px;
@@ -726,7 +737,7 @@
726
737
  position: relative;
727
738
  overflow: hidden;
728
739
  display: block;
729
- background: var(--color-bg-muted);
740
+ background: var(--color-border);
730
741
  border-radius: var(--radius-sm);
731
742
  }
732
743
  .skeleton::after {