@webority/theme 0.9.5 → 0.9.7

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.9.5",
3
+ "version": "0.9.7",
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": {
@@ -58,6 +58,28 @@
58
58
  --bs-btn-active-border-color: transparent;
59
59
  }
60
60
 
61
+ // A soft-tinted affirmative — the success counterpart of .btn-secondary. Dark success text on a
62
+ // faint success fill, so it reads as "resolved / confirmed" without the weight of a solid green.
63
+ .btn-success {
64
+ --bs-btn-color: var(--color-success-text);
65
+ --bs-btn-bg: color-mix(in srgb, var(--color-success) 14%, transparent);
66
+ --bs-btn-border-color: transparent;
67
+ --bs-btn-hover-color: var(--color-success-text);
68
+ --bs-btn-hover-bg: color-mix(in srgb, var(--color-success) 20%, transparent);
69
+ --bs-btn-hover-border-color: transparent;
70
+ --bs-btn-active-color: var(--color-success-text);
71
+ --bs-btn-active-bg: color-mix(in srgb, var(--color-success) 28%, transparent);
72
+ --bs-btn-active-border-color: transparent;
73
+ }
74
+
75
+ // A button-shaped label that does nothing: keeps the .btn chrome but takes no pointer, so it
76
+ // neither clicks nor lifts on hover. Used for a resolved confirmation (AppButton `static`) that
77
+ // must sit exactly where its action button was.
78
+ .btn-static {
79
+ cursor: default;
80
+ pointer-events: none;
81
+ }
82
+
61
83
  .btn-danger {
62
84
  // White-on-red destructive look via the --wui-danger-strong token: white fails AA on the
63
85
  // brighter danger fills (#F8285A → 3.86:1, #E82646 → 4.38:1), so the button uses the
@@ -943,6 +943,14 @@ button.datepicker-month:hover {
943
943
  // Match AppInput's soft invalid border exactly (danger at 30%, mirroring primary-30 focus).
944
944
  border-color: color-mix(in srgb, var(--color-danger) 30%, transparent);
945
945
  }
946
+ // The live-validation error renders INSIDE <wui-phone> (after .phone-input-wrap), not as a
947
+ // direct child of .field — so .field's 4px column gap can't separate it from the control, and
948
+ // .field-error's -2px pull then makes it touch the input. <wui-phone> is display:block with no
949
+ // gap of its own, so restore the same effective 2px control→error gap the plain field gives,
950
+ // matching AppInput.
951
+ .app-phone-number-input wui-phone > .field-error {
952
+ margin-top: 2px;
953
+ }
946
954
  // Popover-field controls (date / date-range / time) carry aria-invalid on the HOST element —
947
955
  // React/Razor set it from the `error` prop — while the visible border lives on the inner trigger
948
956
  // button. Redden that trigger, and keep it red while the popover is open (mirroring AppInput,
@@ -657,6 +657,26 @@ textarea.form-control.autosize {
657
657
  color: var(--color-primary);
658
658
  }
659
659
 
660
+ // Trailing action beside the field — a control (a labelled button, or a confirmation once the
661
+ // value resolves) that sits OUTSIDE the input border. The field flexes to fill the row; the
662
+ // action keeps its natural width and centres against the control.
663
+ .input-action-row {
664
+ display: flex;
665
+ align-items: center;
666
+ gap: 0.5rem;
667
+ }
668
+ .input-action-row > .input-wrap,
669
+ .input-action-row > .input-icon {
670
+ flex: 1 1 auto;
671
+ min-width: 0;
672
+ }
673
+ .input-action {
674
+ flex: 0 0 auto;
675
+ display: flex;
676
+ align-items: center;
677
+ white-space: nowrap;
678
+ }
679
+
660
680
  // Password reveal toggle (place inside .input-wrap).
661
681
  .input.pw {
662
682
  padding-right: 44px;
@@ -865,7 +885,11 @@ textarea.form-control.autosize {
865
885
  }
866
886
  // Character counter — a right-aligned count under the field; turns danger at the limit.
867
887
  .field-count {
868
- margin-top: 2px;
888
+ // `.field` is align-items:flex-start, so a shrink-wrapped count would sit on the LEFT —
889
+ // text-align alone can't move it. align-self pushes it to the control's right edge.
890
+ align-self: flex-end;
891
+ // Tighten the space above the count: .field's 4px gap → effective 2px, matching .field-error.
892
+ margin-top: -2px;
869
893
  font-size: 12px;
870
894
  line-height: normal;
871
895
  text-align: right;
@@ -58,19 +58,6 @@
58
58
  align-items: center;
59
59
  text-align: center;
60
60
  padding: 40px 24px;
61
- // An empty ledger still renders its header row, whose nowrap cells can push the
62
- // table wider than the viewport, so `.table-wrap` scrolls horizontally with no
63
- // data to justify it. This state row spans the full scroll width, so without a
64
- // pin the message centres over that width and slides off screen on mobile.
65
- // Stick it to the scrollport's left edge and size it to the visible wrap width
66
- // (`100cqw`, from the container on `.table-wrap`), so the message stays centred
67
- // and fully in view no matter how far the header scrolls. `left: 0` is relative
68
- // to the scroll container; on a wide screen `100cqw` equals the content width, so
69
- // this is a no-op there.
70
- position: sticky;
71
- left: 0;
72
- width: 100cqw;
73
- box-sizing: border-box;
74
61
  }
75
62
  .tbl-empty-icon {
76
63
  display: inline-grid;
@@ -115,16 +102,11 @@
115
102
  border-bottom: 0;
116
103
  }
117
104
  // A plain-string empty (no `.tbl-empty` wrapper) — carries the padding the cell
118
- // used to own, plus the same viewport pin as `.tbl-empty` so it stays on screen
119
- // when a narrow ledger scrolls horizontally (see the pin note on `.tbl-empty`).
105
+ // used to own.
120
106
  .tbl-empty-plain {
121
107
  padding: 36px 24px;
122
108
  text-align: center;
123
109
  color: var(--color-text-muted);
124
- position: sticky;
125
- left: 0;
126
- width: 100cqw;
127
- box-sizing: border-box;
128
110
  }
129
111
  .table tbody tr:hover td.wui-table-empty:has(> .tbl-empty),
130
112
  .table-ledger tbody tr:hover td.wui-table-empty:has(> .tbl-empty) {
@@ -279,11 +261,13 @@
279
261
  // class (set --wui-table-pad) without overriding this selector. Bottom padding is now
280
262
  // included (was 0) so the last row isn't flush against the card edge.
281
263
  padding: var(--wui-table-pad, 20px);
282
- // Query container for the empty-state pin below. The header row can force the
283
- // ledger wider than the viewport, so on a narrow screen `.table-wrap` scrolls
284
- // horizontally; `100cqw` here is the *visible* wrap width regardless of that
285
- // scroll, which is what keeps the empty message on screen (see `.tbl-empty`).
286
- container-type: inline-size;
264
+ // NOTE: do NOT set `container-type` here. Size containment (from `container-type:
265
+ // inline-size`) collapses `.table-wrap` to a ~40px sliver whenever it is a flex/grid
266
+ // ITEM (a very common product layout), forcing the whole table into a tiny horizontal
267
+ // scroll. It was briefly added for a `100cqw` empty-state pin; the collapse is far worse
268
+ // than the empty message not being perfectly centred on a narrow scrolling table, so the
269
+ // pin was removed. If the empty state ever needs viewport-relative sizing again, do it
270
+ // without turning the scroll container into a query container.
287
271
  }
288
272
  .table-ledger {
289
273
  border-spacing: 0;