Added task files
This commit is contained in:
@@ -0,0 +1,265 @@
|
||||
# PRD: Career Constellation — Clinical Pathway Overhaul
|
||||
|
||||
## Introduction
|
||||
|
||||
The CareerConstellation D3 force-directed graph sits alongside the work experience timeline in the "Patient Pathway" section. It currently looks prototype-quality: the timeline runs in the wrong direction, the chart doesn't fill the available height, node styling is basic, and the visual language doesn't match the refined GP clinical system aesthetic used across the rest of the portfolio.
|
||||
|
||||
This PRD covers a comprehensive visual and structural overhaul to transform the graph into a polished, clinical-style patient pathway diagram that complements the adjacent work experience timeline — with synchronised year positions, bidirectional hover highlighting, and a refined design language matching the rest of the dashboard.
|
||||
|
||||
**Implementation note:** All user stories involving D3 rendering changes should use the `d3-viz` skill.
|
||||
|
||||
## Goals
|
||||
|
||||
- Reverse the timeline to top = latest (2025), bottom = earliest (2017) so it visually syncs with the reverse-chronological work experience cards beside it
|
||||
- Dynamically match the graph's height to the work experience column so both columns align
|
||||
- Achieve visual parity with the rest of the dashboard — clean, clinical, premium, not prototype-looking
|
||||
- Implement bidirectional highlighting between the work experience timeline cards and the constellation graph
|
||||
- Create a clear visual hierarchy where skill nodes stay muted until contextually relevant (hover/click)
|
||||
|
||||
## User Stories
|
||||
|
||||
### US-001: Reverse timeline direction (top = most recent)
|
||||
|
||||
**Description:** As a visitor, I want the graph's vertical timeline to run top-to-bottom from 2025→2017 so that the year positions visually align with the reverse-chronological work experience cards in the adjacent column.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] `yScale` domain is reversed: `[maxYear, minYear]` maps to `[topPadding, height - bottomPadding]`
|
||||
- [ ] Role nodes appear at their correct year positions with 2025 near the top and 2017 near the bottom
|
||||
- [ ] Year labels along the timeline axis read top-to-bottom: 2025, 2024, 2023, ... 2017
|
||||
- [ ] Skill nodes cluster around their linked roles at the correct vertical positions
|
||||
- [ ] The timeline vertical line, year dots, and horizontal guide lines all reflect the reversed scale
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser using dev server
|
||||
|
||||
### US-002: Dynamic height matching with work experience column
|
||||
|
||||
**Description:** As a visitor, I want the constellation graph to fill the same vertical space as the work experience column so both columns appear balanced and the graph uses its full available height.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Remove fixed `DESKTOP_HEIGHT`, `TABLET_HEIGHT`, `MOBILE_HEIGHT` constants
|
||||
- [ ] The graph container measures the rendered height of the adjacent `.chronology-stream` element and uses that as its own height
|
||||
- [ ] Use a `ResizeObserver` on the chronology column to update the graph height when cards expand/collapse
|
||||
- [ ] Set a sensible minimum height (e.g. 400px) so the graph doesn't collapse on short content
|
||||
- [ ] On mobile (single-column layout), the graph uses a reasonable standalone height (e.g. 360px) since the columns stack
|
||||
- [ ] The `viewBox` and all D3 scales update correctly when height changes
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — expand/collapse work experience cards and confirm the graph height adjusts
|
||||
|
||||
### US-003: Clinical pathway visual language — background and structure
|
||||
|
||||
**Description:** As a visitor, I want the graph to look like a clinical patient pathway diagram — clean, precise, and institutional — matching the GP system dashboard aesthetic.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Replace the radial gradient background with a clean white (`var(--surface)`) or very subtle warm tint matching `var(--bg-dashboard)`
|
||||
- [ ] Add a subtle 1px border matching `var(--border-light)` and `border-radius: var(--radius-sm)` consistent with other dashboard cards
|
||||
- [ ] Timeline axis styled as a refined vertical rule: 1px solid `var(--border)` colour, not the current thick teal line
|
||||
- [ ] Year markers are small ticks extending from the timeline, not floating dots — styled like clinical chart gridlines
|
||||
- [ ] Year labels use `font-family: var(--font-geist-mono)`, `font-size: 10px`, colour `var(--text-tertiary)` — matching dashboard data labels
|
||||
- [ ] Horizontal guide lines are very subtle (0.3 opacity, dashed or dotted) — they guide the eye without dominating
|
||||
- [ ] Remove the existing legend box (it takes up valuable space and will be replaced in US-007)
|
||||
- [ ] All colours use CSS custom properties from the design system (`var(--accent)`, `var(--success)`, `var(--amber)`, etc.)
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — the graph should feel like it belongs on the same page as the other tiles
|
||||
|
||||
### US-004: Role node redesign — clinical record anchors
|
||||
|
||||
**Description:** As a visitor, I want role nodes to look like refined clinical record entries rather than basic coloured circles, clearly anchored to their timeline position.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Role nodes rendered as rounded rectangles (pill shapes) rather than circles — wider to accommodate text, roughly 90-110px wide x 32-36px tall
|
||||
- [ ] Each role node displays the `shortLabel` text centred inside, using `font-family: var(--font-ui)`, weight 600, size 11px
|
||||
- [ ] Role node fill uses the `orgColor` from data at reduced opacity (e.g. 0.12) with a 1px border of the same colour at higher opacity (0.4), and text in the `orgColor` at full strength — creating a subtle badge effect
|
||||
- [ ] A thin connector line links each role node horizontally back to the timeline axis at its year position — like a clinical event marker
|
||||
- [ ] Role nodes have a subtle hover state: border opacity increases, shadow appears (`var(--shadow-sm)`)
|
||||
- [ ] Active/pinned role node: border becomes solid at full `orgColor`, subtle inset glow or stronger shadow
|
||||
- [ ] Role nodes are positioned to the right of the timeline axis with consistent horizontal offset
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — role nodes should look like labelled clinical event markers
|
||||
|
||||
### US-005: Skill node redesign — muted by default, revealed on interaction
|
||||
|
||||
**Description:** As a visitor, I want skill nodes to be visually subdued by default, becoming prominent only when a connected role or skill is hovered or clicked — creating a clean resting state and a meaningful highlighted state.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Default (resting) state for skill nodes: small circles (radius 6-8px), fill opacity 0.25, no visible label
|
||||
- [ ] Skill node fill colour determined by domain: technical = `var(--accent)`, clinical = `var(--success)`, leadership = `var(--amber)`
|
||||
- [ ] When a connected role is hovered/pinned: connected skill nodes transition to radius 10-12px, fill opacity 0.85, and their labels fade in (opacity 0 → 1, 200ms ease-out)
|
||||
- [ ] Skill labels use `font-family: var(--font-geist-mono)`, size 10px, colour `var(--text-secondary)`
|
||||
- [ ] When a skill node itself is hovered: that skill and all its connected roles highlight, with the skill growing to full size and showing its label
|
||||
- [ ] Link lines from roles to skills: default state is very subtle (opacity 0.08-0.12); highlighted state is 0.5-0.7 with domain colour
|
||||
- [ ] Unconnected nodes (not part of the active highlight group) reduce to opacity 0.08 — nearly invisible
|
||||
- [ ] Transitions between states are smooth (150-200ms) and respect `prefers-reduced-motion`
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — the graph should feel clean and quiet at rest, informative on interaction
|
||||
|
||||
### US-006: Bidirectional hover highlighting with work experience cards
|
||||
|
||||
**Description:** As a visitor, I want to hover over a work experience card in the timeline and see the corresponding role and its skills light up in the graph, and vice versa — creating a clear visual link between the two columns.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Hovering a `RoleItem` in `WorkExperienceSubsection` calls `onNodeHighlight(consultation.id)` (already partially implemented)
|
||||
- [ ] The `CareerConstellation` component receives `highlightedNodeId` and applies the highlight logic from US-005
|
||||
- [ ] Hovering a role node in the graph triggers a callback that highlights the corresponding work experience card in the timeline (new: requires a reverse callback)
|
||||
- [ ] Add a new prop `onNodeHover?: (id: string | null) => void` to `CareerConstellation` — fires on mouseenter/mouseleave of role nodes
|
||||
- [ ] `DashboardLayout` passes this callback and uses it to set a `highlightedRoleId` state
|
||||
- [ ] `WorkExperienceSubsection` receives `highlightedRoleId` and applies a subtle highlight style to the matching card (e.g. border colour change to `var(--accent-border)`, light background tint)
|
||||
- [ ] `LastConsultationSubsection` also participates in the highlight system for the most recent role
|
||||
- [ ] Highlight clears when mouse leaves both the card and the graph node
|
||||
- [ ] On touch devices, tap-to-pin behaviour works as before — tapping a role pins the highlight in both the graph and the timeline
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — hover over work experience cards and confirm the graph highlights; hover graph nodes and confirm the timeline cards highlight
|
||||
|
||||
### US-007: Compact domain legend and graph header
|
||||
|
||||
**Description:** As a visitor, I want a small, unobtrusive legend that explains the domain colour coding without taking up significant graph space.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Remove the existing boxed legend from inside the SVG
|
||||
- [ ] Add a compact inline legend below (or above) the SVG container — rendered as React HTML, not SVG
|
||||
- [ ] Legend shows three small coloured dots with labels: "Technical", "Clinical", "Leadership" — using the domain colours from the design system
|
||||
- [ ] Legend text uses `font-family: var(--font-geist-mono)`, size 10px, colour `var(--text-tertiary)`
|
||||
- [ ] Legend is horizontally laid out with subtle separators, taking minimal vertical space (single line, ~20px tall)
|
||||
- [ ] Include a small "Hover to explore connections" hint text in the legend row, matching the tertiary text style
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser
|
||||
|
||||
### US-008: Link line refinement — clinical pathway connections
|
||||
|
||||
**Description:** As a visitor, I want the connection lines between roles and skills to look like refined clinical pathway links rather than basic straight lines.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Replace straight `<line>` elements with curved `<path>` elements using D3 curve generators (e.g. `d3.curveBasis` or `d3.curveBundle`)
|
||||
- [ ] Default link styling: 1px stroke, colour `var(--border-light)`, opacity 0.12 — barely visible at rest
|
||||
- [ ] Highlighted link styling: 1.5-2px stroke, domain colour of the skill end, opacity 0.5-0.7
|
||||
- [ ] Link `strength` value from data influences the highlighted stroke opacity (stronger connections more visible)
|
||||
- [ ] Links animate smoothly between default and highlighted states (150ms transition)
|
||||
- [ ] Respect `prefers-reduced-motion` — skip transitions, jump to final state
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — links should be nearly invisible at rest and clearly trace pathways on hover
|
||||
|
||||
### US-009: Force simulation tuning for clinical layout
|
||||
|
||||
**Description:** As a developer, I want the D3 force simulation tuned so that role nodes stay firmly anchored to their timeline positions while skill nodes distribute cleanly in the available space to the right.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Role nodes are effectively fixed to their timeline Y position (very high `forceY` strength, e.g. 0.95-1.0) and a consistent X position offset from the timeline
|
||||
- [ ] Skill nodes distribute in the space to the right of the role nodes, clustered near their connected roles but with enough separation to avoid overlap
|
||||
- [ ] Increase collision radius slightly to prevent label overlap when skills are revealed on hover
|
||||
- [ ] Simulation settles quickly — `alphaDecay` tuned so the graph stabilises within 1-2 seconds (or immediately for `prefers-reduced-motion`)
|
||||
- [ ] Boundary clamping keeps all nodes within the SVG viewport with adequate padding (role labels don't clip, skill labels don't overflow)
|
||||
- [ ] On height changes (from US-002), the simulation re-initialises smoothly without jarring jumps
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser — nodes should feel organised and intentional, not randomly scattered
|
||||
|
||||
### US-010: Content audit — verify role descriptions against CV
|
||||
|
||||
**Description:** As the portfolio owner, I want to ensure all role titles, organisations, dates, and achievement bullets in the work experience data are accurate and up-to-date against the source CV.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Cross-reference `src/data/consultations.ts` against `References/CV_v4.md` and `References/Andy_Charlwood_CV_ATS_Optimised.pdf`
|
||||
- [ ] Verify all role titles match exactly (e.g. "Interim Head, Population Health & Data Analysis" not abbreviated incorrectly)
|
||||
- [ ] Verify all organisation names match (e.g. "NHS Norfolk & Waveney ICB" consistently)
|
||||
- [ ] Verify all date ranges are correct (start/end dates for each role)
|
||||
- [ ] Verify achievement bullets (`examination` arrays) are accurate — numbers, percentages, and claims match the CV source
|
||||
- [ ] Verify `constellation.ts` role node data (labels, shortLabels, orgColors, years) is consistent with consultations data
|
||||
- [ ] Flag and fix any discrepancies found
|
||||
- [ ] Document any intentional differences (e.g. shortened bullet text for space)
|
||||
|
||||
### US-011: Accessibility hardening
|
||||
|
||||
**Description:** As a visitor using assistive technology, I want the constellation graph to be fully accessible with keyboard navigation and screen reader support.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] The hidden accessibility buttons (already present) have `pointerEvents: 'auto'` so they are actually focusable/clickable (currently set to `'none'`)
|
||||
- [ ] Tab order follows a logical sequence: role nodes in reverse-chronological order, then skill nodes grouped by domain
|
||||
- [ ] Focus ring styling is visible and uses the design system accent colour with sufficient contrast
|
||||
- [ ] Screen reader description (`srDescription`) is updated to reflect the reversed timeline direction
|
||||
- [ ] `aria-label` on the SVG is updated to mention the clinical pathway metaphor
|
||||
- [ ] All interactive states (hover highlight, pin, expand) are achievable via keyboard
|
||||
- [ ] `prefers-reduced-motion` is respected throughout — all animations skip to final state
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Test with keyboard navigation — Tab through all nodes, Enter to activate
|
||||
|
||||
### US-012: Responsive behaviour — mobile and tablet
|
||||
|
||||
**Description:** As a visitor on a smaller screen, I want the constellation graph to display appropriately when the columns stack vertically.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] On mobile/tablet (single-column `.pathway-columns` layout), the graph renders at a reasonable fixed height (360-400px) since it no longer has a column to match
|
||||
- [ ] The graph simplifies slightly on mobile: role labels may use shorter text, skill node default radius decreases slightly
|
||||
- [ ] Touch interactions work correctly: tap to pin a node, tap elsewhere to unpin
|
||||
- [ ] The graph is not cropped or overflowing on narrow viewports (min-width handling)
|
||||
- [ ] The HTML legend from US-007 wraps gracefully on narrow screens
|
||||
- [ ] Typecheck passes
|
||||
- [ ] Verify in browser at mobile viewport widths (375px, 430px)
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
- FR-1: The constellation graph's vertical axis must run top = 2025, bottom = 2017 (reverse chronological)
|
||||
- FR-2: The graph container must dynamically match the height of the adjacent chronology stream column
|
||||
- FR-3: All visual styling must use the project's CSS custom properties and design tokens
|
||||
- FR-4: Role nodes must be rendered as labelled rounded rectangles (pills) anchored to timeline positions
|
||||
- FR-5: Skill nodes must default to low opacity (0.25) with small radius, becoming prominent only on hover/pin
|
||||
- FR-6: Hovering a work experience card must highlight the corresponding graph node and its connections
|
||||
- FR-7: Hovering a graph role node must highlight the corresponding work experience card
|
||||
- FR-8: Connection lines must use curved paths, barely visible at rest, prominent when highlighted
|
||||
- FR-9: The force simulation must keep role nodes firmly at their timeline positions
|
||||
- FR-10: All role data must be verified against the source CV documents
|
||||
- FR-11: Keyboard navigation and screen reader support must be maintained and improved
|
||||
- FR-12: The graph must handle responsive breakpoints (desktop dual-column, mobile/tablet single-column)
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No animation of nodes entering the viewport (scroll-triggered animation)
|
||||
- No zoom/pan interaction on the graph
|
||||
- No tooltip popovers on nodes — interactions open the existing detail panel
|
||||
- No changes to the work experience card design itself (only adding highlight state)
|
||||
- No changes to the `LastConsultationSubsection` design (only adding highlight participation)
|
||||
- No changes to the boot, ECG, or login phases
|
||||
- No addition of new skills or roles beyond what's in the CV
|
||||
|
||||
## Design Considerations
|
||||
|
||||
### Visual Language
|
||||
The graph should feel like a **clinical patient pathway diagram** — the kind of clean, precise visualisation you'd see in a modern healthcare analytics dashboard. Think: straight connector lines with subtle curves, institutional colour palette, monospace data labels, status-indicator dots.
|
||||
|
||||
### Colour Usage
|
||||
- Role nodes: Use `orgColor` from data at low opacity for fill, higher opacity for border and text — creating subtle badges
|
||||
- Skill nodes by domain: Technical `var(--accent)` / Clinical `var(--success)` / Leadership `var(--amber)`
|
||||
- All links and guides: Use `var(--border)` and `var(--border-light)` tokens
|
||||
- Highlighted state: Domain colour at moderate opacity, never garish
|
||||
|
||||
### Typography in SVG
|
||||
- Role labels inside nodes: `var(--font-ui)`, weight 600, 11px
|
||||
- Skill labels below nodes: `var(--font-geist-mono)`, 10px
|
||||
- Year labels: `var(--font-geist-mono)`, 10px, `var(--text-tertiary)`
|
||||
- All SVG text should use the CSS custom property font stacks
|
||||
|
||||
### Spacing
|
||||
- Timeline axis positioned ~100-140px from left edge
|
||||
- Role nodes offset ~80px right of the timeline axis
|
||||
- Generous top/bottom padding (40-50px) for breathing room
|
||||
- Skill nodes distributed in the remaining right-side space
|
||||
|
||||
## Technical Considerations
|
||||
|
||||
- **D3 version**: Use the existing `d3` import (already in `package.json`)
|
||||
- **Skill**: All D3 rendering work should use the `d3-viz` skill for implementation
|
||||
- **ResizeObserver**: For height synchronisation, observe the `.chronology-stream` element. The graph component needs a ref or selector to find it
|
||||
- **Simulation re-init**: When dimensions change, the simulation should restart with new scales but preserve node positions where possible to avoid jarring jumps
|
||||
- **Performance**: The simulation `tick` handler calls `setNodeButtonPositions` which triggers React re-renders. The current diffing logic should be preserved but tested under the new height-changing scenario
|
||||
- **Module-level code**: The current component has module-level `window.matchMedia` calls (`prefersReducedMotion`, `supportsCoarsePointer`) — these are fine for SPA but would break SSR. Not a concern for this project, but worth noting
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- The constellation graph visually matches the quality level of other dashboard components (cards, sidebar, topbar)
|
||||
- Timeline year positions in the graph correspond to the vertical positions of the work experience cards in the adjacent column
|
||||
- A visitor can hover between the timeline and the graph and immediately understand the connection
|
||||
- The graph feels quiet and clean at rest, informative and precise on interaction
|
||||
- No accessibility regressions — keyboard navigation and screen reader support maintained or improved
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Should the "Last Consultation" (most recent role) card participate in the bidirectional highlighting, or only the accordion items in `WorkExperienceSubsection`? **Answer: Yes, it should participate (noted in US-006)**
|
||||
- Should role nodes show the date range (e.g. "2024–Present") below the short label, or keep it minimal? Consider during implementation — add if space permits without clutter
|
||||
- Should skill nodes that appear in multiple roles show any visual indicator of "shared" status (e.g. a small count badge)? Defer to future iteration
|
||||
@@ -0,0 +1,237 @@
|
||||
# PRD: Career Constellation Refinement
|
||||
|
||||
## Introduction
|
||||
|
||||
The career constellation graph needs visual and interaction refinements for better usability on large screens (1440p+), improved skill visibility, a more intuitive hover-based interaction model, and the addition of the full career + education timeline. The current implementation has overly aggressive opacity dimming on skills, too-small text at high resolutions, an unintuitive click-to-pin interaction, a constellation column that takes up too much horizontal space, and is missing early-career roles and education. Additionally, the work experience cards in the left column don't visually tie to their corresponding constellation nodes — they should use matching employer colours.
|
||||
|
||||
## Goals
|
||||
|
||||
- Improve readability of skill nodes and labels on large displays (1440p+)
|
||||
- Reduce the constellation column width to ~35% giving work experience ~65% of horizontal space
|
||||
- Replace click-to-highlight with hover-to-highlight on desktop, tap-to-highlight on mobile
|
||||
- Replace the slide-out detail sidebar on mobile with in-place accordion expansion
|
||||
- Scale all graph elements proportionally based on viewport width so the graph looks good from 1024px to 2560px+
|
||||
- Add the full timeline: Duty Pharmacy Manager, Pre-Reg Pharmacist, UEA MPharm, and Highworth A-Levels
|
||||
- Colour-match work experience cards to their constellation node employer colours
|
||||
- Establish a consistent employer/institution colour scheme across the entire UI
|
||||
|
||||
## User Stories
|
||||
|
||||
### US-001: Increase default skill node visibility
|
||||
**Description:** As a visitor, I want skill nodes to be more visible by default so I can see the full constellation without needing to interact.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Increase default skill circle `fill-opacity` from `0.2` to `0.35`
|
||||
- [ ] Increase active (highlighted) skill circle `fill-opacity` from `0.85` to `0.9`
|
||||
- [ ] Reduce the dimming of unconnected nodes when a role is highlighted — change from `opacity: 0.06` to `opacity: 0.15`
|
||||
- [ ] Skill labels should be partially visible by default at `opacity: 0.5` (currently hidden at `0`), fully visible at `opacity: 1` when highlighted
|
||||
- [ ] Link default `stroke-opacity` increased from `0.08` to `0.15` so the connection web is subtly visible
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: skills should be recognisable at a glance without hovering
|
||||
|
||||
### US-002: Viewport-proportional scaling for large screens
|
||||
**Description:** As a visitor on a 1440p or larger display, I want the constellation elements to scale up so they aren't tiny relative to the screen.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Compute a scale factor based on viewport width: `scaleFactor = Math.max(1, Math.min(1.6, viewportWidth / 1440))` (1.0x at 1440px, up to 1.6x at 2560px+)
|
||||
- [ ] Apply scale factor to: `SKILL_RADIUS_DEFAULT` (7 -> up to ~11), `SKILL_RADIUS_ACTIVE` (11 -> up to ~18), `ROLE_WIDTH` (104 -> up to ~166), `ROLE_HEIGHT` (32 -> up to ~51)
|
||||
- [ ] Base skill label `font-size` raised to 11px minimum (from 10px), then scales proportionally (up to ~18px at max scale)
|
||||
- [ ] Base role label `font-size` raised to 12px minimum (from 11px), then scales proportionally (up to ~19px at max scale)
|
||||
- [ ] Base year label `font-size` raised to 11px minimum (from 10px), then scales proportionally
|
||||
- [ ] Scale padding, gaps, and force simulation parameters (charge, link distance, collision radius) proportionally
|
||||
- [ ] Mobile breakpoint (`< 640px`) is unaffected — scaling only applies at `>= 1024px`
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser at 1440px and 2560px widths: elements should be clearly legible and well-proportioned
|
||||
|
||||
### US-003: Reduce constellation column width
|
||||
**Description:** As a visitor, I want more horizontal space for work experience content so the chronology stream is easier to read.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Change `.pathway-columns` desktop grid from `minmax(0, 1.15fr) minmax(0, 1.5fr)` to `minmax(0, 1.85fr) minmax(0, 1fr)` (approximately 65/35 split)
|
||||
- [ ] The constellation graph adapts to the narrower container without clipping or overflow
|
||||
- [ ] Force simulation parameters still produce a clean, non-overlapping layout in the narrower space
|
||||
- [ ] The timeline axis, role pills, and skill nodes remain fully visible
|
||||
- [ ] Sticky positioning of the graph column still works correctly
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: work experience column is visibly wider, graph is compact but readable
|
||||
|
||||
### US-004: Hover-to-highlight interaction on desktop
|
||||
**Description:** As a desktop visitor, I want hovering over a role to highlight its connected skills, and hovering away to reset — without needing to click to toggle.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] On desktop (fine pointer): hovering a role node highlights connected skills, shows their labels, and colorises links — same visual effect as current click behaviour
|
||||
- [ ] Moving the mouse away from a role resets to the default state (all nodes visible at baseline opacity per US-001)
|
||||
- [ ] Remove the click-to-pin toggle behaviour on desktop — clicking a role node should only trigger the detail action (e.g. expand accordion), not pin the highlight
|
||||
- [ ] Hovering a skill node still highlights that skill and its connected roles
|
||||
- [ ] The `pinnedNodeId` state is removed or only used for touch/keyboard
|
||||
- [ ] Keyboard navigation (Tab + Enter) still works: focus highlights the node, Enter opens details
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: hover on/off roles cycles highlight cleanly with no "stuck" states
|
||||
|
||||
### US-005: Tap-to-highlight with accordion expansion on mobile
|
||||
**Description:** As a mobile visitor, I want tapping a role to highlight its skills and expand role details in-place, rather than opening a side panel.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] On touch devices (coarse pointer): first tap on a role highlights its connected skills (same visual as desktop hover)
|
||||
- [ ] First tap also expands an accordion panel below the constellation graph showing the role's condensed details: title, organisation, date range, and top 3 key achievements
|
||||
- [ ] The accordion includes a "Show more" link/button to reveal the full set of achievements and details
|
||||
- [ ] Tapping a different role switches the highlight and accordion content (auto-collapses "show more" back to summary)
|
||||
- [ ] Tapping the same role again (or tapping elsewhere) collapses the accordion and resets highlights
|
||||
- [ ] The accordion uses the same expand/collapse animation pattern as other tiles (height-only, 200ms ease-out)
|
||||
- [ ] No slide-out sidebar panel on mobile — detail content lives in the accordion below the graph
|
||||
- [ ] Tapping a skill node highlights it and shows a brief skill tooltip or label, does not open a panel
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser at mobile viewport: tap role -> accordion expands, tap again -> collapses
|
||||
|
||||
### US-006: Add Duty Pharmacy Manager role (Aug 2016 – Oct 2017)
|
||||
**Description:** As a visitor, I want to see the Duty Pharmacy Manager role in the constellation so the full career timeline is represented.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Add role node to `constellation.ts`: id `duty-pharmacy-manager-2016`, label "Duty Pharmacy Manager", shortLabel "Duty Pharm Mgr", organisation "Tesco PLC", startYear 2016, endYear 2017, orgColor `#E53935` (Tesco red)
|
||||
- [ ] Add role-skill mapping with these skill connections: `medicines-optimisation` (0.8), `data-analysis` (0.5), `excel` (0.6), `change-management` (0.5), `stakeholder-engagement` (0.4)
|
||||
- [ ] Add corresponding links to `constellationLinks` array
|
||||
- [ ] Add consultation entry to `consultations.ts` with title "Duty Pharmacy Manager", org "Tesco PLC", dates Aug 2016 – Oct 2017, location "Great Yarmouth, Norfolk", and key achievements from CV: service development leadership (NMS/asthma referrals), national clinical innovation (quality payments solution), clinical foundation building
|
||||
- [ ] The role appears on the timeline in correct chronological position (between Pre-Reg and Pharmacy Manager)
|
||||
- [ ] Screen reader description updates to include the new role
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: new role node appears on timeline, hover highlights correct skills
|
||||
|
||||
### US-007: Add Pre-Registration Pharmacist role (Jul 2015 – Jul 2016)
|
||||
**Description:** As a visitor, I want to see the Pre-Registration Pharmacist role in the constellation as the earliest professional entry.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Add role node to `constellation.ts`: id `pre-reg-pharmacist-2015`, label "Pre-Registration Pharmacist", shortLabel "Pre-Reg", organisation "Paydens Pharmacy", startYear 2015, endYear 2016, orgColor `#66BB6A` (Paydens light green)
|
||||
- [ ] Add role-skill mapping with these skill connections: `medicines-optimisation` (0.7), `change-management` (0.4), `stakeholder-engagement` (0.3)
|
||||
- [ ] Add corresponding links to `constellationLinks` array
|
||||
- [ ] Add consultation entry to `consultations.ts` with title "Pre-Registration Pharmacist", org "Paydens Pharmacy", dates Jul 2015 – Jul 2016, location "Tunbridge Wells & Ashford, Kent", and key achievements from CV: clinical service expansion (PGDs for NRT, EHC, chlamydia), NMS audit improvement (under 10% to 50-60%), palliative care screening, operational learning
|
||||
- [ ] The role appears on the timeline below Duty Pharmacy Manager
|
||||
- [ ] Screen reader description updates to include the new role
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: new role node appears on timeline, hover highlights correct skills
|
||||
|
||||
### US-008: Add University of East Anglia education node (2011 – 2015)
|
||||
**Description:** As a visitor, I want to see the MPharm degree on the timeline as the foundation of the career.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Add node to `constellation.ts`: id `uea-mpharm-2011`, type `role` (treated the same as work roles on the timeline), label "MPharm (Hons) 2:1", shortLabel "MPharm", organisation "University of East Anglia", startYear 2011, endYear 2015, orgColor `#7B2D8E` (UEA purple — distinct education colour)
|
||||
- [ ] Add role-skill mapping with foundational skill connections: `medicines-optimisation` (0.5), `data-analysis` (0.3)
|
||||
- [ ] Add corresponding links to `constellationLinks` array
|
||||
- [ ] Add consultation entry to `consultations.ts` with title "MPharm (Hons) 2:1", org "University of East Anglia", dates 2011 – 2015, location "Norwich", and key achievements: independent research project on drug delivery and cocrystals (75.1%, Distinction), 4th year OSCE 80%, President of UEA Pharmacy Society
|
||||
- [ ] The node appears on the timeline below Pre-Reg Pharmacist
|
||||
- [ ] Screen reader description updates to include the education entry
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: education node appears on timeline with distinct purple colour
|
||||
|
||||
### US-009: Add Highworth Grammar School education node (2009 – 2011)
|
||||
**Description:** As a visitor, I want to see A-Levels on the timeline as the earliest entry, showing the complete timeline from 2009 to present.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] Add node to `constellation.ts`: id `highworth-alevels-2009`, type `role`, label "A-Levels: Maths A*, Chem B", shortLabel "A-Levels", organisation "Highworth Grammar School", startYear 2009, endYear 2011, orgColor `#9C27B0` (lighter purple — education colour family, distinct shade from UEA)
|
||||
- [ ] Minimal skill connections: `data-analysis` (0.2) — reflects strong mathematics foundation
|
||||
- [ ] Add corresponding link to `constellationLinks` array
|
||||
- [ ] Add consultation entry to `consultations.ts` with title "A-Levels", org "Highworth Grammar School", dates 2009 – 2011, location "Ashford, Kent", and results: Mathematics A*, Chemistry B, Politics C
|
||||
- [ ] The node appears at the very bottom of the timeline as the earliest entry
|
||||
- [ ] Screen reader description updates to include the education entry
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: A-Levels node appears at bottom of timeline
|
||||
|
||||
### US-010: Unify employer/institution colour scheme
|
||||
**Description:** As a visitor, I want each employer/institution to have a distinct, consistent colour so I can visually group entries by organisation.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] NHS Norfolk & Waveney ICB roles use NHS blue `#005EB8` (already correct — Deputy Head, Interim Head, High-Cost Drugs)
|
||||
- [ ] Tesco PLC roles use Tesco red `#E53935` — update existing Pharmacy Manager node `orgColor` from `#00897B` to `#E53935` in both `constellation.ts` and `consultations.ts`
|
||||
- [ ] Paydens Pharmacy uses light green `#66BB6A` for Pre-Registration Pharmacist
|
||||
- [ ] University of East Anglia uses UEA purple `#7B2D8E`
|
||||
- [ ] Highworth Grammar School uses lighter purple `#9C27B0`
|
||||
- [ ] The domain legend below the graph is unchanged (Technical/Clinical/Leadership) — institution colours only appear on role/education pill nodes
|
||||
- [ ] All role pills remain legible with appropriate text contrast against the coloured fill/stroke
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: five distinct institution colour groups are immediately recognisable
|
||||
|
||||
### US-011: Colour-match work experience cards to constellation nodes
|
||||
**Description:** As a visitor, I want the work experience cards in the left column to use matching colours from their constellation nodes, creating a visual link between the card list and the graph.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] The dot indicator on each work experience card uses the consultation's `orgColor` instead of hardcoded `#0D6E6E`
|
||||
- [ ] The expanded card's left border uses the consultation's `orgColor` instead of `var(--accent)`
|
||||
- [ ] The bullet point dots in the expanded detail use the consultation's `orgColor` (at 0.5 opacity, matching current pattern) instead of `var(--accent)`
|
||||
- [ ] The coded entry tags use the consultation's `orgColor` for text colour and a lightened variant for background/border (same pattern as current teal, but using the org colour)
|
||||
- [ ] The "View full record" link uses the consultation's `orgColor` instead of `var(--accent)`
|
||||
- [ ] The highlight background when a card is highlighted from the graph uses a tinted version of `orgColor` at low opacity (e.g. `rgba(r,g,b,0.03)`) instead of hardcoded `rgba(10,128,128,0.03)`
|
||||
- [ ] The hover/expanded border colour uses a border variant of the `orgColor` instead of `var(--accent-border)`
|
||||
- [ ] The CardHeader dot for "WORK EXPERIENCE" section title remains teal (it's the section accent, not per-card)
|
||||
- [ ] All colour changes maintain WCAG AA contrast ratios for text legibility
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser: NHS roles show blue-tinted cards, Tesco roles show red-tinted cards, Paydens shows green, education shows purple
|
||||
|
||||
### US-012: Re-tune force simulation for 8 timeline entries
|
||||
**Description:** As a developer, I need the force simulation to produce a clean layout with 8 entries (6 roles + 2 education) spanning 2009–2025, in the narrower column.
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- [ ] The y-scale range accommodates 8 entries (2009–2025) without excessive cramping
|
||||
- [ ] Timeline year labels show the full range from 2009 to 2025
|
||||
- [ ] Role/education nodes don't overlap each other on the timeline
|
||||
- [ ] Skill nodes distribute cleanly in the available space to the right of role pills
|
||||
- [ ] Adjust charge, collision, and link forces if needed to prevent overlapping with the additional nodes and narrower space
|
||||
- [ ] Links don't create an unreadable tangle — connections remain traceable
|
||||
- [ ] Education nodes at the bottom (2009–2015) have fewer skill connections so the lower portion isn't cluttered
|
||||
- [ ] The graph still works at mobile viewport widths with 8 entries
|
||||
- [ ] Typecheck passes (`npm run typecheck`)
|
||||
- [ ] Verify in browser at both desktop and mobile: all 8 entries visible, no overlaps, clean layout
|
||||
|
||||
## Functional Requirements
|
||||
|
||||
- FR-1: Skill node default opacity increased to 0.35 with labels at 0.5 opacity
|
||||
- FR-2: All graph element sizes (nodes, text, padding) scale proportionally with viewport width from 1024px to 2560px+
|
||||
- FR-3: Grid layout changes to ~65/35 split favouring the work experience column
|
||||
- FR-4: Desktop interaction model is hover-only (no click-to-pin for highlighting)
|
||||
- FR-5: Mobile interaction model is tap-to-highlight with accordion expansion for details (no sidebar panel)
|
||||
- FR-6: Four new timeline entries added: Duty Pharmacy Manager, Pre-Reg Pharmacist, UEA MPharm, Highworth A-Levels
|
||||
- FR-7: Force simulation produces a clean layout with 8 entries in a narrower column
|
||||
- FR-8: All accessibility features (keyboard navigation, screen reader descriptions, focus management) continue to work with 8 entries
|
||||
- FR-9: Institution colour scheme: NHS blue `#005EB8`, Tesco red `#E53935`, Paydens green `#66BB6A`, UEA purple `#7B2D8E`, Highworth purple `#9C27B0`
|
||||
- FR-10: Minimum font size of 11px for all text in the constellation graph on desktop
|
||||
- FR-11: Work experience cards use matching `orgColor` for dot, border, bullets, coded entries, and links
|
||||
- FR-12: Timeline spans 2009–2025 showing the complete career + education journey
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- No changes to the boot sequence, ECG animation, or login screen
|
||||
- No new skill nodes — only new role/education nodes and links to existing skills
|
||||
- No changes to the domain legend below the graph (Technical/Clinical/Leadership categories)
|
||||
- No changes to the mobile stacked layout breakpoint (stays at 1024px)
|
||||
- No changes to skill detail panel or RepeatMedicationsSubsection
|
||||
|
||||
## Design Considerations
|
||||
|
||||
- The constellation is getting denser with 8 entries. The narrower column means less horizontal space for skill distribution. The force simulation tuning (US-012) is critical to prevent visual clutter.
|
||||
- Education entries at the bottom of the timeline (2009–2015) have deliberately few skill connections (2 for UEA, 1 for Highworth) to keep the lower portion clean and visually suggest the "before specialisation" phase.
|
||||
- The proportional scaling should feel natural — not just "zoomed in" but properly scaled with appropriate spacing.
|
||||
- The accordion on mobile (US-005) should match the existing tile expansion pattern — summary first (top 3 achievements), "show more" for full detail.
|
||||
- **Institution colours**: NHS blue, Tesco red, Paydens green, and purple shades for education. The purple family groups both education entries while using different shades to distinguish them. Role pill text uses the institution colour for both the label and the border/fill tint.
|
||||
- **Card colour matching**: The work experience cards should feel like they "belong to" their constellation node. The colour theming should be subtle — tinted backgrounds, coloured dots and borders — not overwhelming. Think: the current teal treatment but swapped per employer.
|
||||
|
||||
## Technical Considerations
|
||||
|
||||
- The scale factor computation should happen once per resize, not per render tick
|
||||
- Force simulation parameters (charge, link distance, collision radius) all need to scale with the viewport factor
|
||||
- The existing `chronologyRef` + `ResizeObserver` pattern for height matching should continue to work
|
||||
- The accordion component for mobile detail expansion can reuse existing expand/collapse patterns from `WorkExperienceSubsection`
|
||||
- Adding 4 entries increases total nodes from 25 to 29 and links from 46 to ~57
|
||||
- The `Consultation` type in `types/pmr.ts` may need updating if education entries need different fields (e.g. no `codedEntries`, different `examination` semantics) — or education entries can use the same shape with adapted content
|
||||
- For the card colour matching (US-011), a utility function to derive light/border variants from a hex colour would avoid hardcoding multiple CSS variable overrides per employer. Something like `hexToRgba(color, opacity)` for backgrounds and borders
|
||||
- The `orgColor` already exists on the `Consultation` type — it just isn't used in `WorkExperienceSubsection.tsx` yet
|
||||
|
||||
## Success Metrics
|
||||
|
||||
- All skill labels legible at 1440p without squinting
|
||||
- Hover-to-highlight feels instant and responsive (no stuck states)
|
||||
- Work experience column has noticeably more reading space
|
||||
- The full timeline (2009–present) is represented with education and career
|
||||
- Employer/institution colour coding is immediately recognisable across cards and graph
|
||||
- No visual overlaps or clipping at any supported viewport width
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None — all decisions resolved.
|
||||
Reference in New Issue
Block a user