@webority/theme 0.78.1 → 0.79.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/theme",
3
- "version": "0.78.1",
3
+ "version": "0.79.1",
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": {
@@ -847,7 +847,8 @@
847
847
  padding: 0;
848
848
  border: 0;
849
849
  border-radius: var(--radius);
850
- background: transparent;
850
+ // The same resting grey as the modal and drawer close buttons.
851
+ background: var(--color-bg-subtle);
851
852
  color: var(--color-text-muted);
852
853
  cursor: pointer;
853
854
  transition:
@@ -75,8 +75,16 @@ wui-chat[position="start"] .wui-chat-panel {
75
75
  overflow-wrap: anywhere;
76
76
  }
77
77
 
78
- // The question box grows with its text, up to a few lines.
79
- .wui-chat-foot .form-control {
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.
80
+ .wui-chat-composer .form-control {
81
+ min-height: var(--wui-control-height);
80
82
  max-height: 9rem;
83
+ padding-block: 10px;
81
84
  resize: none;
82
85
  }
86
+ // A form reserves a line under each field for its error; the question box has none, and the
87
+ // empty line pushed Send below the box.
88
+ .wui-chat-composer .wui-field-message:empty {
89
+ display: none;
90
+ }
@@ -72,6 +72,10 @@
72
72
  background: var(--color-surface);
73
73
  color: var(--color-primary-ink);
74
74
  }
75
+ // Hover previews the chosen glyph colour; a card that cannot change keeps its grey.
76
+ .struct-card:hover:not(:has(.struct-card-input:disabled)) .struct-card-ic {
77
+ color: var(--color-primary-ink);
78
+ }
75
79
  // An image in the round icon disc (React iconNode={<img …/>}) keeps its own colours whether or not
76
80
  // the card is selected, fills the whole disc and is cropped to its circle, whatever the image's own
77
81
  // size or aspect. The tile variant drops the disc and sizes its illustration itself, so it is left out.
@@ -99,6 +99,80 @@
99
99
  .wui-radio-group .form-check-label {
100
100
  min-width: auto;
101
101
  }
102
+ // An option's description: a muted line under its label, in the label's column.
103
+ .wui-radio-option-desc {
104
+ grid-column: 2;
105
+ font-size: 13px;
106
+ line-height: 1.4;
107
+ color: var(--color-text-subtle);
108
+ }
109
+ // With a description the glyph spans both lines, so it sits centred against the label and description.
110
+ .form-check:has(> .wui-radio-option-desc) > .form-check-input {
111
+ grid-row: 1 / span 2;
112
+ }
113
+
114
+ // variant="card": each option is a bordered card. The label's ::after covers the whole card, so a
115
+ // click anywhere on it (description included) selects the option; the chosen card takes the
116
+ // primary border and a tinted fill.
117
+ .wui-radio-group-card {
118
+ gap: 12px;
119
+ }
120
+ .wui-radio-group-card.wui-radio-group-inline {
121
+ column-gap: 12px;
122
+ }
123
+ .wui-radio-group-card > .form-check {
124
+ position: relative;
125
+ padding: 14px 16px;
126
+ min-height: 56px;
127
+ border: 1.5px solid var(--color-border);
128
+ border-radius: var(--radius);
129
+ background: var(--color-surface);
130
+ transition:
131
+ border-color 0.12s ease,
132
+ background-color 0.12s ease;
133
+ }
134
+ .wui-radio-group-card.wui-radio-group-inline > .form-check {
135
+ flex: 1 1 200px;
136
+ min-width: 0;
137
+ }
138
+ .wui-radio-group-card .form-check-label {
139
+ font-size: 15px;
140
+ font-weight: 500;
141
+ }
142
+ .wui-radio-group-card .form-check-label::after {
143
+ content: "";
144
+ position: absolute;
145
+ inset: 0;
146
+ border-radius: inherit;
147
+ }
148
+ .wui-radio-group-card > .form-check:hover:not(:has(:disabled)):not(:has(:checked)) {
149
+ border-color: color-mix(in srgb, var(--color-primary) 40%, var(--color-border));
150
+ }
151
+ .wui-radio-group-card > .form-check:has(:checked) {
152
+ border-color: var(--color-primary);
153
+ background: color-mix(in srgb, var(--color-primary) 7%, var(--color-surface));
154
+ }
155
+ // The keyboard ring goes round the card, not the small glyph inside it.
156
+ .wui-radio-group-card > .form-check:has(.form-check-input:focus-visible) {
157
+ outline: var(--wui-focus-ring-width) solid var(--color-focus-ring);
158
+ outline-offset: var(--wui-focus-ring-offset);
159
+ }
160
+ .wui-radio-group-card .form-check-input:focus-visible {
161
+ outline: none;
162
+ }
163
+ // Hovering the card glows the glyph as hovering the glyph itself does.
164
+ .wui-radio-group-card > .form-check:hover .form-check-input:not(:disabled):not(:checked) {
165
+ border-color: var(--color-primary);
166
+ box-shadow: 0 0 0 2px var(--color-primary-soft);
167
+ }
168
+ .wui-radio-group-card > .form-check:has(:disabled) {
169
+ cursor: not-allowed;
170
+ background: var(--color-bg-muted);
171
+ }
172
+ .wui-radio-group-card[aria-invalid="true"] > .form-check:not(:has(:checked)) {
173
+ border-color: var(--color-danger);
174
+ }
175
+
102
176
  // Beside-label forms centre a label on a text control; a radio group's first option is shorter,
