@keenmate/pure-admin-core 2.7.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 +8 -9
- package/dist/css/main.css +1520 -0
- package/package.json +1 -1
- package/src/scss/_core.scss +11 -0
- 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
|
@@ -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
|
+
}
|