@webority/theme 0.76.0 → 0.77.1

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.
@@ -9,6 +9,7 @@
9
9
  // .stepper — compact: numbered circle above a label, line behind.
10
10
  // .stepper-journey — wide: 40px dot beside a label + title, for a page masthead.
11
11
  // .stepper-icons — large connected icon badges with a "STEP n" eyebrow.
12
+ // .wui-step-tiles — a row of tiles: rounded icon square, label and a state line, chevrons between.
12
13
  //
13
14
  // Fully themable through a small set of `--wui-step-*` custom properties — set them on
14
15
  // the stepper (or the wizard host, or any ancestor: they inherit), or flip the whole
@@ -517,11 +518,160 @@ button.step.done:focus-visible .step-circle {
517
518
  }
518
519
  }
519
520
 
521
+ // .wui-step-tiles — each step is a list item holding a rounded icon square with the label and a
522
+ // state line (Done, Current, To do) beside it; chevrons join the tiles. Like every variant it is one
523
+ // brand-primary accent: the current tile is solid accent and done tiles the soft tint, so a tone
524
+ // class recolours the current one and a done-tone class the finished ones.
525
+ // ----------------------------------------------------------------------------
526
+ .wui-step-tiles {
527
+ padding: 0 16px;
528
+ }
529
+ .wui-step-tiles > ol {
530
+ display: flex;
531
+ align-items: center;
532
+ gap: 6px;
533
+ width: 100%;
534
+ margin: 0;
535
+ padding: 0;
536
+ list-style: none;
537
+ }
538
+ .wui-step-tile {
539
+ display: flex;
540
+ align-items: center;
541
+ min-width: 0;
542
+ }
543
+ // Every tile after the first takes an equal share of the free width and centres its chevron in it.
544
+ .wui-step-tile + .wui-step-tile {
545
+ flex: 1 1 auto;
546
+ padding-inline-start: 12px;
547
+ }
548
+ .wui-step-tile + .wui-step-tile > .wui-step-tile-body {
549
+ margin-inline-start: 12px;
550
+ }
551
+ .wui-step-tile + .wui-step-tile::before {
552
+ content: "";
553
+ flex: none;
554
+ width: 7px;
555
+ height: 7px;
556
+ margin-inline: auto;
557
+ border-top: 2px solid var(--wui-step-connector, var(--color-border-strong));
558
+ border-right: 2px solid var(--wui-step-connector, var(--color-border-strong));
559
+ transform: rotate(45deg);
560
+ }
561
+ .wui-step-tile-body {
562
+ display: flex;
563
+ align-items: center;
564
+ gap: 10px;
565
+ min-width: 0;
566
+ padding: 4px 8px 4px 0;
567
+ border: 0;
568
+ border-radius: var(--radius);
569
+ background: none;
570
+ font: inherit;
571
+ text-align: start;
572
+ color: inherit;
573
+ }
574
+ button.wui-step-tile-body {
575
+ cursor: pointer;
576
+ }
577
+ button.wui-step-tile-body:focus-visible {
578
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
579
+ outline-offset: var(--wui-focus-ring-offset);
580
+ }
581
+ .wui-step-tiles .step-circle {
582
+ width: var(--wui-step-tile-size, 34px);
583
+ height: var(--wui-step-tile-size, 34px);
584
+ border: 0;
585
+ border-radius: var(--radius);
586
+ background: var(--color-bg-muted);
587
+ color: var(--color-text-subtle);
588
+ font-size: var(--wui-step-number-font, 13px);
589
+ }
590
+ .wui-step-tile.active .step-circle {
591
+ background: var(--wui-step-accent, var(--color-primary-ink));
592
+ color: var(--wui-step-accent-fg, var(--color-on-primary-ink));
593
+ }
594
+ .wui-step-tile.done .step-circle {
595
+ background: var(--wui-step-done-soft, var(--wui-step-soft, var(--color-primary-soft)));
596
+ color: var(--wui-step-done-soft-fg, var(--wui-step-soft-fg, var(--color-primary-ink)));
597
+ }
598
+ .wui-step-tile.error .step-circle {
599
+ background: var(--color-danger-soft);
600
+ color: var(--color-danger-text);
601
+ }
602
+ .wui-step-tile.skipped .step-circle {
603
+ border: 1px dashed var(--color-border-strong);
604
+ color: var(--color-text-muted);
605
+ }
606
+ .wui-step-tiles .step-text {
607
+ display: flex;
608
+ flex-direction: column;
609
+ gap: 1px;
610
+ min-width: 0;
611
+ }
612
+ .wui-step-tiles .step-label {
613
+ max-width: none;
614
+ font-size: var(--wui-step-label-font, 13px);
615
+ font-weight: 600;
616
+ line-height: 1.25;
617
+ color: var(--color-text);
618
+ white-space: nowrap;
619
+ }
620
+ .wui-step-tile.active .step-label {
621
+ color: var(--wui-step-accent, var(--color-primary-ink));
622
+ }
623
+ .wui-step-tile.error .step-label {
624
+ color: var(--color-danger-text);
625
+ }
626
+ button.wui-step-tile-body:hover .step-label {
627
+ color: var(--wui-step-accent, var(--color-primary-ink));
628
+ }
629
+ .wui-step-tiles .wui-step-tile-state {
630
+ font-size: 12px;
631
+ line-height: 1.3;
632
+ color: var(--color-text-muted);
633
+ white-space: nowrap;
634
+ }
635
+ // A vertical wizard, or a phone, stacks the tiles into a list; the chevrons only make sense in a row.
636
+ .wui-step-tiles.stepper-vertical > ol {
637
+ flex-direction: column;
638
+ align-items: flex-start;
639
+ gap: 12px;
640
+ }
641
+ .wui-step-tiles.stepper-vertical .wui-step-tile + .wui-step-tile {
642
+ flex: none;
643
+ padding-inline-start: 0;
644
+ }
645
+ .wui-step-tiles.stepper-vertical .wui-step-tile + .wui-step-tile > .wui-step-tile-body {
646
+ margin-inline-start: 0;
647
+ }
648
+ .wui-step-tiles.stepper-vertical .wui-step-tile + .wui-step-tile::before {
649
+ content: none;
650
+ }
651
+ @include media-breakpoint-down(md) {
652
+ .wui-step-tiles.wui-step-tiles > ol {
653
+ flex-direction: column;
654
+ align-items: flex-start;
655
+ gap: 12px;
656
+ }
657
+ .wui-step-tiles.wui-step-tiles .wui-step-tile + .wui-step-tile {
658
+ flex: none;
659
+ padding-inline-start: 0;
660
+ }
661
+ .wui-step-tiles.wui-step-tiles .wui-step-tile + .wui-step-tile > .wui-step-tile-body {
662
+ margin-inline-start: 0;
663
+ }
664
+ .wui-step-tiles.wui-step-tiles .wui-step-tile + .wui-step-tile::before {
665
+ content: none;
666
+ }
667
+ }
668
+
520
669
  // No connectors: the wizard's hide-connectors option drops the line between steps on every
