@webority/theme 0.27.0 → 0.27.2

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.27.0",
3
+ "version": "0.27.2",
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": {
@@ -135,7 +135,8 @@
135
135
  .page-title,
136
136
  .card-title,
137
137
  .wui-modal-title,
138
- .empty-state-title {
138
+ .empty-state-title,
139
+ .result-title {
139
140
  font-family: var(--wui-font-display);
140
141
  font-weight: 600;
141
142
  font-style: normal;
package/scss/_tokens.scss CHANGED
@@ -258,7 +258,10 @@
258
258
  --wui-dark-text: #e6e8ee;
259
259
  --wui-dark-text-muted: #b4b9c6;
260
260
  --wui-dark-text-subtle: #8a90a0;
261
- --wui-dark-primary: #6B83EC;
261
+ // Primary as TEXT and as the fill under near-black ink. Lifted from #6B83EC, which measured
262
+ // 3.75:1 as text on its own soft tint over the muted fill (avatar initials, selected rows, primary
263
+ // pills, the dropzone's Browse link); this clears 4.5:1 on every dark surface and tint.
264
+ --wui-dark-primary: #8097F0;
262
265
  --wui-dark-primary-hover:#93A6F2;
263
266
 
264
267
  // Dark mode shadow remaps — lighter shadows (white ink) for visibility on dark surfaces.
@@ -194,7 +194,7 @@
194
194
  --color-primary-hover: var(--wui-dark-primary-hover);
195
195
  --color-primary-soft: color-mix(in srgb, var(--wui-primary) 20%, transparent);
196
196
  // Dark mode primary text: #fff on #6B83EC measures 3.5:1, below WCAG AA (4.5:1).
197
- // Map to a near-black for safe contrast (7.5:1+) when text sits on primary fill.
197
+ // Map to a near-black for safe contrast (6.9:1 on --wui-dark-primary) when text sits on primary fill.
198
198
  --color-primary-text: #0F0F0F;
199
199
 
200
200
  // On a dark surface the FILL colours are already the readable ones — the darkened
@@ -222,22 +222,22 @@ wui-calendar[data-view="week"] .wui-calendar-surface > * {
222
222
  .wui-calendar-event-success {
223
223
  --fc-event-bg-color: var(--color-success-soft);
224
224
  --fc-event-border-color: var(--color-success);
225
- --fc-event-text-color: var(--color-success-text);
225
+ --fc-event-text-color: var(--color-success-text-on-soft);
226
226
  }
227
227
  .wui-calendar-event-warning {
228
228
  --fc-event-bg-color: var(--color-warning-soft);
229
229
  --fc-event-border-color: var(--color-warning);
230
- --fc-event-text-color: var(--color-warning-text);
230
+ --fc-event-text-color: var(--color-warning-text-on-soft);
231
231
  }
232
232
  .wui-calendar-event-danger {
233
233
  --fc-event-bg-color: var(--color-danger-soft);
234
234
  --fc-event-border-color: var(--color-danger);
235
- --fc-event-text-color: var(--color-danger-text);
235
+ --fc-event-text-color: var(--color-danger-text-on-soft);
236
236
  }
237
237
  .wui-calendar-event-info {
238
238
  --fc-event-bg-color: var(--color-info-soft);
239
239
  --fc-event-border-color: var(--color-info);
240
- --fc-event-text-color: var(--color-info-text);
240
+ --fc-event-text-color: var(--color-info-text-on-soft);
241
241
  }
242
242
 
243
243
  // What a page with no script shows until the element's script replaces it.
@@ -351,7 +351,10 @@ a.info-row:hover .info-value {
351
351
  padding: 0;
352
352
  }
353
353
  .descs-item {
354
- display: contents;
354
+ display: flex;
355
+ flex-direction: column;
356
+ min-width: 0;
357
+ border-bottom: 1px solid var(--color-border);
355
358
  grid-column: span var(--descs-span, 1);
356
359
  }
357
360
  .descs-label {
@@ -360,16 +363,14 @@ a.info-row:hover .info-value {
360
363
  text-transform: uppercase;
361
364
  letter-spacing: 0.04em;
362
365
  color: var(--color-text-subtle);
363
- padding: 12px 16px;
364
- border-bottom: 1px solid var(--color-border);
366
+ padding: 12px 16px 0;
365
367
  margin: 0;
366
368
  }
367
369
  .descs-value {
368
370
  font-size: 14px;
369
371
  font-weight: 500;
370
372
  color: var(--color-text);
371
- padding: 12px 16px;
372
- border-bottom: 1px solid var(--color-border);
373
+ padding: 4px 16px 12px;
373
374
  margin: 0;
374
375
  word-break: break-word;
375
376
  }
@@ -379,24 +380,22 @@ a.info-row:hover .info-value {
379
380
  color: var(--color-text-subtle);
380
381
  }
381
382
  // Small size variant.
382
- .descs-sm .descs-label,
383
+ .descs-sm .descs-label {
384
+ font-size: 12px;
385
+ padding: 8px 12px 0;
386
+ }
383
387
  .descs-sm .descs-value {
384
388
  font-size: 12px;
385
- padding: 8px 12px;
389
+ padding: 4px 12px 8px;
386
390
  }
387
- // Bordered variant removes inner dividers (only outer border on cells).
388
- .descs-bordered .descs-label,
389
- .descs-bordered .descs-value {
391
+ // Bordered variant draws dividers between neighbouring items instead of under each row.
392
+ .descs-bordered .descs-item {
390
393
  border-bottom: none;
391
394
  border-right: 1px solid var(--color-border);
392
395
  }
393
- .descs-bordered .descs-item:last-child .descs-label,
394
- .descs-bordered .descs-item:last-child .descs-value {
396
+ .descs-bordered .descs-item:last-child {
395
397
  border-right: none;
396
398
  }
397
- .descs-bordered .descs-list > :nth-child(2n-1) {
398
- border-bottom: 1px solid var(--color-border);
399
- }
400
399
  // Column variants — set the grid-template-columns.
401
400
  .descs-col-1 .descs-list {
402
401
  --descs-cols: 1;
@@ -843,27 +842,27 @@ a.info-row:hover .info-value {
843
842
  background: var(--color-surface);
844
843
  box-shadow: inset 0 0 0 2px var(--color-border);
845
844
  }
846
- // Solid status discs with a white glyph and a soft concentric halo ring in the
845
+ // Solid status discs with a light glyph (a dark ink in dark mode, where white fails on the bright fills) and a soft concentric halo ring in the
847
846
  // dot's own hue. The fill is softened a touch (mixed toward the surface) so the
848
847
  // states read gentler than the raw brand tones.
849
848
  .timeline--progress .timeline-item.is-done .timeline-dot {
850
- color: var(--color-on-scrim);
849
+ color: var(--color-progress-label);
851
850
  background: color-mix(in srgb, var(--color-success) 82%, var(--color-surface));
852
851
  box-shadow: 0 0 0 var(--wui-timeline-halo) var(--color-success-soft);
853
852
  }
854
853
  .timeline--progress .timeline-item.is-current .timeline-dot {
855
- color: var(--color-on-scrim);
854
+ color: var(--color-progress-label);
856
855
  background: color-mix(in srgb, var(--color-warning) 82%, var(--color-surface));
857
856
  box-shadow: 0 0 0 var(--wui-timeline-halo) var(--color-warning-soft);
858
857
  }
859
858
  .timeline--progress .timeline-item.is-rejected .timeline-dot {
860
- color: var(--color-on-scrim);
859
+ color: var(--color-progress-label);
861
860
  background: color-mix(in srgb, var(--color-danger) 82%, var(--color-surface));
862
861
  box-shadow: 0 0 0 var(--wui-timeline-halo) var(--color-danger-soft);
863
862
  }
864
863
  // Blocked / waiting on an external action — informational blue.
865
864
  .timeline--progress .timeline-item.is-on-hold .timeline-dot {
866
- color: var(--color-on-scrim);
865
+ color: var(--color-progress-label);
867
866
  background: color-mix(in srgb, var(--color-info) 82%, var(--color-surface));
868
867
  box-shadow: 0 0 0 var(--wui-timeline-halo) var(--color-info-soft);
869
868
  }
@@ -43,7 +43,7 @@
43
43
  // specificity, so a .wui-step-tone-* class or an inline --wui-step-* override still wins.
44
44
  :where(.stepper:not(.wizard-stepper)) {
45
45
  --wui-step-accent: var(--color-primary);
46
- --wui-step-accent-fg: var(--color-on-scrim);
46
+ --wui-step-accent-fg: var(--color-primary-text);
47
47
  --wui-step-soft: var(--color-primary-soft);
48
48
  --wui-step-soft-fg: var(--color-primary);
49
49
  }
@@ -501,31 +501,32 @@ button.step:focus-visible .step-circle {
501
501
  // ----------------------------------------------------------------------------
502
502
  .wui-step-tone-primary {
503
503
  --wui-step-accent: var(--color-primary);
504
- --wui-step-accent-fg: var(--color-on-scrim);
504
+ --wui-step-accent-fg: var(--color-primary-text);
505
505
  --wui-step-soft: var(--color-primary-soft);
506
506
  --wui-step-soft-fg: var(--color-primary);
507
507
  }
508
+ // Text on a bright status fill: white in light mode, a dark ink in dark mode, where white fails AA.
508
509
  .wui-step-tone-success {
509
510
  --wui-step-accent: var(--color-success);
510
- --wui-step-accent-fg: var(--color-on-scrim);
511
+ --wui-step-accent-fg: var(--color-progress-label);
511
512
  --wui-step-soft: var(--color-success-soft);
512
513
  --wui-step-soft-fg: var(--color-success-text);
513
514
  }
514
515
  .wui-step-tone-warning {
515
516
  --wui-step-accent: var(--color-warning);
516
- --wui-step-accent-fg: var(--color-on-scrim);
517
+ --wui-step-accent-fg: var(--color-progress-label);
517
518
  --wui-step-soft: var(--color-warning-soft);
518
519
  --wui-step-soft-fg: var(--color-warning-text);
519
520
  }
520
521
  .wui-step-tone-danger {
521
522
  --wui-step-accent: var(--color-danger);
522
- --wui-step-accent-fg: var(--color-on-scrim);
523
+ --wui-step-accent-fg: var(--color-progress-label);
523
524
  --wui-step-soft: var(--color-danger-soft);
524
525
  --wui-step-soft-fg: var(--color-danger-text);
525
526
  }
526
527
  .wui-step-tone-info {
527
528
  --wui-step-accent: var(--color-info);
528
- --wui-step-accent-fg: var(--color-on-scrim);
529
+ --wui-step-accent-fg: var(--color-progress-label);
529
530
  --wui-step-soft: var(--color-info-soft);
530
531
  --wui-step-soft-fg: var(--color-info-text);
531
532
  }
@@ -594,7 +595,7 @@ button.step:focus-visible .step-circle {
594
595
  padding: 5px 14px;
595
596
  border-radius: 999px;
596
597
  background: var(--color-primary);
597
- color: var(--color-on-scrim);
598
+ color: var(--color-primary-text);
598
599
  font-size: 11px;
599
600
  font-weight: 600;
600
601
  text-transform: uppercase;
@@ -87,19 +87,19 @@
87
87
  }
88
88
  .avatar-success {
89
89
  background: var(--color-success-soft);
90
- color: var(--color-success-text);
90
+ color: var(--color-success-text-on-soft);
91
91
  }
92
92
  .avatar-warning {
93
93
  background: var(--color-warning-soft);
94
- color: var(--color-warning-text);
94
+ color: var(--color-warning-text-on-soft);
95
95
  }
96
96
  .avatar-danger {
97
97
  background: var(--color-danger-soft);
98
- color: var(--color-danger-text);
98
+ color: var(--color-danger-text-on-soft);
99
99
  }
100
100
  .avatar-info {
101
101
  background: var(--color-info-soft);
102
- color: var(--color-info-text);
102
+ color: var(--color-info-text-on-soft);
103
103
  }
104
104
  .avatar-auto {
105
105
  background: hsl(var(--avatar-hue, 0) 60% 90%);
@@ -239,7 +239,7 @@
239
239
  border: 2px solid var(--color-surface);
240
240
  border-radius: 999px;
241
241
  background: var(--color-danger-strong);
242
- color: var(--wui-bg-light);
242
+ color: var(--color-progress-label);
243
243
  font-size: 11px;
244
244
  font-weight: 700;
245
245
  line-height: 18px;
@@ -43,7 +43,7 @@
43
43
  place-items: center;
44
44
  border-radius: var(--radius-lg);
45
45
  background: var(--color-primary);
46
- color: var(--color-on-scrim);
46
+ color: var(--color-primary-text);
47
47
  font-size: calc(var(--wui-splash-size, 56px) * 0.39);
48
48
  font-weight: 700;
49
49
  animation: wui-splash-breathe 2.6s ease-in-out infinite;
@@ -263,8 +263,8 @@
263
263
  flex-direction: column;
264
264
  gap: 2px;
265
265
  overflow-y: auto;
266
- // The rail is chrome, not content: a scrollbar here reads as clutter and, at
267
- // 88px collapsed, would eat a meaningful share of the width.
266
+ // A native scrollbar always takes layout width, and its width differs by browser and OS, so
267
+ // it stays hidden; the thumb below is drawn over the links instead.
268
268
  scrollbar-width: none;
269
269
  }
270
270
  .app-sidebar-scroll::-webkit-scrollbar {
@@ -272,6 +272,47 @@
272
272
  width: 0;
273
273
  height: 0;
274
274
  }
275
+ // Scroll thumb for a long menu, shown on hover or keyboard focus and only when the links
276
+ // overflow. It is a sticky pseudo-element over the nav's right edge, moved by the nav's own
277
+ // scroll timeline, so it takes no width. The negative bottom margin cancels its height and the
278
+ // flex gap, so no link moves. Browsers without scroll timelines keep the hidden scrollbar.
279
+ @supports (animation-timeline: scroll()) {
280
+ .app-sidebar-scroll {
281
+ container-type: scroll-state;
282
+ }
283
+ .app-sidebar-scroll::before {
284
+ content: "";
285
+ position: sticky;
286
+ top: 0;
287
+ flex: none;
288
+ align-self: flex-end;
289
+ width: 6px;
290
+ height: 48px;
291
+ margin-bottom: -50px;
292
+ border-radius: 9999px;
293
+ background: var(--wui-scrollbar);
294
+ visibility: hidden;
295
+ opacity: 0;
296
+ pointer-events: none;
297
+ transition: opacity 0.2s var(--wui-ease-ui);
298
+ animation: wui-sidebar-thumb linear both;
299
+ animation-timeline: scroll(nearest);
300
+ }
301
+ @container scroll-state(scrollable: y) {
302
+ .app-sidebar-scroll::before {
303
+ visibility: visible;
304
+ }
305
+ }
306
+ .app-sidebar-scroll:hover::before,
307
+ .app-sidebar-scroll:focus-within::before {
308
+ opacity: 1;
309
+ }
310
+ }
311
+ @keyframes wui-sidebar-thumb {
312
+ to {
313
+ top: calc(100% - 48px);
314
+ }
315
+ }
275
316
  // Between the brand row and the nav — a workspace/tenant switcher, an environment
276
317
  // badge. It must not shrink when the nav overflows. The full card has no place on
277
318
  // the 88px rail, so the collapsed state hides it (the mobile drawer restores it).
@@ -1,11 +1,11 @@
1
1
  // ── Shared tone-pill color mixin ──
2
2
  // Consolidates the tone→color mapping used by .badge, .status-label, and .chip:
3
3
  // background: var(--color-{tone}-soft)
4
- // color: var(--color-{tone}-text) (override via $text — see below)
4
+ // color: var(--color-{tone}-text-on-soft) (override via $text — see below)
5
5
  // border-color: transparent
6
6
  //
7
- // $text exists because the status tones and `primary` name their on-tint color
8
- // differently: --color-{status}-text IS the on-tint hue, but --color-primary-text
7
+ // $text exists because `primary` has no on-tint token: --color-{status}-text-on-soft is the
8
+ // on-tint hue (equal to -text in light, lifted in dark), but --color-primary-text
9
9
  // is the text-on-SOLID-primary color (near-black in dark mode) and fails AA on the
10
10
  // soft tint — primary pills pass var(--color-primary) instead.
11
11
  //
@@ -17,7 +17,7 @@
17
17
  @if $text {
18
18
  color: $text;
19
19
  } @else {
20
- color: var(--color-#{$tone}-text);
20
+ color: var(--color-#{$tone}-text-on-soft);
21
21
  }
22
22
  border-color: transparent;
23
23
  }