@webority/theme 0.8.2 → 0.8.4

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.8.2",
3
+ "version": "0.8.4",
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": {
@@ -355,16 +355,16 @@
355
355
  font-weight: 500;
356
356
  transition: background-color 0.12s ease, color 0.12s ease;
357
357
 
358
- // Leading glyph: quiet by default, brand-tinted on hover — a font-size so both
359
- // the React <Icon> (a sized <i>) and the Razor <i class="bi"> land the same.
360
- .bi, i, svg {
358
+ // Leading glyph: quiet by default, brand-tinted on hover. The library's own icons
359
+ // are .wui-icon SVGs; bare i/svg keeps product-supplied glyph nodes in step.
360
+ .wui-icon, i, svg {
361
361
  flex-shrink: 0;
362
362
  font-size: 1rem;
363
363
  color: var(--wui-text-3);
364
364
  transition: color 0.12s ease;
365
365
  }
366
- &:hover .bi, &:hover i, &:hover svg,
367
- &:focus .bi, &:focus i, &:focus svg {
366
+ &:hover .wui-icon, &:hover i, &:hover svg,
367
+ &:focus .wui-icon, &:focus i, &:focus svg {
368
368
  color: var(--wui-primary);
369
369
  }
370
370
 
@@ -383,9 +383,9 @@
383
383
  --bs-dropdown-link-color: var(--wui-danger-text);
384
384
  --bs-dropdown-link-hover-color: var(--wui-danger-text);
385
385
  --bs-dropdown-link-hover-bg: var(--color-danger-soft);
386
- .bi, i, svg { color: var(--wui-danger); }
387
- &:hover .bi, &:hover i, &:hover svg,
388
- &:focus .bi, &:focus i, &:focus svg { color: var(--wui-danger); }
386
+ .wui-icon, i, svg { color: var(--wui-danger); }
387
+ &:hover .wui-icon, &:hover i, &:hover svg,
388
+ &:focus .wui-icon, &:focus i, &:focus svg { color: var(--wui-danger); }
389
389
  }
390
390
  }
391
391
 
@@ -277,9 +277,10 @@
277
277
  min-width: 0;
278
278
  vertical-align: middle;
279
279
  }
280
- .wui-opt-label > .bi {
280
+ .wui-opt-label > .wui-icon {
281
281
  flex-shrink: 0;
282
- font-size: 15px;
282
+ width: 15px;
283
+ height: 15px;
283
284
  }
284
285
 
285
286
  // AppSelectMini — the compact single-purpose picker (page size, a range switch). It shares
@@ -460,7 +461,7 @@
460
461
  white-space: nowrap;
461
462
  text-overflow: ellipsis;
462
463
  }
