diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md index 6c57311..6e65c7e 100644 --- a/IMPLEMENTATION_PLAN.md +++ b/IMPLEMENTATION_PLAN.md @@ -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 ### 10.10 CSS updates + polish -- [ ] Global filter sub-header styling per design from 10.1 -- [ ] Trust Comparison landing page styling (directorate buttons grid) -- [ ] Trust Comparison dashboard grid styling (6-chart layout) -- [ ] Header fraction KPI styling -- [ ] Remove or repurpose `.kpi-row` / `.kpi-card` CSS -- [ ] Ensure responsive behavior -- [ ] Update `01_nhs_classic.html` if it serves as an ongoing design reference (or note that Phase 10 diverges) +- [x] Global filter sub-header styling per design from 10.1 +- [x] Trust Comparison landing page styling (directorate buttons grid) +- [x] Trust Comparison dashboard grid styling (6-chart layout) +- [x] Header fraction KPI styling +- [x] Remove or repurpose `.kpi-row` / `.kpi-card` CSS +- [x] Ensure responsive behavior +- [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 ### 10.11 Final integration + documentation diff --git a/dash_app/assets/nhs.css b/dash_app/assets/nhs.css index db5090f..c7fe416 100644 --- a/dash_app/assets/nhs.css +++ b/dash_app/assets/nhs.css @@ -12,6 +12,8 @@ --nhs-yellow: #FFB81C; --nhs-red: #DA291C; --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; } @@ -53,11 +55,6 @@ body { font-size: 20px; font-weight: 700; 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 { 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); 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__icon { width: 18px; height: 18px; flex-shrink: 0; } .sidebar__footer { @@ -162,7 +154,7 @@ body { left: var(--sidebar-w); right: 0; z-index: 150; - height: 44px; + height: var(--sub-header-h); background: #E8F0FE; border-bottom: 1px solid #C5D4E8; display: flex; @@ -193,41 +185,12 @@ body { /* ── Main Content ── */ .main { margin-left: var(--sidebar-w); - margin-top: 100px; + margin-top: var(--header-total-h); padding: 24px; - min-height: calc(100vh - 100px); + min-height: calc(100vh - var(--header-total-h)); 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 ── */ .pathway-filters { background: var(--nhs-white); @@ -262,18 +225,6 @@ body { .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; } -/* 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 */ .filter-dropdown { min-width: 160px; @@ -527,15 +478,15 @@ body { @media (max-width: 1200px) { .tc-landing__grid { grid-template-columns: repeat(2, 1fr); } .tc-landing__grid--wide { grid-template-columns: repeat(3, 1fr); } -} -@media (max-width: 1024px) { - .kpi-row { grid-template-columns: repeat(2, 1fr); } + .top-header__kpis { gap: 16px; } + .header-kpi__label { display: none; } } @media (max-width: 768px) { .sidebar { display: none; } .main { margin-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-dashboard__grid { grid-template-columns: 1fr; } + .pathway-filters { flex-wrap: wrap; gap: 8px; } } diff --git a/dash_app/components/kpi_row.py b/dash_app/components/kpi_row.py deleted file mode 100644 index 3f12159..0000000 --- a/dash_app/components/kpi_row.py +++ /dev/null @@ -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"), - ], - )