user-journey
User journey map with SVG emotion curve, phase grid, and cross-references to personas and stories.
Overview
A web component that renders a complete user journey map with two visual layers: an SVG emotion curve that plots the user's emotional state across phases, and a detail grid showing actions, thoughts, touchpoints, pain points, and opportunities for each phase. Supports JSON loading via src attribute or programmatic data via the .phases property.
<user-journey title="API Platform Evaluation" persona="Sarah Chen" persona-id="persona-sarah-chen" summary="How a developer discovers, evaluates, and adopts our platform" story-ids="PROJ-142,PROJ-156" src="/data/journey-api-evaluation.json"></user-journey>
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
title |
string | "User Journey" |
Journey map heading |
persona |
string | — | Name of the persona taking this journey |
persona-id |
string | — | ID of a <user-persona> element to link to (renders as an anchor) |
summary |
string | — | Brief description shown below the title |
story-ids |
string (comma-separated) | — | Related story IDs shown as chip links in the header (e.g., "PROJ-142,PROJ-156") |
src |
string (URL) | — | Path to a JSON file containing the full journey data including phases |
compact |
boolean | — | Reduces padding, font sizes, curve height, and grid cell widths |
Slot-Based Metadata
Scalar metadata (title, persona, summary) can also be provided as named slots instead of attributes. This is useful for server-rendered pages where inline content is preferred over attributes. Attributes take priority when both exist.
<user-journey persona-id="persona-sarah-chen" src="/data/journey.json"> <span slot="title">API Platform Evaluation</span> <span slot="persona">Sarah Chen</span> <span slot="summary">How a developer discovers, evaluates, and adopts our platform</span></user-journey>
Data Model
Phase data can be loaded from a JSON file via the src attribute or set programmatically via the .phases property. The JSON schema supports top-level metadata plus an array of phase objects.
{ "title": "API Platform Evaluation", "persona": "Sarah Chen", "personaId": "persona-sarah-chen", "summary": "How a developer discovers, evaluates, and adopts our platform", "phases": [ { "name": "Awareness", "emotion": "curious", "storyIds": ["PROJ-142"], "actions": ["Searches for solutions", "Reads comparison articles"], "thoughts": ["There must be a better way"], "touchpoints": ["Google", "Hacker News"], "painPoints": ["Too many options to compare"], "opportunities": ["Clear, developer-focused landing page"] }, { "name": "Evaluation", "emotion": "hopeful", "storyIds": ["PROJ-156"], "actions": ["Reads documentation", "Tries quick-start guide"], "thoughts": ["This looks promising"], "touchpoints": ["Docs site", "GitHub"], "painPoints": ["Missing advanced examples"], "opportunities": ["Interactive code playground"] } ]}
Each phase object supports these fields:
| Field | Type | Description |
|---|---|---|
name |
string | Phase heading (e.g., "Awareness", "Evaluation") |
emotion |
string | One of the 9 emotion values (see Emotion Scale below) |
storyIds |
string[] | Related user story IDs shown as chips in the phase header |
actions |
string[] | What the user does during this phase |
thoughts |
string[] | What the user thinks or feels |
touchpoints |
string[] | Channels and interfaces encountered |
painPoints |
string[] | Friction points and problems. Cells tinted red. |
opportunities |
string[] | Improvement ideas and design opportunities. Cells tinted green. |
Emotion Scale
The emotion field in each phase drives the Y-position of the SVG curve dot and its color. Nine values are supported, ranging from positive to negative.
| Value | Emoji | Score | Color |
|---|---|---|---|
delighted |
😄 | 0.95 | #16a34a |
satisfied |
😊 | 0.80 | #22c55e |
hopeful |
🙂 | 0.68 | #84cc16 |
curious |
🤔 | 0.55 | #eab308 |
neutral |
😐 | 0.50 | #94a3b8 |
uncertain |
😕 | 0.40 | #f97316 |
confused |
😵 | 0.30 | #fb923c |
frustrated |
😤 | 0.18 | #ef4444 |
angry |
😠 | 0.05 | #dc2626 |
The curve is rendered as an SVG with Bezier curves connecting each phase dot. The area under the curve uses a gradient fill. Three horizontal zones (green/yellow/red) provide visual context for positive, neutral, and negative emotional ranges.
Compact Variant
Add the compact attribute for tighter layouts with reduced padding, smaller fonts, and a shorter emotion curve. Useful for dashboards or pages with multiple journey maps.
<user-journey title="Support Incident Journey" persona="Sarah Chen" summary="From first alert to resolved incident" compact></user-journey>
Programmatic Usage
For dynamic applications, set the .phases property directly instead of using a JSON file. The component re-renders automatically when phases are assigned.
const journey = document.querySelector('user-journey'); journey.phases = [ { name: 'Discovery', emotion: 'curious', actions: ['Browses landing page'], thoughts: ['Looks interesting'], touchpoints: ['Website'], painPoints: [], opportunities: ['Add video walkthrough'] }, { name: 'Onboarding', emotion: 'hopeful', actions: ['Completes setup wizard'], thoughts: ['This is straightforward'], touchpoints: ['App', 'Email'], painPoints: ['Too many steps'], opportunities: ['Reduce to 3 steps'] }, { name: 'First Success', emotion: 'delighted', actions: ['Completes first task'], thoughts: ['This actually works!'], touchpoints: ['App'], painPoints: [], opportunities: ['Celebrate with confetti'] }];
Cross-References
The <user-journey> component is designed to link to related <user-persona> and <user-story> elements on the same page:
- Persona linking — set
persona-idto theidof a <user-persona> element. The persona name renders as an anchor that scrolls to that element. - Story linking — set
story-idsto a comma-separated list of story IDs. Each ID renders as a chip link. Per-phasestoryIdsin the JSON data also render as chips in the phase header row.
<user-persona id="persona-sarah-chen" name="Sarah Chen" role="Product Manager"> <p slot="bio">Experienced PM focused on developer tools.</p></user-persona> <user-story story-id="PROJ-142" persona="Sarah Chen" action="view project timelines in one dashboard" priority="high" status="in-progress" points="5"></user-story> <user-journey title="Platform Evaluation" persona="Sarah Chen" persona-id="persona-sarah-chen" story-ids="PROJ-142" src="/data/journey.json"></user-journey>
CSS Custom Properties
| Variable | Default | Description |
|---|---|---|
--user-journey-bg |
#f8f9fa / #121212 |
Background for grid row labels and curve area |
--user-journey-card |
#ffffff / #1e1e1e |
Main card background |
--user-journey-border |
#e0e0e0 / #333333 |
Border color for card, grid lines, and curve vertical guides |
--user-journey-muted |
#666666 / #888888 |
Muted text color for labels, summary, and empty cells |
--user-journey-text |
#1a1a1a / #e8e8e8 |
Primary text color |
--user-journey-curve-stroke |
#6366f1 |
Stroke color for the emotion curve line |
--user-journey-radius |
12px |
Outer card border radius |
Events
| Event | Detail | When |
|---|---|---|
journey-ready |
{ title, persona, phaseCount } |
Fires after the component finishes rendering (including after JSON load) |
Accessibility
- The SVG emotion curve uses
aria-hidden="true"— it is decorative and the phase data is fully available in the grid table below - The phase grid renders as a semantic
<table>witharia-labeldescribing the journey title and breakdown - Row and column headers (
<th>) provide screen reader context for every data cell - The first column (row labels) and corner cell are
position: stickyso they remain visible when the grid scrolls horizontally - Pain point and opportunity rows have tinted backgrounds for sighted users, plus the row label text for screen readers
- Uses
container-type: inline-sizefor responsive adjustments without media queries - Print styles remove sticky positioning for correct print layout
Related
<user-persona>— Persona cards linked viapersona-id<user-story>— Story cards linked viastory-ids<empathy-map>— Empathy maps using the same emotion vocabulary<impact-effort>— Prioritization matrix for triaging stories<story-map>— Story mapping linked viadata-journey-phase- UX Planning Pack — loads all six UX components together