463
- .datepicker-trigger > .bi {
464
+ .datepicker-trigger > .wui-icon {
464
465
  flex-shrink: 0;
465
466
  color: var(--color-text-subtle);
466
467
  }
@@ -795,7 +796,7 @@ button.datepicker-month:hover {
795
796
  white-space: nowrap;
796
797
  text-overflow: ellipsis;
797
798
  }
798
- .daterange-trigger > .bi {
799
+ .daterange-trigger > .wui-icon {
799
800
  flex-shrink: 0;
800
801
  color: var(--color-text-subtle);
801
802
  }
@@ -1179,7 +1180,7 @@ button.datepicker-month:hover {
1179
1180
  white-space: nowrap;
1180
1181
  text-overflow: ellipsis;
1181
1182
  }
1182
- .timepicker-trigger > .bi {
1183
+ .timepicker-trigger > .wui-icon {
1183
1184
  flex-shrink: 0;
1184
1185
  color: var(--color-text-subtle);
1185
1186
  }
@@ -234,10 +234,10 @@
234
234
  outline: 2px solid var(--color-primary);
235
235
  outline-offset: 2px;
236
236
  }
237
- .wui-expand-toggle .bi {
237
+ .wui-expand-toggle .wui-icon {
238
238
  transition: transform 0.18s var(--wui-ease-out-quart, ease);
239
239
  }
240
- .wui-expand-toggle.is-open .bi {
240
+ .wui-expand-toggle.is-open .wui-icon {
241
241
  transform: rotate(180deg);
242
242
  }
243
243
  .table-ledger tr.wui-row-expanded > td {
@@ -521,7 +521,7 @@ a.info-row:hover .info-value {
521
521
  background: transparent;
522
522
  }
523
523
  // Icon pop — the selected segment's glyph springs up a touch as it becomes active.
524
- .segmented-option:has(.segmented-input:checked) .bi {
524
+ .segmented-option:has(.segmented-input:checked) .wui-icon {
525
525
  transform: scale(1.14);
526
526
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
527
527
  }
@@ -561,7 +561,7 @@ a.info-row:hover .info-value {
561
561
  // The thumb still jumps to the selected segment — it just does not slide, pop or press.
562
562
  .segmented-option,
563
563
  .segmented.is-animated .segmented-thumb,
564
- .segmented-option:has(.segmented-input:checked) .bi {
564
+ .segmented-option:has(.segmented-input:checked) .wui-icon {
565
565
  transition: none;
566
566
  }
567
567
  }
@@ -301,10 +301,24 @@
301
301
  line-height: 0;
302
302
  margin-bottom: 22px;
303
303
  }
304
+ // Lift the badge off the modal surface with a soft outer shadow. `drop-shadow` traces
305
+ // the SVG's circular alpha (a `box-shadow` would cast a square), and takes no spread —
306
+ // so this is authored spread-free rather than reusing the `--wui-shadow-overlay` token.
307
+ .wui-confirm-icon svg {
308
+ filter: drop-shadow(0 10px 18px rgba(7, 20, 55, 0.18));
309
+ }
310
+ // Icon size tracks the copy: a title+message dialog keeps the full 80px badge (set on
311
+ // the element), but a lone title (no message) is one line and gets a smaller badge.
312
+ // `.wui-confirm-msg` is a real element rendered only when a message exists, so `:has()`
313
+ // is reliable here; CSS width/height override the SVG's own width/height attributes.
314
+ .wui-confirm-content:not(:has(.wui-confirm-msg)) .wui-confirm-icon svg {
315
+ width: 56px;
316
+ height: 56px;
317
+ }
304
318
  .wui-confirm-title {
305
319
  margin: 0 0 10px;
306
320
  font-size: 22px;
307
- font-weight: 700;
321
+ font-weight: 600;
308
322
  letter-spacing: -0.01em;
309
323
  color: var(--color-text);
310
324
  }
@@ -76,7 +76,7 @@
76
76
  // Bootstrap Icons carry a -.125em baseline nudge meant for inline-with-text use;
77
77
  // inside the chip's flex row it just drops the glyph below the label's centre.
78
78
  // Reset it so a library-icon leading glyph lines up with the label.
79
- .chip-ic .bi::before {
79
+ .chip-ic .wui-icon {
80
80
  vertical-align: middle;
81
81
  }
82
82
  .chip-avatar {
@@ -6,6 +6,14 @@
6
6
  // partials are a split of one stylesheet, not independent modules, so a rule
7
7
  // here may be overridden by a later partial. Never reorder the imports.
8
8
 
9
+ // ── Icon base ──
10
+ // Every library glyph (React <Icon>, Razor <app-icon>, wui-element internals) is an
11
+ // inline SVG carrying this class; size comes from its width/height attributes.
12
+ .wui-icon {
13
+ display: inline-block;
14
+ flex-shrink: 0;
15
+ }
16
+
9
17
  // ── Grid / layout utils ──
10
18
  // Responsive card grids (Bootstrap has no grid-template utility).
11
19
  .wui-grid {
@@ -567,65 +575,277 @@
567
575
  }
568
576
  }
569
577
 
570
- // Info callout — a soft branded aside for guidance, distinct from `.alert`.
571
- // An alert reports a state; a callout explains something and stays.
578
+ // Callout — a soft branded aside that EXPLAINS something and stays (distinct from
579
+ // `.alert`, which reports a state). A thick coloured LEFT edge reads as an aside; a
580
+ // circular icon badge + optional coloured heading keep it visually in the alert family.
581
+ // One local `--callout-accent`/-border/-bg triad, swapped per tone, drives the left
582
+ // edge, the icon badge fill, the heading colour, and the compact body text.
572
583
  .info-callout {
584
+ --callout-accent: var(--color-info-active);
585
+ // AA-safe text colour for the heading / compact body / <strong> (the vivid --callout-accent
586
+ // is fine for the badge fill, left edge and halo, but fails AA as text on the soft bg).
587
+ --callout-text: var(--color-info-text);
588
+ --callout-border: var(--color-info-30);
589
+ --callout-bg: var(--color-info-10);
590
+
573
591
  display: flex;
574
592
  align-items: center;
575
593
  gap: 12px;
576
594
  padding: 14px 18px;
577
- border: none;
578
- // A single accent edge instead of a full border: it reads as an aside rather
579
- // than a boxed message.
580
- border-left: 2px solid color-mix(in srgb, var(--color-primary) 50%, transparent);
581
- border-radius: var(--radius-xl);
595
+ border: 1px solid var(--callout-border);
596
+ // A thick coloured left edge — the callout's signature aside marker.
597
+ border-left: 4px solid var(--callout-accent);
598
+ border-radius: var(--radius-lg);
582
599
  corner-shape: squircle;
583
- background: var(--color-primary-soft);
600
+ background: var(--callout-bg);
584
601
  font-size: 14px;
585
- font-weight: 500;
602
+ // Sub-content (the body/subtitle) reads at #252F4A / 400; the heading and the
603
+ // compact-size text override colour + weight below.
604
+ font-weight: 400;
586
605
  line-height: 1.5;
587
- color: var(--color-primary);
606
+ color: var(--wui-text-1);
607
+ }
608
+ .info-callout.tone-success {
609
+ --callout-accent: var(--color-success-active);
610
+ --callout-text: var(--color-success-text);
611
+ --callout-border: var(--color-success-30);
612
+ --callout-bg: var(--color-success-10);
613
+ }
614
+ .info-callout.tone-warning {
615
+ --callout-accent: var(--color-warning-active);
616
+ --callout-text: var(--color-warning-text);
617
+ --callout-border: var(--color-warning-30);
618
+ --callout-bg: var(--color-warning-10);
619
+ }
620
+ .info-callout.tone-danger {
621
+ --callout-accent: var(--color-danger-active);
622
+ --callout-text: var(--color-danger-text);
623
+ --callout-border: var(--color-danger-30);
624
+ --callout-bg: var(--color-danger-10);
588
625
  }
626
+
627
+ // The leading glyph is a solid circular badge — tone fill, white glyph centred, with a
628
+ // soft 3px same-colour halo ring. Base is the single-content size (20px badge / 20px
629
+ // glyph); a title+body stack steps it up to 24px. The badge stays VERTICALLY CENTRED
630
+ // against the whole block in both cases (align-items: center on .info-callout).
589
631
  .info-callout-icon {
590
632
  flex: none;
591
633
  display: inline-flex;
592
634
  align-items: center;
593
- color: var(--color-primary);
635
+ justify-content: center;
636
+ width: 20px;
637
+ height: 20px;
638
+ border-radius: 50%;
639
+ background: var(--callout-accent);
640
+ color: #fff;
641
+ // 4px translucent ring in the badge's own colour — the "outer shadow".
642
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--callout-accent) 20%, transparent);
643
+
644
+ .wui-icon {
645
+ line-height: 1;
646
+ }
647
+ }
648
+ // A title+body stack gets the larger badge (24px / 22px glyph).
649
+ .info-callout-stack .info-callout-icon {
650
+ width: 24px;
651
+ height: 24px;
652
+ }
653
+
654
+ // Custom image in the badge (icon replacement): the image fills the circle, so drop the
655
+ // tone fill and clip it round. Applies to both AppCallout and AppAlert badges.
656
+ .info-callout-icon-image,
657
+ .alert-icon-image {
658
+ background: transparent;
659
+ overflow: hidden;
660
+ }
661
+ .info-callout-icon img,
662
+ .alert-icon img {
663
+ width: 100%;
664
+ height: 100%;
665
+ object-fit: cover;
666
+ border-radius: 50%;
667
+ }
668
+
669
+ .info-callout-content {
670
+ min-width: 0;
671
+ font-size: 12px;
672
+ }
673
+ .info-callout-heading {
674
+ font-size: 14px;
675
+ font-weight: 600;
676
+ line-height: 1.3;
677
+ margin-bottom: 1px;
678
+ color: var(--callout-text);
594
679
  }
595
680
  .info-callout strong {
596
681
  font-weight: 700;
597
- color: var(--color-primary);
682
+ color: var(--callout-text);
683
+ }
684
+
685
+ // Optional dismiss × — pushed to the right edge, vertically centred, subtle.
686
+ .info-callout-close {
687
+ flex: none;
688
+ align-self: center;
689
+ margin-left: auto;
690
+ display: inline-flex;
691
+ align-items: center;
692
+ justify-content: center;
693
+ padding: 4px;
694
+ border: none;
695
+ background: transparent;
696
+ color: var(--color-text-muted);
697
+ cursor: pointer;
698
+ opacity: 0.7;
699
+ border-radius: var(--radius-sm);
700
+ transition: opacity 0.15s;
701
+ }
702
+ .info-callout-close:hover {
703
+ opacity: 1;
704
+ }
705
+ .info-callout-close:focus-visible {
706
+ outline: 2px solid currentColor;
707
+ outline-offset: 2px;
708
+ }
709
+
710
+ // Compact size — a single tinted line: tighter padding and the body text itself carries
711
+ // the tone colour. The badge stays the single-content 20px base.
712
+ .info-callout-sm {
713
+ padding: 9px 14px;
714
+ gap: 10px;
715
+ font-weight: 600;
716
+ color: var(--callout-text);
717
+ }
718
+
719
+ // AppAlert — a soft tinted status banner with a filled circular icon badge and a
720
+ // coloured heading line. Bootstrap styles the base `.alert`; these rules set the
721
+ // per-variant surface (soft-tint background, soft border, dark body text), lay out
722
+ // the icon column, turn the leading glyph into a solid circular badge, and colour
723
+ // the heading to the variant. Only the heading takes the variant colour — the body
724
+ // stays dark ink so the message reads calmly.
725
+ .alert {
726
+ --bs-alert-border-radius: var(--wui-radius-lg);
727
+ padding: 16px 18px;
728
+ border-width: 1px;
729
+ }
730
+
731
+ // Per-variant surface: soft tint fill + soft border; body text stays dark ink.
732
+ .alert-info {
733
+ --bs-alert-bg: var(--wui-info-10);
734
+ --bs-alert-border-color: var(--wui-info-30);
735
+ --bs-alert-color: var(--wui-text-1);
736
+ --alert-accent: var(--wui-info-active);
737
+ }
738
+ .alert-success {
739
+ --bs-alert-bg: var(--wui-success-10);
740
+ --bs-alert-border-color: var(--wui-success-30);
741
+ --bs-alert-color: var(--wui-text-1);
742
+ --alert-accent: var(--wui-success-active);
743
+ }
744
+ .alert-warning {
745
+ --bs-alert-bg: var(--wui-warning-10);
746
+ --bs-alert-border-color: var(--wui-warning-30);
747
+ --bs-alert-color: var(--wui-text-1);
748
+ --alert-accent: var(--wui-warning-active);
749
+ }
750
+ .alert-danger {
751
+ --bs-alert-bg: var(--wui-danger-10);
752
+ --bs-alert-border-color: var(--wui-danger-30);
753
+ --bs-alert-color: var(--wui-text-1);
754
+ --alert-accent: var(--wui-danger-active);
755
+ }
756
+
757
+ // Borderless variant (`bordered={false}` / `bordered="false"`): drop the soft ring and
758
+ // keep only the tint fill. `transparent` rather than `border: 0` so the box keeps its
759
+ // 1px so nothing shifts when toggling the border on and off.
760
+ .alert-borderless {
761
+ border-color: transparent;
598
762
  }
599
763
 
600
- // AppAlert extras — a leading icon and/or a bold heading line. Bootstrap already
601
- // styles `.alert`/`.alert-{variant}`; these rules only lay out the icon column and
602
- // give the plain `.alert-heading` div its type treatment (Bootstrap's own rule is
603
- // just `color: inherit`, meant for an <h4>).
604
764
  .alert-has-icon {
605
765
  display: flex;
606
- align-items: flex-start;
607
- gap: 12px;
766
+ // Single-line alerts (a lone body, or a lone title) read best with the badge
767
+ // centred against the one line. A heading+body STACK top-aligns instead — the
768
+ // wrapper adds `.alert-stack` when both a title and a body are present.
769
+ align-items: center;
770
+ gap: 14px;
771
+ }
772
+ // A title+body stack gets the larger badge (24px, 22px glyph); a lone line keeps the
773
+ // smaller base below. The badge stays VERTICALLY CENTRED against the whole block in
774
+ // both cases (align-items: center on .alert-has-icon), matching the design.
775
+ .alert-has-icon.alert-stack .alert-icon {
776
+ width: 24px;
777
+ height: 24px;
608
778
  }
779
+
780
+ // The leading glyph is a solid circular badge — variant fill, white glyph centred, with
781
+ // a soft 3px same-colour halo ring around it. Base size is the SINGLE-line badge (20px,
782
+ // 20px glyph); the .alert-stack override above enlarges it when a title and body appear
783
+ // together. (The glyph itself is a Bootstrap Icons font `<i>` sized by the component.)
609
784
  .alert-icon {
610
785
  flex: none;
611
786
  display: inline-flex;
612
- // Nudge onto the first line's optical centre.
613
- margin-top: 1px;
787
+ align-items: center;
788
+ justify-content: center;
789
+ width: 20px;
790
+ height: 20px;
791
+ border-radius: 50%;
792
+ background: var(--alert-accent);
793
+ color: #fff;
794
+ // 4px translucent ring in the badge's own colour — the "outer shadow".
795
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--alert-accent) 20%, transparent);
796
+
797
+ .wui-icon {
798
+ line-height: 1;
799
+ }
614
800
  }
801
+
615
802
  .alert-content {
616
803
  flex: 1;
617
804
  min-width: 0;
805
+ // Body copy sits at 12px; the heading keeps its own explicit 14px above.
806
+ font-size: 12px;
618
807
  }
808
+
809
+ // Coloured, bold heading line (Bootstrap's own rule is just `color: inherit`).
619
810
  .alert .alert-heading {
620
811
  margin-bottom: 2px;
621
- font-size: 1rem;
622
- font-weight: 700;
812
+ font-size: 14px;
813
+ font-weight: 600;
814
+ line-height: 1.3;
815
+ }
816
+ // Use the AA-safe `-text` tokens (not the vivid `-active`, which fails AA as text on
817
+ // the soft `-10` background); the badge fill / halo keep the vivid `-active`.
818
+ .alert-info .alert-heading {
819
+ color: var(--wui-info-text);
820
+ }
821
+ .alert-success .alert-heading {
822
+ color: var(--wui-success-text);
623
823
  }
824
+ .alert-warning .alert-heading {
825
+ color: var(--wui-warning-text);
826
+ }
827
+ .alert-danger .alert-heading {
828
+ color: var(--wui-danger-text);
829
+ }
830
+
624
831
  // The body's trailing paragraph shouldn't add space below the alert.
625
832
  .alert .alert-content > :last-child {
626
833
  margin-bottom: 0;
627
834
  }
628
835
 
836
+ // Reserve room on the right for the absolutely-positioned close button. The theme's
837
+ // base `.alert` padding overrides Bootstrap's own `.alert-dismissible` padding-right, so
838
+ // without this the body text runs under the × (the button is ~48px wide at right:0).
839
+ .alert-dismissible {
840
+ padding-right: 52px;
841
+ }
842
+ // Centre the dismiss × vertically rather than pinning it to the top corner.
843
+ .alert-dismissible .btn-close {
844
+ top: 50%;
845
+ padding: 12px 16px;
846
+ transform: translateY(-50%);
847
+ }
848
+
629
849
  // ============================================================================
630
850
  // Inline help glyph — a hint attached to a word rather than to a field label.
631
851
  // (For a field label use `.infotip`, which is a real popover button.)