feat: complete drug-aware indication matching and cleanup app_v2
- Remove app_v2.py (consolidated into pathways_app.py), fix __init__ import - Add DimSearchTerm.csv, drug_indication_clusters.csv, drug_snomed_mapping_enriched.csv as reference data for SNOMED-based indication matching - Add snomed_indication_mapping_query.sql (source for embedded cluster mapping) - Update DESIGN_SYSTEM.md, RALPH_PROMPT.md, ralph.ps1, uv.lock
This commit is contained in:
+151
-146
@@ -1,189 +1,194 @@
|
||||
# Design System - HCD Analysis v2
|
||||
# Design System - HCD Analysis v2.1 (SaaS Redesign)
|
||||
|
||||
This document defines the visual design language for the UI redesign. All components should reference these tokens for consistency.
|
||||
This document defines the visual design language for the UI redesign. The goal is a **modern SaaS aesthetic** - think Stripe, Linear, Vercel - while staying thematically aligned with the blue color palette.
|
||||
|
||||
**Design Philosophy**:
|
||||
- The chart is the hero; everything else supports it
|
||||
- Minimal chrome, maximum data visibility
|
||||
- Clean, confident, spacious - not clinical or governmental
|
||||
- Every pixel of vertical space matters
|
||||
|
||||
## Color Palette
|
||||
|
||||
### Primary Blues (NHS-inspired, modernized)
|
||||
### Primary Blues (kept from original, used sparingly)
|
||||
| Name | Hex | Usage |
|
||||
|------|-----|-------|
|
||||
| Heritage Blue | `#003087` | Deep headers, authoritative accents |
|
||||
| Primary Blue | `#0066CC` | Main actions, links, focus states |
|
||||
| Vibrant Blue | `#1E88E5` | Highlights, hover states, chart primary |
|
||||
| Sky Blue | `#4FC3F7` | Accents, progress bars, secondary elements |
|
||||
| Pale Blue | `#E3F2FD` | Subtle backgrounds, card tints |
|
||||
| Heritage Blue | `#003087` | Top bar background, strong accents |
|
||||
| Primary Blue | `#0066CC` | Interactive elements, links, focus |
|
||||
| Vibrant Blue | `#1E88E5` | Hover states, active elements |
|
||||
| Sky Blue | `#4FC3F7` | Subtle accents, progress indicators |
|
||||
| Pale Blue | `#E3F2FD` | Selected states, subtle backgrounds |
|
||||
|
||||
### Neutrals (warm-tinted for clinical warmth)
|
||||
### Neutrals (refined for modern feel)
|
||||
| Name | Hex | Usage |
|
||||
|------|-----|-------|
|
||||
| Slate 900 | `#1E293B` | Primary text |
|
||||
| Slate 900 | `#0F172A` | Primary text (slightly darker) |
|
||||
| Slate 700 | `#334155` | Secondary text |
|
||||
| Slate 500 | `#64748B` | Muted text, placeholders |
|
||||
| Slate 300 | `#CBD5E1` | Borders, dividers |
|
||||
| Slate 100 | `#F1F5F9` | Card backgrounds, hover states |
|
||||
| White | `#FFFFFF` | Page background |
|
||||
| Slate 100 | `#F8FAFC` | Backgrounds (slightly lighter) |
|
||||
| White | `#FFFFFF` | Card/modal backgrounds |
|
||||
|
||||
### Semantic Colors
|
||||
| Name | Hex | Usage |
|
||||
|------|-----|-------|
|
||||
| Success | `#059669` | Positive states, confirmations |
|
||||
| Warning | `#D97706` | Caution states, alerts |
|
||||
| Error | `#DC2626` | Error states, destructive actions |
|
||||
| Info | `#0284C7` | Informational (matches primary family) |
|
||||
|
||||
### Chart Palette
|
||||
```
|
||||
Primary series: #003087, #0066CC, #1E88E5, #4FC3F7, #90CAF9
|
||||
Categorical: #0066CC, #059669, #D97706, #8B5CF6, #EC4899
|
||||
```
|
||||
| Success | `#10B981` | Positive (modern green) |
|
||||
| Warning | `#F59E0B` | Caution |
|
||||
| Error | `#EF4444` | Errors |
|
||||
| Info | `#3B82F6` | Informational |
|
||||
|
||||
## Typography
|
||||
|
||||
**Font Family:** Inter (primary), system-ui (fallback)
|
||||
|
||||
| Style | Size | Weight | Tracking | Line Height | Usage |
|
||||
|-------|------|--------|----------|-------------|-------|
|
||||
| Display | 32px | 700 | -0.02em | 1.2 | Page titles |
|
||||
| Heading 1 | 24px | 600 | -0.01em | 1.3 | Section headers |
|
||||
| Heading 2 | 20px | 600 | normal | 1.4 | Card titles |
|
||||
| Heading 3 | 16px | 600 | normal | 1.4 | Subsections |
|
||||
| Body | 14px | 400 | normal | 1.5 | Default text |
|
||||
| Body Small | 13px | 400 | normal | 1.5 | Secondary info |
|
||||
| Caption | 12px | 500 | normal | 1.4 | Labels, metadata |
|
||||
| Mono | 13px | 400 | normal | 1.5 | Data values, codes (JetBrains Mono) |
|
||||
| Style | Size | Weight | Usage |
|
||||
|-------|------|--------|-------|
|
||||
| Display | 28px | 600 | Page titles (reduced from 32px) |
|
||||
| Heading 1 | 18px | 600 | Section headers (reduced from 24px) |
|
||||
| Heading 2 | 16px | 600 | Card titles (reduced from 20px) |
|
||||
| Heading 3 | 14px | 600 | Subsections |
|
||||
| Body | 14px | 400 | Default text |
|
||||
| Body Small | 13px | 400 | Secondary info |
|
||||
| Caption | 11px | 500 | Labels, metadata (reduced from 12px) |
|
||||
| Mono | 13px | 500 | Data values (JetBrains Mono) |
|
||||
|
||||
## Spacing Scale
|
||||
## Spacing Scale (Tighter)
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| xs | 4px | Tight internal padding |
|
||||
| sm | 8px | Between related elements |
|
||||
| md | 12px | Standard gaps |
|
||||
| lg | 16px | Section padding |
|
||||
| xl | 24px | Card padding |
|
||||
| 2xl | 32px | Major section gaps |
|
||||
| 3xl | 48px | Page margins |
|
||||
| xs | 4px | Tight gaps |
|
||||
| sm | 6px | Between related elements (was 8px) |
|
||||
| md | 8px | Standard gaps (was 12px) |
|
||||
| lg | 12px | Section padding (was 16px) |
|
||||
| xl | 16px | Card padding (was 24px) |
|
||||
| 2xl | 24px | Major gaps (was 32px) |
|
||||
| 3xl | 32px | Page margins (was 48px) |
|
||||
|
||||
## Border Radius
|
||||
## Layout Specifications
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| sm | 4px | Small elements, inputs |
|
||||
| md | 8px | Buttons, small cards |
|
||||
| lg | 12px | Cards, modals |
|
||||
| xl | 16px | Large containers |
|
||||
| full | 9999px | Pills, avatars |
|
||||
### Page Structure (Target)
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Logo │ Tabs │ Freshness │ 48px
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ [Initiated▾] [LastSeen▾] │ [Drugs▾] [Ind▾] [Dir▾] │ KPI badges │ 48px
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ I C I C L E C H A R T │ flex
|
||||
│ (full viewport width) │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Top Bar
|
||||
- **Height**: 48px (reduced from 64px)
|
||||
- **Background**: Heritage Blue
|
||||
- **Logo**: 28px height (reduced from 36px)
|
||||
- **Tabs**: Small pills, 28px height
|
||||
|
||||
### Filter Strip
|
||||
- **Height**: 48px (single row)
|
||||
- **Layout**: Horizontal flex, all filters inline
|
||||
- **Dropdown triggers**: 32px height, 8px padding
|
||||
- **No section header** - labels are in dropdown triggers
|
||||
- **Background**: Slate 100 or transparent
|
||||
|
||||
### KPI Section (Options)
|
||||
|
||||
**Option A: Inline badges** (preferred - zero extra height)
|
||||
```
|
||||
Filters row: [Initiated▾] [LastSeen▾] | [Drugs▾] ... | 12,345 patients • £45.2M • 89 drugs
|
||||
```
|
||||
|
||||
**Option B: Compact strip** (48px max)
|
||||
```
|
||||
┌─────┬─────┬─────┬─────┐
|
||||
│12.3K│£45M │ 89 │ 7 │ 28px value
|
||||
│pts │cost │drugs│trust│ 14px label
|
||||
└─────┴─────┴─────┴─────┘
|
||||
```
|
||||
|
||||
### Chart Container
|
||||
- **Width**: Full viewport minus 32px (16px padding each side)
|
||||
- **Height**: Fill remaining space (min 500px)
|
||||
- **No max-width constraint**
|
||||
- **Margins**: Minimal (t:40, l:8, r:8, b:24)
|
||||
|
||||
## Component Specifications
|
||||
|
||||
### Compact Dropdown Trigger
|
||||
- Height: 32px
|
||||
- Padding: 8px 12px
|
||||
- Border: 1px Slate 300
|
||||
- Border radius: 6px
|
||||
- Font: 13px
|
||||
- Chevron: 14px icon
|
||||
|
||||
### Compact KPI Badge
|
||||
- Padding: 4px 12px
|
||||
- Border radius: 16px (pill)
|
||||
- Background: Slate 100
|
||||
- Value: 14px mono, weight 600
|
||||
- Label: 11px, Slate 500
|
||||
|
||||
### Searchable Dropdown Panel
|
||||
- Max height: 200px (items area)
|
||||
- Item padding: 6px 8px
|
||||
- Search input height: 28px
|
||||
- Width: 240px min
|
||||
|
||||
## Shadows
|
||||
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| sm | `0 1px 2px rgba(0,0,0,0.05)` | Subtle elevation |
|
||||
| md | `0 1px 3px rgba(0,0,0,0.08)` | Cards at rest |
|
||||
| lg | `0 4px 6px rgba(0,0,0,0.1)` | Cards on hover, dropdowns |
|
||||
| xl | `0 10px 15px rgba(0,0,0,0.1)` | Modals, popovers |
|
||||
| sm | `0 1px 2px rgba(0,0,0,0.04)` | Subtle (lighter) |
|
||||
| md | `0 1px 3px rgba(0,0,0,0.06)` | Cards at rest |
|
||||
| lg | `0 4px 8px rgba(0,0,0,0.08)` | Dropdowns, hover |
|
||||
|
||||
## Component Specifications
|
||||
## Border Radius
|
||||
|
||||
### Cards
|
||||
- Background: White
|
||||
- Border: 1px Slate 300 (optional, or use shadow only)
|
||||
- Border radius: lg (12px)
|
||||
- Padding: xl (24px)
|
||||
- Shadow: md at rest, lg on hover
|
||||
- Hover: translateY(-2px) transition
|
||||
|
||||
### Buttons
|
||||
**Primary:**
|
||||
- Background: Primary Blue
|
||||
- Text: White
|
||||
- Border radius: md (8px)
|
||||
- Padding: 10px 20px
|
||||
- Hover: Vibrant Blue background, slight scale (1.02)
|
||||
|
||||
**Secondary:**
|
||||
- Background: White
|
||||
- Border: 1px Primary Blue
|
||||
- Text: Primary Blue
|
||||
- Hover: Pale Blue background
|
||||
|
||||
**Ghost:**
|
||||
- Background: transparent
|
||||
- Text: Primary Blue
|
||||
- Hover: Pale Blue background
|
||||
|
||||
### Form Controls
|
||||
- Height: 40px (inputs, selects)
|
||||
- Border: 1px Slate 300
|
||||
- Border radius: md (8px)
|
||||
- Focus: 2px Primary Blue ring
|
||||
- Placeholder: Slate 500
|
||||
|
||||
### Data Cards (KPIs)
|
||||
- Large mono number: 32-48px, Slate 900
|
||||
- Label: Caption size, Slate 500
|
||||
- Background: White or Pale Blue tint
|
||||
- Optional trend indicator or sparkline
|
||||
|
||||
## Layout
|
||||
|
||||
### Page Structure
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Logo + App Name [Chart Tabs] Data Freshness │ ← Top Bar (64px height)
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─ Filters ─────────────────────────────────────────────────┐ │ ← Filter Section
|
||||
│ │ Date ranges, dropdowns, filter controls │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ KPIs ────────────────────────────────────────────────────┐ │ ← KPI Row
|
||||
│ │ [ Metric 1 ] [ Metric 2 ] [ Metric 3 ] [ Metric 4 ] │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─ Chart ───────────────────────────────────────────────────┐ │ ← Main Chart (fills remaining)
|
||||
│ │ │ │
|
||||
│ │ [ Interactive Visualization ] │ │
|
||||
│ │ │ │
|
||||
│ └───────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Responsive Breakpoints
|
||||
- Mobile: < 640px
|
||||
- Tablet: 640px - 1024px
|
||||
- Desktop: > 1024px
|
||||
| Token | Value | Usage |
|
||||
|-------|-------|-------|
|
||||
| sm | 4px | Small elements |
|
||||
| md | 6px | Inputs, buttons |
|
||||
| lg | 8px | Cards |
|
||||
| full | 9999px | Pills, badges |
|
||||
|
||||
## Transitions
|
||||
|
||||
| Property | Duration | Easing |
|
||||
|----------|----------|--------|
|
||||
| Color, background | 150ms | ease-out |
|
||||
| Transform | 200ms | ease-out |
|
||||
| Shadow | 200ms | ease-out |
|
||||
| Opacity | 200ms | ease-in-out |
|
||||
All transitions: 150ms ease-out (faster than before)
|
||||
|
||||
## Reflex Implementation Notes
|
||||
## Implementation Notes
|
||||
|
||||
### Using Design Tokens
|
||||
Create a `styles.py` module with these values as Python constants. Import throughout the app:
|
||||
### Key Changes from v2.0
|
||||
1. **Vertical space reduction**: ~210px saved (364px → ~156px overhead)
|
||||
2. **Full-width chart**: Remove PAGE_MAX_WIDTH for chart
|
||||
3. **Inline KPIs**: Either badges in filter row or minimal strip
|
||||
4. **Smaller fonts**: Headlines and captions reduced
|
||||
5. **Tighter spacing**: All spacing tokens reduced by ~25%
|
||||
|
||||
```python
|
||||
# Example structure
|
||||
class Colors:
|
||||
PRIMARY = "#0066CC"
|
||||
PRIMARY_DARK = "#003087"
|
||||
# etc.
|
||||
### CSS Patterns
|
||||
```css
|
||||
/* Full-height chart container */
|
||||
.chart-container {
|
||||
height: calc(100vh - 96px); /* viewport minus top bar + filter strip */
|
||||
min-height: 500px;
|
||||
width: calc(100vw - 32px);
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
class Spacing:
|
||||
XS = "4px"
|
||||
SM = "8px"
|
||||
# etc.
|
||||
/* Filter strip */
|
||||
.filter-strip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 48px;
|
||||
gap: 12px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
```
|
||||
|
||||
### rx.theme Configuration
|
||||
Configure Reflex's theme provider with the color palette for consistent component styling.
|
||||
|
||||
### Custom CSS
|
||||
For styles not achievable via Reflex props, use `rx.style` or a custom CSS file.
|
||||
### Reflex Implementation
|
||||
- Use `height="calc(100vh - 96px)"` for chart container
|
||||
- Use `width="100%"` with `padding_x="16px"` for full-width
|
||||
- Use `flex="1"` to let chart grow
|
||||
- Keep `min_height="500px"` as fallback
|
||||
|
||||
Reference in New Issue
Block a user