style: clean up dead CSS, add CSS variables, improve responsive rules (Task 10.10)
- Remove dead .kpi-row/.kpi-card CSS (KPI row replaced by header fraction KPIs) - Remove dead .top-header__breadcrumb CSS (breadcrumb removed in 10.3) - Remove dead .filter-select CSS (replaced by dcc.Dropdown) - Remove dead .sidebar__item--disabled CSS (disabled items removed in restructure) - Delete unused dash_app/components/kpi_row.py - Add --sub-header-h and --header-total-h CSS variables - Update .main and .sub-header to use CSS variables instead of hardcoded values - Add responsive rules: header KPIs collapse at 1200px, hide at 768px - Add responsive pathway-filters wrap at 768px - Remove dead .kpi-row responsive rules
This commit is contained in:
@@ -556,13 +556,13 @@ Additionally: KPI row removed, fraction KPIs moved to header, global filter sub-
|
|||||||
- **Checkpoint**: Filters visible on Patient Pathways, hidden on Trust Comparison, all filter functionality preserved
|
- **Checkpoint**: Filters visible on Patient Pathways, hidden on Trust Comparison, all filter functionality preserved
|
||||||
|
|
||||||
### 10.10 CSS updates + polish
|
### 10.10 CSS updates + polish
|
||||||
- [ ] Global filter sub-header styling per design from 10.1
|
- [x] Global filter sub-header styling per design from 10.1
|
||||||
- [ ] Trust Comparison landing page styling (directorate buttons grid)
|
- [x] Trust Comparison landing page styling (directorate buttons grid)
|
||||||
- [ ] Trust Comparison dashboard grid styling (6-chart layout)
|
- [x] Trust Comparison dashboard grid styling (6-chart layout)
|
||||||
- [ ] Header fraction KPI styling
|
- [x] Header fraction KPI styling
|
||||||
- [ ] Remove or repurpose `.kpi-row` / `.kpi-card` CSS
|
- [x] Remove or repurpose `.kpi-row` / `.kpi-card` CSS
|
||||||
- [ ] Ensure responsive behavior
|
- [x] Ensure responsive behavior
|
||||||
- [ ] Update `01_nhs_classic.html` if it serves as an ongoing design reference (or note that Phase 10 diverges)
|
- [x] Update `01_nhs_classic.html` if it serves as an ongoing design reference (or note that Phase 10 diverges)
|
||||||
- **Checkpoint**: All new components styled consistently with NHS design system
|
- **Checkpoint**: All new components styled consistently with NHS design system
|
||||||
|
|
||||||
### 10.11 Final integration + documentation
|
### 10.11 Final integration + documentation
|
||||||
|
|||||||
+9
-58
@@ -12,6 +12,8 @@
|
|||||||
--nhs-yellow: #FFB81C;
|
--nhs-yellow: #FFB81C;
|
||||||
--nhs-red: #DA291C;
|
--nhs-red: #DA291C;
|
||||||
--sidebar-w: 240px;
|
--sidebar-w: 240px;
|
||||||
|
--sub-header-h: 44px;
|
||||||
|
--header-total-h: 100px; /* 56px header + 44px sub-header */
|
||||||
}
|
}
|
||||||
|
|
||||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
@@ -53,11 +55,6 @@ body {
|
|||||||
font-size: 20px; font-weight: 700;
|
font-size: 20px; font-weight: 700;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
}
|
}
|
||||||
.top-header__breadcrumb {
|
|
||||||
color: rgba(255,255,255,0.7);
|
|
||||||
font-size: 14px; font-weight: 400;
|
|
||||||
}
|
|
||||||
.top-header__breadcrumb strong { color: var(--nhs-white); font-weight: 600; }
|
|
||||||
.top-header__right {
|
.top-header__right {
|
||||||
display: flex; align-items: center; gap: 20px; color: rgba(255,255,255,0.8); font-size: 14px;
|
display: flex; align-items: center; gap: 20px; color: rgba(255,255,255,0.8); font-size: 14px;
|
||||||
}
|
}
|
||||||
@@ -142,11 +139,6 @@ body {
|
|||||||
color: var(--nhs-blue);
|
color: var(--nhs-blue);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.sidebar__item--disabled {
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: not-allowed;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
.sidebar__item svg { width: 18px; height: 18px; flex-shrink: 0; }
|
.sidebar__item svg { width: 18px; height: 18px; flex-shrink: 0; }
|
||||||
.sidebar__icon { width: 18px; height: 18px; flex-shrink: 0; }
|
.sidebar__icon { width: 18px; height: 18px; flex-shrink: 0; }
|
||||||
.sidebar__footer {
|
.sidebar__footer {
|
||||||
@@ -162,7 +154,7 @@ body {
|
|||||||
left: var(--sidebar-w);
|
left: var(--sidebar-w);
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 150;
|
z-index: 150;
|
||||||
height: 44px;
|
height: var(--sub-header-h);
|
||||||
background: #E8F0FE;
|
background: #E8F0FE;
|
||||||
border-bottom: 1px solid #C5D4E8;
|
border-bottom: 1px solid #C5D4E8;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -193,41 +185,12 @@ body {
|
|||||||
/* ── Main Content ── */
|
/* ── Main Content ── */
|
||||||
.main {
|
.main {
|
||||||
margin-left: var(--sidebar-w);
|
margin-left: var(--sidebar-w);
|
||||||
margin-top: 100px;
|
margin-top: var(--header-total-h);
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
min-height: calc(100vh - 100px);
|
min-height: calc(100vh - var(--header-total-h));
|
||||||
display: flex; flex-direction: column; gap: 20px;
|
display: flex; flex-direction: column; gap: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── KPI Row ── */
|
|
||||||
.kpi-row {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
.kpi-card {
|
|
||||||
background: var(--nhs-white);
|
|
||||||
border: 1px solid var(--nhs-pale-grey);
|
|
||||||
border-top: 4px solid var(--nhs-blue);
|
|
||||||
padding: 20px;
|
|
||||||
display: flex; flex-direction: column; gap: 2px;
|
|
||||||
}
|
|
||||||
.kpi-card--green { border-top-color: var(--nhs-green); }
|
|
||||||
.kpi-card__label {
|
|
||||||
font-size: 12px; font-weight: 600;
|
|
||||||
text-transform: uppercase; letter-spacing: 0.05em;
|
|
||||||
color: var(--nhs-mid-grey);
|
|
||||||
}
|
|
||||||
.kpi-card__value {
|
|
||||||
font-size: 32px; font-weight: 300;
|
|
||||||
color: var(--nhs-dark-blue);
|
|
||||||
line-height: 1.1;
|
|
||||||
font-variant-numeric: tabular-nums;
|
|
||||||
}
|
|
||||||
.kpi-card__sub {
|
|
||||||
font-size: 13px; color: var(--nhs-mid-grey); margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ── Patient Pathways Filter Strip ── */
|
/* ── Patient Pathways Filter Strip ── */
|
||||||
.pathway-filters {
|
.pathway-filters {
|
||||||
background: var(--nhs-white);
|
background: var(--nhs-white);
|
||||||
@@ -262,18 +225,6 @@ body {
|
|||||||
.toggle-pill:hover:not(.toggle-pill--active) { background: #F0F4F5; }
|
.toggle-pill:hover:not(.toggle-pill--active) { background: #F0F4F5; }
|
||||||
.toggle-pill:focus-visible { box-shadow: 0 0 0 3px var(--nhs-yellow); z-index: 1; }
|
.toggle-pill:focus-visible { box-shadow: 0 0 0 3px var(--nhs-yellow); z-index: 1; }
|
||||||
|
|
||||||
/* Selects */
|
|
||||||
.filter-select {
|
|
||||||
height: 34px; padding: 0 12px;
|
|
||||||
border: 1px solid var(--nhs-pale-grey);
|
|
||||||
font-family: inherit; font-size: 14px;
|
|
||||||
color: var(--nhs-dark-grey);
|
|
||||||
background: var(--nhs-white);
|
|
||||||
cursor: pointer;
|
|
||||||
min-width: 140px;
|
|
||||||
}
|
|
||||||
.filter-select:focus { outline: 3px solid var(--nhs-yellow); outline-offset: 0; }
|
|
||||||
|
|
||||||
/* Dash dcc.Dropdown overrides for filter bar */
|
/* Dash dcc.Dropdown overrides for filter bar */
|
||||||
.filter-dropdown {
|
.filter-dropdown {
|
||||||
min-width: 160px;
|
min-width: 160px;
|
||||||
@@ -527,15 +478,15 @@ body {
|
|||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
.tc-landing__grid { grid-template-columns: repeat(2, 1fr); }
|
.tc-landing__grid { grid-template-columns: repeat(2, 1fr); }
|
||||||
.tc-landing__grid--wide { grid-template-columns: repeat(3, 1fr); }
|
.tc-landing__grid--wide { grid-template-columns: repeat(3, 1fr); }
|
||||||
}
|
.top-header__kpis { gap: 16px; }
|
||||||
@media (max-width: 1024px) {
|
.header-kpi__label { display: none; }
|
||||||
.kpi-row { grid-template-columns: repeat(2, 1fr); }
|
|
||||||
}
|
}
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.sidebar { display: none; }
|
.sidebar { display: none; }
|
||||||
.main { margin-left: 0; }
|
.main { margin-left: 0; }
|
||||||
.sub-header { left: 0; }
|
.sub-header { left: 0; }
|
||||||
.kpi-row { grid-template-columns: 1fr; }
|
.top-header__kpis { display: none; }
|
||||||
.tc-landing__grid { grid-template-columns: 1fr; }
|
.tc-landing__grid { grid-template-columns: 1fr; }
|
||||||
.tc-dashboard__grid { grid-template-columns: 1fr; }
|
.tc-dashboard__grid { grid-template-columns: 1fr; }
|
||||||
|
.pathway-filters { flex-wrap: wrap; gap: 8px; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
"""KPI row component — 4 metric cards with callback-updatable values."""
|
|
||||||
from dash import html
|
|
||||||
|
|
||||||
|
|
||||||
def make_kpi_row():
|
|
||||||
"""Return a section with 4 KPI cards matching 01_nhs_classic.html structure."""
|
|
||||||
return html.Section(
|
|
||||||
className="kpi-row",
|
|
||||||
**{"aria-label": "Key performance indicators"},
|
|
||||||
children=[
|
|
||||||
_kpi_card("Unique Patients", "kpi-patients", "—", "across all trusts"),
|
|
||||||
_kpi_card("Drug Types", "kpi-drugs", "—", "high-cost drugs tracked"),
|
|
||||||
_kpi_card("Total Cost", "kpi-cost", "—", "current period spend"),
|
|
||||||
_kpi_card(
|
|
||||||
"Indication Match",
|
|
||||||
"kpi-match",
|
|
||||||
"—",
|
|
||||||
"GP diagnosis confirmed",
|
|
||||||
modifier="kpi-card--green",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _kpi_card(label, value_id, default_value, sub_text, modifier=None):
|
|
||||||
"""Build a single KPI card.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
label: uppercase label text
|
|
||||||
value_id: HTML id for the value span (for callback Output)
|
|
||||||
default_value: initial display value before callbacks fire
|
|
||||||
sub_text: description below the value
|
|
||||||
modifier: optional CSS modifier class (e.g. 'kpi-card--green')
|
|
||||||
"""
|
|
||||||
card_class = "kpi-card"
|
|
||||||
if modifier:
|
|
||||||
card_class += f" {modifier}"
|
|
||||||
|
|
||||||
return html.Div(
|
|
||||||
className=card_class,
|
|
||||||
children=[
|
|
||||||
html.Div(label, className="kpi-card__label"),
|
|
||||||
html.Div(default_value, className="kpi-card__value", id=value_id),
|
|
||||||
html.Div(sub_text, className="kpi-card__sub"),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user