@foxeltech/angular-ui 0.7.106 → 0.7.124
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/components.css +201 -0
- package/fesm2022/foxeltech-angular-ui-chart.mjs +117 -44
- package/fesm2022/foxeltech-angular-ui-chart.mjs.map +1 -1
- package/fesm2022/foxeltech-angular-ui.mjs +73 -21
- package/fesm2022/foxeltech-angular-ui.mjs.map +1 -1
- package/package.json +3 -2
- package/src/lib/styles/components.css +201 -0
- package/src/lib/styles/tokens.css +3 -0
- package/src/lib/ui/components/bar-list/bar-list.component.html +19 -18
- package/src/lib/ui/components/bar-list/bar-list.component.scss +63 -0
- package/src/lib/ui/components/breadcrumb/breadcrumb.component.css +31 -0
- package/src/lib/ui/components/breadcrumb/breadcrumb.component.html +6 -1
- package/src/lib/ui/components/drawer/drawer.component.html +34 -9
- package/src/lib/ui/components/drawer/drawer.component.scss +158 -41
- package/src/lib/ui/components/filter-pills/filter-pills.component.html +4 -1
- package/src/lib/ui/components/filter-pills/filter-pills.component.scss +23 -0
- package/src/lib/ui/components/section-card/section-card.component.html +10 -5
- package/src/lib/ui/components/section-card/section-card.component.scss +28 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.css +48 -0
- package/src/lib/ui/components/stat-cards/stat-cards.component.html +16 -7
- package/tokens.css +3 -0
- package/types/foxeltech-angular-ui-chart.d.ts +22 -2
- package/types/foxeltech-angular-ui.d.ts +70 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@foxeltech/angular-ui",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.124",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"@microsoft/signalr": "^10.0.0",
|
|
27
27
|
"d3-drag": "^3.0.0",
|
|
28
28
|
"d3-selection": "^3.0.0",
|
|
29
|
-
"d3-zoom": "^3.0.0"
|
|
29
|
+
"d3-zoom": "^3.0.0",
|
|
30
|
+
"lucide-angular": "^1.0.0"
|
|
30
31
|
},
|
|
31
32
|
"exports": {
|
|
32
33
|
"./tailwind.css": "./tailwind.css",
|
|
@@ -631,6 +631,10 @@ input[type='password'] {
|
|
|
631
631
|
0 1px 2px rgb(0 0 0 / 0.15);
|
|
632
632
|
}
|
|
633
633
|
.btn-cta:hover {
|
|
634
|
+
/* The edge darkens a step past the fill — reference `.bi-newbtn:hover`
|
|
635
|
+
(measured 16/09). Without it the button only changed fill and shadow, so
|
|
636
|
+
the hover read softer than the design's. */
|
|
637
|
+
border-color: var(--color-cta-hover-border);
|
|
634
638
|
box-shadow:
|
|
635
639
|
inset 0 1px 0 rgb(255 255 255 / 0.18),
|
|
636
640
|
0 2px 6px rgb(0 0 0 / 0.2);
|
|
@@ -849,3 +853,200 @@ input[type='password'] {
|
|
|
849
853
|
.fx-rs-busy > *:not(fx-ui-route-skeleton) {
|
|
850
854
|
display: none !important;
|
|
851
855
|
}
|
|
856
|
+
|
|
857
|
+
/* ============================================================================
|
|
858
|
+
Grid tables, badges and status dots to the reference HTML (Binary
|
|
859
|
+
Intelligence Dashboard, porcelain) — anh Tú 15/09, moved into the lib in
|
|
860
|
+
0.7.107 from three identical copies in analyze/knowledge/host styles.scss.
|
|
861
|
+
|
|
862
|
+
The reference draws its lists as CSS-grid rows, not <table>: a sunken 10px
|
|
863
|
+
header in 10.5px/600 tracked faint, 11px rows split by hairlines, hover to
|
|
864
|
+
surface-sunken, a trailing caret that turns accent and slides 2px. Columns
|
|
865
|
+
come from the consumer as `--fx-cols` on `.fx-grid-table`.
|
|
866
|
+
|
|
867
|
+
Inside layer(components) like the rest of this file, so a Tailwind utility
|
|
868
|
+
on the same element still wins.
|
|
869
|
+
============================================================================ */
|
|
870
|
+
.fx-grid-table {
|
|
871
|
+
border: 1px solid rgb(var(--og-border));
|
|
872
|
+
border-radius: var(--og-radius-card);
|
|
873
|
+
background: rgb(var(--og-surface));
|
|
874
|
+
overflow: hidden;
|
|
875
|
+
}
|
|
876
|
+
.fx-grid-table__head,
|
|
877
|
+
.fx-grid-table__row {
|
|
878
|
+
display: grid;
|
|
879
|
+
grid-template-columns: var(--fx-cols);
|
|
880
|
+
gap: 12px;
|
|
881
|
+
align-items: center;
|
|
882
|
+
padding: 10px 12px;
|
|
883
|
+
}
|
|
884
|
+
.fx-grid-table__head {
|
|
885
|
+
border-bottom: 1px solid rgb(var(--og-border));
|
|
886
|
+
background: rgb(var(--og-surface-sunken));
|
|
887
|
+
font-size: var(--og-fs-2xs);
|
|
888
|
+
font-weight: 600;
|
|
889
|
+
letter-spacing: var(--og-tracking-label);
|
|
890
|
+
color: rgb(var(--og-text-faint));
|
|
891
|
+
}
|
|
892
|
+
.fx-grid-table__row {
|
|
893
|
+
appearance: none;
|
|
894
|
+
width: 100%;
|
|
895
|
+
padding: 11px 12px;
|
|
896
|
+
border: 0;
|
|
897
|
+
border-bottom: 1px solid rgb(var(--og-border-subtle));
|
|
898
|
+
background: transparent;
|
|
899
|
+
text-align: left;
|
|
900
|
+
cursor: pointer;
|
|
901
|
+
font: inherit;
|
|
902
|
+
color: inherit;
|
|
903
|
+
transition: background-color 130ms ease;
|
|
904
|
+
}
|
|
905
|
+
.fx-grid-table__row:last-child {
|
|
906
|
+
border-bottom: 0;
|
|
907
|
+
}
|
|
908
|
+
.fx-grid-table__row:hover {
|
|
909
|
+
background: rgb(var(--og-surface-sunken));
|
|
910
|
+
}
|
|
911
|
+
.fx-grid-table__row--on {
|
|
912
|
+
background: rgb(var(--og-accent-soft-bg));
|
|
913
|
+
}
|
|
914
|
+
.fx-grid-table__row:focus-visible {
|
|
915
|
+
outline: 2px solid rgb(var(--og-accent));
|
|
916
|
+
outline-offset: -2px;
|
|
917
|
+
}
|
|
918
|
+
.fx-grid-caret {
|
|
919
|
+
font-size: 15px;
|
|
920
|
+
line-height: 1;
|
|
921
|
+
color: rgb(var(--og-text-faint));
|
|
922
|
+
justify-self: end;
|
|
923
|
+
transition:
|
|
924
|
+
color 130ms ease,
|
|
925
|
+
transform 130ms ease;
|
|
926
|
+
}
|
|
927
|
+
.fx-grid-table__row:hover .fx-grid-caret {
|
|
928
|
+
color: rgb(var(--og-accent));
|
|
929
|
+
transform: translateX(2px);
|
|
930
|
+
}
|
|
931
|
+
.fx-grid-table__num {
|
|
932
|
+
font-family: var(--og-font-mono);
|
|
933
|
+
font-size: var(--og-fs-sm);
|
|
934
|
+
color: rgb(var(--og-text-body));
|
|
935
|
+
text-align: right;
|
|
936
|
+
font-variant-numeric: tabular-nums;
|
|
937
|
+
}
|
|
938
|
+
.fx-grid-table__head .fx-grid-table__num {
|
|
939
|
+
font-family: inherit;
|
|
940
|
+
font-size: inherit;
|
|
941
|
+
color: inherit;
|
|
942
|
+
}
|
|
943
|
+
.fx-grid-table__strong {
|
|
944
|
+
font-size: var(--og-fs-sm);
|
|
945
|
+
font-weight: 600;
|
|
946
|
+
color: rgb(var(--og-text));
|
|
947
|
+
}
|
|
948
|
+
.fx-grid-table__muted {
|
|
949
|
+
font-size: var(--og-fs-xs);
|
|
950
|
+
color: rgb(var(--og-text-muted));
|
|
951
|
+
}
|
|
952
|
+
.fx-grid-table__mono {
|
|
953
|
+
font-family: var(--og-font-mono);
|
|
954
|
+
font-size: var(--og-fs-xs);
|
|
955
|
+
color: rgb(var(--og-text-faint));
|
|
956
|
+
}
|
|
957
|
+
.fx-grid-empty {
|
|
958
|
+
padding: 15px;
|
|
959
|
+
text-align: center;
|
|
960
|
+
color: rgb(var(--og-text-muted));
|
|
961
|
+
font-size: var(--og-fs-sm);
|
|
962
|
+
border: 1px dashed rgb(var(--og-border));
|
|
963
|
+
border-radius: var(--og-radius-card);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
/* `.og-badge`: 3px 10px, pill, 11.5px, soft tint by tone; outline = the
|
|
967
|
+
neutral "Low" band; solid = Critical. Tone names are the SEMANTIC tokens
|
|
968
|
+
(`--og-negative`, not the chart ramp) — see the note above `.tone-tint-*`. */
|
|
969
|
+
.fx-badge {
|
|
970
|
+
display: inline-flex;
|
|
971
|
+
align-items: center;
|
|
972
|
+
gap: 5px;
|
|
973
|
+
padding: 3px 10px;
|
|
974
|
+
border-radius: var(--og-radius-pill);
|
|
975
|
+
font-size: var(--og-fs-xs);
|
|
976
|
+
line-height: 1.5;
|
|
977
|
+
white-space: nowrap;
|
|
978
|
+
/* 400, per the reference's risk badge ("High · 82", measured 16/09). At 500
|
|
979
|
+
it sat a step heavier than every other 11.5px label around it. */
|
|
980
|
+
font-weight: 400;
|
|
981
|
+
}
|
|
982
|
+
.fx-badge--negative {
|
|
983
|
+
background: rgb(var(--og-negative-soft-bg));
|
|
984
|
+
color: rgb(var(--og-negative));
|
|
985
|
+
}
|
|
986
|
+
.fx-badge--warning {
|
|
987
|
+
background: rgb(var(--og-warning-soft-bg));
|
|
988
|
+
color: rgb(var(--og-warning));
|
|
989
|
+
}
|
|
990
|
+
.fx-badge--positive {
|
|
991
|
+
background: rgb(var(--og-positive-soft-bg));
|
|
992
|
+
color: rgb(var(--og-positive));
|
|
993
|
+
}
|
|
994
|
+
.fx-badge--neutral {
|
|
995
|
+
background: rgb(var(--og-neutral-soft-bg));
|
|
996
|
+
color: rgb(var(--og-neutral-soft-fg));
|
|
997
|
+
}
|
|
998
|
+
.fx-badge--accent {
|
|
999
|
+
background: rgb(var(--og-accent-soft-bg));
|
|
1000
|
+
color: rgb(var(--og-accent-soft-fg));
|
|
1001
|
+
}
|
|
1002
|
+
.fx-badge--outline {
|
|
1003
|
+
background: none;
|
|
1004
|
+
border: 1px solid rgb(var(--og-border));
|
|
1005
|
+
color: rgb(var(--og-text-muted));
|
|
1006
|
+
}
|
|
1007
|
+
.fx-badge--solid {
|
|
1008
|
+
background: rgb(var(--og-text));
|
|
1009
|
+
color: rgb(var(--og-surface));
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
/* `.og-statusdot`: a 7px mark and the state's name. */
|
|
1013
|
+
.fx-statusdot {
|
|
1014
|
+
display: inline-flex;
|
|
1015
|
+
align-items: center;
|
|
1016
|
+
gap: 6px;
|
|
1017
|
+
font-size: var(--og-fs-sm);
|
|
1018
|
+
color: rgb(var(--og-text-body));
|
|
1019
|
+
white-space: nowrap;
|
|
1020
|
+
}
|
|
1021
|
+
.fx-statusdot::before {
|
|
1022
|
+
content: '';
|
|
1023
|
+
width: 7px;
|
|
1024
|
+
height: 7px;
|
|
1025
|
+
border-radius: 50%;
|
|
1026
|
+
background: rgb(var(--og-text-faint));
|
|
1027
|
+
flex: none;
|
|
1028
|
+
}
|
|
1029
|
+
.fx-statusdot--positive::before {
|
|
1030
|
+
background: rgb(var(--og-positive));
|
|
1031
|
+
}
|
|
1032
|
+
.fx-statusdot--negative::before {
|
|
1033
|
+
background: rgb(var(--og-negative));
|
|
1034
|
+
}
|
|
1035
|
+
.fx-statusdot--warning::before {
|
|
1036
|
+
background: rgb(var(--og-warning));
|
|
1037
|
+
}
|
|
1038
|
+
.fx-statusdot--accent::before {
|
|
1039
|
+
background: rgb(var(--og-accent));
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
/* A tooltip must never take the pointer. Material gives its overlay pane
|
|
1043
|
+
`pointer-events: auto`, and with the drawer COLLAPSED a nav item's tooltip
|
|
1044
|
+
opens at x≈70..110 while the collapse/expand button sits at 58..82 — the
|
|
1045
|
+
tooltip covered the button's right half and swallowed the click, which is
|
|
1046
|
+
why the toggle "sometimes" did nothing (MEASURED 16/09). Nothing in a
|
|
1047
|
+
tooltip is interactive, so this is safe everywhere. */
|
|
1048
|
+
.mat-mdc-tooltip-panel,
|
|
1049
|
+
.mat-mdc-tooltip,
|
|
1050
|
+
.mat-mdc-tooltip-panel > * {
|
|
1051
|
+
pointer-events: none !important;
|
|
1052
|
+
}
|
|
@@ -53,6 +53,9 @@
|
|
|
53
53
|
|
|
54
54
|
--color-cta: #c2582a;
|
|
55
55
|
--color-cta-hover: #b34e24;
|
|
56
|
+
/* Border of the CTA while hovered — the reference's `.bi-newbtn:hover`
|
|
57
|
+
darkens the edge one more step than the fill (16/09). */
|
|
58
|
+
--color-cta-hover-border: #a3461f;
|
|
56
59
|
|
|
57
60
|
/* ---- Legacy colour names (@deprecated — remove after the V2 campaign;
|
|
58
61
|
they resolve through the alias layer in theme.css, so every existing
|
|
@@ -1,29 +1,30 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<!-- Ranked list, to the reference's "Top projects by risk" (measured in the
|
|
2
|
+
browser 16/09): the SCORE leads, right-aligned in a 70px column, then the
|
|
3
|
+
label in a 150px column, then a 3px track taking the rest. It used to be
|
|
4
|
+
label-left / score-right with a 5px full-width track underneath, which is a
|
|
5
|
+
different object — two lines per row instead of one. -->
|
|
6
|
+
<div class="fx-barlist flex flex-col">
|
|
7
|
+
@for (item of items(); track item.label; let first = $first) {
|
|
3
8
|
<button
|
|
4
9
|
type="button"
|
|
5
|
-
class="text-left
|
|
10
|
+
class="fx-barlist__row text-left flex items-center"
|
|
6
11
|
[class.hover:bg-surface-sunken]="interactive()"
|
|
7
12
|
[class.cursor-default]="!interactive()"
|
|
8
13
|
[tabindex]="interactive() ? 0 : -1"
|
|
9
14
|
(click)="onSelect(item)"
|
|
10
15
|
>
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@if (item.meta) {
|
|
18
|
-
<div class="txt-utility-description truncate">{{ item.meta }}</div>
|
|
19
|
-
}
|
|
20
|
-
<div class="mt-xs h-[var(--og-track-h)] rounded-pill bg-track overflow-hidden">
|
|
21
|
-
<div
|
|
22
|
-
class="h-full rounded-pill transition-all duration-500"
|
|
23
|
-
[ngClass]="barClass(item)"
|
|
16
|
+
<span class="fx-barlist__score shrink-0">{{ item.valueLabel ?? item.value }}</span>
|
|
17
|
+
<span class="fx-barlist__label shrink-0 truncate">{{ item.label }}</span>
|
|
18
|
+
<span class="fx-barlist__track flex-1">
|
|
19
|
+
<span
|
|
20
|
+
class="fx-barlist__fill block"
|
|
21
|
+
[class.fx-barlist__fill--lead]="first"
|
|
24
22
|
[style.width.%]="widthOf(item)"
|
|
25
|
-
></
|
|
26
|
-
</
|
|
23
|
+
></span>
|
|
24
|
+
</span>
|
|
27
25
|
</button>
|
|
26
|
+
@if (item.meta) {
|
|
27
|
+
<div class="fx-barlist__meta truncate">{{ item.meta }}</div>
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
30
|
</div>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
@reference '../../../styles/tailwind.css';
|
|
2
|
+
|
|
3
|
+
/* Metrics from the reference (measured 16/09): rows 8px apart, each 18px tall
|
|
4
|
+
with a 10px gap between its three cells. */
|
|
5
|
+
.fx-barlist {
|
|
6
|
+
gap: 8px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.fx-barlist__row {
|
|
10
|
+
gap: 10px;
|
|
11
|
+
min-height: 18px;
|
|
12
|
+
/* A right gutter so the bar stops short of the panel edge (anh Tú 16/09).
|
|
13
|
+
The reference's row is 387px wide and its 147px track happens to end level
|
|
14
|
+
with the card's padding; this panel is twice that, so a track that fills
|
|
15
|
+
the remainder runs right up to the edge and reads as an overflow. */
|
|
16
|
+
padding: 0 24px 0 0;
|
|
17
|
+
background: transparent;
|
|
18
|
+
border: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Score first, right-aligned in its own column — that alignment is what makes
|
|
22
|
+
the numbers read as a ranked column rather than trailing labels. */
|
|
23
|
+
.fx-barlist__score {
|
|
24
|
+
width: 70px;
|
|
25
|
+
text-align: right;
|
|
26
|
+
font-family: var(--og-font-mono);
|
|
27
|
+
font-size: var(--og-fs-sm);
|
|
28
|
+
font-weight: 400;
|
|
29
|
+
color: rgb(var(--og-text));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.fx-barlist__label {
|
|
33
|
+
width: 150px;
|
|
34
|
+
font-size: var(--og-fs-sm);
|
|
35
|
+
font-weight: 400;
|
|
36
|
+
color: rgb(var(--og-text-muted));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* A 3px hairline track, square ends — not the 5px pill it was. */
|
|
40
|
+
.fx-barlist__track {
|
|
41
|
+
height: 3px;
|
|
42
|
+
background: rgb(var(--og-track));
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Every bar is muted EXCEPT the leader, which takes the accent. The reference
|
|
47
|
+
ranks by one colour and highlights the top row; tone-per-row turned the
|
|
48
|
+
panel into a severity chart, which is the donut's job, not this one. */
|
|
49
|
+
.fx-barlist__fill {
|
|
50
|
+
height: 100%;
|
|
51
|
+
background: rgb(var(--og-text-muted));
|
|
52
|
+
transition: width 500ms ease;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.fx-barlist__fill--lead {
|
|
56
|
+
background: rgb(var(--og-accent));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.fx-barlist__meta {
|
|
60
|
+
font-size: var(--og-fs-2xs);
|
|
61
|
+
color: rgb(var(--og-text-faint));
|
|
62
|
+
padding-left: 80px;
|
|
63
|
+
}
|
|
@@ -260,3 +260,34 @@
|
|
|
260
260
|
.text-faint { color: rgb(var(--og-text-faint)); }
|
|
261
261
|
.text-strong { color: rgb(var(--og-text)); }
|
|
262
262
|
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
|
|
263
|
+
|
|
264
|
+
/* CTA crumb — the reference's "+ Create project" at the end of the Project
|
|
265
|
+
Management trail (measured 16/09: 24px tall, 4px 10px 4px 8px, gap 5,
|
|
266
|
+
10.5px/600, radius 7, a light accent fill with an accent border).
|
|
267
|
+
The exact demo colours are #eaf1fa / #b9cde6 / #2a4f7c; the accent-soft
|
|
268
|
+
TOKENS are used instead so the pill follows the theme in all six — they sit
|
|
269
|
+
within ~3 of those values in light mode, and the border is mixed from the
|
|
270
|
+
accent rather than hard-coded because no token matches it. */
|
|
271
|
+
.fx-crumb-cta {
|
|
272
|
+
appearance: none;
|
|
273
|
+
display: inline-flex;
|
|
274
|
+
align-items: center;
|
|
275
|
+
gap: 5px;
|
|
276
|
+
min-width: 0;
|
|
277
|
+
padding: 4px 10px 4px 8px;
|
|
278
|
+
line-height: 1.5;
|
|
279
|
+
border: 1px solid color-mix(in srgb, rgb(var(--og-accent)) 35%, transparent);
|
|
280
|
+
border-radius: var(--og-radius-control);
|
|
281
|
+
background: rgb(var(--og-accent-soft-bg));
|
|
282
|
+
color: rgb(var(--og-accent-soft-fg));
|
|
283
|
+
font-size: var(--og-fs-2xs);
|
|
284
|
+
font-weight: 600;
|
|
285
|
+
white-space: nowrap;
|
|
286
|
+
cursor: pointer;
|
|
287
|
+
transition: background-color 130ms ease, border-color 130ms ease;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.fx-crumb-cta:hover {
|
|
291
|
+
background: color-mix(in srgb, rgb(var(--og-accent)) 16%, rgb(var(--og-accent-soft-bg)));
|
|
292
|
+
border-color: color-mix(in srgb, rgb(var(--og-accent)) 55%, transparent);
|
|
293
|
+
}
|
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
@if (i > 0) {
|
|
4
4
|
<span aria-hidden="true" class="fx-crumb-sep">/</span>
|
|
5
5
|
}
|
|
6
|
-
@if (
|
|
6
|
+
@if (crumb.cta) {
|
|
7
|
+
<button type="button" class="fx-crumb-cta" (click)="go($event, crumb.url || '')">
|
|
8
|
+
<fx-ui-hero-icon [icon]="crumb.icon || 'plus'" [size]="13" class="flex shrink-0" />
|
|
9
|
+
<span class="truncate">{{ crumb.label }}</span>
|
|
10
|
+
</button>
|
|
11
|
+
} @else if (isChip(crumb)) {
|
|
7
12
|
<span class="relative inline-flex min-w-0">
|
|
8
13
|
<button
|
|
9
14
|
type="button"
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
<div class="drawer-host-wrapper">
|
|
2
2
|
<a href="/" class="drawer-brand" [class.is-collapsed]="!isExpanded">
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
<!-- Logo sits in its own sunken tile (reference `.sb-logo`, measured 16/09):
|
|
4
|
+
the tile is what carries the hover border, so the mark keeps its own
|
|
5
|
+
size and nothing shifts by a pixel when that border appears. -->
|
|
6
|
+
<span class="drawer-brand-logo">
|
|
7
|
+
@if (logo) {
|
|
8
|
+
<img [src]="logo" alt="Home" class="drawer-brand-mark" />
|
|
9
|
+
} @else {
|
|
10
|
+
<span class="drawer-brand-mark"></span>
|
|
11
|
+
}
|
|
12
|
+
</span>
|
|
8
13
|
@if (isExpanded && (logoText || logoSubtext)) {
|
|
9
14
|
<span class="drawer-brand-copy">
|
|
10
15
|
@if (logoText) {
|
|
@@ -87,16 +92,26 @@
|
|
|
87
92
|
<a
|
|
88
93
|
[routerLink]="item.route"
|
|
89
94
|
class="drawer-item"
|
|
95
|
+
[class.is-collapsed]="!isExpanded"
|
|
90
96
|
[class.active]="isActiveRoute(item.route)"
|
|
91
97
|
[class.has-children]="item.children && item.children.length > 0"
|
|
92
|
-
[style.paddingLeft.px]="isExpanded ?
|
|
98
|
+
[style.paddingLeft.px]="isExpanded ? 8 + level * 16 : 16"
|
|
93
99
|
[matTooltip]="!isExpanded ? item.label : ''"
|
|
94
100
|
matTooltipPosition="right"
|
|
95
101
|
matTooltipClass="text-text-primary text-xs font-semibold"
|
|
96
102
|
(click)="onItemClick(item, $event)"
|
|
97
103
|
>
|
|
98
104
|
<div class="item-content">
|
|
99
|
-
|
|
105
|
+
@if (item.iconData) {
|
|
106
|
+
<lucide-icon
|
|
107
|
+
[img]="item.iconData"
|
|
108
|
+
[size]="isExpanded ? 13 : 18"
|
|
109
|
+
class="item-icon"
|
|
110
|
+
[class.item-icon--solid]="item.iconSolid"
|
|
111
|
+
/>
|
|
112
|
+
} @else {
|
|
113
|
+
<fx-ui-hero-icon [icon]="item.icon" [size]="isExpanded ? 13 : 18" class="item-icon"></fx-ui-hero-icon>
|
|
114
|
+
}
|
|
100
115
|
@if (isExpanded) {
|
|
101
116
|
<span class="item-label">{{ item.label }}</span>
|
|
102
117
|
}
|
|
@@ -108,16 +123,26 @@
|
|
|
108
123
|
<button
|
|
109
124
|
type="button"
|
|
110
125
|
class="drawer-item"
|
|
126
|
+
[class.is-collapsed]="!isExpanded"
|
|
111
127
|
[class.active]="isActiveRoute(item.route)"
|
|
112
128
|
[class.has-children]="item.children && item.children.length > 0"
|
|
113
|
-
[style.paddingLeft.px]="isExpanded ?
|
|
129
|
+
[style.paddingLeft.px]="isExpanded ? 8 + level * 16 : 16"
|
|
114
130
|
[matTooltip]="!isExpanded ? item.label : ''"
|
|
115
131
|
matTooltipPosition="right"
|
|
116
132
|
matTooltipClass="text-text-primary text-sm font-semibold"
|
|
117
133
|
(click)="onItemClick(item, $event)"
|
|
118
134
|
>
|
|
119
135
|
<div class="item-content">
|
|
120
|
-
|
|
136
|
+
@if (item.iconData) {
|
|
137
|
+
<lucide-icon
|
|
138
|
+
[img]="item.iconData"
|
|
139
|
+
[size]="isExpanded ? 13 : 18"
|
|
140
|
+
class="item-icon"
|
|
141
|
+
[class.item-icon--solid]="item.iconSolid"
|
|
142
|
+
/>
|
|
143
|
+
} @else {
|
|
144
|
+
<fx-ui-hero-icon [icon]="item.icon" [size]="isExpanded ? 13 : 18" class="item-icon"></fx-ui-hero-icon>
|
|
145
|
+
}
|
|
121
146
|
@if (isExpanded) {
|
|
122
147
|
<span class="item-label">{{ item.label }}</span>
|
|
123
148
|
}
|