@webority/theme 0.12.4 → 0.13.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webority/theme",
3
- "version": "0.12.4",
3
+ "version": "0.13.0",
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": {
@@ -353,14 +353,21 @@
353
353
  height: 40px;
354
354
  border: 1px solid var(--color-border);
355
355
  border-radius: var(--radius);
356
- background: var(--color-surface);
356
+ // AppInput's field model: muted resting fill that lifts to a clean surface on focus.
357
+ background: var(--color-field-bg);
357
358
  color: var(--color-text-subtle);
358
359
  }
359
360
  .search-select-search {
360
361
  position: relative;
361
362
  }
363
+ // Hover and focus follow AppInput, as the phone country search does: a stronger border on hover,
364
+ // then a clean surface fill + soft primary border on focus.
365
+ .search-select-search:hover:not(:focus-within) {
366
+ border-color: var(--color-border-strong);
367
+ }
362
368
  .search-select-search:focus-within {
363
- background: var(--color-field-bg);
369
+ background: var(--color-surface);
370
+ border-color: var(--wui-primary-30);
364
371
  }
365
372
  .search-select-search:focus-within svg {
366
373
  color: var(--color-primary);
@@ -395,6 +402,10 @@
395
402
  color: var(--color-text);
396
403
  background: transparent;
397
404
  }
405
+ // AppInput's placeholder colour, not the browser default grey.
406
+ .search-select-input::placeholder {
407
+ color: var(--color-text-subtle);
408
+ }
398
409
  .search-select-options {
399
410
  max-height: 300px;
400
411
  overflow-y: auto;
@@ -927,9 +938,13 @@ button.datepicker-month:hover {
927
938
  border-color 0.12s,
928
939
  background-color 0.12s;
929
940
  }
930
- // Not while invalid — an errored control holds its red border/fill on hover (the host carries
931
- // aria-invalid, so scope the hover treatment to a non-invalid host).
932
- .app-phone-number-input wui-phone:not([aria-invalid="true"]) .phone-input-wrap:hover:not(:focus-within) {
941
+ // Not while invalid — an errored control holds its white fill and red border on hover. Two
942
+ // sources mark it invalid: the `error` prop sets aria-invalid on the host, and the element's own
943
+ // live validation marks only the inner input. Exclude both, or hovering a live-validation error
944
+ // turns the field grey.
945
+ .app-phone-number-input
946
+ wui-phone:not([aria-invalid="true"])
947
+ .phone-input-wrap:hover:not(:focus-within):not(:has(> .input.error)):not(:has(> .input.is-invalid)):not(:has(> .input[aria-invalid="true"])) {
933
948
  background: var(--color-field-bg);
934
949
  border-color: var(--color-border-strong);
935
950
  }
@@ -944,11 +959,20 @@ button.datepicker-month:hover {
944
959
  }
945
960
  .app-phone-number-input .phone-input-wrap:has(.input.error),
946
961
  .app-phone-number-input .phone-input-wrap:has(.input.is-invalid),
962
+ .app-phone-number-input .phone-input-wrap:has(.input[aria-invalid="true"]),
947
963
  // An explicit `error` prop sets aria-invalid on the host <wui-phone> (React + Razor); redden the
948
964
  // shell for it too, not just the internal live-validation state above.
949
965
  .app-phone-number-input wui-phone[aria-invalid="true"] .phone-input-wrap {
950
- // Match AppInput's soft invalid border exactly (danger at 30%, mirroring primary-30 focus).
966
+ // Match AppInput's invalid state exactly: clean surface fill + soft danger border (danger at
967
+ // 30%, mirroring primary-30 focus).
968
+ background: var(--color-surface);
951
969
  border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
970
+ // AppInput's trailing error glyph, drawn on the shell (the inner input stays transparent).
971
+ padding-right: 41px;
972
+ background-image: $wui-field-error-glyph;
973
+ background-repeat: no-repeat;
974
+ background-position: right 14px center;
975
+ background-size: 18px;
952
976
  }
953
977
  // The live-validation error renders INSIDE <wui-phone> (after .phone-input-wrap), not as a
954
978
  // direct child of .field — so .field's 4px column gap can't separate it from the control, and
@@ -969,6 +993,7 @@ wui-date-range[aria-invalid="true"] .daterange-trigger,
969
993
  wui-date-range[aria-invalid="true"] .daterange.open .daterange-trigger,
970
994
  wui-timepicker[aria-invalid="true"] .timepicker-trigger,
971
995
  wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
996
+ background: var(--color-surface);
972
997
  border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
973
998
  }
974
999
  // The inner control drops its own chrome — the shell carries it.
@@ -1139,7 +1164,8 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
1139
1164
  border-radius: var(--radius);
1140
1165
  font-size: 14px;
1141
1166
  color: var(--color-text);
1142
- background: var(--color-surface);
1167
+ // AppInput's field model: muted resting fill that lifts to a clean surface on focus.
1168
+ background: var(--color-field-bg);
1143
1169
  outline: none;
1144
1170
  }
