@webority/theme 0.8.4 → 0.8.5
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/dist/webority-theme.css +1 -1
- package/package.json +1 -1
- package/scss/_components.scss +6 -6
- package/scss/_tokens.scss +8 -0
- package/scss/wui/_choice.scss +2 -0
- package/scss/wui/_controls.scss +18 -7
- package/scss/wui/_navigation.scss +21 -0
- package/scss/wui/_overlays.scss +59 -0
- package/scss/wui/_utilities.scss +12 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webority/theme",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
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": {
|
package/scss/_components.scss
CHANGED
|
@@ -170,9 +170,9 @@
|
|
|
170
170
|
// sizes step font-size, horizontal padding and radius together (vertical size
|
|
171
171
|
// comes from --wui-control-height, so a button lines up with an input). Weight
|
|
172
172
|
// is 600 on every rung — buttons read as a deliberate action, not body text.
|
|
173
|
-
// Medium (default): 15px / 600, 24px side padding,
|
|
173
|
+
// Medium (default): 15px / 600, 24px side padding, 18px squircle radius, 45px tall.
|
|
174
174
|
.btn {
|
|
175
|
-
--bs-btn-border-radius:
|
|
175
|
+
--bs-btn-border-radius: 18px;
|
|
176
176
|
--bs-btn-font-size: 0.9375rem;
|
|
177
177
|
--bs-btn-font-weight: 600;
|
|
178
178
|
--bs-btn-padding-x: 1.5rem;
|
|
@@ -180,10 +180,10 @@
|
|
|
180
180
|
// keep a plain border-radius arc — not a cross-browser design contract.
|
|
181
181
|
corner-shape: squircle;
|
|
182
182
|
}
|
|
183
|
-
// Small: 14px, 18px side padding,
|
|
183
|
+
// Small: 14px, 18px side padding, 14px squircle radius (proportional to md), 35px tall.
|
|
184
184
|
.btn-sm:not(.btn-icon),
|
|
185
185
|
.btn-group-sm > .btn:not(.btn-icon) {
|
|
186
|
-
--bs-btn-border-radius:
|
|
186
|
+
--bs-btn-border-radius: 14px;
|
|
187
187
|
--bs-btn-font-size: 0.875rem;
|
|
188
188
|
--bs-btn-padding-x: 1.125rem;
|
|
189
189
|
display: inline-flex;
|
|
@@ -191,10 +191,10 @@
|
|
|
191
191
|
justify-content: center;
|
|
192
192
|
min-height: 35px;
|
|
193
193
|
}
|
|
194
|
-
// Large: 17px, 32px side padding,
|
|
194
|
+
// Large: 17px, 32px side padding, 22px squircle radius (proportional to md), 55px tall — a spacious CTA.
|
|
195
195
|
.btn-lg:not(.btn-icon),
|
|
196
196
|
.btn-group-lg > .btn:not(.btn-icon) {
|
|
197
|
-
--bs-btn-border-radius:
|
|
197
|
+
--bs-btn-border-radius: 22px;
|
|
198
198
|
--bs-btn-font-size: 1.0625rem;
|
|
199
199
|
--bs-btn-padding-x: 2rem;
|
|
200
200
|
display: inline-flex;
|
package/scss/_tokens.scss
CHANGED
|
@@ -195,6 +195,14 @@
|
|
|
195
195
|
--wui-radius-lg: 14px;
|
|
196
196
|
--wui-radius-xl: 16px;
|
|
197
197
|
|
|
198
|
+
// Field (input/select/datepicker/…) radius — a rounder squircle than the
|
|
199
|
+
// generic radius ladder, matched to the button radius language. md is 18px;
|
|
200
|
+
// sm/lg step with the control height (36/44/52px → ~0.41 ratio) so every
|
|
201
|
+
// field size keeps a proportional corner.
|
|
202
|
+
--wui-field-radius: 18px;
|
|
203
|
+
--wui-field-radius-sm: 15px;
|
|
204
|
+
--wui-field-radius-lg: 21px;
|
|
205
|
+
|
|
198
206
|
// ---- Portal dark palette ----------------------------------------
|
|
199
207
|
// Marketing stays light. Portal flips [data-theme="dark"] and maps
|
|
200
208
|
// --color-* aliases onto these so dark hexes live in theme/, not the app.
|
package/scss/wui/_choice.scss
CHANGED
|
@@ -203,11 +203,13 @@
|
|
|
203
203
|
height: var(--wui-control-height-sm);
|
|
204
204
|
min-height: var(--wui-control-height-sm);
|
|
205
205
|
font-size: 13px;
|
|
206
|
+
border-radius: var(--wui-field-radius-sm);
|
|
206
207
|
}
|
|
207
208
|
.search-select-lg .search-select-control {
|
|
208
209
|
height: var(--wui-control-height-lg);
|
|
209
210
|
min-height: var(--wui-control-height-lg);
|
|
210
211
|
font-size: 16px;
|
|
212
|
+
border-radius: var(--wui-field-radius-lg);
|
|
211
213
|
}
|
|
212
214
|
// Multi-select grows with its chips, so a size sets the FLOOR (min-height from the rule
|
|
213
215
|
// above) but never a fixed height — reset height:auto so a second row of chips can appear.
|
package/scss/wui/_controls.scss
CHANGED
|
@@ -255,7 +255,8 @@
|
|
|
255
255
|
width: 100%;
|
|
256
256
|
height: var(--wui-control-height);
|
|
257
257
|
padding: 12px;
|
|
258
|
-
border-radius: var(--radius);
|
|
258
|
+
border-radius: var(--wui-field-radius);
|
|
259
|
+
corner-shape: squircle;
|
|
259
260
|
border: 1px solid var(--color-border);
|
|
260
261
|
background: var(--color-bg-muted);
|
|
261
262
|
font-size: 14px;
|
|
@@ -274,12 +275,14 @@
|
|
|
274
275
|
height: var(--wui-control-height-sm);
|
|
275
276
|
padding: 6px 10px;
|
|
276
277
|
font-size: 13px;
|
|
278
|
+
border-radius: var(--wui-field-radius-sm);
|
|
277
279
|
}
|
|
278
280
|
.form-control-lg,
|
|
279
281
|
.input-lg {
|
|
280
282
|
height: var(--wui-control-height-lg);
|
|
281
283
|
padding: 14px 16px;
|
|
282
284
|
font-size: 16px;
|
|
285
|
+
border-radius: var(--wui-field-radius-lg);
|
|
283
286
|
}
|
|
284
287
|
.textarea,
|
|
285
288
|
textarea.form-control {
|
|
@@ -420,7 +423,12 @@ textarea.form-control.autosize {
|
|
|
420
423
|
.field-error {
|
|
421
424
|
font-size: 12px;
|
|
422
425
|
line-height: normal;
|
|
426
|
+
// Must clear AA against the surface: --color-danger-active (#E82646) is 4.38:1 at this
|
|
427
|
+
// 12px size, under the 4.5:1 floor the a11y gate enforces.
|
|
423
428
|
color: var(--color-danger-text);
|
|
429
|
+
// Tighten the space above the message: .field's 4px gap → effective 2px, without
|
|
430
|
+
// touching the label→control gap.
|
|
431
|
+
margin-top: -2px;
|
|
424
432
|
}
|
|
425
433
|
|
|
426
434
|
// Native select with a rounded squircle, custom chevron, off-surface fill.
|
|
@@ -675,7 +683,8 @@ textarea.form-control.autosize {
|
|
|
675
683
|
align-items: stretch;
|
|
676
684
|
width: 100%;
|
|
677
685
|
border: 1px solid var(--color-border);
|
|
678
|
-
border-radius: var(--radius);
|
|
686
|
+
border-radius: var(--wui-field-radius);
|
|
687
|
+
corner-shape: squircle;
|
|
679
688
|
// Soft-filled at rest, white on focus — one shared fill for the whole control so the
|
|
680
689
|
// prefix/suffix and the input body are always the SAME colour combination as the field.
|
|
681
690
|
background: var(--color-bg-muted);
|
|
@@ -714,11 +723,11 @@ textarea.form-control.autosize {
|
|
|
714
723
|
}
|
|
715
724
|
.input-affixed .affix-pre {
|
|
716
725
|
border-right: 1px solid var(--color-border);
|
|
717
|
-
border-radius: var(--radius) 0 0 var(--radius);
|
|
726
|
+
border-radius: var(--wui-field-radius) 0 0 var(--wui-field-radius);
|
|
718
727
|
}
|
|
719
728
|
.input-affixed .affix-suf {
|
|
720
729
|
border-left: 1px solid var(--color-border);
|
|
721
|
-
border-radius: 0 var(--radius) var(--radius) 0;
|
|
730
|
+
border-radius: 0 var(--wui-field-radius) var(--wui-field-radius) 0;
|
|
722
731
|
}
|
|
723
732
|
|
|
724
733
|
// Floating label — the label starts centred as the placeholder, then slides up and shrinks
|
|
@@ -831,12 +840,14 @@ textarea.form-control.autosize {
|
|
|
831
840
|
color: var(--color-text-subtle);
|
|
832
841
|
}
|
|
833
842
|
.required {
|
|
843
|
+
// AA against the surface — see .field-error; --color-danger-active is 4.38:1.
|
|
834
844
|
color: var(--color-danger-text);
|
|
835
845
|
// The gap is CSS, not a significant space in the markup. RequiredMark used to render
|
|
836
846
|
// `{' '}*` while AppDatePicker and every Razor helper rendered a bare `*`, so the same
|
|
837
847
|
// asterisk sat 4px further out in some fields than others — and no check could see it,
|
|
838
|
-
// because HTML comparison collapses whitespace by design.
|
|
839
|
-
|
|
848
|
+
// because HTML comparison collapses whitespace by design. Gap removed — the star sits
|
|
849
|
+
// flush against the label.
|
|
850
|
+
margin-inline-start: 0;
|
|
840
851
|
}
|
|
841
852
|
.field {
|
|
842
853
|
display: flex;
|
|
@@ -942,7 +953,7 @@ wui-select[compact] {
|
|
|
942
953
|
display: flex;
|
|
943
954
|
align-items: stretch;
|
|
944
955
|
border: 1px solid var(--color-border);
|
|
945
|
-
border-radius: var(--radius
|
|
956
|
+
border-radius: var(--wui-field-radius);
|
|
946
957
|
corner-shape: squircle;
|
|
947
958
|
// Soft-filled at rest, white on focus — the numeric input and its unit pill share the
|
|
948
959
|
// one wrapper fill, same colour combination as every other field.
|
|
@@ -182,6 +182,19 @@
|
|
|
182
182
|
color 0.12s ease,
|
|
183
183
|
border-color 0.12s ease;
|
|
184
184
|
}
|
|
185
|
+
// Leading icon / image — sit before the label with the strip's 8px gap (from .app-tab).
|
|
186
|
+
// The library Icon sizes itself; a custom <img> is constrained to a small rounded square
|
|
187
|
+
// (product logo / avatar). Both never shrink when the label truncates.
|
|
188
|
+
.app-tab-icon {
|
|
189
|
+
flex-shrink: 0;
|
|
190
|
+
}
|
|
191
|
+
.app-tab-img {
|
|
192
|
+
flex-shrink: 0;
|
|
193
|
+
width: 18px;
|
|
194
|
+
height: 18px;
|
|
195
|
+
object-fit: cover;
|
|
196
|
+
border-radius: var(--radius-sm);
|
|
197
|
+
}
|
|
185
198
|
.app-tab:hover:not(:disabled):not(.active) {
|
|
186
199
|
color: var(--color-text);
|
|
187
200
|
}
|
|
@@ -296,10 +309,18 @@
|
|
|
296
309
|
gap: 6px;
|
|
297
310
|
font-size: 13px;
|
|
298
311
|
}
|
|
312
|
+
.app-tabs-sm .app-tab-img {
|
|
313
|
+
width: 16px;
|
|
314
|
+
height: 16px;
|
|
315
|
+
}
|
|
299
316
|
.app-tabs-lg .app-tab {
|
|
300
317
|
padding: 14px 18px;
|
|
301
318
|
font-size: 15px;
|
|
302
319
|
}
|
|
320
|
+
.app-tabs-lg .app-tab-img {
|
|
321
|
+
width: 20px;
|
|
322
|
+
height: 20px;
|
|
323
|
+
}
|
|
303
324
|
|
|
304
325
|
// ── Fitted: tabs share the width equally (no scroll). ──
|
|
305
326
|
.app-tabs-fitted .app-tab {
|
package/scss/wui/_overlays.scss
CHANGED
|
@@ -395,6 +395,65 @@
|
|
|
395
395
|
box-shadow: var(--wui-tooltip-shadow);
|
|
396
396
|
}
|
|
397
397
|
|
|
398
|
+
// ── CSS-only tooltip ──────────────────────────────────────────────────────────────────
|
|
399
|
+
// Any element carrying `data-wui-tip="…"` grows a hover/focus bubble reusing the AppTooltip
|
|
400
|
+
// surface look — no JS, no Popper, instant, and identical on React and Razor by construction.
|
|
401
|
+
// It sits above the element; for a collision-aware / richer tooltip, use AppTooltip /
|
|
402
|
+
// <app-tooltip> instead.
|
|
403
|
+
//
|
|
404
|
+
// Two users, for different reasons:
|
|
405
|
+
// - `.wui-icon-tip`, the wrapper the `tooltip` prop on AppIcon / <app-icon> puts around a
|
|
406
|
+
// glyph (it adds the inline-flex layout below).
|
|
407
|
+
// - <app-tabs> tab buttons, which CANNOT use a Bootstrap tooltip: the button already owns a
|
|
408
|
+
// `bs.tab` instance and Bootstrap permits only one instance per element, so binding
|
|
409
|
+
// `bs.Tooltip` to it logs "Bootstrap doesn't allow more than one instance per element"
|
|
410
|
+
// and the tab instance is never registered.
|
|
411
|
+
[data-wui-tip] {
|
|
412
|
+
position: relative;
|
|
413
|
+
}
|
|
414
|
+
.wui-icon-tip {
|
|
415
|
+
display: inline-flex;
|
|
416
|
+
vertical-align: -0.125em;
|
|
417
|
+
}
|
|
418
|
+
[data-wui-tip]::after {
|
|
419
|
+
content: attr(data-wui-tip);
|
|
420
|
+
position: absolute;
|
|
421
|
+
bottom: calc(100% + 8px);
|
|
422
|
+
left: 50%;
|
|
423
|
+
transform: translateX(-50%);
|
|
424
|
+
z-index: var(--wui-z-menu, 1080);
|
|
425
|
+
width: max-content;
|
|
426
|
+
max-width: 240px;
|
|
427
|
+
padding: 7px 11px;
|
|
428
|
+
border-radius: var(--radius, 10px);
|
|
429
|
+
corner-shape: squircle;
|
|
430
|
+
background: var(--color-surface);
|
|
431
|
+
color: var(--color-text);
|
|
432
|
+
border: 1px solid var(--color-border-light);
|
|
433
|
+
box-shadow: var(--wui-shadow-overlay);
|
|
434
|
+
font-size: 0.8125rem;
|
|
435
|
+
font-weight: 500;
|
|
436
|
+
line-height: 1.4;
|
|
437
|
+
text-align: left;
|
|
438
|
+
white-space: normal;
|
|
439
|
+
pointer-events: none;
|
|
440
|
+
opacity: 0;
|
|
441
|
+
visibility: hidden;
|
|
442
|
+
transition:
|
|
443
|
+
opacity 0.12s ease,
|
|
444
|
+
visibility 0.12s;
|
|
445
|
+
}
|
|
446
|
+
[data-wui-tip]:hover::after,
|
|
447
|
+
[data-wui-tip]:focus-visible::after {
|
|
448
|
+
opacity: 1;
|
|
449
|
+
visibility: visible;
|
|
450
|
+
}
|
|
451
|
+
@media (prefers-reduced-motion: reduce) {
|
|
452
|
+
[data-wui-tip]::after {
|
|
453
|
+
transition: none;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
398
457
|
// Size presets — swap the four size vars. `md` is the :where default (no class).
|
|
399
458
|
.tooltip.wui-tooltip.size-sm {
|
|
400
459
|
--wui-tooltip-max-width: 200px;
|
package/scss/wui/_utilities.scss
CHANGED
|
@@ -595,7 +595,7 @@
|
|
|
595
595
|
border: 1px solid var(--callout-border);
|
|
596
596
|
// A thick coloured left edge — the callout's signature aside marker.
|
|
597
597
|
border-left: 4px solid var(--callout-accent);
|
|
598
|
-
border-radius:
|
|
598
|
+
border-radius: 20px;
|
|
599
599
|
corner-shape: squircle;
|
|
600
600
|
background: var(--callout-bg);
|
|
601
601
|
font-size: 14px;
|
|
@@ -624,6 +624,14 @@
|
|
|
624
624
|
--callout-bg: var(--color-danger-10);
|
|
625
625
|
}
|
|
626
626
|
|
|
627
|
+
// Borderless variant (`bordered={false}` / `bordered="false"`): drop the soft ring AND
|
|
628
|
+
// the thick tone-coloured left edge, keeping only the tint fill. Colours go `transparent`
|
|
629
|
+
// rather than the widths to 0 so the box keeps its 1px / 4px-left footprint — nothing
|
|
630
|
+
// shifts when toggling the border on and off. Mirrors `.alert-borderless`.
|
|
631
|
+
.info-callout-borderless {
|
|
632
|
+
border-color: transparent;
|
|
633
|
+
}
|
|
634
|
+
|
|
627
635
|
// The leading glyph is a solid circular badge — tone fill, white glyph centred, with a
|
|
628
636
|
// soft 3px same-colour halo ring. Base is the single-content size (20px badge / 20px
|
|
629
637
|
// glyph); a title+body stack steps it up to 24px. The badge stays VERTICALLY CENTRED
|
|
@@ -723,7 +731,9 @@
|
|
|
723
731
|
// the heading to the variant. Only the heading takes the variant colour — the body
|
|
724
732
|
// stays dark ink so the message reads calmly.
|
|
725
733
|
.alert {
|
|
726
|
-
--bs-alert-border-radius:
|
|
734
|
+
--bs-alert-border-radius: 20px;
|
|
735
|
+
border-radius: 20px;
|
|
736
|
+
corner-shape: squircle;
|
|
727
737
|
padding: 16px 18px;
|
|
728
738
|
border-width: 1px;
|
|
729
739
|
}
|