@keenmate/pure-admin-core 2.7.1 → 2.8.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/README.md +8 -17
- package/dist/css/main.css +620 -83
- package/package.json +1 -1
- package/src/scss/_base-css-variables.scss +6 -0
- package/src/scss/core-components/_kpi-bento.scss +41 -6
- package/src/scss/core-components/_kpi-comparison-gauges.scss +60 -23
- package/src/scss/core-components/_kpi-editorial-minimal.scss +63 -20
- package/src/scss/core-components/_kpi-hero-supporting.scss +15 -1
- package/src/scss/core-components/_kpi-numeric-strip.scss +74 -15
- package/src/scss/core-components/_kpi-sparkline-list.scss +56 -4
- package/src/scss/core-components/_kpi-terminal.scss +22 -15
- package/src/scss/main.scss +11 -0
package/package.json
CHANGED
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
// --ms-accent-color: var(--base-accent-color, #3b82f6);
|
|
15
15
|
// ============================================================================
|
|
16
16
|
|
|
17
|
+
// Make variables resolvable when this file is loaded as a @use module
|
|
18
|
+
// (e.g. from main.scss). Legacy @import callers (themes) are unaffected —
|
|
19
|
+
// Sass places @use'd members into the importing file's global scope, where
|
|
20
|
+
// theme-set overrides already live.
|
|
21
|
+
@use 'variables/index' as *;
|
|
22
|
+
|
|
17
23
|
@mixin output-base-css-variables {
|
|
18
24
|
// === Accent Colors ===
|
|
19
25
|
--base-accent-color: #{$base-accent-color};
|
|
@@ -1,22 +1,32 @@
|
|
|
1
1
|
/* ========================================
|
|
2
2
|
KPI · Bento layout
|
|
3
3
|
Magazine-style asymmetric tile sizing with sparklines as soft background
|
|
4
|
-
fills behind the values. 6
|
|
4
|
+
fills behind the values. Default 6-tile layout on a 6-col × 3-row grid
|
|
5
5
|
(hero left-half × 2 rows, two stacked right-half × 2 rows, three equal
|
|
6
|
-
tiles bottom row). Tile placement by source order via :nth-child
|
|
6
|
+
tiles bottom row). Tile placement is by source order via :nth-child, so
|
|
7
|
+
markup stays identical across layout modifiers.
|
|
8
|
+
|
|
9
|
+
Layout modifiers (below) swap `grid-template-areas` to provide
|
|
10
|
+
alternative compositions:
|
|
11
|
+
· default (no modifier) — 6 tiles, hero on the left
|
|
12
|
+
· `--hero-right` — 6 tiles, mirror of default (hero on right)
|
|
13
|
+
· `--5-tile` — 5 tiles, hero + 4 supporting
|
|
14
|
+
Row height is a CSS variable (`--pa-kpi-bento-row-height`, default
|
|
15
|
+
`12rem`) so authors can dial tile height per instance.
|
|
7
16
|
======================================== */
|
|
8
17
|
@use '../variables' as *;
|
|
9
18
|
|
|
10
19
|
.pa-kpi-bento {
|
|
11
20
|
container-type: inline-size;
|
|
21
|
+
--pa-kpi-bento-row-height: 12rem;
|
|
12
22
|
}
|
|
13
23
|
.pa-kpi-bento__body { padding: 1.6rem; }
|
|
14
24
|
|
|
15
|
-
/* ----- Bento grid
|
|
25
|
+
/* ----- Bento grid (default: 6 tiles, hero on left) ---------------------- */
|
|
16
26
|
.pa-kpi-bento__grid {
|
|
17
27
|
display: grid;
|
|
18
28
|
grid-template-columns: repeat(6, 1fr);
|
|
19
|
-
grid-template-rows:
|
|
29
|
+
grid-template-rows: repeat(3, var(--pa-kpi-bento-row-height));
|
|
20
30
|
grid-template-areas:
|
|
21
31
|
"hero hero hero a a a"
|
|
22
32
|
"hero hero hero b b b"
|
|
@@ -31,8 +41,33 @@
|
|
|
31
41
|
> :nth-child(6) { grid-area: e; }
|
|
32
42
|
}
|
|
33
43
|
|
|
34
|
-
/*
|
|
35
|
-
|
|
44
|
+
/* Modifier: --hero-right — mirror of default. Hero on the right half,
|
|
45
|
+
two stacked tiles on the left of rows 1-2, three equal tiles below.
|
|
46
|
+
Same 6-tile contract as default; only the template flips. Source
|
|
47
|
+
order stays unchanged (1st = hero, 2nd = a, …). */
|
|
48
|
+
.pa-kpi-bento__grid--hero-right {
|
|
49
|
+
grid-template-areas:
|
|
50
|
+
"a a a hero hero hero"
|
|
51
|
+
"b b b hero hero hero"
|
|
52
|
+
"c c d d e e";
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* Modifier: --5-tile — hero + 4 supporting. Hero spans the left half ×
|
|
56
|
+
2 rows, two stacked tiles on the right (rows 1-2), two equal halves on
|
|
57
|
+
the bottom row. Requires exactly 5 tiles — a 6th tile (if present)
|
|
58
|
+
would be auto-placed in a new row and break the layout. */
|
|
59
|
+
.pa-kpi-bento__grid--5-tile {
|
|
60
|
+
grid-template-areas:
|
|
61
|
+
"hero hero hero a a a"
|
|
62
|
+
"hero hero hero b b b"
|
|
63
|
+
"c c c d d d";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Narrow card → stack everything single column. Resets `grid-area: auto`
|
|
67
|
+
on every tile so the same markup works regardless of which layout
|
|
68
|
+
modifier the grid carries (the @container override sets
|
|
69
|
+
`grid-template-areas: none` and the `grid-area: auto` on nth-child
|
|
70
|
+
together neutralise any modifier's template). */
|
|
36
71
|
@container (max-width: 700px) {
|
|
37
72
|
.pa-kpi-bento__grid {
|
|
38
73
|
grid-template-columns: 1fr;
|
|
@@ -3,55 +3,92 @@
|
|
|
3
3
|
Goal-oriented progress bars. Each KPI shows label · value, a bar with a
|
|
4
4
|
target tick, and a 0 · tgt scale below. Bar fill = value/target * 100%,
|
|
5
5
|
capped visually so overshoots are signalled by colour, not overflow.
|
|
6
|
+
|
|
7
|
+
Layout is a cell-min-driven `auto-fit` grid — cells stay at least
|
|
8
|
+
`--pa-kpi-gauge-cell-min` wide, the grid fits as many columns as the
|
|
9
|
+
container allows, and the responsive cascade is intrinsic to the grid
|
|
10
|
+
template (no `@container` queries). `--max-N` cap modifiers cap the
|
|
11
|
+
column count at N while still collapsing below the cell-min × N
|
|
12
|
+
threshold. Same pattern as `_kpi-editorial-minimal.scss`.
|
|
6
13
|
======================================== */
|
|
7
14
|
@use '../variables' as *;
|
|
8
15
|
|
|
9
|
-
.pa-kpi-gauge-list {
|
|
10
|
-
container-type: inline-size;
|
|
11
|
-
}
|
|
12
16
|
.pa-kpi-gauge-list__body { padding: 0; }
|
|
13
17
|
|
|
14
|
-
/*
|
|
18
|
+
/* ----- Grid + hairline rules -------------------------------------------
|
|
19
|
+
Cell-min-driven responsive layout. Override `--pa-kpi-gauge-cell-min`
|
|
20
|
+
per instance to change density (smaller min → more columns at the same
|
|
21
|
+
container width).
|
|
22
|
+
|
|
23
|
+
`gap: 1px` over `background: var(--pa-border-color)` with each tile
|
|
24
|
+
painting `background: var(--pa-card-bg)` on top — only the gap shows
|
|
25
|
+
through, giving single-pixel hairlines on every interior boundary
|
|
26
|
+
regardless of column count. The card's outer border supplies the
|
|
27
|
+
perimeter. Replaces the previous per-tile `border-right` +
|
|
28
|
+
`border-bottom` + nth-child suppression machinery, which only worked
|
|
29
|
+
for the hardcoded 2-col layout. */
|
|
15
30
|
.pa-kpi-gauge-list__grid {
|
|
16
31
|
display: grid;
|
|
17
|
-
grid-template-columns: repeat(
|
|
32
|
+
grid-template-columns: repeat(auto-fit, minmax(var(--pa-kpi-gauge-cell-min, 20rem), 1fr));
|
|
33
|
+
gap: 1px;
|
|
34
|
+
background: var(--pa-border-color);
|
|
18
35
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
|
|
37
|
+
/* Modifier: force exactly 2 columns regardless of cell-min or container
|
|
38
|
+
width. For placements wanting a deterministic 2×N layout. */
|
|
39
|
+
.pa-kpi-gauge-list__grid--2col { grid-template-columns: repeat(2, 1fr); }
|
|
40
|
+
|
|
41
|
+
/* Cap-at-N modifiers: combine auto-fit with a ceiling on the column
|
|
42
|
+
count. Cells stay at least --pa-kpi-gauge-cell-min wide, but the grid
|
|
43
|
+
never exceeds N columns even when the container is wide enough to fit
|
|
44
|
+
more. Below the cell-min × N threshold the grid still collapses
|
|
45
|
+
responsively — these modifiers cap the maximum, not the minimum.
|
|
46
|
+
|
|
47
|
+
How the calc reads: each track's effective min is
|
|
48
|
+
max(cell-min, (container − total-gap) / N)
|
|
49
|
+
On a wide container the calc wins (so tracks grow, you stay at N).
|
|
50
|
+
On a narrow container cell-min wins (so the grid collapses).
|
|
51
|
+
|
|
52
|
+
Pick the cap so your item count divides into clean rows. */
|
|
53
|
+
.pa-kpi-gauge-list__grid--max-2 {
|
|
54
|
+
grid-template-columns:
|
|
55
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-gauge-cell-min, 20rem), calc((100% - 1px) / 2)), 1fr));
|
|
56
|
+
}
|
|
57
|
+
.pa-kpi-gauge-list__grid--max-3 {
|
|
58
|
+
grid-template-columns:
|
|
59
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-gauge-cell-min, 20rem), calc((100% - 1px * 2) / 3)), 1fr));
|
|
60
|
+
}
|
|
61
|
+
.pa-kpi-gauge-list__grid--max-4 {
|
|
62
|
+
grid-template-columns:
|
|
63
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-gauge-cell-min, 20rem), calc((100% - 1px * 3) / 4)), 1fr));
|
|
64
|
+
}
|
|
65
|
+
.pa-kpi-gauge-list__grid--max-5 {
|
|
66
|
+
grid-template-columns:
|
|
67
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-gauge-cell-min, 20rem), calc((100% - 1px * 4) / 5)), 1fr));
|
|
68
|
+
}
|
|
69
|
+
.pa-kpi-gauge-list__grid--max-6 {
|
|
70
|
+
grid-template-columns:
|
|
71
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-gauge-cell-min, 20rem), calc((100% - 1px * 5) / 6)), 1fr));
|
|
23
72
|
}
|
|
24
73
|
|
|
25
74
|
/* ----- Gauge tile (label/value head · bar · 0/tgt scale) ---------------- */
|
|
26
75
|
.pa-kpi-gauge {
|
|
27
76
|
position: relative;
|
|
77
|
+
background: var(--pa-card-bg);
|
|
28
78
|
padding: 1.6rem 2rem;
|
|
29
|
-
|
|
30
|
-
border-right: 1px solid var(--pa-border-color);
|
|
79
|
+
min-width: 0;
|
|
31
80
|
|
|
32
81
|
/* Per-tile bar colour cascade — modifiers below set the var, the fill
|
|
33
82
|
reads it. Cleaner than per-modifier-per-element rules; host apps can
|
|
34
83
|
override at the tile level via inline style="--pa-kpi-bar-color: …". */
|
|
35
84
|
--pa-kpi-bar-color: var(--pa-positive);
|
|
36
85
|
|
|
37
|
-
&:nth-child(2n) { border-right: 0; }
|
|
38
|
-
&:nth-last-child(-n+2) { border-bottom: 0; }
|
|
39
|
-
|
|
40
86
|
&--positive { --pa-kpi-bar-color: var(--pa-positive); }
|
|
41
87
|
&--warning { --pa-kpi-bar-color: var(--pa-warning); }
|
|
42
88
|
&--negative { --pa-kpi-bar-color: var(--pa-negative); }
|
|
43
89
|
&--neutral { --pa-kpi-bar-color: color-mix(in srgb, var(--pa-text-color-1) 70%, transparent); }
|
|
44
90
|
}
|
|
45
91
|
|
|
46
|
-
@container (max-width: 600px) {
|
|
47
|
-
.pa-kpi-gauge {
|
|
48
|
-
border-right: 0;
|
|
49
|
-
|
|
50
|
-
&:nth-last-child(-n+2) { border-bottom: 1px solid var(--pa-border-color); }
|
|
51
|
-
&:last-child { border-bottom: 0; }
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
92
|
/* ----- Head: label left, value right (baseline-aligned) ----------------- */
|
|
56
93
|
.pa-kpi-gauge__head {
|
|
57
94
|
display: flex;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ========================================
|
|
2
2
|
KPI · Editorial minimal
|
|
3
|
-
|
|
3
|
+
KPI tiles in a responsive grid with hairline rules between cells,
|
|
4
4
|
generous space, and an extra-light-weight number as the focal point per
|
|
5
5
|
tile. No charts, no pills — the design's whole identity is the thin
|
|
6
6
|
numeral. Renders as a table card (zero card-body padding) so hairlines
|
|
@@ -11,32 +11,73 @@
|
|
|
11
11
|
.pa-kpi-edit__body { padding: 0; }
|
|
12
12
|
|
|
13
13
|
/* ----- Grid + hairline rules -------------------------------------------
|
|
14
|
+
Cell-min-driven responsive layout: cells stay at least
|
|
15
|
+
--pa-kpi-edit-cell-min wide; the grid fits as many columns as the
|
|
16
|
+
container allows. No @container queries — `auto-fit + minmax` handles
|
|
17
|
+
the cascade intrinsically. Override the min per instance to change
|
|
18
|
+
density (smaller min → more columns at the same container width).
|
|
19
|
+
|
|
14
20
|
`gap: 1px` over `background: var(--pa-border-color)` with each tile
|
|
15
|
-
painting `background: var(--pa-card-bg)` on top
|
|
16
|
-
through, giving
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
painting `background: var(--pa-card-bg)` on top — only the gap shows
|
|
22
|
+
through, giving single-pixel hairlines on every interior boundary
|
|
23
|
+
regardless of column count. The card's outer border supplies the
|
|
24
|
+
perimeter. */
|
|
19
25
|
.pa-kpi-edit__grid {
|
|
20
26
|
display: grid;
|
|
21
|
-
grid-template-columns: repeat(
|
|
27
|
+
grid-template-columns: repeat(auto-fit, minmax(var(--pa-kpi-edit-cell-min, 14rem), 1fr));
|
|
22
28
|
gap: 1px;
|
|
23
29
|
background: var(--pa-border-color);
|
|
24
|
-
container-type: inline-size;
|
|
25
|
-
}
|
|
26
|
-
@container (max-width: 640px) {
|
|
27
|
-
.pa-kpi-edit__grid { grid-template-columns: repeat(2, 1fr); }
|
|
28
|
-
}
|
|
29
|
-
@container (max-width: 360px) {
|
|
30
|
-
.pa-kpi-edit__grid { grid-template-columns: 1fr; }
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
/* Modifier: force 2
|
|
34
|
-
a deterministic 2×N layout (e.g. 4 tiles
|
|
35
|
-
|
|
32
|
+
/* Modifier: force exactly 2 columns regardless of cell-min or container
|
|
33
|
+
width. For placements wanting a deterministic 2×N layout (e.g. 4 tiles
|
|
34
|
+
as a clean 2×2 even when the container is wide enough for more). */
|
|
36
35
|
.pa-kpi-edit__grid--2col { grid-template-columns: repeat(2, 1fr); }
|
|
37
36
|
|
|
38
|
-
/*
|
|
37
|
+
/* Cap-at-N modifiers: combine auto-fit with a ceiling on the column
|
|
38
|
+
count. Cells stay at least --pa-kpi-edit-cell-min wide, but the grid
|
|
39
|
+
never exceeds N columns even when the container is wide enough to fit
|
|
40
|
+
more. Below the cell-min × N threshold the grid still collapses
|
|
41
|
+
responsively — these modifiers cap the maximum, not the minimum.
|
|
42
|
+
|
|
43
|
+
How the calc reads: each track's effective min is
|
|
44
|
+
max(cell-min, (container − total-gap) / N)
|
|
45
|
+
On a wide container the calc wins (so tracks grow, you stay at N).
|
|
46
|
+
On a narrow container cell-min wins (so the grid collapses).
|
|
47
|
+
|
|
48
|
+
Why this matters for the gray-void edge case: `auto-fit` keeps as many
|
|
49
|
+
tracks as fit the container, then only collapses tracks empty across
|
|
50
|
+
the *whole* grid. With 6 items at 4-col auto-fit, tracks 1–4 all have
|
|
51
|
+
row-1 items, so row 2's tracks 3–4 stay (and show the gap background).
|
|
52
|
+
Capping at 3 makes 6 items pack 3×2 cleanly. Pick the cap so your item
|
|
53
|
+
count divides into clean rows. */
|
|
54
|
+
.pa-kpi-edit__grid--max-2 {
|
|
55
|
+
grid-template-columns:
|
|
56
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-edit-cell-min, 14rem), calc((100% - 1px) / 2)), 1fr));
|
|
57
|
+
}
|
|
58
|
+
.pa-kpi-edit__grid--max-3 {
|
|
59
|
+
grid-template-columns:
|
|
60
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-edit-cell-min, 14rem), calc((100% - 1px * 2) / 3)), 1fr));
|
|
61
|
+
}
|
|
62
|
+
.pa-kpi-edit__grid--max-4 {
|
|
63
|
+
grid-template-columns:
|
|
64
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-edit-cell-min, 14rem), calc((100% - 1px * 3) / 4)), 1fr));
|
|
65
|
+
}
|
|
66
|
+
.pa-kpi-edit__grid--max-5 {
|
|
67
|
+
grid-template-columns:
|
|
68
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-edit-cell-min, 14rem), calc((100% - 1px * 4) / 5)), 1fr));
|
|
69
|
+
}
|
|
70
|
+
.pa-kpi-edit__grid--max-6 {
|
|
71
|
+
grid-template-columns:
|
|
72
|
+
repeat(auto-fit, minmax(max(var(--pa-kpi-edit-cell-min, 14rem), calc((100% - 1px * 5) / 6)), 1fr));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ----- Tile (editorial spacing leans on the 2.4rem padding) -------------
|
|
76
|
+
Per-cell container: the value's `cqi`-based font-size scales with
|
|
77
|
+
*this* tile's width, not the whole grid's. Keeps typography legible as
|
|
78
|
+
the grid packs more cells into the same row. */
|
|
39
79
|
.pa-kpi-edit__tile {
|
|
80
|
+
container-type: inline-size;
|
|
40
81
|
background: var(--pa-card-bg);
|
|
41
82
|
padding: 2.4rem 2rem;
|
|
42
83
|
display: flex;
|
|
@@ -69,11 +110,13 @@
|
|
|
69
110
|
"monospace at low contrast".
|
|
70
111
|
- font-weight: 200 (extra-light). 300 was tested first but didn't read
|
|
71
112
|
distinctly enough as "light" against the body's 400 default.
|
|
72
|
-
- clamp() lets the number shrink in narrow
|
|
73
|
-
|
|
113
|
+
- clamp() lets the number shrink in narrow cells without manual
|
|
114
|
+
breakpoints. `cqi` measures per-cell (tile is a container) so the
|
|
115
|
+
value tracks each cell's actual width as the grid packs more
|
|
116
|
+
columns into a wider container. */
|
|
74
117
|
.pa-kpi-edit__value {
|
|
75
118
|
font-family: var(--base-font-family);
|
|
76
|
-
font-size: clamp(3.2rem,
|
|
119
|
+
font-size: clamp(3.2rem, 22cqi, 5.6rem);
|
|
77
120
|
font-weight: 200;
|
|
78
121
|
letter-spacing: -0.02em;
|
|
79
122
|
line-height: 1;
|
|
@@ -12,12 +12,26 @@
|
|
|
12
12
|
}
|
|
13
13
|
.pa-kpi-hero-list__body { padding: 1.6rem; }
|
|
14
14
|
|
|
15
|
-
/* ----- Layout: hero left, rail right ------------------------------------
|
|
15
|
+
/* ----- Layout: hero left, rail right ------------------------------------
|
|
16
|
+
Default split is 1:1 (50% hero / 50% rail). Modifiers below shift the
|
|
17
|
+
weight to the hero, which is the more common "executive dashboard"
|
|
18
|
+
shape — one big headline, supporting tiles compressed into a narrower
|
|
19
|
+
rail. Pick a modifier per instance; the markup stays unchanged. */
|
|
16
20
|
.pa-kpi-hero-list__layout {
|
|
17
21
|
display: grid;
|
|
18
22
|
grid-template-columns: 1fr 1fr;
|
|
19
23
|
gap: 1.4rem;
|
|
20
24
|
}
|
|
25
|
+
/* Hero 2/3, rail 1/3. */
|
|
26
|
+
.pa-kpi-hero-list__layout--hero-2-3 {
|
|
27
|
+
grid-template-columns: 2fr 1fr;
|
|
28
|
+
}
|
|
29
|
+
/* Hero 3/4, rail 1/4 — hero-dominant; rail is a thin sidebar. */
|
|
30
|
+
.pa-kpi-hero-list__layout--hero-3-4 {
|
|
31
|
+
grid-template-columns: 3fr 1fr;
|
|
32
|
+
}
|
|
33
|
+
/* Narrow card → stack to single column. Overrides any --hero-N-M modifier
|
|
34
|
+
that lives on the same element. */
|
|
21
35
|
@container (max-width: 700px) {
|
|
22
36
|
.pa-kpi-hero-list__layout {
|
|
23
37
|
grid-template-columns: 1fr;
|
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
/* ========================================
|
|
2
2
|
KPI · Numeric strip (densest)
|
|
3
|
-
Tabular "spreadsheet-style" table card with metric/now/prev
|
|
4
|
-
columns — most data per pixel, no chart chrome. Each row is its
|
|
5
|
-
grid sharing the same column template so cells align across rows
|
|
3
|
+
Tabular "spreadsheet-style" table card with metric / now / prev / Δ% /
|
|
4
|
+
target columns — most data per pixel, no chart chrome. Each row is its
|
|
5
|
+
own grid sharing the same column template so cells align across rows
|
|
6
6
|
without needing subgrid. Wide-only by design — no responsive collapse;
|
|
7
7
|
narrow placements should use Comparison gauges instead.
|
|
8
|
+
|
|
9
|
+
Column contract: `metric` + `now` are always present; `prev`, `delta`,
|
|
10
|
+
and `target` are independently optional via toggle modifiers on the
|
|
11
|
+
strip (`--no-prev`, `--no-delta`, `--no-target`). Modifiers compose, so
|
|
12
|
+
the visible column count ranges from 2 (all three optional columns
|
|
13
|
+
dropped) to 5 (none dropped). Each combination has its own template
|
|
14
|
+
selector below so the grid tracks always match the visible cell count.
|
|
8
15
|
======================================== */
|
|
9
16
|
@use '../variables' as *;
|
|
10
17
|
|
|
18
|
+
/* Per-column track widths — referenced from every template selector. */
|
|
19
|
+
$strip-col-metric: minmax(0, 2fr);
|
|
20
|
+
$strip-col-now: minmax(0, 1.1fr);
|
|
21
|
+
$strip-col-prev: minmax(0, 1fr);
|
|
22
|
+
$strip-col-delta: minmax(0, 1fr);
|
|
23
|
+
$strip-col-target: minmax(0, 1.6fr);
|
|
24
|
+
|
|
11
25
|
.pa-kpi-strip__body { padding: 0; }
|
|
12
26
|
|
|
13
27
|
/* ----- Table layout ----------------------------------------------------- */
|
|
@@ -15,11 +29,11 @@
|
|
|
15
29
|
.pa-kpi-strip__head-row {
|
|
16
30
|
display: grid;
|
|
17
31
|
grid-template-columns:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
32
|
+
$strip-col-metric
|
|
33
|
+
$strip-col-now
|
|
34
|
+
$strip-col-prev
|
|
35
|
+
$strip-col-delta
|
|
36
|
+
$strip-col-target;
|
|
23
37
|
column-gap: 1.6rem;
|
|
24
38
|
align-items: center;
|
|
25
39
|
position: relative;
|
|
@@ -142,13 +156,58 @@
|
|
|
142
156
|
line-height: 1;
|
|
143
157
|
}
|
|
144
158
|
|
|
145
|
-
/* -----
|
|
146
|
-
|
|
159
|
+
/* ----- Toggle modifiers ------------------------------------------------
|
|
160
|
+
`--no-prev`, `--no-delta`, `--no-target` are independently composable.
|
|
161
|
+
Each hides its column's cells (data + header) and the matching template
|
|
162
|
+
selector below adjusts `grid-template-columns` to the visible cell
|
|
163
|
+
count, so source order (metric, now, prev, delta, target) is preserved
|
|
164
|
+
and the remaining cells slot into the right tracks.
|
|
165
|
+
|
|
166
|
+
`metric` and `now` are mandatory — no toggle drops them. If a strip
|
|
167
|
+
doesn't need a focal value, it's a different design (use comparison
|
|
168
|
+
gauges or editorial-minimal). */
|
|
169
|
+
.pa-kpi-strip--no-prev .pa-kpi-strip__prev,
|
|
170
|
+
.pa-kpi-strip--no-prev .pa-kpi-strip__head--prev { display: none; }
|
|
171
|
+
.pa-kpi-strip--no-delta .pa-kpi-strip__delta,
|
|
172
|
+
.pa-kpi-strip--no-delta .pa-kpi-strip__head--delta { display: none; }
|
|
173
|
+
.pa-kpi-strip--no-target .pa-kpi-strip__target,
|
|
174
|
+
.pa-kpi-strip--no-target .pa-kpi-strip__head--target { display: none; }
|
|
175
|
+
|
|
176
|
+
/* ----- Grid templates per visible-column combination -------------------
|
|
177
|
+
8 combos (1 default + 3 single-drops + 3 double-drops + 1 triple-drop).
|
|
178
|
+
Each lists the visible columns in source order with their declared
|
|
179
|
+
`$strip-col-*` width. */
|
|
180
|
+
|
|
181
|
+
/* 4-col: one optional column dropped */
|
|
147
182
|
.pa-kpi-strip--no-prev .pa-kpi-strip__row,
|
|
148
183
|
.pa-kpi-strip--no-prev .pa-kpi-strip__head-row {
|
|
149
|
-
grid-template-columns:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
184
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-delta $strip-col-target;
|
|
185
|
+
}
|
|
186
|
+
.pa-kpi-strip--no-delta .pa-kpi-strip__row,
|
|
187
|
+
.pa-kpi-strip--no-delta .pa-kpi-strip__head-row {
|
|
188
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-prev $strip-col-target;
|
|
189
|
+
}
|
|
190
|
+
.pa-kpi-strip--no-target .pa-kpi-strip__row,
|
|
191
|
+
.pa-kpi-strip--no-target .pa-kpi-strip__head-row {
|
|
192
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-prev $strip-col-delta;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* 3-col: two optional columns dropped */
|
|
196
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-delta .pa-kpi-strip__row,
|
|
197
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-delta .pa-kpi-strip__head-row {
|
|
198
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-target;
|
|
199
|
+
}
|
|
200
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-target .pa-kpi-strip__row,
|
|
201
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-target .pa-kpi-strip__head-row {
|
|
202
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-delta;
|
|
203
|
+
}
|
|
204
|
+
.pa-kpi-strip--no-delta.pa-kpi-strip--no-target .pa-kpi-strip__row,
|
|
205
|
+
.pa-kpi-strip--no-delta.pa-kpi-strip--no-target .pa-kpi-strip__head-row {
|
|
206
|
+
grid-template-columns: $strip-col-metric $strip-col-now $strip-col-prev;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* 2-col: all three optional columns dropped (metric + now only) */
|
|
210
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-delta.pa-kpi-strip--no-target .pa-kpi-strip__row,
|
|
211
|
+
.pa-kpi-strip--no-prev.pa-kpi-strip--no-delta.pa-kpi-strip--no-target .pa-kpi-strip__head-row {
|
|
212
|
+
grid-template-columns: $strip-col-metric $strip-col-now;
|
|
154
213
|
}
|
|
@@ -4,9 +4,23 @@
|
|
|
4
4
|
scanning rather than per-tile depth — no view-mode toggle, no status
|
|
5
5
|
pills. Container queries collapse 4-col → 2-row → 3-row as the card
|
|
6
6
|
narrows.
|
|
7
|
+
|
|
8
|
+
Row template uses local SCSS variables for the four column widths
|
|
9
|
+
(`$spark-col-label`, `$spark-col-chart`, `$spark-col-value`,
|
|
10
|
+
`$spark-col-delta`) so all responsive overrides reference the same
|
|
11
|
+
widths — change one and every breakpoint follows. The `--no-delta`
|
|
12
|
+
modifier drops the rightmost column; the other three are load-bearing
|
|
13
|
+
(a sparkline list without label, chart, or value is a different
|
|
14
|
+
design).
|
|
7
15
|
======================================== */
|
|
8
16
|
@use '../variables' as *;
|
|
9
17
|
|
|
18
|
+
/* Per-column track widths — referenced from every template selector. */
|
|
19
|
+
$spark-col-label: minmax(14rem, 28%);
|
|
20
|
+
$spark-col-chart: minmax(10rem, 1fr);
|
|
21
|
+
$spark-col-value: minmax(8rem, 18%);
|
|
22
|
+
$spark-col-delta: minmax(7rem, 12%);
|
|
23
|
+
|
|
10
24
|
/* Card is a query container so rows react to *card* width, not viewport. */
|
|
11
25
|
.pa-kpi-spark-list {
|
|
12
26
|
container-type: inline-size;
|
|
@@ -17,10 +31,10 @@
|
|
|
17
31
|
.pa-kpi-spark-row {
|
|
18
32
|
display: grid;
|
|
19
33
|
grid-template-columns:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
$spark-col-label
|
|
35
|
+
$spark-col-chart
|
|
36
|
+
$spark-col-value
|
|
37
|
+
$spark-col-delta;
|
|
24
38
|
align-items: center;
|
|
25
39
|
gap: 1.6rem;
|
|
26
40
|
padding: 1.4rem 2rem;
|
|
@@ -29,6 +43,18 @@
|
|
|
29
43
|
&:last-child { border-bottom: 0; }
|
|
30
44
|
}
|
|
31
45
|
|
|
46
|
+
/* Modifier: --no-delta — drops the rightmost column. label · chart ·
|
|
47
|
+
value only. Useful when the chart's slope already conveys direction
|
|
48
|
+
and the delta would be redundant. Hides the delta element and shrinks
|
|
49
|
+
the row template to 3 columns. */
|
|
50
|
+
.pa-kpi-spark-list--no-delta .pa-kpi-spark-row {
|
|
51
|
+
grid-template-columns:
|
|
52
|
+
$spark-col-label
|
|
53
|
+
$spark-col-chart
|
|
54
|
+
$spark-col-value;
|
|
55
|
+
}
|
|
56
|
+
.pa-kpi-spark-list--no-delta .pa-kpi-spark-row__delta { display: none; }
|
|
57
|
+
|
|
32
58
|
/* Mid-narrow card (1×3 page-grid + 45% column): stack to 2 rows.
|
|
33
59
|
Label/value/delta on top, full-width chart below. Default order is
|
|
34
60
|
value-above-chart; use .pa-kpi-spark-list--chart-first to flip. */
|
|
@@ -66,6 +92,23 @@
|
|
|
66
92
|
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__label { align-self: start; }
|
|
67
93
|
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__value { text-align: start; align-self: baseline; }
|
|
68
94
|
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__delta { align-self: baseline; }
|
|
95
|
+
|
|
96
|
+
/* --no-delta at mid-narrow: 2-row layout, top row is label+value only. */
|
|
97
|
+
.pa-kpi-spark-list--no-delta .pa-kpi-spark-row {
|
|
98
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
99
|
+
grid-template-areas:
|
|
100
|
+
"label value"
|
|
101
|
+
"chart chart";
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* --no-delta + --chart-first: 3-row single-column stack. */
|
|
105
|
+
.pa-kpi-spark-list--no-delta.pa-kpi-spark-list--chart-first .pa-kpi-spark-row {
|
|
106
|
+
grid-template-columns: 1fr;
|
|
107
|
+
grid-template-areas:
|
|
108
|
+
"label"
|
|
109
|
+
"chart"
|
|
110
|
+
"value";
|
|
111
|
+
}
|
|
69
112
|
}
|
|
70
113
|
|
|
71
114
|
/* Very narrow card (~280–360px, 25% page-grid stress test): force the
|
|
@@ -86,6 +129,15 @@
|
|
|
86
129
|
.pa-kpi-spark-row__chart { grid-area: chart; }
|
|
87
130
|
.pa-kpi-spark-row__value { grid-area: value; text-align: start; align-self: baseline; }
|
|
88
131
|
.pa-kpi-spark-row__delta { grid-area: delta; align-self: baseline; }
|
|
132
|
+
|
|
133
|
+
/* --no-delta at very-narrow: 3-row single-column stack (no delta cell). */
|
|
134
|
+
.pa-kpi-spark-list--no-delta .pa-kpi-spark-row {
|
|
135
|
+
grid-template-columns: 1fr;
|
|
136
|
+
grid-template-areas:
|
|
137
|
+
"label"
|
|
138
|
+
"chart"
|
|
139
|
+
"value";
|
|
140
|
+
}
|
|
89
141
|
}
|
|
90
142
|
|
|
91
143
|
/* ----- Cell typography -------------------------------------------------- */
|
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
/* ========================================
|
|
2
2
|
KPI · Terminal grid
|
|
3
3
|
Bloomberg-style dense panel: mono numbers, status pills, inline SVG
|
|
4
|
-
sparklines, ▲▼ deltas, segmented
|
|
4
|
+
sparklines, ▲▼ deltas, optional segmented tab strip for swapping
|
|
5
|
+
the body content (different tile sets / grids per tab).
|
|
5
6
|
Shared chrome (header, live, footer, detail popover, spark-dot) is in
|
|
6
7
|
_kpi-base.scss.
|
|
7
8
|
======================================== */
|
|
8
9
|
@use '../variables' as *;
|
|
9
10
|
|
|
10
|
-
/* -----
|
|
11
|
+
/* ----- Tab strip (segmented button group) ------------------------------
|
|
12
|
+
Generalised tabs — each `.pa-kpi-terminal__tab` carries a `data-tab`
|
|
13
|
+
slug that matches a `.pa-kpi-terminal__pane[data-tab="…"]` in the body.
|
|
14
|
+
JS toggles `.is-active` on the clicked tab + matching pane; tabs and
|
|
15
|
+
panes are otherwise independent so each pane can hold a completely
|
|
16
|
+
different grid (different tile count, different grid modifier). */
|
|
11
17
|
.pa-kpi-terminal__controls {
|
|
12
18
|
display: inline-flex;
|
|
13
19
|
align-items: center;
|
|
14
20
|
gap: 1.6rem;
|
|
15
21
|
}
|
|
16
|
-
.pa-kpi-
|
|
22
|
+
.pa-kpi-terminal__tabs {
|
|
17
23
|
display: inline-flex;
|
|
18
24
|
border: 1px solid var(--pa-border-color);
|
|
19
25
|
border-radius: 0.4rem;
|
|
20
26
|
overflow: hidden;
|
|
21
27
|
}
|
|
22
|
-
.pa-kpi-
|
|
28
|
+
.pa-kpi-terminal__tab {
|
|
23
29
|
background: transparent;
|
|
24
30
|
border: 0;
|
|
25
31
|
color: var(--pa-text-color-2);
|
|
@@ -41,6 +47,13 @@
|
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
50
|
+
/* ----- Pane visibility ------------------------------------------------- */
|
|
51
|
+
.pa-kpi-terminal__pane {
|
|
52
|
+
display: none;
|
|
53
|
+
|
|
54
|
+
&.is-active { display: block; }
|
|
55
|
+
}
|
|
56
|
+
|
|
44
57
|
/* ----- Grid + tile borders ----------------------------------------------
|
|
45
58
|
Hairline 1px borders between tiles, no gap. Last-row/last-column
|
|
46
59
|
borders suppressed via :nth-last-child / :nth-child selectors. */
|
|
@@ -132,16 +145,15 @@
|
|
|
132
145
|
margin-bottom: 0.8rem;
|
|
133
146
|
}
|
|
134
147
|
|
|
135
|
-
/* ----- Big value
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
when the segmented control is clicked. */
|
|
148
|
+
/* ----- Big value -------------------------------------------------------
|
|
149
|
+
One value per tile — sentiment colour set via `--very-positive` /
|
|
150
|
+
`--positive` / `--neutral` / `--negative` / `--very-negative` modifier
|
|
151
|
+
on the value element. */
|
|
140
152
|
.pa-kpi-tile__values {
|
|
141
153
|
margin-bottom: 0.4rem;
|
|
142
154
|
}
|
|
143
155
|
.pa-kpi-tile__value {
|
|
144
|
-
display:
|
|
156
|
+
display: inline-flex;
|
|
145
157
|
align-items: baseline;
|
|
146
158
|
gap: 0.3rem;
|
|
147
159
|
font-family: var(--base-font-family-mono);
|
|
@@ -153,11 +165,6 @@
|
|
|
153
165
|
&--negative .pa-kpi-tile__num { color: var(--pa-negative); }
|
|
154
166
|
&--very-negative .pa-kpi-tile__num { color: var(--pa-very-negative); }
|
|
155
167
|
}
|
|
156
|
-
.pa-kpi-terminal[data-view="value"] .pa-kpi-tile__value[data-mode="value"],
|
|
157
|
-
.pa-kpi-terminal[data-view="delta"] .pa-kpi-tile__value[data-mode="delta"],
|
|
158
|
-
.pa-kpi-terminal[data-view="trend"] .pa-kpi-tile__value[data-mode="trend"] {
|
|
159
|
-
display: inline-flex;
|
|
160
|
-
}
|
|
161
168
|
|
|
162
169
|
.pa-kpi-tile__num {
|
|
163
170
|
font-size: 3.8rem;
|
package/src/scss/main.scss
CHANGED
|
@@ -5,3 +5,14 @@
|
|
|
5
5
|
|
|
6
6
|
// Core framework (includes variables and all core-components)
|
|
7
7
|
@use 'core' as *;
|
|
8
|
+
|
|
9
|
+
// CSS variable defaults at :root. Themes don't go through main.scss — they
|
|
10
|
+
// @import core + base-css-variables and emit their own values — so this only
|
|
11
|
+
// affects the unthemed bundle (dist/css/main.css) and the FOUC window before
|
|
12
|
+
// a theme stylesheet resolves.
|
|
13
|
+
@use 'base-css-variables' as bcv;
|
|
14
|
+
:root {
|
|
15
|
+
@include bcv.output-base-css-variables;
|
|
16
|
+
@include bcv.output-pa-css-variables;
|
|
17
|
+
@include bcv.output-pa-alert-variables-light;
|
|
18
|
+
}
|