1145
1171
  .dropdown-search-input:hover:not(:focus) {
@@ -1147,10 +1173,14 @@ wui-timepicker[aria-invalid="true"] .timepicker.open .timepicker-trigger {
1147
1173
  border-color: var(--color-border-strong);
1148
1174
  }
1149
1175
  // Border is the focus cue everywhere else in the system — no glow ring here.
1150
- // Soft primary, matching AppInput / the phone field shell rather than a full-strength border.
1176
+ // AppInput's exact focus: clean surface fill + its soft primary border token.
1151
1177
  .dropdown-search-input:focus {
1152
- background: var(--color-field-bg);
1153
- border-color: color-mix(in srgb, var(--color-primary) 30%, transparent);
1178
+ background: var(--color-surface);
1179
+ border-color: var(--wui-primary-30);
1180
+ }
1181
+ // AppInput's placeholder colour, not the browser default grey.
1182
+ .dropdown-search-input::placeholder {
1183
+ color: var(--color-text-subtle);
1154
1184
  }
1155
1185
  .country-list-scroll {
1156
1186
  max-height: 250px;
@@ -325,9 +325,14 @@ textarea.form-control.autosize {
325
325
  // OPEN (datepicker/date-range/time-picker triggers set aria-expanded on the trigger, but carry
326
326
  // their `.open` class on the WRAPPER, not the trigger) must keep its open white fill — without
327
327
  // this the resting-hover grey repaints over it the moment the cursor sits on the open trigger.
328
+ // `:not(.phone-input-wrap > .input)`: the phone shell owns the fill and border, so its inner input
329
+ // must stay transparent. This rule's specificity beats that shell's transparent rule, so without
330
+ // the exclusion the number half of an errored phone field turned grey on hover.
328
331
  .form-control:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error),
329
332
  .form-select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
330
- .input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"]),
333
+ .input:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error):not(.open):not([aria-expanded="true"]):not(
334
+ .phone-input-wrap > .input
335
+ ),
331
336
  .select:hover:not(:focus):not(:disabled):not([aria-invalid="true"]):not(.is-invalid):not(.error),
332
337
  .textarea:hover:not(:focus):not(:disabled):not([readonly]):not([aria-invalid="true"]):not(.is-invalid):not(.error) {
333
338
  background-color: var(--color-field-bg);
@@ -590,6 +595,9 @@ textarea.form-control.autosize {
590
595
  pointer-events: none;
591
596
  }
592
597
 
598
+ // The trailing error glyph, shared by every field that shows one (the phone shell draws it too).
599
+ $wui-field-error-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F8285A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%3E%3C/svg%3E");
600
+
593
601
  // Trailing error glyph on a PLAIN field only (child combinator). Shell-wrapped
594
602
  // inputs sit one level deeper and keep their own right edge.
595
603
  // Note: background-image here re-applies after the shared invalid rule zeroed BS's SVG.
@@ -600,7 +608,7 @@ textarea.form-control.autosize {
600
608
  .field > .input.is-invalid,
601
609
  .field > .input[aria-invalid="true"] {
602
610
  padding-right: 41px;
603
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23F8285A' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cline x1='12' y1='8' x2='12' y2='12'/%3E%3Cline x1='12' y1='16' x2='12.01' y2='16'/%3E%3C/svg%3E");
611
+ background-image: $wui-field-error-glyph;
604
612
  background-repeat: no-repeat;
605
613
  background-position: right 14px center;
606
614
  background-size: 18px;
@@ -1141,7 +1149,9 @@ wui-select[compact] {
1141
1149
  .num-wrap:has(.num-input[aria-invalid="true"]) {
1142
1150
  // Soft invalid border — match AppInput / AppPhoneNumberInput exactly (danger at 30%,
1143
1151
  // mirroring the primary-30 focus border), not the solid full-strength danger this used to
1144
- // carry, so every field's error border reads the same light red.
1152
+ // carry, so every field's error border reads the same light red. Clean surface fill, as
1153
+ // AppInput's invalid state.
1154
+ background: var(--color-surface);
1145
1155
  border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
1146
1156
  }
1147
1157