103
177
  // so its label lines up with that row instead.
104
178
  .wui-form-labels-start .field:has(> .wui-radio-group) > .label {
@@ -201,6 +201,11 @@ button.step.done:focus-visible .step-circle {
201
201
  color: var(--color-text-muted);
202
202
  overflow-wrap: break-word;
203
203
  }
204
+ // The label and its description read as one block: pull the description up so the
205
+ // step's 10px column gap leaves 2px between them (the journey bar's spacing).
206
+ .step > .step-label + .step-desc {
207
+ margin-top: -8px;
208
+ }
204
209
 
205
210
  .stepper-journey {
206
211
  display: flex;
@@ -369,6 +374,10 @@ button.step.done:focus-visible .step-circle {
369
374
  grid-row: 2;
370
375
  max-width: none;
371
376
  }
377
+ // The vertical grid has no row gap, so the description sits right under the label.
378
+ .stepper-vertical .step > .step-label + .step-desc {
379
+ margin-top: 0;
380
+ }
372
381
  // The compact connector is horizontal (::before); redraw it as a vertical segment
373
382
  // down the circle's centre, from below one circle to the top of the next.
374
383
  .stepper-vertical .step + .step::before {
@@ -414,6 +423,10 @@ button.step.done:focus-visible .step-circle {
414
423
  .stepper-icons .step {
415
424
  gap: 6px;
416
425
  }
426
+ // The icons column gap is 6px, so the description pulls up less to land 2px under the label.
427
+ .stepper-icons .step > .step-label + .step-desc {
428
+ margin-top: -4px;
429
+ }
417
430
  .stepper-icons .step-circle {
418
431
  width: var(--wui-step-badge-size, 56px);
419
432
  height: var(--wui-step-badge-size, 56px);
@@ -513,6 +526,10 @@ button.step.done:focus-visible .step-circle {
513
526
  gap: 14px;
514
527
  text-align: left;
515
528
  }
529
+ // A row has no column gap to pull the description back from.
530
+ .stepper-icons.stepper-icons .step > .step-label + .step-desc {
531
+ margin-top: 0;
532
+ }
516
533
  .stepper-icons.stepper-icons .step + .step::before {
517
534
  content: none;
518
535
  }
@@ -675,6 +692,42 @@ button.wui-step-tile-body:hover .step-label {
675
692
  content: none;
676
693
  }
677
694
 
695
+ // Start alignment: the wizard's align="start" sets each step's badge, label and description at
696
+ // the start of its column instead of centred. Only the centred variants change (compact steps, and
697
+ // icons from md up); journey, tiles and vertical steps are start-aligned already. The steps share
698
+ // the row equally, so the step before sits one full column back: its badge starts at -100%, and
699
+ // the line runs from that badge's end edge to this step's badge, with the variant's usual gap.
700
+ .wui-stepper-start:not(.stepper-vertical, .stepper-journey, .stepper-icons, .wui-step-tiles) {
701
+ .step {
702
+ align-items: flex-start;
703
+ text-align: left;
704
+ }
705
+ .step + .step::before {
706
+ left: calc(-100% + var(--wui-step-size, 28px) + 4px);
707
+ right: calc(100% + 4px);
708
+ }
709
+ // The active badge's 4px ring would swallow the gap, so the lines touching it start further out.
710
+ .step.active + .step::before {
711
+ left: calc(-100% + var(--wui-step-size, 28px) + 8px);
712
+ }
713
+ .step.active::before {
714
+ right: calc(100% + 8px);
715
+ }
716
+ }
717
+ // Below md the icons stepper stacks into a list, which needs no alignment change.
718
+ @include media-breakpoint-up(md) {
719
+ .wui-stepper-start.stepper-icons:not(.stepper-vertical) {
720
+ .step {
721
+ align-items: flex-start;
722
+ text-align: left;
723
+ }
724
+ .step + .step::before {
725
+ left: calc(-100% + var(--wui-step-badge-size, 56px) + 8px);
726
+ right: calc(100% + 8px);
727
+ }
728
+ }
729
+ }
730
+
678
731
  @media (prefers-reduced-motion: reduce) {
679
732
  a.step:hover .step-circle,
680
733
  button.step:hover .step-circle,
@@ -208,6 +208,9 @@
208
208
  // A tab can be a real <a href> (link tab) — strip the browser's link underline so a link
209
209
  // tab is visually identical to a button tab.
210
210
  text-decoration: none;
211
+ // A tab sits on the page surface with no fill of its own, so the shared 12% pressed wash
212
+ // reads as a heavy grey block; half of it still answers the press.
213
+ --color-pressed-overlay: color-mix(in srgb, currentColor 6%, transparent);
211
214
  transition:
212
215
  color 0.12s ease,
213
216
  border-color 0.12s ease;