521
670
  // variant and orientation. Placed after the variants so it outranks their equal-specificity
522
671
  // rails; the journey bar's .step-line siblings are simply not emitted.
523
672
  .wui-stepper-no-connectors .step + .step::before,
524
- .wui-stepper-no-connectors .step:not(:last-child)::after {
673
+ .wui-stepper-no-connectors .step:not(:last-child)::after,
674
+ .wui-stepper-no-connectors .wui-step-tile + .wui-step-tile::before {
525
675
  content: none;
526
676
  }
527
677
 
@@ -999,6 +1149,11 @@ button.step.done:focus-visible .step-circle {
999
1149
  // width here and lines up with the fields beside it. A .date-w-* class on the field still wins.
1000
1150
  --wui-datepicker-width: 100%;
1001
1151
  }
1152
+ @for $n from 1 through 12 {
1153
+ .wui-form-cols-#{$n} {
1154
+ --form-cols: #{$n};
1155
+ }
1156
+ }
1002
1157
  // Below md, collapse to 1 column.
1003
1158
  @include media-breakpoint-down(md) {
1004
1159
  .form-row-grid.form-row-grid {
@@ -1056,6 +1211,60 @@ wui-wizard-step[hidden] {
1056
1211
  .wizard-stepper {
1057
1212
  margin-bottom: 24px;
1058
1213
  }
1214
+ // The optional bar above the stepper (`top-bar`): the title at the start, then the step count and the
1215
+ // close button at the end.
1216
+ .wui-wizard-topbar {
1217
+ display: flex;
1218
+ align-items: center;
1219
+ gap: 12px;
1220
+ box-sizing: border-box;
1221
+ height: 56px;
1222
+ padding: 0 16px;
1223
+ border-bottom: 1px solid var(--color-border);
1224
+ }
1225
+ .wui-wizard-topbar + .wizard-stepper {
1226
+ margin-top: 16px;
1227
+ }
1228
+ .wui-wizard-topbar-title {
1229
+ flex: 1 1 auto;
1230
+ min-width: 0;
1231
+ overflow: hidden;
1232
+ font-size: 16px;
1233
+ font-weight: 600;
1234
+ text-overflow: ellipsis;
1235
+ white-space: nowrap;
1236
+ color: var(--color-text);
1237
+ }
1238
+ .wui-wizard-topbar-count {
1239
+ flex: none;
1240
+ font-size: 13px;
1241
+ color: var(--color-text-subtle);
1242
+ white-space: nowrap;
1243
+ }
1244
+ .wui-wizard-topbar-close {
1245
+ display: inline-grid;
1246
+ flex: none;
1247
+ place-items: center;
1248
+ width: 32px;
1249
+ height: 32px;
1250
+ padding: 0;
1251
+ border: 0;
1252
+ border-radius: var(--radius);
1253
+ background: transparent;
1254
+ color: var(--color-text-muted);
1255
+ cursor: pointer;
1256
+ transition:
1257
+ background-color 0.12s ease,
1258
+ color 0.12s ease;
1259
+ }
1260
+ .wui-wizard-topbar-close:hover {
1261
+ background: var(--color-bg-muted);
1262
+ color: var(--color-text);
1263
+ }
1264
+ .wui-wizard-topbar-close:focus-visible {
1265
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
1266
+ outline-offset: var(--wui-focus-ring-offset);
1267
+ }
1059
1268
  // A skipped step reads as "passed over", not "achieved": a dashed, muted circle so it
1060
1269
  // is visibly distinct from a ticked (done) step.
1061
1270
  .step.skipped .step-circle {
@@ -213,3 +213,8 @@ wui-image-crop {
213
213
  min-height: 44px;
214
214
  }
215
215
  }
216
+
217
+ // The shared pressed wash of wui/interaction, restated here so it ships with this on-demand layer.
218
+ :is(.wui-crop-toolbtn, .wui-crop-zoombtn):active:not(:disabled, [aria-disabled="true"]) {
219
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
220
+ }
@@ -90,25 +90,14 @@ html:has(.form-actions-sticky) {
90
90
  scroll-padding-bottom: 96px;
91
91
  }
92
92
 
93
- // ---- Workspace switcher trigger ------------------------------------------------
94
- // A button styled like a field: its soft focus border alone is under 3:1, so keyboard focus
95
- // adds the outline right outside it. Form fields keep the soft border without an outline.
96
- .workspace-switcher-trigger:focus-visible,
97
- .workspace-switcher-trigger[aria-expanded="true"] {
98
- outline: calc(var(--wui-focus-ring-width) - 1px) solid var(--color-focus-ring);
99
- outline-offset: 0;
100
- }
101
-
102
93
  // ---- Active option in a pop-up list --------------------------------------------
103
- // Search results, the country list, mentions and the command
104
- // palette keep focus in their input and mark the keyboard's row (aria-activedescendant) with
105
- // the hover tint alone, about 1.2:1. The inset ring makes that row plain; inset, because the
106
- // list scrolls and would clip an outer ring. Select and autocomplete options draw their own
107
- // light edge in _choice.scss.
94
+ // Search results, the country list and mentions keep focus in their input and mark the
95
+ // keyboard's row (aria-activedescendant) with the hover tint alone, about 1.2:1. The inset ring
96
+ // makes that row plain; inset, because the list scrolls and would clip an outer ring. Select and
97
+ // autocomplete options draw their own light edge in _choice.scss.
108
98
  .wui-topsearch-hit.is-active,
109
99
  .country-dropdown-item.is-active,
110
- .wui-mention-option.is-active,
111
- .wui-cmd-item[aria-selected="true"] {
100
+ .wui-mention-option.is-active {
112
101
  outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
113
102
  outline-offset: var(--wui-focus-ring-inset);
114
103
  }
@@ -119,7 +108,8 @@ html:has(.form-actions-sticky) {
119
108
  // reduced-motion variant. !important because pressing always happens under the pointer, so a
120
109
  // more specific hover rule's `background` shorthand would otherwise reset the wash.
121
110
  // Buttons (.btn) keep Bootstrap's active fill. Controls drawn by a background image (checkbox,
122
- // switch, Bootstrap's close glyph) are not in this list.
111
+ // switch, Bootstrap's close glyph) are not in this list. The on-demand widget partials restate
112
+ // this rule for their own controls, so the wash ships with the layer that draws them.
123
113
  :is(
124
114
  .u-action,
125
115
  .pw-toggle,
@@ -139,9 +129,6 @@ html:has(.form-actions-sticky) {
139
129
  .datepicker-cell,
140
130
  .wui-daterange-preset,
141
131
  .timepicker-option,
142
- .wui-calendar-nav-btn,
143
- .wui-calendar-today-btn,
144
- .wui-calendar-view-btn,
145
132
  .app-tabs-scroll-btn,
146
133
  .wui-overflow-more,
147
134
  .wui-overflow-item,
@@ -157,22 +144,10 @@ html:has(.form-actions-sticky) {
157
144
  .wui-shortcut-close,
158
145
  .wui-shortcut-toggle,
159
146
  .wui-sortable-handle,
160
- .wui-crop-toolbtn,
161
- .wui-crop-zoombtn,
162
- .wui-file-viewer-zoom,
163
- .wui-rich-text-button,
164
- .wui-rich-text-link-apply,
165
- .wui-rich-text-link-cancel,
166
- .wui-rich-text-link-remove,
167
- .wui-kanban-action,
168
- .wui-kanban-collapse,
169
- .wui-kanban-more,
170
147
  .wui-comment-action,
171
148
  .wui-reaction-add,
172
149
  .wui-reaction-choice,
173
150
  button.wui-reaction,
174
- .wui-cmd-back,
175
- button.wui-cmd-crumb,
176
151
  .wui-code-copy,
177
152
  .wui-notification-center-markall,
178
153
  .wui-notification-center-foot,
@@ -187,9 +162,6 @@ html:has(.form-actions-sticky) {
187
162
  .chip-remove,
188
163
  .repeater-remove,
189
164
  .wui-usermenu-trigger,
190
- .workspace-switcher-trigger,
191
- .workspace-switcher-create,
192
- .workspace-switcher-footer-action,
193
165
  .wui-carousel-arrow,
194
166
  .wui-carousel-pause,
195
167
  .wui-menubar-trigger,
@@ -202,15 +174,12 @@ html:has(.form-actions-sticky) {
202
174
  .dropdown-item,
203
175
  .country-dropdown-item,
204
176
  .search-select-option,
205
- .wui-tree-row,
206
177
  .wui-split-link,
207
178
  .wui-topsearch-hit,
208
179
  a.wui-bell-item,
209
180
  .wui-notification-center-item,
210
- .workspace-switcher-option,
211
181
  .app-nav-item,
212
182
  .wui-tabbar-item,
213
- .dock-item,
214
183
  .toolbar-item,
215
184
  .toolbar-action,
216
185
  .app-tab,
@@ -254,3 +223,24 @@ html:has(.form-actions-sticky) {
254
223
  transition: transform var(--wui-press-duration) ease-out;
255
224
  }
256
225
  }
226
+
227
+ // Phone touch targets
228
+ // Below sm the pointer is a finger: every small control the library draws reaches 44px.
229
+ @media (max-width: 575.98px) {
230
+ .btn-sm,
231
+ .btn-group-sm > .btn {
232
+ min-height: 44px;
233
+ }
234
+ .topbar-icon-btn,
235
+ .app-tabs-scroll-btn,
236
+ .select.tpg-select {
237
+ min-height: 44px;
238
+ }
239
+ .topbar-icon-btn,
240
+ .app-tabs-scroll-btn {
241
+ min-width: 44px;
242
+ }
243
+ wui-select[compact] .search-select-control {
244
+ min-height: 44px;
245
+ }
246
+ }
@@ -653,3 +653,8 @@
653
653
  background: var(--color-primary);
654
654
  }
655
655
  }
656
+
657
+ // The shared pressed wash of wui/interaction, restated here so it ships with this on-demand layer.
658
+ :is(.wui-kanban-action, .wui-kanban-collapse, .wui-kanban-more):active:not(:disabled, [aria-disabled="true"]) {
659
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
660
+ }
@@ -127,8 +127,9 @@
127
127
  height: 16px;
128
128
  padding: 0 4px;
129
129
  border-radius: 999px;
130
- background: var(--color-danger);
131
- color: var(--wui-bg-light);
130
+ // The pairing .wui-bell-count uses (_shell-parts.scss): it clears contrast in light and dark.
131
+ background: var(--color-danger-strong);
132
+ color: var(--color-progress-label);
132
133
  font-size: 10px;
133
134
  font-weight: 700;
134
135
  line-height: 1;
@@ -430,7 +431,7 @@
430
431
  background: var(--color-scrim-strong);
431
432
  backdrop-filter: blur(10px);
432
433
  -webkit-backdrop-filter: blur(10px);
433
- color: #fff;
434
+ color: var(--color-on-scrim);
434
435
  border-radius: 999px;
435
436
  cursor: pointer;
436
437
  transition: background 0.2s;
@@ -849,7 +850,7 @@
849
850
  border: 2px solid transparent;
850
851
  border-radius: 50%;
851
852
  background: var(--color-scrim-strong);
852
- color: #fff;
853
+ color: var(--color-on-scrim);
853
854
  cursor: pointer;
854
855
  opacity: 0;
855
856
  transition:
@@ -971,7 +972,7 @@
971
972
  gap: clamp(2px, calc(var(--wui-logo-size) * 0.035), 4px);
972
973
  padding: 0 6%;
973
974
  background: var(--color-scrim-strong);
974
- color: #fff;
975
+ color: var(--color-on-scrim);
975
976
  font-size: clamp(9px, calc(var(--wui-logo-size) * 0.1), 11px);
976
977
  line-height: 1.15;
977
978
  text-align: center;
@@ -9,6 +9,11 @@ wui-rich-text {
9
9
  display: block;
10
10
  min-width: 0;
11
11
  }
12
+ // Inside a form field's flex column it would size to its content, so it stretches to the field.
13
+ .field > wui-rich-text {
14
+ align-self: stretch;
15
+ width: 100%;
16
+ }
12
17
  // Until the editor's own script has run, the field shows its starting value in a plain box.
13
18
  wui-rich-text:not(:defined) > textarea {
14
19
  display: block;
@@ -114,6 +119,12 @@ wui-rich-text[readonly] .wui-rich-text-shell {
114
119
  font-weight: 600;
115
120
  line-height: 1;
116
121
  }
122
+ .wui-rich-text-glyph-bold {
123
+ font-weight: 700;
124
+ }
125
+ .wui-rich-text-glyph-italic {
126
+ font-style: italic;
127
+ }
117
128
 
118
129
  // ── Link box ──
119
130
  .wui-rich-text-linkbar {
@@ -279,3 +290,13 @@ wui-rich-text[readonly] .wui-rich-text-prose {
279
290
  transition: none;
280
291
  }
281
292
  }
293
+
294
+ // The shared pressed wash of wui/interaction, restated here so it ships with this on-demand layer.
295
+ :is(
296
+ .wui-rich-text-button,
297
+ .wui-rich-text-link-apply,
298
+ .wui-rich-text-link-cancel,
299
+ .wui-rich-text-link-remove
300
+ ):active:not(:disabled, [aria-disabled="true"]) {
301
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
302
+ }
@@ -573,6 +573,11 @@
573
573
  padding-left: calc(46px + (var(--wui-nav-depth, 1) - 1) * 16px);
574
574
  font-size: 13px;
575
575
  }
576
+ @for $n from 2 through 6 {
577
+ .wui-nav-depth-#{$n} {
578
+ --wui-nav-depth: #{$n};
579
+ }
580
+ }
576
581
  // A sub-item label wraps to two lines before it is cut, so a long child label stays readable.
577
582
  // Top-level labels keep the single-line ellipsis.
578
583
  .app-nav-subitem .app-nav-text {
@@ -735,7 +740,7 @@
735
740
  .app-topbar {
736
741
  position: sticky;
737
742
  top: 0;
738
- z-index: 10;
743
+ z-index: var(--wui-z-sticky);
739
744
  display: flex;
740
745
  align-items: center;
741
746
  justify-content: space-between;
@@ -18,6 +18,11 @@
18
18
  pointer-events: none;
19
19
  transition: opacity 0.15s ease;
20
20
  }
21
+ .wui-skeleton-cell {
22
+ display: block;
23
+ height: 0.9rem;
24
+ border-radius: 0.25rem;
25
+ }
21
26
 
22
27
  // A failed fetch shows its message and Retry in the state block; the stale rows of the previous
23
28
  // page are hidden rather than left looking current.
@@ -122,3 +122,8 @@ wui-tree {
122
122
  animation-duration: 2s;
123
123
  }
124
124
  }
125
+
126
+ // The shared pressed wash of wui/interaction, restated here so it ships with this on-demand layer.
127
+ .wui-tree-row:active:not(:disabled, [aria-disabled="true"]) {
128
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
129
+ }
@@ -12,6 +12,7 @@
12
12
  .wui-icon {
13
13
  display: inline-block;
14
14
  flex-shrink: 0;
15
+ vertical-align: -.125em;
15
16
  }
16
17
 
17
18
  // ── Grid / layout utils ──
@@ -41,13 +41,25 @@
41
41
  .workspace-switcher-trigger:hover:not(:focus):not([aria-expanded="true"]) {
42
42
  border-color: var(--color-border-strong);
43
43
  }
44
+ // A button styled like a field: its soft focus border alone is under 3:1, so keyboard focus
45
+ // adds the outline right outside it. Form fields keep the soft border without an outline.
44
46
  .workspace-switcher-trigger:focus-visible,
45
47
  .workspace-switcher-trigger[aria-expanded="true"] {
46
- outline: none;
48
+ outline: calc(var(--wui-focus-ring-width) - 1px) solid var(--color-focus-ring);
49
+ outline-offset: 0;
47
50
  background: var(--color-surface);
48
51
  border-color: var(--color-focus-border);
49
52
  box-shadow: none;
50
53
  }
54
+ // The shared pressed wash of wui/interaction, restated here so it ships with this on-demand layer.
55
+ :is(
56
+ .workspace-switcher-trigger,
57
+ .workspace-switcher-create,
58
+ .workspace-switcher-footer-action,
59
+ .workspace-switcher-option
60
+ ):active:not(:disabled, [aria-disabled="true"]) {
61
+ background-image: linear-gradient(var(--color-pressed-overlay), var(--color-pressed-overlay)) !important;
62
+ }
51
63
  .workspace-switcher-trigger.is-compact {
52
64
  width: 40px;
53
65
  min-height: 40px;
@@ -382,3 +394,12 @@
382
394
  transition: none;
383
395
  }
384
396
  }
397
+
398
+ // Phone touch targets
399
+ // Below sm the pointer is a finger: every small control the library draws reaches 44px.
400
+ @media (max-width: 575.98px) {
401
+ .workspace-switcher-trigger.is-compact {
402
+ min-width: 44px;
403
+ min-height: 44px;
404
+ }
405
+ }