@keenmate/pure-admin-core 2.6.0 → 2.7.1
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 +24 -16
- package/dist/css/main.css +1865 -257
- package/package.json +1 -1
- package/src/scss/_base-css-variables.scss +37 -19
- package/src/scss/_core.scss +11 -0
- package/src/scss/core-components/_alerts.scss +2 -2
- package/src/scss/core-components/_base.scss +19 -2
- package/src/scss/core-components/_buttons.scss +12 -8
- package/src/scss/core-components/_callouts.scss +1 -1
- package/src/scss/core-components/_cards.scss +4 -4
- package/src/scss/core-components/_checkbox-lists.scss +2 -2
- package/src/scss/core-components/_comparison.scss +7 -4
- package/src/scss/core-components/_data-display.scss +24 -15
- package/src/scss/core-components/_data-viz.scss +139 -131
- package/src/scss/core-components/_file-selector.scss +34 -34
- package/src/scss/core-components/_kpi-base.scss +169 -0
- package/src/scss/core-components/_kpi-bento.scss +182 -0
- package/src/scss/core-components/_kpi-comparison-gauges.scss +132 -0
- package/src/scss/core-components/_kpi-editorial-minimal.scss +128 -0
- package/src/scss/core-components/_kpi-hero-supporting.scss +210 -0
- package/src/scss/core-components/_kpi-numeric-strip.scss +154 -0
- package/src/scss/core-components/_kpi-sparkline-list.scss +171 -0
- package/src/scss/core-components/_kpi-terminal.scss +229 -0
- package/src/scss/core-components/_lists.scss +4 -4
- package/src/scss/core-components/_logic-tree.scss +2 -2
- package/src/scss/core-components/_modals.scss +69 -0
- package/src/scss/core-components/_notifications.scss +17 -17
- package/src/scss/core-components/_popconfirm.scss +1 -1
- package/src/scss/core-components/_statistics.scss +25 -19
- package/src/scss/core-components/_tabs.scss +12 -12
- package/src/scss/core-components/_timeline.scss +30 -30
- package/src/scss/core-components/badges/_composite-badge-variants.scss +7 -7
- package/src/scss/core-components/badges/_composite-badge.scss +1 -1
- package/src/scss/core-components/badges/_labels.scss +6 -6
- package/src/scss/core-components/forms/_input-wrapper.scss +1 -1
- package/src/scss/core-components/forms/_query-editor.scss +10 -10
- package/src/scss/core-components/layout/_sidebar-states.scss +1 -0
- package/src/scss/core-components/layout/_sidebar.scss +1 -0
- package/src/scss/variables/_colors.scss +1 -0
- package/src/scss/variables/_components.scss +3 -2
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
KPI · Sparkline list
|
|
3
|
+
Each KPI is one row: label · sparkline · value · Δ%. Built for vertical
|
|
4
|
+
scanning rather than per-tile depth — no view-mode toggle, no status
|
|
5
|
+
pills. Container queries collapse 4-col → 2-row → 3-row as the card
|
|
6
|
+
narrows.
|
|
7
|
+
======================================== */
|
|
8
|
+
@use '../variables' as *;
|
|
9
|
+
|
|
10
|
+
/* Card is a query container so rows react to *card* width, not viewport. */
|
|
11
|
+
.pa-kpi-spark-list {
|
|
12
|
+
container-type: inline-size;
|
|
13
|
+
}
|
|
14
|
+
.pa-kpi-spark-list__body { padding: 0; }
|
|
15
|
+
|
|
16
|
+
/* ----- Row: wide 4-column grid (label · chart · value · delta) ---------- */
|
|
17
|
+
.pa-kpi-spark-row {
|
|
18
|
+
display: grid;
|
|
19
|
+
grid-template-columns:
|
|
20
|
+
minmax(14rem, 28%)
|
|
21
|
+
minmax(10rem, 1fr)
|
|
22
|
+
minmax(8rem, 18%)
|
|
23
|
+
minmax(7rem, 12%);
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 1.6rem;
|
|
26
|
+
padding: 1.4rem 2rem;
|
|
27
|
+
border-bottom: 1px solid var(--pa-border-color);
|
|
28
|
+
|
|
29
|
+
&:last-child { border-bottom: 0; }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Mid-narrow card (1×3 page-grid + 45% column): stack to 2 rows.
|
|
33
|
+
Label/value/delta on top, full-width chart below. Default order is
|
|
34
|
+
value-above-chart; use .pa-kpi-spark-list--chart-first to flip. */
|
|
35
|
+
@container (max-width: 640px) {
|
|
36
|
+
.pa-kpi-spark-row {
|
|
37
|
+
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
38
|
+
grid-template-rows: auto auto;
|
|
39
|
+
grid-template-areas:
|
|
40
|
+
"label value delta"
|
|
41
|
+
"chart chart chart";
|
|
42
|
+
column-gap: 1.2rem;
|
|
43
|
+
row-gap: 0.4rem;
|
|
44
|
+
align-items: baseline;
|
|
45
|
+
padding: 1.2rem 1.6rem;
|
|
46
|
+
}
|
|
47
|
+
.pa-kpi-spark-row__label { grid-area: label; align-self: center; font-size: 1.25rem; }
|
|
48
|
+
.pa-kpi-spark-row__value { grid-area: value; }
|
|
49
|
+
.pa-kpi-spark-row__delta { grid-area: delta; font-size: 1.25rem; }
|
|
50
|
+
.pa-kpi-spark-row__chart { grid-area: chart; }
|
|
51
|
+
.pa-kpi-spark-row__num { font-size: 2rem; }
|
|
52
|
+
|
|
53
|
+
/* --chart-first: rotates the canonical L→R order 90°. Label on top,
|
|
54
|
+
chart in the middle, value+delta side-by-side at the bottom. */
|
|
55
|
+
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row {
|
|
56
|
+
grid-template-columns: 1fr auto;
|
|
57
|
+
grid-template-rows: auto auto auto;
|
|
58
|
+
grid-template-areas:
|
|
59
|
+
"label label"
|
|
60
|
+
"chart chart"
|
|
61
|
+
"value delta";
|
|
62
|
+
row-gap: 0.5rem;
|
|
63
|
+
column-gap: 1rem;
|
|
64
|
+
padding: 1.2rem 1.6rem;
|
|
65
|
+
}
|
|
66
|
+
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__label { align-self: start; }
|
|
67
|
+
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__value { text-align: start; align-self: baseline; }
|
|
68
|
+
.pa-kpi-spark-list--chart-first .pa-kpi-spark-row__delta { align-self: baseline; }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* Very narrow card (~280–360px, 25% page-grid stress test): force the
|
|
72
|
+
chart-first 3-row layout regardless of modifier. */
|
|
73
|
+
@container (max-width: 360px) {
|
|
74
|
+
.pa-kpi-spark-row {
|
|
75
|
+
grid-template-columns: 1fr auto;
|
|
76
|
+
grid-template-rows: auto auto auto;
|
|
77
|
+
grid-template-areas:
|
|
78
|
+
"label label"
|
|
79
|
+
"chart chart"
|
|
80
|
+
"value delta";
|
|
81
|
+
row-gap: 0.5rem;
|
|
82
|
+
column-gap: 1rem;
|
|
83
|
+
padding: 1.2rem 1.4rem;
|
|
84
|
+
}
|
|
85
|
+
.pa-kpi-spark-row__label { grid-area: label; align-self: start; }
|
|
86
|
+
.pa-kpi-spark-row__chart { grid-area: chart; }
|
|
87
|
+
.pa-kpi-spark-row__value { grid-area: value; text-align: start; align-self: baseline; }
|
|
88
|
+
.pa-kpi-spark-row__delta { grid-area: delta; align-self: baseline; }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/* ----- Cell typography -------------------------------------------------- */
|
|
92
|
+
.pa-kpi-spark-row__label {
|
|
93
|
+
font-family: var(--base-font-family-mono);
|
|
94
|
+
font-size: 1.4rem;
|
|
95
|
+
font-weight: 700;
|
|
96
|
+
letter-spacing: 0.1em;
|
|
97
|
+
text-transform: uppercase;
|
|
98
|
+
color: color-mix(in srgb, var(--pa-text-color-1) 60%, transparent);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Sparkline cell — line + filled area + trailing dot (the dot is rendered
|
|
102
|
+
as a CSS span by the JS init pass; see kpi-showcases.js). */
|
|
103
|
+
.pa-kpi-spark-row__chart {
|
|
104
|
+
position: relative; /* anchor for .pa-kpi-spark-dot */
|
|
105
|
+
|
|
106
|
+
svg {
|
|
107
|
+
display: block;
|
|
108
|
+
width: 100%;
|
|
109
|
+
height: var(--pa-chart-trendline-height);
|
|
110
|
+
overflow: visible;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
polyline {
|
|
114
|
+
fill: none;
|
|
115
|
+
stroke: currentColor;
|
|
116
|
+
stroke-width: var(--pa-chart-trendline-stroke);
|
|
117
|
+
stroke-linecap: round;
|
|
118
|
+
stroke-linejoin: round;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
polygon {
|
|
122
|
+
fill: currentColor;
|
|
123
|
+
fill-opacity: 0.18; /* same hue as line, soft area shading */
|
|
124
|
+
stroke: none;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Sentiment-coloured sparkline. Color is set on the chart wrapper so
|
|
129
|
+
currentColor resolves for both the SVG content (line/area) and the
|
|
130
|
+
dot inside the wrapper. */
|
|
131
|
+
.pa-kpi-spark-row {
|
|
132
|
+
&--up-strong .pa-kpi-spark-row__chart { color: var(--pa-very-positive); }
|
|
133
|
+
&--up .pa-kpi-spark-row__chart { color: var(--pa-positive); }
|
|
134
|
+
&--flat .pa-kpi-spark-row__chart { color: var(--pa-neutral); }
|
|
135
|
+
&--down .pa-kpi-spark-row__chart { color: var(--pa-negative); }
|
|
136
|
+
&--down-strong .pa-kpi-spark-row__chart { color: var(--pa-very-negative); }
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* ----- Value (focal white number + muted unit) ------------------------- */
|
|
140
|
+
.pa-kpi-spark-row__value {
|
|
141
|
+
font-family: var(--base-font-family-mono);
|
|
142
|
+
text-align: end;
|
|
143
|
+
line-height: 1;
|
|
144
|
+
}
|
|
145
|
+
.pa-kpi-spark-row__num {
|
|
146
|
+
font-size: 2.6rem;
|
|
147
|
+
font-weight: 700;
|
|
148
|
+
letter-spacing: -0.02em;
|
|
149
|
+
color: var(--pa-text-color-1);
|
|
150
|
+
}
|
|
151
|
+
.pa-kpi-spark-row__unit {
|
|
152
|
+
font-size: 1.3rem;
|
|
153
|
+
font-weight: 500;
|
|
154
|
+
color: var(--pa-text-secondary);
|
|
155
|
+
margin-left: 0.2rem;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* ----- Delta (sentiment-coloured) -------------------------------------- */
|
|
159
|
+
.pa-kpi-spark-row__delta {
|
|
160
|
+
font-family: var(--base-font-family-mono);
|
|
161
|
+
font-size: 1.4rem;
|
|
162
|
+
font-weight: 600;
|
|
163
|
+
text-align: end;
|
|
164
|
+
font-variant-numeric: tabular-nums;
|
|
165
|
+
|
|
166
|
+
&--very-positive { color: var(--pa-very-positive); }
|
|
167
|
+
&--positive { color: var(--pa-positive); }
|
|
168
|
+
&--neutral { color: var(--pa-neutral); }
|
|
169
|
+
&--negative { color: var(--pa-negative); }
|
|
170
|
+
&--very-negative { color: var(--pa-very-negative); }
|
|
171
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
KPI · Terminal grid
|
|
3
|
+
Bloomberg-style dense panel: mono numbers, status pills, inline SVG
|
|
4
|
+
sparklines, ▲▼ deltas, segmented view-mode toggle (VALUE/Δ%/TREND).
|
|
5
|
+
Shared chrome (header, live, footer, detail popover, spark-dot) is in
|
|
6
|
+
_kpi-base.scss.
|
|
7
|
+
======================================== */
|
|
8
|
+
@use '../variables' as *;
|
|
9
|
+
|
|
10
|
+
/* ----- View-mode toggle (segmented button group) ------------------------ */
|
|
11
|
+
.pa-kpi-terminal__controls {
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
gap: 1.6rem;
|
|
15
|
+
}
|
|
16
|
+
.pa-kpi-terminal__viewtoggle {
|
|
17
|
+
display: inline-flex;
|
|
18
|
+
border: 1px solid var(--pa-border-color);
|
|
19
|
+
border-radius: 0.4rem;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
}
|
|
22
|
+
.pa-kpi-terminal__viewbtn {
|
|
23
|
+
background: transparent;
|
|
24
|
+
border: 0;
|
|
25
|
+
color: var(--pa-text-color-2);
|
|
26
|
+
padding: 0.4rem 1.1rem;
|
|
27
|
+
font-family: var(--base-font-family-mono);
|
|
28
|
+
font-size: 1.1rem;
|
|
29
|
+
font-weight: 600;
|
|
30
|
+
letter-spacing: 0.06em;
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
transition: background-color 0.1s ease-out, color 0.1s ease-out;
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
color: var(--pa-text-color-1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&.is-active {
|
|
39
|
+
background: var(--pa-text-color-1);
|
|
40
|
+
color: var(--pa-card-bg);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ----- Grid + tile borders ----------------------------------------------
|
|
45
|
+
Hairline 1px borders between tiles, no gap. Last-row/last-column
|
|
46
|
+
borders suppressed via :nth-last-child / :nth-child selectors. */
|
|
47
|
+
.pa-kpi-terminal__body {
|
|
48
|
+
padding: 0;
|
|
49
|
+
}
|
|
50
|
+
.pa-kpi-terminal__grid {
|
|
51
|
+
display: grid;
|
|
52
|
+
grid-template-columns: repeat(2, 1fr);
|
|
53
|
+
|
|
54
|
+
.pa-kpi-tile {
|
|
55
|
+
border-bottom: 1px solid var(--pa-border-color);
|
|
56
|
+
border-right: 1px solid var(--pa-border-color);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
.pa-kpi-terminal__grid--2col {
|
|
60
|
+
.pa-kpi-tile:nth-child(2n) { border-right: 0; }
|
|
61
|
+
.pa-kpi-tile:nth-last-child(-n+2) { border-bottom: 0; }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* ----- Tile (per-KPI panel) --------------------------------------------- */
|
|
65
|
+
.pa-kpi-tile {
|
|
66
|
+
position: relative;
|
|
67
|
+
padding: 1.4rem 1.8rem 1.6rem;
|
|
68
|
+
min-height: 16rem;
|
|
69
|
+
display: flex;
|
|
70
|
+
flex-direction: column;
|
|
71
|
+
|
|
72
|
+
/* Standalone modifier: tile lives directly inside a .pa-col-* (no
|
|
73
|
+
neighbour cells in a parent grid) — gets a full border + card bg so
|
|
74
|
+
it doesn't look orphaned. */
|
|
75
|
+
&--standalone {
|
|
76
|
+
background: var(--pa-card-bg);
|
|
77
|
+
border: 1px solid var(--pa-border-color);
|
|
78
|
+
margin-bottom: 1.2rem;
|
|
79
|
+
|
|
80
|
+
&:last-child { margin-bottom: 0; }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ----- Tile head: ID · period + status pill ----------------------------- */
|
|
85
|
+
.pa-kpi-tile__head {
|
|
86
|
+
display: flex;
|
|
87
|
+
justify-content: space-between;
|
|
88
|
+
align-items: center;
|
|
89
|
+
font-family: var(--base-font-family-mono);
|
|
90
|
+
font-size: 1.3rem;
|
|
91
|
+
letter-spacing: 0.04em;
|
|
92
|
+
margin-bottom: 0.3rem;
|
|
93
|
+
}
|
|
94
|
+
.pa-kpi-tile__id {
|
|
95
|
+
color: var(--pa-text-tertiary);
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
}
|
|
98
|
+
.pa-kpi-tile__status {
|
|
99
|
+
font-family: var(--base-font-family-mono);
|
|
100
|
+
font-size: 1.2rem;
|
|
101
|
+
font-weight: 700;
|
|
102
|
+
letter-spacing: 0.08em;
|
|
103
|
+
padding: 0.3rem 0.9rem;
|
|
104
|
+
line-height: 1.3;
|
|
105
|
+
|
|
106
|
+
&--warn {
|
|
107
|
+
background: var(--pa-warning-bg);
|
|
108
|
+
color: var(--pa-btn-warning-text);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* GOOD is the "default" state — text-only, no chrome */
|
|
112
|
+
&--good {
|
|
113
|
+
background: transparent;
|
|
114
|
+
color: var(--pa-text-color-1);
|
|
115
|
+
padding: 0.2rem 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&--neutral {
|
|
119
|
+
background: color-mix(in srgb, var(--pa-text-color-2) 25%, transparent);
|
|
120
|
+
color: var(--pa-text-color-1);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* ----- Label ------------------------------------------------------------ */
|
|
125
|
+
.pa-kpi-tile__label {
|
|
126
|
+
font-family: var(--base-font-family-mono);
|
|
127
|
+
font-size: 1.4rem;
|
|
128
|
+
font-weight: 700;
|
|
129
|
+
letter-spacing: 0.1em;
|
|
130
|
+
text-transform: uppercase;
|
|
131
|
+
color: var(--pa-text-strong);
|
|
132
|
+
margin-bottom: 0.8rem;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* ----- Big value with 3-mode swap --------------------------------------
|
|
136
|
+
Author renders three .pa-kpi-tile__value siblings (data-mode="value" /
|
|
137
|
+
"delta" / "trend"); the active mode is selected via the
|
|
138
|
+
.pa-kpi-terminal[data-view="X"] attribute. JS toggles that attribute
|
|
139
|
+
when the segmented control is clicked. */
|
|
140
|
+
.pa-kpi-tile__values {
|
|
141
|
+
margin-bottom: 0.4rem;
|
|
142
|
+
}
|
|
143
|
+
.pa-kpi-tile__value {
|
|
144
|
+
display: none;
|
|
145
|
+
align-items: baseline;
|
|
146
|
+
gap: 0.3rem;
|
|
147
|
+
font-family: var(--base-font-family-mono);
|
|
148
|
+
line-height: 1;
|
|
149
|
+
|
|
150
|
+
&--very-positive .pa-kpi-tile__num { color: var(--pa-very-positive); }
|
|
151
|
+
&--positive .pa-kpi-tile__num { color: var(--pa-positive); }
|
|
152
|
+
&--neutral .pa-kpi-tile__num { color: var(--pa-neutral); }
|
|
153
|
+
&--negative .pa-kpi-tile__num { color: var(--pa-negative); }
|
|
154
|
+
&--very-negative .pa-kpi-tile__num { color: var(--pa-very-negative); }
|
|
155
|
+
}
|
|
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
|
+
|
|
162
|
+
.pa-kpi-tile__num {
|
|
163
|
+
font-size: 3.8rem;
|
|
164
|
+
font-weight: 700;
|
|
165
|
+
letter-spacing: -0.02em;
|
|
166
|
+
color: var(--pa-text-color-1);
|
|
167
|
+
}
|
|
168
|
+
.pa-kpi-tile__unit {
|
|
169
|
+
font-size: 1.6rem;
|
|
170
|
+
font-weight: 500;
|
|
171
|
+
color: var(--pa-text-secondary);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* ----- Previous-value + delta row -------------------------------------- */
|
|
175
|
+
.pa-kpi-tile__prev {
|
|
176
|
+
display: flex;
|
|
177
|
+
justify-content: space-between;
|
|
178
|
+
align-items: center;
|
|
179
|
+
font-family: var(--base-font-family-mono);
|
|
180
|
+
font-size: 1.3rem;
|
|
181
|
+
margin-top: auto; /* push to bottom of flex column */
|
|
182
|
+
margin-bottom: 0.4rem;
|
|
183
|
+
color: var(--pa-text-tertiary);
|
|
184
|
+
}
|
|
185
|
+
.pa-kpi-tile__delta {
|
|
186
|
+
&--very-positive { color: var(--pa-very-positive); }
|
|
187
|
+
&--positive { color: var(--pa-positive); }
|
|
188
|
+
&--neutral { color: var(--pa-neutral); }
|
|
189
|
+
&--negative { color: var(--pa-negative); }
|
|
190
|
+
&--very-negative { color: var(--pa-very-negative); }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* ----- Sparkline -------------------------------------------------------- */
|
|
194
|
+
.pa-kpi-tile__spark {
|
|
195
|
+
display: block;
|
|
196
|
+
width: 100%;
|
|
197
|
+
height: var(--pa-chart-trendline-height);
|
|
198
|
+
overflow: visible;
|
|
199
|
+
|
|
200
|
+
polyline {
|
|
201
|
+
fill: none;
|
|
202
|
+
stroke: currentColor;
|
|
203
|
+
stroke-width: var(--pa-chart-trendline-stroke);
|
|
204
|
+
stroke-linecap: round;
|
|
205
|
+
stroke-linejoin: round;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/* Sentiment-coloured sparkline. Class names use up/down wording but pick
|
|
209
|
+
colours from the sentiment-of-the-change axis, not line shape — so an
|
|
210
|
+
error-rate metric whose line is falling but the change is good uses
|
|
211
|
+
--up. See showcase docs for the rationale. Colour is set on both the
|
|
212
|
+
SVG and the JS-inserted .pa-kpi-spark-wrap so currentColor resolves
|
|
213
|
+
for the SVG content (line) and the HTML dot (inside the wrap). */
|
|
214
|
+
.pa-kpi-tile {
|
|
215
|
+
&--up-strong .pa-kpi-tile__spark,
|
|
216
|
+
&--up-strong .pa-kpi-spark-wrap { color: var(--pa-very-positive); }
|
|
217
|
+
|
|
218
|
+
&--up .pa-kpi-tile__spark,
|
|
219
|
+
&--up .pa-kpi-spark-wrap { color: var(--pa-positive); }
|
|
220
|
+
|
|
221
|
+
&--flat .pa-kpi-tile__spark,
|
|
222
|
+
&--flat .pa-kpi-spark-wrap { color: var(--pa-neutral); }
|
|
223
|
+
|
|
224
|
+
&--down .pa-kpi-tile__spark,
|
|
225
|
+
&--down .pa-kpi-spark-wrap { color: var(--pa-negative); }
|
|
226
|
+
|
|
227
|
+
&--down-strong .pa-kpi-tile__spark,
|
|
228
|
+
&--down-strong .pa-kpi-spark-wrap { color: var(--pa-very-negative); }
|
|
229
|
+
}
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
|
|
74
74
|
&::before {
|
|
75
75
|
content: '✓';
|
|
76
|
-
color:
|
|
76
|
+
color: var(--pa-success);
|
|
77
77
|
font-weight: $font-weight-semibold;
|
|
78
78
|
flex-shrink: 0;
|
|
79
79
|
}
|
|
@@ -81,17 +81,17 @@
|
|
|
81
81
|
|
|
82
82
|
&.pa-list-basic--danger li::before {
|
|
83
83
|
content: '✗';
|
|
84
|
-
color:
|
|
84
|
+
color: var(--pa-danger);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
&.pa-list-basic--info li::before {
|
|
88
88
|
content: '→';
|
|
89
|
-
color:
|
|
89
|
+
color: var(--pa-info);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
&.pa-list-basic--warning li::before {
|
|
93
93
|
content: '!';
|
|
94
|
-
color:
|
|
94
|
+
color: var(--pa-warning);
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
}
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
&--and {
|
|
69
|
-
border-color:
|
|
69
|
+
border-color: var(--pa-warning);
|
|
70
70
|
background: linear-gradient(135deg, #fff8e1 0%, #ffffff 100%);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
&--or {
|
|
74
|
-
border-color:
|
|
74
|
+
border-color: var(--pa-info);
|
|
75
75
|
background: linear-gradient(135deg, #e3f2fd 0%, #ffffff 100%);
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -106,6 +106,7 @@
|
|
|
106
106
|
.pa-modal__footer {
|
|
107
107
|
padding: $modal-footer-padding;
|
|
108
108
|
border-top: $border-width-base solid var(--pa-border-color);
|
|
109
|
+
border-radius: 0 0 var(--pa-border-radius) var(--pa-border-radius); // Match container's bottom corners
|
|
109
110
|
display: flex;
|
|
110
111
|
justify-content: flex-end;
|
|
111
112
|
gap: $spacing-md;
|
|
@@ -153,6 +154,74 @@
|
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
|
|
157
|
+
// Banded variant — header AND footer wear the role colour as filled bands,
|
|
158
|
+
// body and buttons stay neutral. Bands consume the alert tokens (15% mix
|
|
159
|
+
// in light mode, 45% in dark) so banded modals stay in lock-step with the
|
|
160
|
+
// alert palette across both themes — single source of truth.
|
|
161
|
+
//
|
|
162
|
+
// Compose with a role modifier to colour the bands:
|
|
163
|
+
// <div class="pa-modal pa-modal--success pa-modal--banded">
|
|
164
|
+
//
|
|
165
|
+
// Defined AFTER the role-only rules above so the compound selectors win on
|
|
166
|
+
// source order (specificity is identical, last-rule wins).
|
|
167
|
+
.pa-modal--banded {
|
|
168
|
+
.pa-modal__header {
|
|
169
|
+
background-color: var(--pa-modal-band-bg);
|
|
170
|
+
color: var(--pa-modal-band-text);
|
|
171
|
+
border-bottom-color: var(--pa-modal-band-border);
|
|
172
|
+
|
|
173
|
+
.pa-modal__title {
|
|
174
|
+
color: var(--pa-modal-band-text);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.pa-modal__footer {
|
|
179
|
+
background-color: var(--pa-modal-band-bg);
|
|
180
|
+
color: var(--pa-modal-band-text);
|
|
181
|
+
border-top-color: var(--pa-modal-band-border);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Buttons inside the bands invert the modal's colour scheme so they
|
|
185
|
+
// pop against any role's band on either light or dark themes — using
|
|
186
|
+
// generic --light/--dark modifiers landed too close in luminance to
|
|
187
|
+
// the muted band on most themes.
|
|
188
|
+
.pa-modal__header .pa-btn,
|
|
189
|
+
.pa-modal__footer .pa-btn {
|
|
190
|
+
background-color: var(--pa-text-color-1);
|
|
191
|
+
color: var(--pa-modal-content-bg);
|
|
192
|
+
border-color: var(--pa-text-color-1);
|
|
193
|
+
|
|
194
|
+
&:hover {
|
|
195
|
+
background-color: color-mix(in srgb, var(--pa-text-color-1) 85%, transparent);
|
|
196
|
+
border-color: color-mix(in srgb, var(--pa-text-color-1) 85%, transparent);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.pa-modal--banded.pa-modal--success {
|
|
202
|
+
--pa-modal-band-bg: var(--pa-alert-success-bg);
|
|
203
|
+
--pa-modal-band-text: var(--pa-alert-success-text);
|
|
204
|
+
--pa-modal-band-border: var(--pa-alert-success-border);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.pa-modal--banded.pa-modal--warning {
|
|
208
|
+
--pa-modal-band-bg: var(--pa-alert-warning-bg);
|
|
209
|
+
--pa-modal-band-text: var(--pa-alert-warning-text);
|
|
210
|
+
--pa-modal-band-border: var(--pa-alert-warning-border);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.pa-modal--banded.pa-modal--danger {
|
|
214
|
+
--pa-modal-band-bg: var(--pa-alert-danger-bg);
|
|
215
|
+
--pa-modal-band-text: var(--pa-alert-danger-text);
|
|
216
|
+
--pa-modal-band-border: var(--pa-alert-danger-border);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.pa-modal--banded.pa-modal--info {
|
|
220
|
+
--pa-modal-band-bg: var(--pa-alert-info-bg);
|
|
221
|
+
--pa-modal-band-text: var(--pa-alert-info-text);
|
|
222
|
+
--pa-modal-band-border: var(--pa-alert-info-border);
|
|
223
|
+
}
|
|
224
|
+
|
|
156
225
|
// Modal scrollable content
|
|
157
226
|
.pa-modal__body--scrollable {
|
|
158
227
|
max-height: $modal-body-scrollable-max-height;
|
|
@@ -106,14 +106,14 @@
|
|
|
106
106
|
background: none;
|
|
107
107
|
border: none;
|
|
108
108
|
padding: 0;
|
|
109
|
-
color:
|
|
109
|
+
color: var(--pa-accent);
|
|
110
110
|
font-size: $font-size-sm;
|
|
111
111
|
font-weight: $font-weight-medium;
|
|
112
112
|
cursor: pointer;
|
|
113
113
|
transition: color $transition-fast $easing-snappy;
|
|
114
114
|
|
|
115
115
|
&:hover {
|
|
116
|
-
color:
|
|
116
|
+
color: var(--pa-accent-hover);
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -145,10 +145,10 @@
|
|
|
145
145
|
|
|
146
146
|
// Unread notification (darker background)
|
|
147
147
|
&--unread {
|
|
148
|
-
background-color:
|
|
148
|
+
background-color: color-mix(in srgb, var(--pa-accent) 5%, transparent);
|
|
149
149
|
|
|
150
150
|
&:hover {
|
|
151
|
-
background-color:
|
|
151
|
+
background-color: color-mix(in srgb, var(--pa-accent) 10%, transparent);
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
}
|
|
@@ -161,33 +161,33 @@
|
|
|
161
161
|
display: flex;
|
|
162
162
|
align-items: center;
|
|
163
163
|
justify-content: center;
|
|
164
|
-
border-radius: 50%;
|
|
165
164
|
font-size: $font-size-base;
|
|
166
|
-
background-color: var(--pa-accent-light);
|
|
167
165
|
color: var(--pa-accent);
|
|
166
|
+
border: 1px solid transparent;
|
|
167
|
+
border-radius: var(--pa-border-radius);
|
|
168
168
|
|
|
169
169
|
&--primary {
|
|
170
|
-
|
|
171
|
-
color:
|
|
170
|
+
border-color: var(--pa-btn-primary-bg);
|
|
171
|
+
color: var(--pa-btn-primary-bg);
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
&--success {
|
|
175
|
-
|
|
176
|
-
color:
|
|
175
|
+
border-color: var(--pa-success);
|
|
176
|
+
color: var(--pa-success);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
&--warning {
|
|
180
|
-
|
|
181
|
-
color:
|
|
180
|
+
border-color: var(--pa-warning);
|
|
181
|
+
color: var(--pa-warning);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
&--danger {
|
|
185
|
-
|
|
186
|
-
color:
|
|
185
|
+
border-color: var(--pa-danger);
|
|
186
|
+
color: var(--pa-danger);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
&--secondary {
|
|
190
|
-
|
|
190
|
+
border-color: var(--pa-text-color-2);
|
|
191
191
|
color: var(--pa-text-color-2);
|
|
192
192
|
}
|
|
193
193
|
}
|
|
@@ -231,14 +231,14 @@
|
|
|
231
231
|
text-align: center;
|
|
232
232
|
|
|
233
233
|
a {
|
|
234
|
-
color:
|
|
234
|
+
color: var(--pa-accent);
|
|
235
235
|
font-size: $font-size-sm;
|
|
236
236
|
font-weight: $font-weight-medium;
|
|
237
237
|
text-decoration: none;
|
|
238
238
|
transition: color $transition-fast $easing-snappy;
|
|
239
239
|
|
|
240
240
|
&:hover {
|
|
241
|
-
color:
|
|
241
|
+
color: var(--pa-accent-hover);
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
}
|
|
@@ -19,24 +19,32 @@
|
|
|
19
19
|
justify-content: center;
|
|
20
20
|
font-size: $font-size-xl;
|
|
21
21
|
|
|
22
|
+
// Colour variants resolve via CSS custom properties so theme overrides
|
|
23
|
+
// (--pa-success-bg, --pa-warning-bg, etc.) cascade at runtime instead of
|
|
24
|
+
// baking at SCSS compile time.
|
|
22
25
|
&--primary {
|
|
23
|
-
background-color:
|
|
24
|
-
color:
|
|
26
|
+
background-color: var(--pa-accent-light);
|
|
27
|
+
color: var(--pa-accent);
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
&--success {
|
|
28
|
-
background-color:
|
|
29
|
-
color:
|
|
31
|
+
background-color: var(--pa-success-bg-light);
|
|
32
|
+
color: var(--pa-success-bg);
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
&--warning {
|
|
33
|
-
background-color:
|
|
34
|
-
color:
|
|
36
|
+
background-color: var(--pa-warning-bg-light);
|
|
37
|
+
color: var(--pa-warning-bg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&--danger {
|
|
41
|
+
background-color: var(--pa-danger-bg-light);
|
|
42
|
+
color: var(--pa-danger-bg);
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
&--info {
|
|
38
|
-
background-color:
|
|
39
|
-
color:
|
|
46
|
+
background-color: var(--pa-info-bg-light);
|
|
47
|
+
color: var(--pa-info-bg);
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
|
|
@@ -80,21 +88,19 @@
|
|
|
80
88
|
margin-bottom: $spacing-xs;
|
|
81
89
|
}
|
|
82
90
|
|
|
91
|
+
// Delta indicator — uses the 5-step sentiment scale (direction of change),
|
|
92
|
+
// distinct from role colours. --positive / --negative alias the success /
|
|
93
|
+
// danger roles so themes that retune those automatically retune deltas;
|
|
94
|
+
// --very-* are explicit darker stops.
|
|
83
95
|
.pa-stat__change {
|
|
84
96
|
font-size: $font-size-xs;
|
|
85
97
|
font-weight: $font-weight-semibold;
|
|
86
98
|
|
|
87
|
-
&--positive {
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
&--negative {
|
|
92
|
-
color: $danger-bg;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
&--neutral {
|
|
96
|
-
color: var(--pa-text-color-2);
|
|
97
|
-
}
|
|
99
|
+
&--very-positive { color: var(--pa-very-positive); }
|
|
100
|
+
&--positive { color: var(--pa-positive); }
|
|
101
|
+
&--neutral { color: var(--pa-neutral); }
|
|
102
|
+
&--negative { color: var(--pa-negative); }
|
|
103
|
+
&--very-negative { color: var(--pa-very-negative); }
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|