diff --git a/.ralph/agent/handoff.md b/.ralph/agent/handoff.md index db2122f..4320a31 100644 --- a/.ralph/agent/handoff.md +++ b/.ralph/agent/handoff.md @@ -1,11 +1,11 @@ # Session Handoff -_Generated: 2026-02-16 10:43:45 UTC_ +_Generated: 2026-02-16 11:04:21 UTC_ ## Git Context -- **Branch:** `codex/kpi` -- **HEAD:** 24ffe03: chore: auto-commit before merge (loop primary) +- **Branch:** `codex/projects` +- **HEAD:** 78e994e: chore: auto-commit before merge (loop primary) ## Tasks @@ -13,22 +13,28 @@ _Generated: 2026-02-16 10:43:45 UTC_ - [x] Compact Latest Results KPI section - [x] Validate KPI objective and close loop +- [x] Rename Active Projects language to Significant Interventions +- [x] Add autoplay + reduced-motion behavior for carousel +- [x] Responsive polish and full verification for interventions carousel +- [x] Implement Embla carousel in ProjectsTile +- [x] Add autoplay + reduced-motion behavior for carousel +- [x] Responsive polish and full verification for interventions carousel ## Key Files Recently modified: -- `.ralph/agent/handoff.md` - `.ralph/agent/memories.md` -- `.ralph/agent/memories.md.lock` - `.ralph/agent/scratchpad.md` - `.ralph/agent/summary.md` - `.ralph/agent/tasks.jsonl` -- `.ralph/agent/tasks.jsonl.lock` - `.ralph/current-events` - `.ralph/current-loop-id` -- `.ralph/events-20260216-103430.jsonl` +- `.ralph/events-20260216-105626.jsonl` +- `.ralph/history.jsonl` +- `.ralph/loop.lock` +- `package-lock.json` ## Next Session diff --git a/Ralph/prompt.md b/Ralph/prompt.md deleted file mode 100644 index 3285e8b..0000000 --- a/Ralph/prompt.md +++ /dev/null @@ -1,53 +0,0 @@ -# Significant Interventions Carousel (Ralph Prompt) - -## Goal -Replace the current one-column **Active Projects** list with a **Significant Interventions** carousel that supports thumbnail cards and auto-scroll behavior (Embla-based), while preserving panel-open behavior on card click. - -## Scope -- Rename all relevant UI/content references from **Active Projects** to **Significant Interventions**. -- Replace `ProjectsTile` list layout with an Embla carousel. -- Use auto-scroll as the default carousel behavior. -- Keep room for thumbnails now; real thumbnail assets will be added later. - -## Implementation Task List - -- [ ] Install carousel dependencies: - - `embla-carousel-react` - - `embla-carousel-autoplay` -- [ ] Update tile heading in `src/components/tiles/ProjectsTile.tsx`: - - `ACTIVE PROJECTS` -> `SIGNIFICANT INTERVENTIONS` -- [ ] Refactor `ProjectsTile` in `src/components/tiles/ProjectsTile.tsx`: - - Replace vertical list container with Embla viewport/container/slides - - Convert each project item to a carousel slide card - - Add thumbnail region in each slide (use placeholder block/image container for now) - - Keep keyboard activation (`Enter`/`Space`) and click-to-open detail panel -- [ ] Implement auto-scroll behavior: - - Use Embla autoplay plugin with sensible defaults (continuous feel, pauses on hover/focus) - - Respect reduced motion (`prefers-reduced-motion`) by disabling autoplay -- [ ] Responsive behavior: - - Mobile: single-card view - - Tablet/Desktop: multi-card visible area (based on available width) - - Ensure overflow clipping and smooth transitions -- [ ] Update navigation/search labels to match naming: - - `src/components/SubNav.tsx`: `Projects` -> `Significant Interventions` - - `src/lib/search.ts`: `Active Projects` -> `Significant Interventions` (section type and related labels/comments) -- [ ] Keep detail panel integration unchanged: - - Clicking a carousel card still calls `openPanel({ type: 'project', investigation: project })` -- [ ] Styling pass: - - Align with current dashboard tokens (`--surface`, `--border-light`, `--accent`, etc.) - - Ensure cards remain readable without thumbnails - -## Acceptance Criteria - -- The dashboard section title displays **Significant Interventions**. -- The old one-column projects list is replaced by a working carousel. -- Carousel auto-scrolls by default and pauses appropriately on interaction. -- In reduced-motion environments, carousel does not auto-scroll. -- Clicking or keyboard-activating a card opens the existing project detail panel. -- Layout works on mobile and desktop without overflow bugs. -- Search/navigation language no longer references **Active Projects**. - -## Notes for Implementation - -- Thumbnail assets are intentionally deferred; implement with placeholders now. -- Keep the component name `ProjectsTile` for this pass to minimize refactor risk; rename component/file in a later cleanup task if desired. diff --git a/Ralph/refs/ref-01-design-tokens.md b/Ralph/refs/ref-01-design-tokens.md deleted file mode 100644 index 19fc4e1..0000000 --- a/Ralph/refs/ref-01-design-tokens.md +++ /dev/null @@ -1,120 +0,0 @@ -# Reference: Task 1 — Design Tokens and Tailwind Config - -## Overview - -Update the design system from the dark-sidebar NHS Blue palette to the GP System concept's light teal palette. The concept reference is `References/GPSystemconcept.html`. - -## CSS Custom Properties (`src/index.css`) - -Add/update these variables in the PMR section (keep boot/ECG/login variables unchanged): - -```css -/* GP System Dashboard tokens */ ---bg: #F0F5F4; ---surface: #FFFFFF; ---sidebar-bg: #F7FAFA; ---text-primary: #1A2B2A; ---text-secondary: #5B7A78; ---text-tertiary: #8DA8A5; ---accent: #0D6E6E; ---accent-hover: #0A8080; ---accent-light: rgba(10,128,128,0.08); ---accent-border: rgba(10,128,128,0.18); ---amber: #D97706; ---amber-light: rgba(217,119,6,0.08); ---amber-border: rgba(217,119,6,0.18); ---success: #059669; ---success-light: rgba(5,150,105,0.08); ---success-border: rgba(5,150,105,0.18); ---alert: #DC2626; ---alert-light: rgba(220,38,38,0.08); ---alert-border: rgba(220,38,38,0.18); ---border: #D4E0DE; ---border-light: #E4EDEB; ---sidebar-width: 272px; ---topbar-height: 48px; ---radius: 8px; ---radius-sm: 6px; ---shadow-sm: 0 1px 2px rgba(26,43,42,0.05); ---shadow-md: 0 2px 8px rgba(26,43,42,0.08); ---shadow-lg: 0 8px 32px rgba(26,43,42,0.12); ---font-body: var(--font-ui); ---font-mono: 'Geist Mono', 'Fira Code', monospace; -``` - -## Tailwind Config (`tailwind.config.js`) - -Update the `extend` section: - -### Colors -```js -colors: { - 'pmr-bg': '#F0F5F4', - 'pmr-surface': '#FFFFFF', - 'pmr-sidebar': '#F7FAFA', - 'pmr-accent': '#0D6E6E', - 'pmr-accent-hover': '#0A8080', - 'pmr-text-primary': '#1A2B2A', - 'pmr-text-secondary': '#5B7A78', - 'pmr-text-tertiary': '#8DA8A5', - 'pmr-border': '#D4E0DE', - 'pmr-border-light': '#E4EDEB', - 'pmr-success': '#059669', - 'pmr-amber': '#D97706', - 'pmr-alert': '#DC2626', - 'pmr-purple': '#7C3AED', - // Keep pmr-nhsblue for backward compat during transition - 'pmr-nhsblue': '#005EB8', - // Keep pmr-content as fallback - 'pmr-content': '#F0F5F4', -} -``` - -### Shadows -```js -boxShadow: { - 'pmr-sm': '0 1px 2px rgba(26,43,42,0.05)', - 'pmr-md': '0 2px 8px rgba(26,43,42,0.08)', - 'pmr-lg': '0 8px 32px rgba(26,43,42,0.12)', - // Keep old pmr shadow as alias during transition - 'pmr': '0 1px 2px rgba(26,43,42,0.05)', -} -``` - -### Border Radius -```js -borderRadius: { - 'card': '8px', // was 4px — now 8px per concept - 'card-sm': '6px', // inner elements - 'login': '12px', // login card exception -} -``` - -## Existing Tokens to Replace/Update - -The Tailwind config and CSS already have tokens from the old PMR design. Task 1 needs to UPDATE these, not just add new ones alongside: - -**Existing Tailwind shadow tokens (replace with new three-tier system):** -- `pmr`: `'0 1px 2px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.03)'` → replace with `pmr-sm` -- `pmr-hover`: `'0 2px 4px rgba(0,0,0,0.06), 0 8px 16px rgba(0,0,0,0.04)'` → replace with `pmr-md` -- `pmr-banner`: `'0 2px 8px rgba(0,0,0,0.12)'` → remove (no banner in new design) - -**Existing Tailwind color tokens (keep during transition, Task 21 cleans up):** -- `pmr-nhsblue: '#005EB8'` — keep for login screen (still uses NHS blue) -- `pmr-content: '#F5F7FA'` → update to `pmr-content: '#F0F5F4'` (new bg color) -- `pmr-sidebar: '#1E293B'` → update to `pmr-sidebar: '#F7FAFA'` (light sidebar) - -**Existing CSS custom properties (in `--pmr-*` namespace):** -- Previous iterations added `--pmr-*` variables. The new tokens use shorter names (e.g., `--bg`, `--surface`, `--accent`). Add the new tokens AND keep `--pmr-*` aliases during transition so existing components don't break before they're rebuilt. - -**Existing border-radius tokens:** -- `card: '4px'` → update to `card: '8px'` -- `login: '12px'` — keep unchanged - -## What NOT to Change - -- Boot phase variables (`--matrix-*`, `--terminal-*`) -- ECG phase variables -- Login phase background (`#1E293B` — handled by transition) -- Font declarations (Elvaro, Blumir, Geist Mono, Fira Code already set up correctly) -- Breakpoint values diff --git a/Ralph/refs/ref-02-data-types.md b/Ralph/refs/ref-02-data-types.md deleted file mode 100644 index a00def8..0000000 --- a/Ralph/refs/ref-02-data-types.md +++ /dev/null @@ -1,203 +0,0 @@ -# Reference: Task 2 — Data Files and Types - -## Overview - -Create new data files for dashboard-specific content and update the type system. All CV content must match `References/CV_v4.md` exactly. - -## New Data Files - -### `src/data/profile.ts` - -```typescript -export const personalStatement = `Healthcare leader combining clinical pharmacy expertise with proficiency in Python, SQL, and data analytics, self-taught over the past decade through a drive to find root causes in data and build the most efficient solutions to complex problems. Currently leading population health analytics for NHS Norfolk & Waveney ICB, serving a population of 1.2 million. Experienced in working with messy, real-world prescribing data at scale to deliver actionable insights—from financial scenario modelling and pharmaceutical rebate negotiation to algorithm design and population-level pathway development. Proven track record of identifying and prioritising efficiency programmes worth £14.6M+ through automated, data-driven analysis. Skilled at translating complex clinical, financial, and analytical requirements into clear recommendations for executive stakeholders.` -``` - -### `src/data/tags.ts` - -```typescript -import type { Tag } from '@/types/pmr' - -export const tags: Tag[] = [ - { label: 'Pharmacist', colorVariant: 'teal' }, - { label: 'Data Lead', colorVariant: 'teal' }, - { label: 'NHS', colorVariant: 'teal' }, - { label: 'Population Health', colorVariant: 'amber' }, - { label: 'BI & Analytics', colorVariant: 'green' }, -] -``` - -### `src/data/alerts.ts` - -```typescript -import type { Alert } from '@/types/pmr' - -export const alerts: Alert[] = [ - { - message: '£14.6M SAVINGS IDENTIFIED', - severity: 'alert', - icon: 'AlertTriangle', // lucide-react icon name - }, - { - message: '£220M BUDGET OVERSIGHT', - severity: 'amber', - icon: 'AlertCircle', // lucide-react icon name - }, -] -``` - -### `src/data/kpis.ts` - -```typescript -import type { KPI } from '@/types/pmr' - -export const kpis: KPI[] = [ - { - id: 'budget', - value: '£220M', - label: 'Budget Oversight', - sub: 'NHS prescribing', - colorVariant: 'green', - explanation: 'Managed the ICB\'s total prescribing budget with sophisticated forecasting models identifying cost pressures and enabling proactive financial planning across Norfolk & Waveney.', - }, - { - id: 'savings', - value: '£14.6M', - label: 'Efficiency Savings', - sub: 'Identified & tracked', - colorVariant: 'amber', - explanation: 'Identified and prioritised a £14.6M efficiency programme through comprehensive data analysis; achieved over-target performance through targeted, evidence-based interventions across the integrated care system.', - }, - { - id: 'years', - value: '9+', - label: 'Years in NHS', - sub: 'Since 2016', - colorVariant: 'teal', - explanation: 'Continuous NHS service since August 2016, progressing from community pharmacy through prescribing data analysis to system-level population health data leadership.', - }, - { - id: 'team', - value: '12', - label: 'Team Size Led', - sub: 'Cross-functional', - colorVariant: 'green', - explanation: 'Led a cross-functional team of 12 spanning data analysts, population health specialists, and pharmacists across data, analytics, and population health workstreams.', - }, -] -``` - -### `src/data/skills.ts` - -Skills presented as "medications" with frequency (user-specified values) and years of experience. - -```typescript -import type { SkillMedication } from '@/types/pmr' - -export const skills: SkillMedication[] = [ - { - id: 'data-analysis', - name: 'Data Analysis', - frequency: 'Twice daily', - startYear: 2016, - yearsOfExperience: 9, - proficiency: 95, - category: 'Technical', - status: 'Active', - icon: 'BarChart3', - }, - { - id: 'python', - name: 'Python', - frequency: 'Daily', - startYear: 2019, - yearsOfExperience: 6, - proficiency: 90, - category: 'Technical', - status: 'Active', - icon: 'Code2', - }, - { - id: 'sql', - name: 'SQL', - frequency: 'Daily', - startYear: 2018, - yearsOfExperience: 7, - proficiency: 88, - category: 'Technical', - status: 'Active', - icon: 'Database', - }, - { - id: 'power-bi', - name: 'Power BI', - frequency: 'Once weekly', - startYear: 2020, - yearsOfExperience: 5, - proficiency: 92, - category: 'Technical', - status: 'Active', - icon: 'PieChart', - }, - { - id: 'javascript-typescript', - name: 'JavaScript / TypeScript', - frequency: 'When required', - startYear: 2022, - yearsOfExperience: 3, - proficiency: 70, - category: 'Technical', - status: 'Active', - icon: 'FileCode2', - }, -] -``` - -Note: Additional domain/leadership skills can be added later. Start with the 5 technical skills the user specified frequencies for. - -## Type Updates (`src/types/pmr.ts`) - -Add these interfaces (keep all existing types): - -```typescript -export interface Tag { - label: string - colorVariant: 'teal' | 'amber' | 'green' -} - -export interface Alert { - message: string - severity: 'alert' | 'amber' - icon: string -} - -export interface KPI { - id: string - value: string - label: string - sub: string - colorVariant: 'green' | 'amber' | 'teal' - explanation: string -} - -export interface SkillMedication { - id: string - name: string - frequency: string - startYear: number - yearsOfExperience: number - proficiency: number - category: 'Technical' | 'Domain' | 'Leadership' - status: 'Active' | 'Historical' - icon: string -} -``` - -## Existing Data — No Changes - -These files remain untouched: -- `src/data/patient.ts` -- `src/data/consultations.ts` -- `src/data/medications.ts` -- `src/data/problems.ts` -- `src/data/investigations.ts` -- `src/data/documents.ts` diff --git a/Ralph/refs/ref-03-topbar-sidebar.md b/Ralph/refs/ref-03-topbar-sidebar.md deleted file mode 100644 index 25c65f2..0000000 --- a/Ralph/refs/ref-03-topbar-sidebar.md +++ /dev/null @@ -1,147 +0,0 @@ -# Reference: Tasks 4-6 — TopBar and Sidebar - -## Concept Reference - -All specs below are derived from `References/GPSystemconcept.html`. Open it in a browser for visual reference. - ---- - -## Task 4: TopBar Component - -### File: `src/components/TopBar.tsx` - -### Structure -``` -┌─────────────────────────────────────────────────────────────┐ -│ [🏠] Headhunt Medical Center Remote │ [🔍 Search... Ctrl+K] │ Dr. A.CHARLWOOD · Active Session · 12:23 [Ctrl+K] │ -└─────────────────────────────────────────────────────────────┘ -``` - -### Specs - -**Container:** -- `position: fixed`, `top: 0`, `left: 0`, `right: 0` -- `height: var(--topbar-height)` (48px) -- `background: var(--surface)` (#FFFFFF) -- `border-bottom: 1px solid var(--border)` (#D4E0DE) -- `display: flex`, `align-items: center`, `justify-content: space-between` -- `padding: 0 20px` -- `z-index: 100` - -**Brand (left):** -- `Home` icon from lucide-react (18px, accent color) -- Text: "Headhunt Medical Center" — 13px, font-ui, 600 weight, text-primary -- Version badge: "Remote" — 11px, 400 weight, text-tertiary, margin-left 2px - -**Search bar (center):** -- Wrapper: `max-width: 560px`, `min-width: 400px` -- Container: `height: 42px`, `border: 1.5px solid var(--border)`, `border-radius: var(--radius)` (8px), `padding: 0 14px`, white bg -- Search icon (16px, tertiary) + input + "Ctrl+K" kbd badge -- Input: 13px, font-body, placeholder "Search records, experience, skills... (Ctrl+K)" -- Hover: `border-color: var(--accent-border)` -- Focus: `border-color: var(--accent)`, `box-shadow: 0 0 0 3px rgba(13,110,110,0.12)` -- **On click/focus: opens Command Palette** (Task 18). Does NOT do inline search. -- Kbd badge: mono font, 10px, tertiary, bg: var(--bg), border, padding 2px 6px, radius 4px - -**Session info (right):** -- Text: "Dr. A.CHARLWOOD · Active Session · [time]" — 12px, text-secondary -- Session pill: mono 11px, tertiary, `background: var(--accent-light)`, `padding: 3px 10px`, radius 4px, `border: 1px solid var(--accent-border)` -- Ctrl+K shortcut badge (same style as search bar badge) - -**Responsive:** -- Mobile (<768px): hide center search bar. Show only brand + session info (or hamburger). -- Tablet: search bar may shrink. - ---- - -## Task 5: Sidebar — PersonHeader - -### File: `src/components/Sidebar.tsx` - -### Overall Sidebar Container -- `width: var(--sidebar-width)` (272px) -- `min-width: var(--sidebar-width)` -- `background: var(--sidebar-bg)` (#F7FAFA) -- `border-right: 1px solid var(--border)` (#D4E0DE) -- `overflow-y: auto`, custom scrollbar (4px width, transparent track, border-colored thumb) -- `padding: 20px 16px` -- `display: flex`, `flex-direction: column`, `gap: 2px` - -### PersonHeader Section -Bordered below: `border-bottom: 2px solid var(--accent)`, `padding-bottom: 16px`, `margin-bottom: 6px` - -**Avatar:** -- 52px × 52px circle -- `background: linear-gradient(135deg, var(--accent), #0A8080)` -- White text "AC", 700 weight, 18px, centered -- `box-shadow: 0 2px 8px rgba(13,110,110,0.25)` -- `margin-bottom: 12px` - -**Name:** -- "CHARLWOOD, Andrew" -- 15px, 700 weight, text-primary, `letter-spacing: -0.01em` - -**Title:** -- "Pharmacy Data Technologist" -- 11.5px, mono font, 400 weight, text-secondary -- `margin-top: 2px` - -**Status badge:** -- Inline-flex, gap 5px -- `margin-top: 8px` -- 11px, 500 weight, success color (#059669) -- `background: var(--success-light)`, `border: 1px solid var(--success-border)` -- `padding: 3px 9px`, `border-radius: 20px` (pill) -- Animated dot: 6px circle, success color, `animation: pulse 2s infinite` (opacity 1→0.4→1) -- Text: "Open to Opportunities" - -**Details grid:** -- `display: grid`, `grid-template-columns: 1fr`, `gap: 6px`, `margin-top: 12px` -- Each row: `display: flex`, `justify-content: space-between`, `align-items: center`, 11.5px, `padding: 2px 0` -- Label: text-tertiary, 400 weight -- Value: text-primary, 500 weight, text-align right -- GPhC No. value: mono font, 11px, `letter-spacing: 0.12em` → "2211810" -- Education value: "MPharm 2.1 (Hons)" -- Location: "Norwich, Norfolk" -- Phone: link in accent color, `text-decoration: none`, underline on hover → "07795 553 088" -- Email: link → "andy@charlwood.xyz" -- Registered: "August 2016" - -**Data source:** `src/data/patient.ts` - ---- - -## Task 6: Sidebar — Tags + Alerts - -### Section Title Component -Reusable within sidebar. Used for "Tags", "Alerts / Highlights", and any future sections. - -- `font-size: 10px`, `font-weight: 600`, `text-transform: uppercase`, `letter-spacing: 0.08em` -- Color: text-tertiary -- `margin-bottom: 10px` -- Flex row with `::after` pseudo-element: `flex: 1`, `height: 1px`, `background: var(--border-light)`, `gap: 6px` - -### Tags Section -- Container: `display: flex`, `flex-wrap: wrap`, `gap: 5px` -- Each tag: 10.5px, 500 weight, `padding: 3px 8px`, `border-radius: 4px`, inline-flex, `line-height: 1.3` -- **Color variants:** - - `teal`: `background: var(--accent-light)`, `color: var(--accent)`, `border: 1px solid var(--accent-border)` - - `amber`: `background: var(--amber-light)`, `color: var(--amber)`, `border: 1px solid var(--amber-border)` - - `green`: `background: var(--success-light)`, `color: var(--success)`, `border: 1px solid var(--success-border)` -- **Data source:** `src/data/tags.ts` - -### Alerts / Highlights Section -- Container: `display: flex`, `flex-direction: column`, `gap: 6px` -- Each flag item: `display: flex`, `align-items: center`, `gap: 8px` - - 11px, 700 weight, `padding: 7px 10px`, `border-radius: var(--radius-sm)` (6px), `letter-spacing: 0.02em` -- **Alert variant** (red): - - `background: var(--alert-light)`, `color: var(--alert)`, `border: 1px solid var(--alert-border)` - - Icon: `AlertTriangle` from lucide-react (14px, 2.5 stroke-width) -- **Amber variant:** - - `background: var(--amber-light)`, `color: var(--amber)`, `border: 1px solid var(--amber-border)` - - Icon: `AlertCircle` from lucide-react (14px, 2.5 stroke-width) -- Icon container: 16px square, flex center, flex-shrink-0 -- **Data source:** `src/data/alerts.ts` - -### Section Padding -Each sidebar section: `padding: 14px 0 6px` diff --git a/Ralph/refs/ref-04-dashboard-layout.md b/Ralph/refs/ref-04-dashboard-layout.md deleted file mode 100644 index 5a2ee66..0000000 --- a/Ralph/refs/ref-04-dashboard-layout.md +++ /dev/null @@ -1,163 +0,0 @@ -# Reference: Task 7 — DashboardLayout - -## Overview - -Create the main layout component that replaces `PMRInterface.tsx`. This is the container that houses TopBar, Sidebar, and the scrollable card grid of tiles. - -## File: `src/components/DashboardLayout.tsx` - -### Layout Structure - -``` -┌────────────────────────────────────────────────────┐ -│ TopBar (fixed, z-100, height: 48px) │ -├──────────┬─────────────────────────────────────────┤ -│ │ │ -│ Sidebar │
— scrollable card grid │ -│ (272px) │ padding: 24px 28px 40px │ -│ fixed │ │ -│ │ grid: 1fr 1fr, gap: 16px │ -│ │ │ -│ │ [PatientSummary — full] │ -│ │ [LatestResults] [CoreSkills] │ -│ │ [LastConsultation — full] │ -│ │ [CareerActivity — full] │ -│ │ [Education — full] │ -│ │ [Projects — full] │ -│ │ │ -└──────────┴─────────────────────────────────────────┘ -``` - -### CSS Layout - -``` -.layout { - display: flex; - margin-top: var(--topbar-height); /* 48px */ - height: calc(100vh - var(--topbar-height)); -} - -.sidebar { - /* See ref-03-topbar-sidebar.md for sidebar specs */ - width: var(--sidebar-width); - min-width: var(--sidebar-width); - /* ... */ -} - -.main { - flex: 1; - overflow-y: auto; - padding: 24px 28px 40px; -} - -.card-grid { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16px; -} - -@media (max-width: 900px) { - .card-grid { - grid-template-columns: 1fr; - } -} -``` - -Use Tailwind classes for all of this — the CSS above is for reference only. - -### Framer Motion Entrance Animations - -Staggered entrance when dashboard first renders (after login): - -1. **TopBar**: slides down from `-48px`, 200ms ease-out -2. **Sidebar**: slides from `-272px` left, 250ms ease-out, 50ms delay -3. **Main content**: fades in (opacity 0→1), 300ms, 150ms delay - -```typescript -const topbarVariants = { - hidden: { y: -48, opacity: 0 }, - visible: { y: 0, opacity: 1, transition: { duration: 0.2, ease: 'easeOut' } } -} - -const sidebarVariants = { - hidden: { x: -272, opacity: 0 }, - visible: { x: 0, opacity: 1, transition: { duration: 0.25, ease: 'easeOut', delay: 0.05 } } -} - -const contentVariants = { - hidden: { opacity: 0 }, - visible: { opacity: 1, transition: { duration: 0.3, delay: 0.15 } } -} -``` - -With `prefers-reduced-motion`: all durations → 0, no delays. - -### Tile Ordering in Grid - -The card grid renders tiles in this order: -1. `PatientSummaryTile` — `grid-column: 1 / -1` (full width) -2. `LatestResultsTile` — single column (left) -3. `CoreSkillsTile` — single column (right) -4. `LastConsultationTile` — `grid-column: 1 / -1` (full width) -5. `CareerActivityTile` — `grid-column: 1 / -1` (full width) -6. `EducationTile` — `grid-column: 1 / -1` (full width) -7. `ProjectsTile` — `grid-column: 1 / -1` (full width) - -### App.tsx Wiring - -In `src/App.tsx`, the PMR phase currently renders ``. Change it to render ``. - -```typescript -// In App.tsx phase switch: -case 'pmr': - return -``` - -Keep all other phases (boot, ecg, login) unchanged. The SkipButton that skips to login should still work. - -### Scrollbar Styling - -Main content area scrollbar (matches concept): -- Width: 6px -- Track: transparent -- Thumb: var(--border) (#D4E0DE), border-radius 3px - -### Command Palette Integration - -The DashboardLayout should render the `CommandPalette` component (from Task 18) at the layout level, so it overlays the entire dashboard when triggered. For now (Task 7), just add a placeholder comment or empty div where it will go. The TopBar search bar's click handler should be wired to open the palette (but the palette itself comes in Task 18). - -### Background Color Transition - -The login screen has background `#1E293B`. The dashboard has background `#F0F5F4`. This transition should happen smoothly. Options: -1. The DashboardLayout entrance animation covers the transition (content fades in over the dark background, replacing it) -2. A brief CSS transition on the body/root background color -3. Handle it in App.tsx with a state-based background - -The simplest approach is option 1 — the dashboard's entrance animation effectively replaces the dark login background with the light dashboard. - ---- - -## Established Patterns (from previous iterations) - -These patterns were established across 16 iterations of the old PMR build. Reuse them: - -### Phase name is `'pmr'` -The Phase type in `src/types/index.ts` is `'boot' | 'ecg' | 'login' | 'pmr'`. The `'pmr'` case renders the dashboard. Do NOT rename the phase — just change what it renders. - -### Module-scope `prefersReducedMotion` -All animation components should compute this once at module level, not per render: -```typescript -const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches -``` -This is the established pattern across all existing view components. - -### Pre-existing ESLint warning -`AccessibilityContext.tsx` has 1 pre-existing ESLint warning. This is expected — do not attempt to fix it. Quality checks pass with this warning present. - -### Callback ref pattern for Framer Motion -If you need a ref to a `motion.*` element (e.g., for scroll detection), use `useState` + callback ref instead of `useRef`. Framer Motion elements may not be in the DOM when `useEffect` first runs: -```typescript -const [scrollContainer, setScrollContainer] = useState(null) -// On the element: ref={el => { if (el) setScrollContainer(el) }} -``` -This avoids null ref issues with animated mount timing. diff --git a/Ralph/refs/ref-05-card-and-top-tiles.md b/Ralph/refs/ref-05-card-and-top-tiles.md deleted file mode 100644 index afb2989..0000000 --- a/Ralph/refs/ref-05-card-and-top-tiles.md +++ /dev/null @@ -1,144 +0,0 @@ -# Reference: Tasks 8-11 — Card Component and Top Tiles - -## Task 8: Reusable Card Component - -### File: `src/components/Card.tsx` - -### Base Card -```typescript -interface CardProps { - children: React.ReactNode - full?: boolean // spans both grid columns - className?: string -} -``` - -**Styling:** -- `background: var(--surface)` (#FFFFFF) -- `border: 1px solid var(--border-light)` (#E4EDEB) -- `border-radius: var(--radius)` (8px) -- `padding: 20px` -- `box-shadow: var(--shadow-sm)` (0 1px 2px rgba(26,43,42,0.05)) -- Hover: `box-shadow: var(--shadow-md)`, `border-color: var(--border)` (#D4E0DE) -- `transition: box-shadow 0.2s, border-color 0.2s` -- Full variant: `grid-column: 1 / -1` - -### CardHeader Sub-component -```typescript -interface CardHeaderProps { - dotColor: 'teal' | 'amber' | 'green' | 'alert' | 'purple' - title: string - rightText?: string -} -``` - -**Styling:** -- `display: flex`, `align-items: center`, `gap: 8px`, `margin-bottom: 16px` -- Dot: 8px circle, `border-radius: 50%`, flex-shrink-0 - - teal: `#0D6E6E`, amber: `#D97706`, green: `#059669`, alert: `#DC2626`, purple: `#7C3AED` -- Title: 12px, 600 weight, uppercase, `letter-spacing: 0.06em`, text-secondary (#5B7A78) -- Right text (optional): 10px, 400 weight, normal case, no tracking, text-tertiary, mono font, `margin-left: auto` - ---- - -## Task 9: PatientSummary Tile - -### File: `src/components/tiles/PatientSummaryTile.tsx` - -**Layout:** Full-width card, first in grid. - -**Content:** -- CardHeader: teal dot + "PATIENT SUMMARY" -- Body: personal statement text from `src/data/profile.ts` -- Typography: 13px, font-ui, `line-height: 1.6` (leading-relaxed), text-primary -- No interactive elements — read-only - -**Data:** `import { personalStatement } from '@/data/profile'` - -This is a simple tile. No expansion, no interactivity. - ---- - -## Task 10: LatestResults Tile - -### File: `src/components/tiles/LatestResultsTile.tsx` - -**Layout:** Half-width card (single grid column). Sits in the LEFT column. - -**Content:** -- CardHeader: teal dot + "LATEST RESULTS" + right text "Updated May 2025" -- 2×2 metric grid inside - -**Metric Grid:** -- `display: grid`, `grid-template-columns: 1fr 1fr`, `gap: 12px` - -**Each Metric Card:** -- `padding: 14px`, `border-radius: var(--radius-sm)` (6px) -- `border: 1px solid var(--border-light)`, `background: var(--bg)` (#F0F5F4) -- Value: 22px, 700 weight, `letter-spacing: -0.02em`, `line-height: 1.2` - - Color by variant: green=#059669, amber=#D97706, teal=#0D6E6E -- Label: 11px, text-secondary, 500 weight, `margin-top: 3px` -- Sub: 10px, text-tertiary, mono font, `margin-top: 4px` - -**Data:** `import { kpis } from '@/data/kpis'` - -**KPI flip prep:** Each metric card should accept a `data-kpi-id` or an `onClick` prop placeholder — Task 17 will add the flip interaction. For now, render as static display. - -**Values:** -| Value | Label | Sub | Color | -|-------|-------|-----|-------| -| £220M | Budget Oversight | NHS prescribing | green | -| £14.6M | Efficiency Savings | Identified & tracked | amber | -| 9+ | Years in NHS | Since 2016 | teal | -| 12 | Team Size Led | Cross-functional | green | - ---- - -## Task 11: CoreSkills Tile ("Repeat Medications") - -### File: `src/components/tiles/CoreSkillsTile.tsx` - -**Layout:** Half-width card (single grid column). Sits in the RIGHT column, next to LatestResults. - -**Content:** -- CardHeader: amber dot + "REPEAT MEDICATIONS" -- Vertical list of skill items, `gap: 10px` - -**Each Skill Item:** -Matches the concept's `.dev-item` pattern: -- `display: flex`, `align-items: center`, `gap: 10px` -- 12.5px font, `padding: 10px 12px` -- `background: var(--bg)` (#F0F5F4), `border-radius: var(--radius-sm)` (6px) -- `border: 1px solid var(--border-light)` - -**Item structure:** -- **Icon container** (28px square, 6px radius): - - `background: var(--accent-light)`, `color: var(--accent)` (teal) - - Lucide icon inside (14px): `BarChart3` for Data Analysis, `Code2` for Python, `Database` for SQL, `PieChart` for Power BI, `FileCode2` for JS/TS -- **Text block** (flex: 1): - - Name: 600 weight, text-primary (e.g., "Data Analysis") - - Frequency + years: 11px, text-tertiary, mono font (e.g., "Twice daily · Since 2016 · 9 yrs") -- **Optional status badge**: 10px, 500 weight, pill shape (padding 3px 8px, border-radius 20px), flex-shrink-0 - - Could show proficiency or "Active" status - -**Medication metaphor format:** -``` -[📊] Data Analysis Active - Twice daily · Since 2016 · 9 yrs - -[💻] Python Active - Daily · Since 2019 · 6 yrs - -[🗄️] SQL Active - Daily · Since 2018 · 7 yrs - -[📈] Power BI Active - Once weekly · Since 2020 · 5 yrs - -[📝] JavaScript / TypeScript Active - When required · Since 2022 · 3 yrs -``` - -**Data:** `import { skills } from '@/data/skills'` - -**Expansion prep:** Each item should accept an onClick prop placeholder — Task 16 will add expansion to show prescribing history (from existing medications data). diff --git a/Ralph/refs/ref-06-bottom-tiles.md b/Ralph/refs/ref-06-bottom-tiles.md deleted file mode 100644 index a2b3282..0000000 --- a/Ralph/refs/ref-06-bottom-tiles.md +++ /dev/null @@ -1,204 +0,0 @@ -# Reference: Tasks 12-15 — Bottom Tiles - -## Task 12: LastConsultation Tile - -### File: `src/components/tiles/LastConsultationTile.tsx` - -**Layout:** Full-width card. - -**Content:** -- CardHeader: green dot + "LAST CONSULTATION" + right text "Most recent role" - -**Header info row:** -- `display: flex`, `flex-wrap: wrap`, `gap: 16px` -- `margin-bottom: 14px`, `padding-bottom: 14px`, `border-bottom: 1px solid var(--border-light)` -- Each field: - - Label: 10px, uppercase, `letter-spacing: 0.06em`, text-tertiary - - Value: 11.5px, 600 weight, text-primary - -| Label | Value | -|-------|-------| -| Date | May 2025 | -| Organisation | NHS Norfolk & Waveney ICB | -| Type | Permanent · Full-time | -| Band | 8a | - -**Role title:** -- "Interim Head, Population Health & Data Analysis" -- 13.5px, 600 weight, `color: var(--accent)` (#0D6E6E) -- `margin-bottom: 12px` - -**Bullet list:** -- `list-style: none`, flex column, `gap: 7px` -- Each bullet: 12.5px, text-primary, `padding-left: 16px`, `line-height: 1.5` -- Pseudo `::before`: 5px circle, accent color (#0D6E6E), `opacity: 0.5`, positioned left at top 7px - -**Bullets** (from first consultation's examination array): -- Led a cross-functional team of 12 across data, analytics, and population health workstreams -- Oversaw £220M prescribing budget with full analytical accountability and reporting to ICB board -- Identified £14.6M in efficiency savings through data-driven prescribing interventions -- Designed and deployed Power BI dashboards used by 200+ clinicians and commissioners -- Spearheaded SQL analytics transformation, migrating legacy Access databases to modern data stack -- Established team data literacy programme, upskilling 30+ non-technical staff in data interpretation - -**Data:** `import { consultations } from '@/data/consultations'` — use `consultations[0]` (the most recent). - -Map consultation fields: -- date → Date field -- organization → Organisation field -- role → Role title -- examination array → Bullet points - ---- - -## Task 13: CareerActivity Tile - -### File: `src/components/tiles/CareerActivityTile.tsx` - -**Layout:** Full-width card. - -**Content:** -- CardHeader: teal dot + "CAREER ACTIVITY" + right text "Full timeline" - -**Activity grid:** -- `display: grid`, `grid-template-columns: 1fr 1fr`, `gap: 10px` -- Below 900px: `grid-template-columns: 1fr` (single column) - -**Each activity item:** -- `display: flex`, `gap: 10px` -- `padding: 10px 12px` -- `background: var(--bg)` (#F0F5F4) -- `border-radius: var(--radius-sm)` (6px) -- `border: 1px solid var(--border-light)` -- 12px font -- `transition: border-color 0.15s` -- Hover: `border-color: var(--accent-border)` - -**Dot (left):** -- 8px circle, flex-shrink-0, `margin-top: 2px` (aligns with text) -- Color by type: - - Role: teal (#0D6E6E) - - Project: amber (#D97706) - - Certification: green (#059669) - - Education: purple (#7C3AED) - -**Content (right):** -- Title: 600 weight, text-primary, `line-height: 1.3` -- Meta: 11px, text-secondary, `margin-top: 2px` -- Date: 10px, mono font, text-tertiary, `margin-top: 3px` - -**Building the timeline data:** - -Merge entries from multiple data sources, sorted newest-first: - -```typescript -type ActivityType = 'role' | 'project' | 'cert' | 'edu' - -interface ActivityEntry { - id: string - type: ActivityType - title: string - meta: string - date: string - sortYear: number // for sorting -} -``` - -Sources: -1. `consultations` → type "role": title=role, meta=organization, date=duration -2. `investigations` (selected key ones) → type "project": title=name, meta=short description, date=year -3. `documents` where type='Certificate' → type "cert": title=title, meta=source, date=date -4. `documents` where type='Results' (MPharm) → type "edu": title=title, meta=source, date=date - -Match the concept HTML entries: -| Type | Title | Meta | Date | -|------|-------|------|------| -| role | Interim Head, Population Health & Data Analysis | NHS Norfolk & Waveney ICB | 2024 – 2025 | -| project | £220M Prescribing Budget Oversight | Lead analyst & budget owner | 2024 | -| role | Senior Data Analyst — Medicines Optimisation | NHS Norfolk & Waveney ICB | 2021 – 2024 | -| project | SQL Analytics Transformation | Legacy migration project lead | 2025 | -| cert | Power BI Data Analyst Associate | Microsoft Certified | 2023 | -| role | Prescribing Data Pharmacist | NHS Norwich CCG | 2018 – 2021 | -| cert | Clinical Pharmacy Diploma | Professional development | 2019 | -| role | Community Pharmacist | Boots UK | 2016 – 2018 | -| edu | MPharm (Hons) — 2:1 | University of East Anglia | 2011 – 2015 | -| cert | GPhC Registration | General Pharmaceutical Council | August 2016 | - -**Expansion prep:** Activity items should accept onClick for Task 16 (expand to show full role/project detail). - ---- - -## Task 14: Education Tile - -### File: `src/components/tiles/EducationTile.tsx` - -**Layout:** Full-width card, below Career Activity. - -**Content:** -- CardHeader: purple dot (#7C3AED) + "EDUCATION" - -**Education entries:** -Vertical stack of education items. - -Each item: -- `padding: 7px 10px` -- `background: var(--surface)` (#FFFFFF) -- `border: 1px solid var(--border-light)` -- `border-radius: var(--radius-sm)` (6px) -- 11.5px, text-primary - -Structure: -- Degree name: 600 weight, `display: block` -- Detail: text-secondary, 11px, `margin-top: 2px` - -**Entries** (from CV): -| Degree | Detail | -|--------|--------| -| MPharm (Hons) — 2:1 | University of East Anglia · 2015 | -| NHS Leadership Academy — Mary Seacole Programme | 2018 · 78% | -| A-Levels: Mathematics (A*), Chemistry (B), Politics (C) | Highworth Grammar School · 2009–2011 | - -**Data:** Filter `src/data/documents.ts` for education entries, or hardcode from CV since the documents data may not have all education entries. - -Note: The concept HTML only shows the MPharm entry. But the CV has more education. Include all CV education entries. - ---- - -## Task 15: Projects Tile - -### File: `src/components/tiles/ProjectsTile.tsx` - -**Layout:** Full-width card, prominent position. - -**Content:** -- CardHeader: amber dot + "ACTIVE PROJECTS" - -**Project entries:** -Vertical list, styled as interactive items. - -Each project: -- `display: flex`, `align-items: flex-start`, `gap: 8px` -- `padding: 7px 10px` -- `background: var(--surface)`, `border: 1px solid var(--border-light)` -- `border-radius: var(--radius-sm)` (6px) -- 11.5px, text-primary -- Hover: `border-color: var(--accent-border)` -- `transition: border-color 0.15s` - -Structure: -- **Status dot** (7px circle, flex-shrink-0, `margin-top: 4px`): - - Complete: success (#059669) - - Ongoing: accent (#0D6E6E) - - Live: success with pulse animation -- **Project name**: text-primary, flex 1 -- **Year badge**: 10px, mono font, text-tertiary, `margin-left: auto`, flex-shrink-0 - -**Data:** `import { investigations } from '@/data/investigations'` - -Map investigations to projects: -- name → Project name -- status → dot color -- requestedYear → Year badge -- resultSummary → Available for expansion (Task 16) - -**Expansion prep:** Each item should accept onClick for Task 16 (expand to show methodology, tech stack, results). diff --git a/Ralph/refs/ref-07-interactions.md b/Ralph/refs/ref-07-interactions.md deleted file mode 100644 index eae53d6..0000000 --- a/Ralph/refs/ref-07-interactions.md +++ /dev/null @@ -1,259 +0,0 @@ -# Reference: Tasks 16-18 — Interactions - -## Task 16: Tile Expansion System - -### Overview - -Three tiles have expandable items: CareerActivity (roles), Projects, and CoreSkills. Clicking an item expands it in-place to reveal detail, like expanding a clinical record entry. - -### Expansion Pattern (consistent across all tiles) - -**Animation:** -- Framer Motion `AnimatePresence` + `motion.div` -- Height-only animation: 200ms, ease-out -- **No opacity fade on content** (guardrail) -- `overflow: hidden` on the animated container - -```typescript - - {isExpanded && ( - - {/* expanded content */} - - )} - -``` - -**Behavior:** -- Single-expand accordion: only one item expanded at a time within each tile -- Click expanded item again to collapse -- Click different item: collapses current, expands new -- State: `expandedItemId: string | null` in each tile component - -**Keyboard:** -- Enter/Space: toggle expand/collapse -- Escape: collapse current item -- `aria-expanded` on each clickable item - -**Visual:** -- Expanded content has slightly different background (`var(--bg)` or subtle border-left) -- Colored left border on expanded panel (accent color for roles, amber for projects, teal for skills) -- Content padding: 12-16px - -### CareerActivity Expansion (roles) - -When a role-type activity item is expanded: -- Show full role details from corresponding consultation entry -- Structure: role title, organization, date range -- Achievement bullets (examination array from consultation) -- Coded entries if available -- Match expanded content to `consultations` data by mapping activity item to consultation - -### Projects Expansion - -When a project item is expanded: -- Show from investigation data: - - Methodology - - Tech stack (as tags or inline list) - - Results (bulleted) - - External URL link if available ("View Results" button) - -### CoreSkills Expansion - -When a skill item is expanded: -- Show "prescribing history" — a timeline of skill development -- **Data source:** `import { medications } from '@/data/medications'` (NOT `skills.ts`). The `medications.ts` file has 18 entries, each with a `prescribingHistory` array of `{ year, description }` entries. Map from `skills.ts` to `medications.ts` by matching skill name to medication name (e.g., "Data Analysis" in skills.ts → find the medication with `name: "Data Analysis"` in medications.ts to get its `prescribingHistory`). -- Format: vertical timeline with year markers and descriptions - - Timeline dots: accent color, 6px, with connecting line - - Year: mono font, 12px, semibold - - Description: 12px, regular - ---- - -## Task 17: KPI Flip Cards - -### Overview - -In the LatestResults tile, each metric card can be clicked to "flip" and reveal an explanation of that KPI. - -### Flip Animation - -**CSS Perspective approach:** -```css -.metric-card { - perspective: 1000px; - cursor: pointer; -} - -.metric-card-inner { - transition: transform 0.4s ease-in-out; - transform-style: preserve-3d; - position: relative; -} - -.metric-card-inner.flipped { - transform: rotateY(180deg); -} - -.metric-card-front, -.metric-card-back { - backface-visibility: hidden; - position: absolute; - inset: 0; -} - -.metric-card-back { - transform: rotateY(180deg); -} -``` - -Or use Framer Motion `animate={{ rotateY: isFlipped ? 180 : 0 }}` with `perspective` on parent. - -**Behavior:** -- Click to flip front → back -- Click again to flip back → front -- Only one card flipped at a time (clicking another card flips the current one back) -- State: `flippedCardId: string | null` in LatestResultsTile - -**Front face:** Current metric display (value + label + sub) — same as Task 10. - -**Back face:** -- `background: var(--accent-light)` (subtle teal tint) -- `padding: 14px` -- Text: 12px, text-secondary, `line-height: 1.5` -- The explanation text from KPI data's `explanation` field - -**Reduced motion:** -- No 3D flip animation -- Instant content swap (front → back) -- Could use a simple crossfade or just replace content immediately - -**Keyboard:** -- Enter/Space to flip -- Each metric card should be `tabIndex={0}` with appropriate `aria-label` - -**KPI Explanations** (from `src/data/kpis.ts`): -- £220M: Budget management with forecasting models -- £14.6M: Efficiency programme through data analysis -- 9+ Years: NHS service progression since 2016 -- 12: Cross-functional team leadership - ---- - -## Task 18: Command Palette - -### File: `src/components/CommandPalette.tsx` - -### Trigger -- **Ctrl+K** (global `keydown` listener on `document`) -- **Click** on TopBar search bar (or focus on search input) -- The TopBar search input does NOT do inline search — it opens the palette - -### Overlay -- `position: fixed`, `inset: 0` -- `background: rgba(26,43,42,0.45)` -- `backdrop-filter: blur(4px)` -- `z-index: 1000` -- Fade in: `opacity: 0 → 1`, `visibility: hidden → visible`, 200ms transition -- Click overlay (outside modal) to close - -### Palette Modal -- `width: 580px`, `max-height: 520px` -- `background: var(--surface)` (#FFFFFF) -- `border-radius: 12px` -- `box-shadow: 0 20px 60px rgba(26,43,42,0.2), 0 0 0 1px rgba(26,43,42,0.08)` -- `overflow: hidden` -- Entrance: `transform: scale(0.97) translateY(-8px)` → `scale(1) translateY(0)`, 200ms cubic-bezier - -### Search Input -- Flex row: search icon (18px, accent) + input + "ESC" hint badge -- `padding: 14px 18px`, `border-bottom: 1px solid var(--border-light)` -- Input: 15px, font-body, placeholder "Search records, experience, skills..." -- ESC badge: mono 10px, tertiary, bg var(--bg), border, padding 2px 7px, radius 4px - -### Results Area -- `overflow-y: auto`, `padding: 8px`, `flex: 1` -- Custom scrollbar (4px) - -### Result Sections -Section label: 10px, 600 weight, uppercase, `letter-spacing: 0.08em`, text-tertiary, `padding: 8px 10px 5px` - -### Result Items -- `display: flex`, `align-items: center`, `gap: 10px` -- `padding: 9px 10px`, `border-radius: var(--radius-sm)` (6px) -- `cursor: pointer`, `transition: background 0.1s` -- 13px, text-primary -- Hover/selected: `background: var(--accent-light)` -- Selected also gets: `outline: 1.5px solid var(--accent-border)` - -**Item structure:** -- Icon container: 28px square, 6px radius, colored bg per section - - Experience: teal - - Core Skills: green - - Active Projects: amber - - Achievements: amber - - Education: purple - - Quick Actions: teal -- Text: title (500 weight) + subtitle (11px, tertiary, truncated) -- Optional badge: 10px, mono, tertiary - -### Fuzzy Search - -Adapt existing `src/lib/search.ts` (fuse.js v7.0.0, already installed): - -**Existing code:** `src/lib/search.ts` has `buildSearchIndex()` which creates a Fuse index from consultations, medications, problems, investigations, and documents. It groups results by `sectionLabel` via `groupResultsBySection()`. The `SearchResult` interface has `{ id, title, section: ViewId, sectionLabel, highlight }`. - -**What needs changing:** -- The `section: ViewId` field is designed for view-switching navigation (navigating to `#consultations`, `#medications`, etc.). The new dashboard has no views — it's a single scrollable page. Results should either scroll to the relevant tile or expand an item within a tile. -- Add `skills.ts` data to the index (currently only `medications.ts` is indexed, not the new 5-skill entries) -- Add `kpis.ts` data to the index -- Add Quick Actions (Download CV, Send Email, View LinkedIn, View Projects) -- Update section labels to match palette grouping: "Experience", "Core Skills", "Active Projects", "Achievements", "Education", "Quick Actions" -- Add an `action` field to `SearchResult` so each result knows what to do when selected (scroll to tile, expand item, open link, etc.) - -**Config (keep existing):** -- `threshold: 0.3`, weighted keys (title: 2, content: 1) -- `minMatchCharLength: 2` -- Group results by section -- Highlight matching text in titles using `` with accent-light background - -### Keyboard Navigation -- **Arrow Down/Up**: move selection through results -- **Enter**: select highlighted result (navigate to section or trigger action) -- **Escape**: close palette -- `selectedIndex` state tracks which result is highlighted -- Auto-scroll highlighted result into view - -### Quick Actions Section -| Title | Subtitle | Action | -|-------|----------|--------| -| Download CV | Export as PDF | Trigger download | -| Send Email | andy@charlwood.xyz | `mailto:` link | -| View LinkedIn | Professional profile | External link | -| View Projects | GitHub & portfolio | External link | - -### Footer -- `display: flex`, `gap: 12px` -- `padding: 10px 18px`, `border-top: 1px solid var(--border-light)` -- 11px, text-tertiary -- Keyboard hints: `↑ ↓ Navigate`, `Enter Select`, `Esc Close` -- Each key in `` styled element - -### Reduced Motion -- No scale/translate entrance animation -- Instant show/hide (opacity only, or immediate) - -### State Management -```typescript -const [isOpen, setIsOpen] = useState(false) -const [query, setQuery] = useState('') -const [selectedIndex, setSelectedIndex] = useState(-1) -``` - -Render the palette at the DashboardLayout level so it overlays everything. diff --git a/Ralph/refs/ref-08-polish.md b/Ralph/refs/ref-08-polish.md deleted file mode 100644 index 3fc6ae6..0000000 --- a/Ralph/refs/ref-08-polish.md +++ /dev/null @@ -1,164 +0,0 @@ -# Reference: Tasks 19-21 — Polish - -## Task 19: Responsive Design - -### Desktop (>1024px) -- Full sidebar (272px) + TopBar + 2-column card grid -- All tiles at full spec (as designed in Tasks 8-15) -- Command palette at 580px width - -### Tablet (768–1024px) -- Sidebar: collapse to icon-only (56px) or hide entirely with toggle -- TopBar: full, but search bar may shrink (reduce min-width) -- Card grid: can stay 2-column if space permits, or switch to 1-column -- Activity grid inside CareerActivity tile: switch to 1-column - -### Mobile (<768px) -- Sidebar: hidden entirely (off-canvas or removed) -- TopBar: simplified — brand text may truncate, hide search bar center section -- Navigation: consider a hamburger menu or bottom nav for key actions -- Card grid: single column -- All tiles stack vertically (full-width) -- Metric grid in LatestResults: stays 2x2 (compact enough) -- Activity grid in CareerActivity: single column -- Touch targets: all clickable elements 48px+ minimum -- Command palette: full-width with reduced padding - -### Breakpoint Strategy -Use Tailwind responsive prefixes: -- `lg:` for desktop (>1024px) -- `md:` for tablet (>768px) -- Default styles for mobile-first - -### Key responsive classes: -``` -/* Card grid */ -grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-[16px] - -/* Sidebar visibility */ -hidden lg:flex lg:flex-col - -/* TopBar search */ -hidden md:block - -/* Activity grid */ -grid grid-cols-1 md:grid-cols-2 - -/* Sidebar width */ -lg:w-[272px] lg:min-w-[272px] -``` - ---- - -## Task 20: Accessibility Audit - -### Semantic HTML -| Element | Tag | Notes | -|---------|-----|-------| -| TopBar | `
` | Fixed at top | -| Sidebar | `