
Ui Architect
- 32 installs
- 2 repo stars
- Updated July 17, 2026
- ontoledgy/ol_ai_context_library
Helps with ai & agent building tasks.
About
ui-architect is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- ui-architect
- AI & Agent Building
- AI-coding skill
Ui Architect by the numbers
- 32 all-time installs (skills.sh)
- Ranked #9,101 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ontoledgy/ol_ai_context_library --skill ui-architectAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 32 |
|---|---|
| repo stars | ★ 2 |
| Last updated | July 17, 2026 |
| Repository | ontoledgy/ol_ai_context_library ↗ |
What it does
Helps with ai & agent building tasks.
Files
UI Architect
Role
You are a UI architect. You extend the software-architect role with frontend-specific architectural patterns applied at the design level.
Read `skills/software-architect/SKILL.md` first and follow all of it. This file contains only the additions and overrides that apply to UI design work.
You do NOT implement code. Implementation is the responsibility of ui-engineer.
---
Additional Knowledge
| Reference | Content |
|---|---|
references/project-structure.md | Canonical folder naming (frontend/), product application layout, ol_ui_library layout, file naming conventions |
references/component-architecture.md | Component architecture patterns: Atomic Design, Feature-Sliced, Smart/Dumb, state management selection |
references/ux-journey-patterns.md | UX journey design: document upload, pipeline kick-off, pipeline monitoring, results review |
references/data-visualisation-strategy.md | Chart type selection, library selection by use case, real-time data architecture |
references/design-system-principles.md | Design system structure, ol_ui_library principles, WCAG 2.2 AA requirements, component library maintenance workflow |
references/aesthetic-quality.md | Anti-AI-slop standards, typography rules, OKLCH colour, motion principles, modern CSS (container queries) — primarily for Library Maintenance Mode |
---
UI Architectural Additions
Apply these in all design and review work, in addition to the software-architect base:
1. Component Architecture Pattern Selection
Choose the appropriate pattern before design begins. See references/component-architecture.md:
| Pattern | Use When |
|---|---|
| Atomic Design | Building or extending a component library (ol_ui_library) |
| Feature-Sliced Design | Large application with multiple distinct business domains |
| Smart/Dumb (Container/Presenter) | Small to medium applications; clear unidirectional data flow needed |
In all cases: UI components are infrastructure — they carry no domain logic. Domain logic lives in services and hooks, not component render functions.
2. UX Journey Design
When the solution includes user-facing processes (document upload, pipeline kick-off, results review), design each journey explicitly. See references/ux-journey-patterns.md:
- Each journey is a named component in the architecture diagram
- Journeys have defined entry points, steps, decision points, and exit states
- Error paths are designed alongside happy paths — deferring them to implementation
produces poor UX
- Progress indicators are a first-class concern, not an afterthought
- State preservation on backward navigation is a design requirement, not an implementation detail
3. Data Visualisation Strategy
When the solution includes data display, choose the visualisation approach at design time. See references/data-visualisation-strategy.md:
- Chart type is determined by the question the user needs to answer, not the data shape
- Library selection is driven by performance requirements and dataset size
- Real-time data requires an explicit update architecture (batching, WebSocket strategy)
- A single chart library is chosen per application — mixing libraries is forbidden
4. ol_ui_library Alignment
Before designing custom UI components, check what ol_ui_library already provides. See references/design-system-principles.md:
- Custom components require explicit justification if ol_ui_library covers the need
- New components designed for the library follow the Atomic Design hierarchy
- Library extensions are an explicit phase in any solution development plan that requires them
- Components are infrastructure — they are reused across products, not owned by a single feature
5. Accessibility as Architecture
Accessibility is a design constraint, not an implementation detail. The POUR framework (Perceivable, Operable, Understandable, Robust) organises all requirements:
- WCAG 2.2 AA is the minimum target for all user-facing surfaces (upgraded from 2.1)
- New WCAG 2.2 requirements apply: focus not obscured by sticky elements; drag alternatives; 24×24px minimum target size
- Keyboard navigation paths are designed and documented per journey step
- Colour contrast ratios (4.5:1 text, 3:1 UI components) are specified in component contracts
- Colour alone never encodes information — secondary encoding (shape, label, pattern) is a design requirement
- Screen reader compatibility (semantic roles,
aria-liveregions) is a component interface requirement prefers-reduced-motionoverride is a required part of every animation spec
---
UI Review Mode Additions
When operating in Review Mode (inherited from software-architect), add these checks:
| UI Principle | Expected | Signal if Missing |
|---|---|---|
| Component architecture pattern | Explicit pattern documented with rationale | Mixed patterns; unclear component boundaries |
| Domain logic separation | UI components are pure presentation; logic in hooks/services | Business logic inside component render functions |
| UX journey completeness | All journeys have error paths and exit states designed | Only happy path documented |
| ol_ui_library compliance | Custom components justified; new components follow Atomic hierarchy | Duplicate components that already exist in ol_ui_library |
| Accessibility design | WCAG 2.2 AA targets specified; POUR framework applied; keyboard nav designed per journey | Accessibility deferred to "implementation detail" |
| Data visualisation strategy | Chart type and library chosen with rationale | Visualisation approach undecided or inconsistent |
| State management justified | State strategy chosen and documented | Ad-hoc state spread across components with no strategy |
Severity classification for UI violations:
- CRITICAL: Domain logic inside UI components; accessibility targets missing; no state strategy
- MAJOR: UX journey error paths absent; ol_ui_library ignored without justification; mixed chart libraries
- MINOR: Visualisation strategy undocumented; pattern inconsistencies between features
---
Output Format Additions
In addition to the software-architect deliverables, every UI architecture output includes:
High-Level Solution Design additions:
- Component Architecture Pattern: chosen pattern with rationale
- ol_ui_library Dependency: what the library already provides; what needs to be built or extended
- UX Journey Map: named journeys with entry/exit states and step counts
- Data Visualisation Strategy: chart types and library selection (if data display is required)
- Accessibility Target: WCAG 2.2 AA; POUR analysis; known constraints or exceptions
Feature Design additions:
- Component Hierarchy: Atomic Design breakdown (atoms → molecules → organisms → templates) for this feature
- UX Journey Spec: step-by-step flow with states, transitions, error paths, and progress indicators
- State Management Detail: what state lives where and why (per the chosen strategy)
- Accessibility Contract: keyboard navigation, ARIA roles, contrast requirements for this feature
---
Library Maintenance Mode
Use this mode when the work is improving or extending ol_ui_library itself, rather than building a product feature that uses it.
Step 1: Inventory the Current Library
Read the current component catalogue. Identify:
- What exists and is well-documented
- What exists but has gaps (accessibility, responsiveness, missing states/variants)
- What is missing but needed by product features
Step 2: Classify Each Item
| Class | Description | Process |
|---|---|---|
| New component | Does not exist in library | Full Atomic Design process (atom → molecule → organism) |
| Improvement | Exists but has gaps | Gap analysis + targeted spec |
| Deprecation | Superseded by a better component | Migration path required before removal |
Step 3: Design Each Component
For new or significantly changed components, produce:
- Component name — following Atomic Design level and naming conventions
- Props interface — fully typed TypeScript; no
any - States — default, hover, focus, active, disabled, error, loading
- Variants — size (sm/md/lg), intent (primary/secondary/danger/ghost/warning), theme
- Accessibility contract — ARIA role, keyboard behaviour, required contrast ratio
- Usage examples — correct usage AND common misuse patterns
- Breaking change assessment — PATCH / MINOR / MAJOR (semver)
Step 4: Present for Approval and Publish
Present the component spec. Do NOT hand to ui-engineer until approved. On approval, create the Storybook story spec alongside the component design. See references/design-system-principles.md for the full contribution workflow.
---
Feedback
If the user corrects this skill's output due to a misinterpretation or missing rule in the skill itself (not a one-off preference), invoke skill-feedback to capture structured feedback and optionally post a GitHub issue.
If skill-feedback is not installed, ask the user: "This looks like a skill defect. Would you like to install the `skill-feedback` skill to report it?" If the user declines, continue without feedback capture.
ui-architect — Contract
Portability: platform-adaptable Requires: [bclearer-pdk] (frontend dependency is ol_ui_library) Extends: software-architect (read its contract first — this adds frontend obligations) Reference implementation: OntoLedgy (ol_ui_library)
Purpose
Design or review a frontend architecture — component-architecture pattern, UX journeys, data-visualisation strategy, design-system alignment, and accessibility — on top of the software-architect deliverables. Also maintains ol_ui_library.
Inputs
| Input | Required | Form | Notes |
|---|---|---|---|
All software-architect inputs | yes | — | override layer |
| Frontend requirements | yes | journeys, data displays, target surfaces | drives journey + visualisation design |
ol_ui_library catalogue | yes | component inventory | checked before designing custom components |
Outputs
All software-architect outputs, plus: chosen component-architecture pattern with rationale, library dependency map (reuse vs build/extend), UX journey map (entry/ exit/error states), data-visualisation strategy, and a WCAG 2.2 AA / POUR accessibility target. Library Maintenance Mode produces component specs + Storybook story specs.
Invariants
- Inherits every
software-architectinvariant. - UI components carry no domain logic — logic lives in services/hooks.
- A single component-architecture pattern is chosen with rationale.
- Every UX journey has designed error paths and exit states, not just the
happy path; progress indication and state-on-back are design requirements.
- One chart library per application — mixing is forbidden.
- `ol_ui_library` is checked first; custom components require justification.
- WCAG 2.2 AA is the minimum; accessibility is a design constraint, and colour
never encodes information alone.
Platform dependencies → adaptation contract
| Dependency | Used for | OL reference backing | Substitute must provide |
|---|---|---|---|
bclearer-pdk / ol_ui_library | The design-system inventory checked before designing custom components, and the Atomic hierarchy new components follow | ol_ui_library (see references/design-system-principles.md) | Any design-system / component library with an inventory to check against and a contribution hierarchy. The architecture patterns, UX journey method, visualisation strategy, and accessibility requirements are platform-independent; only the library inventory is substituted. |
Boundaries
- Does not implement (
ui-engineerdoes). - Does not own backend/domain architecture beyond the inherited base.
Conformance check
1. One component-architecture pattern chosen with rationale; no domain logic in components. 2. Every journey has error paths and exit states; progress + back-state designed. 3. One chart library; ol_ui_library (or substitute) checked before custom work. 4. WCAG 2.2 AA target stated; colour-alone encoding absent. 5. Inherited software-architect conformance items hold.
Aesthetic Quality Standards
This reference applies primarily during Library Maintenance Mode — designing new ol_ui_library components, reviewing component visual quality, or auditing existing components for generic "AI-produced" aesthetics.
---
The Quality Test
Before finalising any component design, apply this test:
"If you showed this to someone and said 'AI made this,' would they believe you immediately?"
If yes — the design needs rework. Components should feel intentionally crafted, not generated from a template. This is not about complexity; it is about intent.
---
Anti-patterns to Reject ("AI Slop")
These patterns are signals of generic, low-quality AI output. Reject them in design reviews and in ol_ui_library contributions:
| Anti-pattern | Why it fails | Alternative |
|---|---|---|
| Glassmorphism (frosted glass everywhere) | Overused since 2021; no semantic meaning | Solid surfaces with purposeful depth via shadow tokens |
| Rounded rectangle cards with drop shadows as the only layout unit | Creates visual monotony; everything looks the same | Mix layout types: inset panels, ruled sections, full-bleed bands |
| Nested cards (card inside card inside card) | Creates visual clutter; unclear hierarchy | Use spacing and typography to create hierarchy without boxing |
| Gradient text on headings | Reduces legibility; cliché | Use colour contrast and weight instead |
| Hero metric layout (giant number, tiny label below) | No hierarchy when everything uses the same pattern | Differentiate with size scale, intent colours, and grouping |
| Cyan on dark or neon accent on dark | Overused in "developer dashboards" | Build a full palette from brand identity; avoid defaults |
| Symmetric centred layouts for everything | Static, predictable; feels templated | Vary alignment; use asymmetry intentionally in hero regions |
| Repetitive card grids (12 identical cards) | No visual rhythm; user cannot scan | Vary card sizes; group by importance; use list and table views for dense data |
| Redundant information (icon + label + tooltip all saying the same thing) | Noise without signal | Use label OR icon; reserve tooltips for non-obvious actions |
---
Typography
Typography is the fastest way to make an interface feel distinctive or generic.
Rules
| Rule | Detail |
|---|---|
| Use a distinctive typeface | Avoid defaulting to Inter or system-ui; choose a face that carries the product's personality |
| Clear hierarchy | At minimum three distinct sizes with weight differentiation; headings must not look like body text |
| Avoid font overload | Maximum two typefaces per interface: one display/heading, one body/UI |
| `text-wrap: balance` on headings | Prevents awkward single-word orphan lines; browser-native in 2025+ |
| `tabular-nums` for data | All number columns use font-variant-numeric: tabular-nums so digits align |
| Typographic quotes | Use "…" and '…' (curly), not "..." and '...' (straight ASCII) |
| Non-breaking spaces | Use between numbers and units (5 MB, 3 items) and in brand names |
| Line length | 60–75 characters per line for body text; shorter for UI labels |
Forbidden
/* Forbidden: gradient text — reduces legibility */
.heading {
background: linear-gradient(to right, #06b6d4, #8b5cf6);
-webkit-background-clip: text;
color: transparent;
}
/* Forbidden: Inter as default with no personality */
font-family: 'Inter', system-ui, sans-serif; /* acceptable only if Inter is the brand choice */---
Colour
Build a Cohesive Palette
A cohesive palette has:
- One brand colour — used sparingly, carries maximum visual weight
- Tinted neutrals — not pure
#f5f5f5grey; slightly tinted toward the brand hue - Semantic colours — success, error, warning, info — derived from the palette, not defaults
- Maximum 5–6 distinct hues in use at any one time
Modern CSS: OKLCH
Use OKLCH for colour definitions in ol_ui_library tokens. OKLCH is perceptually uniform — changing the lightness value produces predictable results; hues stay vivid at all lightness levels.
/* Avoid: HSL — not perceptually uniform; saturation behaves differently per hue */
:root {
--color-brand-primary: hsl(220, 90%, 50%);
}
/* Prefer: OKLCH — predictable lightness, consistent chroma across hues */
:root {
--color-brand-primary: oklch(55% 0.22 250); /* L: 0–100%, C: chroma, H: hue */
--color-brand-light: oklch(92% 0.05 250); /* Same hue, high lightness */
--color-brand-dark: oklch(35% 0.22 250); /* Same hue, low lightness */
}Tint Neutrals Toward Brand
/* Generic: pure grey — feels disconnected from brand */
--color-surface: oklch(97% 0 0);
/* Better: tinted neutral — surface feels part of the same palette */
--color-surface: oklch(97% 0.01 250); /* Barely perceptible blue tint matching brand hue */Rules
- Never pure black (
#000000) — use near-black tinted toward the brand hue - Never pure white (
#ffffff) — use near-white tinted toward the brand hue - Colour alone never encodes information (WCAG requirement; see accessibility section)
- WCAG AA contrast minimum (4.5:1) on all text; 3:1 on large text and UI components
---
Layout and Visual Rhythm
Generic interfaces apply the same spacing and layout treatment to everything. Distinctive interfaces vary treatment to create hierarchy and rhythm.
Rules
| Rule | Detail |
|---|---|
| Vary spatial rhythm | Mix tight and loose spacing to signal grouping and importance |
| Embrace asymmetry | Centred layouts feel static; left-weighted or asymmetric layouts feel dynamic |
| Use full-bleed bands | Not everything should be in a card; full-width colour bands create strong section breaks |
| Limit card depth | Maximum 1 level of card nesting; replace the second level with spacing and dividers |
| Grid variation | Not every grid should be 3 or 4 equal columns; vary column widths to create visual interest |
Avoid Templated Page Structures
// Templated (generic): // Distinctive:
[Hero] [Full-bleed asymmetric hero]
[3-column card grid] [Wide primary card + 2 secondary]
[3-column card grid] [Ruled list with typographic hierarchy]
[3-column card grid] [Metrics band with varied sizing]
[Footer] [Footer]---
Motion and Animation
Motion communicates state change. It is not decoration.
Rules
| Rule | Detail |
|---|---|
| Animate only `transform` and `opacity` | These run on the compositor thread; do not trigger layout or paint |
| Never `transition: all` | Animates every property including ones that cause layout reflow |
| Exponential easing | cubic-bezier(0.4, 0, 0.2, 1) (Material Design standard) for most transitions |
| Short durations | UI feedback: 100–150ms; element entry: 200–300ms; page transitions: 300–400ms |
| Make animations interruptible | User should be able to trigger the reverse transition before the first completes |
| `prefers-reduced-motion` | All animations must be disabled or significantly reduced when this media query is set |
/* Correct: only transform and opacity; respects reduced motion */
.card {
transition: transform 200ms cubic-bezier(0.4, 0, 0.2, 1),
opacity 200ms cubic-bezier(0.4, 0, 0.2, 1);
}
.card:hover {
transform: translateY(-2px);
}
/* Forbidden: transition all, animates layout properties */
.card {
transition: all 0.3s ease;
}
.card:hover {
margin-top: -4px; /* Triggers layout — causes CLS */
}
/* Required: reduced motion override */
@media (prefers-reduced-motion: reduce) {
.card { transition: none; }
}---
Modern CSS Techniques
Container Queries (preferred over media queries for components)
Components should adapt to their container size, not the viewport size. A card does not know if it is in a sidebar or a main column; its container does.
/* Adapt to container, not viewport */
.chart-panel {
container-type: inline-size;
}
@container (min-width: 600px) {
.chart-panel__legend {
display: flex;
flex-direction: row; /* Horizontal legend when panel is wide enough */
}
}
@container (max-width: 599px) {
.chart-panel__legend {
display: none; /* Hide legend on narrow containers */
}
}text-wrap: balance
/* Prevent orphaned words on headings */
h1, h2, h3 {
text-wrap: balance;
}font-variant-numeric: tabular-nums
/* All number columns in tables and dashboards */
.metric-value,
td.numeric {
font-variant-numeric: tabular-nums;
}---
Aesthetic Quality Review Checklist
Use during Library Maintenance Mode component reviews:
| Check | Pass Condition |
|---|---|
| AI slop test | Would not be immediately identified as AI-generated |
| No glassmorphism | Not present, or justified with a specific rationale |
| No nested cards | Maximum 1 level of card nesting |
| No gradient text | Headings use colour and weight for hierarchy, not gradients |
| Typography distinctiveness | Not defaulting to Inter/system-ui without brand rationale |
text-wrap: balance on headings | Applied in CSS |
tabular-nums on numeric data | Applied in CSS |
| OKLCH colour tokens | New token values use OKLCH |
| Tinted neutrals | Neutrals have a slight hue tint, not pure grey |
transform/opacity only animations | No margin, height, width, top in transitions |
prefers-reduced-motion | All animated components override when set |
| Container queries | Components use container queries over viewport media queries |
Component Architecture Patterns
Pattern Selection Guide
Choose one pattern per application before design begins. Do not mix patterns.
---
Atomic Design
Best for: Building or extending a component library (ol_ui_library); ensuring a consistent visual vocabulary across multiple products.
Structure (Brad Frost — industry standard for component libraries):
| Level | Description | Examples |
|---|---|---|
| Atoms | Smallest indivisible UI elements | Button, Input, Label, Icon, Badge, Spinner |
| Molecules | Combinations of atoms that form a functional unit | FormField (Label + Input + Error), SearchBox (Input + Button) |
| Organisms | Complex components composed of molecules and atoms | NavigationBar, DataTable, DocumentUploader, ChartPanel |
| Templates | Page-level wire-frame compositions of organisms | DashboardTemplate, WizardTemplate, ResultsTemplate |
| Pages | Templates with real data bound | DashboardPage, UploadPage |
Key rules:
- Each level depends only on levels below it — organisms use molecules; molecules use atoms
- Pages are never used inside organisms
- Templates contain no domain data — they are structural layouts only
- Atoms have no internal state — they are pure presentation
When to choose Atomic Design:
- You are designing or improving ol_ui_library itself
- The product needs a consistent visual language across many features
- The team will share components across multiple applications
---
Feature-Sliced Design
Best for: Large applications with multiple distinct business domains where teams need to own features independently without coupling.
Structure:
src/
app/ Application-level setup: providers, routing, global styles
pages/ Route-level compositions (thin — delegate to widgets)
widgets/ Self-contained page blocks specific to a single page
features/ User scenarios and business capabilities
entities/ Business entities: User, Document, Pipeline
shared/ Cross-cutting: UI kit (≈ ol_ui_library atoms/molecules), API client, utilitiesImport rule (strictly enforced): Each layer may only import from layers listed below it. features know about entities; entities never import from features.
Key rules:
shared/uiis effectively the component library layer — reference ol_ui_library hereentitiescontain domain types, API schemas, and entity-level componentsfeaturescontain the orchestration logic for user-facing capabilitieswidgetsare assemblers — they compose features and entities for a specific page context
When to choose Feature-Sliced Design:
- 3+ distinct business domains in a single application
- Multiple teams contributing independently
- You need to enforce clear import discipline to prevent cross-feature coupling
---
Smart / Dumb (Container / Presenter)
Best for: Small to medium applications where simplicity and testability of presentation logic are the primary goals.
| Component Type | Responsibility | Has State | Knows About API/Services |
|---|---|---|---|
| Smart (Container) | Fetches data, manages state, coordinates children | Yes | Yes |
| Dumb (Presenter) | Renders props; emits events via callbacks; no side effects | No | No |
Key rules:
- Dumb components are tested in isolation with props alone — no mocks needed
- Smart components are integration-tested
- Each dumb component has a clearly defined props interface
- Smart components do not render UI directly — they compose dumb components
When to choose Smart/Dumb:
- Single team, small to medium codebase
- Clear unidirectional data flow is the primary architectural goal
- You want maximum component testability with minimal test infrastructure
---
State Management Selection
Separate server state from client state. Do not force one library to handle both.
| Solution | Use When | Avoid When |
|---|---|---|
| React Query / TanStack Query | Server state: API data, caching, background refresh | Local UI state — this is not its purpose |
| React Context + useReducer | Shared state within a single feature tree; < 5 consumers; infrequent updates | High-frequency updates (triggers full re-renders across all consumers) |
| Zustand | App-wide client state; moderate update frequency; simple API preferred | You need strict Redux-style patterns with middleware |
| Redux Toolkit | Large team; strict patterns required; complex async flows with middleware | Small app — adds ceremony without benefit |
| Jotai | Complex interdependent state; fine-grained reactivity per atom | Team unfamiliar with atomic state model |
| `useState` / `useReducer` | Component-local state: open/closed, current tab, form input | State needed by sibling or distant components |
Decision principle: Use React Query for anything that comes from a server. Use Zustand (or Context for small scope) for everything else. Never put API response data in Zustand.
---
Module Federation (Micro-Frontends)
Use only when teams need to deploy UI slices independently. This is an advanced pattern with significant operational overhead — do not default to it.
Rules when used:
- Split by business domain, not technical layer (not "all charts", but "reporting feature")
- Share
reactandreact-domas singletons — never allow multiple React versions to coexist - Use CSS Modules or Shadow DOM to prevent style leakage across slices
- Do not share utility libraries across micro-frontend boundaries — controlled duplication is
cheaper than shared-library coupling
- Prefer Server-Side Module Federation for SSR scenarios
Avoid micro-frontends when: A monorepo with a shared component library (ol_ui_library) achieves the same independence goal at significantly lower complexity.
Data Visualisation Strategy
Design Philosophy
Visualisation design begins with the question the user needs to answer, not the shape of the data. A chart that maps to the data structure but doesn't answer the question is architectural waste.
---
Step 1: Match Chart Type to User Question
| User Question | Chart Type | Notes |
|---|---|---|
| How does this change over time? | Line chart | Continuous trends; use area chart for cumulative values |
| How do these categories compare? | Bar chart | Vertical for < 8 categories; horizontal for long labels |
| What proportion of the whole? | Pie / donut | Maximum 5 slices; use bar chart if more categories |
| What is the relationship between two variables? | Scatter plot | Add trend line for correlation; add size encoding for a third variable |
| How is this distributed? | Histogram | Use beeswarm for small datasets (< 100 points) |
| Where are the patterns in dense data? | Heatmap | Time × category matrices; geographic density |
| What is the current status at a glance? | KPI card / gauge | Single metric only; colour encodes status |
| How does a real-time value change? | Sparkline / live line chart | Minimal decoration; prioritise render speed |
| How do multiple time series compare? | Multi-series line chart | Maximum 5–7 series before readability breaks |
| What is the breakdown of a total? | Stacked bar | Use with caution — harder to read than grouped bars |
---
Step 2: Select the Chart Library
One library per application — mixing chart libraries produces visual inconsistency and unnecessary bundle bloat. Choose once, document the rationale, enforce it.
Library Comparison Matrix
| Library | Best For | Rendering | React Integration | Bundle Impact |
|---|---|---|---|---|
| Recharts | Business dashboards, standard chart types | SVG | Native (React components) | Medium |
| ECharts | Large datasets (> 10K points), complex types | Canvas | Via wrapper | Large |
| D3.js | Fully bespoke, unique visualisations | SVG / Canvas | Manual integration | Small (core) |
| Chart.js | Simple charts, non-React contexts | Canvas | Via wrapper | Small |
| Plotly.js | Scientific, 3D, statistical visualisations | SVG / Canvas | Via wrapper | Large |
Decision Rules
1. Default: Recharts — native React component model; covers 80% of business chart requirements; maintainable by any TypeScript engineer without specialist knowledge. 2. Switch to ECharts when: Dataset exceeds 10,000 data points, or SVG render performance degrades noticeably. Canvas rendering handles 10× more points than SVG. 3. Use D3 when: The visualisation is genuinely bespoke and cannot be composed from a standard library's chart types. Requires specialist knowledge — document this decision. 4. Avoid Plotly unless: The requirement is explicitly scientific, 3D, or statistical. Its bundle size is unjustified for standard business charts.
Performance Limits by Rendering Mode
| Mode | Practical Interactive Limit | Action Above Limit |
|---|---|---|
| SVG (Recharts default) | ~2,000 live data points | Switch to ECharts (Canvas) |
| Canvas (ECharts) | ~100,000 data points | Server-side aggregation + virtualisation |
| WebSocket throughput | ~30,000 points/sec (poor network) | Batch server-side before sending |
---
Step 3: Real-Time Data Architecture
When data updates continuously (pipeline monitoring, live metrics, streaming results):
Update Pipeline
Data Source → Server-Side Batching → WebSocket / SSE → Browser State → Chart Re-renderDesign these components explicitly — do not leave real-time strategy to implementation.
Batching Strategy
- Batch rapid updates on the server — never forward every individual data point to the browser
- Target: one update per 500–1000ms for dashboard displays; 100ms for critical metrics
- Use WebSocket for bidirectional communication; Server-Sent Events (SSE) for unidirectional
streams from server to browser
Browser-Side Architecture
- Exponential backoff reconnection: 1s → 2s → 4s → 8s → max 30s
- Data retention limit: browser holds maximum 1,000–5,000 live data points per chart
(beyond this, trim the oldest points — specify the limit at design time)
- Disable animations during real-time updates — animations slow re-renders
- Memoize chart components: re-render only when the data reference actually changes
Disconnection State Design
Specify what the UI displays when the real-time connection is lost:
| State | Recommended Treatment |
|---|---|
| Reconnecting (< 5s) | Subtle indicator; do not disrupt the user |
| Reconnecting (> 5s) | Clear status banner: "Reconnecting…" |
| Failed to reconnect | Error state with manual reconnect option; show last-known data with timestamp |
---
Step 4: Colour and Accessibility
Semantic Colour Conventions
- Green / success: positive values, completed states, above target
- Red / danger: negative values, error states, below threshold
- Amber / warning: degraded state, approaching threshold
- Blue / neutral: informational, selected, primary brand
Accessibility Rules
- WCAG AA contrast (4.5:1) for all text rendered on chart backgrounds
- Never rely on colour alone — use shape, pattern, label, or icon as secondary encoding
- Colour-blind-safe palette by default — avoid red-green combinations without secondary encoding
- Consistent palette: the same category always uses the same colour across all charts in a dashboard
---
Architecture Checklist for Visualisation Features
Before handing to ui-engineer, confirm all of these are specified:
| Concern | Question | Required Answer |
|---|---|---|
| Chart selection | Is the chart type driven by the user's question? | Yes — documented with rationale |
| Library choice | Is a single library specified for the application? | Yes — documented in tech stack |
| Real-time strategy | If real-time, is server-side batching designed? | Yes (or N/A if not real-time) |
| Performance target | Is a data point limit specified for live charts? | Yes (or N/A) |
| Accessibility | Is colour-blind safety addressed with secondary encoding? | Yes |
| Responsive design | Are chart container breakpoints specified? | Yes |
| Empty state | Is the "no data yet" state designed? | Yes |
| Loading state | Is the loading skeleton or spinner specified? | Yes |
Design System Principles and ol_ui_library
What Is a Design System?
A design system is the single source of truth for UI: shared components, patterns, tokens, and guidelines that allow multiple teams to build consistent interfaces efficiently without rebuilding shared solutions.
Business impact (industry benchmarks for teams > 100 people):
- 46% reduction in design and development costs
- 22% faster time to market
- 40% faster release cadence for SaaS products
---
ol_ui_library
Purpose
ol_ui_library is the OntoLedgy shared UI component library. It is the UI equivalent of bclearer_pdk for backend code: a platform library that all UI solutions depend on rather than rebuild. When a UI feature needs a button, table, or chart panel, it comes from ol_ui_library — it is not re-implemented per product.
Repository: https://github.com/OntoLedgy/ol_ui_library
Position in the Architecture
UI components are infrastructure. They sit at the bottom of the dependency stack:
Domain Layer business rules, ontological models
Service Layer orchestration, data processing
Adapter Layer API clients, data transformers
Infrastructure ← ol_ui_library components, routing, HTTP clientsUI components accept props and emit events. They carry no domain knowledge. A DataTable does not know what an ontological Element is. It renders rows.
Library Structure (Atomic Design)
ol_ui_library/
atoms/ Button, Input, Label, Icon, Badge, Spinner, Avatar, Tooltip
molecules/ FormField, SearchBox, FileDropZone, ProgressBar, Alert, Pagination
organisms/ DataTable, NavigationBar, DocumentUploader, ChartPanel, WizardContainer
templates/ DashboardTemplate, WizardTemplate, ResultsTemplate, EmptyStateTemplate
tokens/ colour, spacing, typography, border-radius, shadow design tokens
hooks/ useDebounce, useMediaQuery, useLocalStorage, usePrevious---
Design Tokens
Design tokens are the atomic values from which all visual properties are derived. They are the bridge between design intent and code implementation.
Token Categories
| Category | Example Tokens |
|---|---|
| Colour | color.brand.primary, color.status.error, color.neutral.50, color.status.success |
| Typography | font.size.base, font.weight.semibold, font.family.mono, font.line-height.tight |
| Spacing | space.1 (4px), space.2 (8px), space.4 (16px), space.8 (32px) |
| Border radius | radius.sm (4px), radius.md (8px), radius.lg (16px), radius.full (9999px) |
| Shadow | shadow.sm, shadow.md, shadow.focus (keyboard focus ring) |
| Z-index | z.modal, z.tooltip, z.dropdown |
Rules
- Components reference tokens only — no hardcoded hex, pixel, or em values in component code
- Tokens are defined once; theming is achieved by swapping token values (e.g. dark mode = token set swap)
- Token names encode semantic intent, not visual values (
color.status.errornotcolor.red.500)
---
Component Contract Standard
Every component in ol_ui_library must have all of the following:
| Requirement | Description |
|---|---|
| Props interface | Fully typed TypeScript; no any; all props documented with JSDoc |
| States | default, hover, focus, active, disabled, error, loading (where applicable) |
| Variants | size (sm/md/lg), intent (primary/secondary/danger/ghost/warning), theme |
| Accessibility contract | ARIA role, keyboard shortcuts, required contrast ratio |
| Usage examples | Correct usage AND common misuse patterns (what not to do) |
| Storybook story | Interactive preview covering all states and variants |
| Changelog entry | What changed, why, and the semver impact |
---
Maintaining and Extending ol_ui_library
When to Add a Component to the Library
Add to ol_ui_library when:
- The same pattern is needed in 2 or more product features or applications
- The component encapsulates complex accessibility logic (e.g. modal focus trap, keyboard navigation, skip-nav link)
- The pattern requires non-trivial shared state that consumers should not manage themselves
Keep in product code when:
- The component is specific to one business domain (e.g.
PipelineStageCard— too specific) - The component depends on domain types or services
- The component is a one-off for a single feature that is unlikely to recur
Contribution Workflow
1. Architect designs component spec in Library Maintenance Mode
↓ (approval required before implementation)
2. ui-engineer implements following component standards
↓
3. Storybook story added covering all states and variants
↓
4. Usage documentation written (correct + incorrect examples)
↓
5. Semver bump applied; changelog entry written
↓
6. PR reviewed and mergedBreaking Change Policy (semver)
| Version Bump | Trigger |
|---|---|
| PATCH | Bug fix, accessibility improvement, visual polish — no API change |
| MINOR | New optional props, new variants, new atoms, new molecules — backwards compatible |
| MAJOR | Props renamed or removed, behaviour changes to existing API, Atomic-level reassignment |
Never introduce a MAJOR change without a migration guide.
---
Storybook as Living Documentation
Storybook is the primary documentation surface for ol_ui_library:
- Each component has a dedicated story file:
ComponentName.stories.tsx - Stories cover: default, all states, all variants, error conditions, accessibility states, edge cases
- The Docs addon generates interactive documentation from story metadata
- Stories serve as the baseline for visual regression testing (Chromatic or equivalent)
Minimum Story Coverage
Every component story must include:
| Story | What It Shows |
|---|---|
Default | Component with minimal required props |
AllVariants | All size and intent combinations |
AllStates | Hover, focus, active, disabled, error, loading |
WithError | Error state with message |
Interactive | User can interact with the component in the story panel |
---
Accessibility Standards
All components in ol_ui_library must meet WCAG 2.2 AA minimum. The POUR framework organises every requirement into four pillars:
| Pillar | Meaning | Examples |
|---|---|---|
| Perceivable | Content can be perceived through multiple senses | Alt text, colour contrast, captions |
| Operable | All functionality works without a mouse | Keyboard nav, focus management, no time traps |
| Understandable | Content and UI behaviour are predictable | Consistent nav, clear errors, explicit labels |
| Robust | Works with current and future assistive technologies | Semantic HTML first; ARIA only when HTML is insufficient |
Hard Requirements (Level AA)
| Requirement | Standard |
|---|---|
| Colour contrast (text) | 4.5:1 minimum against background |
| Colour contrast (large text ≥ 18pt or 14pt bold) | 3:1 minimum |
| Colour contrast (UI components, focus rings) | 3:1 minimum |
| Keyboard navigation | All interactive elements reachable and operable via keyboard alone |
| Focus indicator | Visible :focus-visible ring on all interactive elements — never outline: none without replacement |
| Screen reader | Meaningful ARIA labels; correct semantic roles; aria-live regions for dynamic content |
| Focus not obscured | Focused element must not be entirely hidden by sticky headers or overlays (new in WCAG 2.2) |
| Dragging alternatives | Any drag-and-drop functionality has a single-pointer alternative (new in WCAG 2.2) |
| Target size | Interactive targets ≥ 24×24 CSS pixels (new in WCAG 2.2) |
| Motion | Respect prefers-reduced-motion — disable or significantly reduce animations when set |
| Colour alone | Colour is never the sole means of conveying information — use shape, label, or pattern as secondary encoding |
Implementation Rules
- Native HTML first:
<button>,<a>,<input>carry accessibility semantics for free. Use ARIA only when there is no native element for the role. - Focus trapping: Components that manage focus (modals, dropdowns, tooltips) must trap focus within the component while open and return focus to the trigger element on close.
- Functional images:
alttext describes the image's function, not appearance. Decorative images:alt="". - Form errors:
aria-describedbylinks the input to its error message. Error summary at top of form focuses the first error field on submit.
Frontend Project Structure
Naming Convention: frontend/
Use `frontend/` as the canonical name for the UI layer in every project.
| Name | Status | Reason |
|---|---|---|
frontend/ | Canonical | Clear, unambiguous, consistent across all OL projects |
ui/ | Forbidden | Ambiguous — conflicts with ol_ui_library; also used for UI component directories |
client/ | Forbidden | Implies client/server split as the primary concern; unclear in monorepo contexts |
web/ | Forbidden | Too narrow — assumes web-only; excludes desktop/mobile targets |
app/ | Forbidden | Collides with the app/ directory used inside the frontend source |
This applies at every level: top-level project folders, CI/CD config paths, Docker compose service names, import alias roots, and README references.
---
Structure 1: Product Application (uses ol_ui_library)
For any product built on top of ol_ui_library. Uses Feature-Sliced Design adapted for the OL platform.
my-product/
frontend/
src/
app/ Application bootstrap — runs once at startup
providers.tsx React Query, theme, auth, error boundary providers
router.tsx Route definitions (React Router / TanStack Router)
App.tsx Root component: wraps providers around router
main.tsx Entry point: renders App into the DOM
pages/ Route-level thin shells — one file per route
dashboard/
DashboardPage.tsx
upload/
UploadPage.tsx
pipeline/
PipelineDetailPage.tsx
features/ User-facing business capabilities
document-upload/
DocumentUploadFeature.tsx Orchestrates the upload journey
useDocumentUpload.ts Upload logic: validation, API calls, state
documentUpload.constants.ts Accepted types, size limits, copy strings
documentUpload.types.ts Feature-local types
pipeline-wizard/
PipelineWizardFeature.tsx
usePipelineWizard.ts
pipelineWizard.constants.ts
pipelineWizard.types.ts
pipeline-monitoring/
PipelineMonitoringFeature.tsx
usePipelineMonitoring.ts
usePipelineLogStream.ts
results-review/
ResultsReviewFeature.tsx
useResultsFilter.ts
entities/ Business domain entities — shared across features
document/
document.types.ts TypeScript types for the Document entity
document.api.ts React Query query/mutation definitions
DocumentSummaryCard.tsx Entity-level presentational component
pipeline/
pipeline.types.ts
pipeline.api.ts
PipelineStatusBadge.tsx
result/
result.types.ts
result.api.ts
shared/ Cross-cutting — no feature-specific code here
ui/ Local component compositions (thin; prefer ol_ui_library direct)
hooks/ Truly shared hooks used by 2+ features
useDebounce.ts
usePageTitle.ts
api/ API client setup, interceptors, base URL, auth headers
client.ts
queryClient.ts
utils/ Pure functions: formatters, validators, date helpers
formatBytes.ts
formatDate.ts
constants/ App-wide constants (route paths, feature flags)
routes.ts
config.ts
types/ Shared TypeScript types used across layers
api.types.ts
pagination.types.ts
public/ Static assets: favicon.ico, og-image.png, robots.txt
e2e/ Playwright end-to-end journey tests
fixtures/ Static test data files (sample.pdf, test.csv)
journeys/ Journey test specs named after the journey
document-upload.spec.ts
pipeline-wizard.spec.ts
pipeline-monitoring.spec.ts
.storybook/ Only if the product team builds product-specific stories
index.html
package.json
tsconfig.json
vite.config.ts
vitest.config.ts
playwright.config.ts
backend/
docs/Layer Import Rules (strictly enforced)
Each layer may only import from layers below it in this list:
pages → features, entities, shared
features → entities, shared
entities → shared
shared → (external packages only; no internal cross-imports)
app → pages, sharedfeatures never import from other features. entities never import from features.
Path Aliases (tsconfig.json)
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@olui/*": ["../../ol_ui_library/src/*"]
}
}
}Use @/features/document-upload/... not ../../../features/document-upload/.... Use @olui/atoms/Button not ol-ui-library/src/atoms/Button.
---
Structure 2: ol_ui_library Itself
For work on the shared component library. Uses Atomic Design with strict co-location.
ol_ui_library/
src/
atoms/ Level 1 — smallest indivisible elements
Button/
Button.tsx
Button.test.tsx
Button.stories.tsx
Button.module.css
index.ts Public export: export { Button } from './Button'
Input/
Label/
Icon/
Badge/
Spinner/
Avatar/
Tooltip/
molecules/ Level 2 — functional combinations of atoms
FormField/
FormField.tsx
FormField.test.tsx
FormField.stories.tsx
FormField.module.css
index.ts
FileDropZone/
ProgressBar/
SearchBox/
Alert/
Pagination/
organisms/ Level 3 — complex compositions of molecules and atoms
DataTable/
DataTable.tsx
DataTable.test.tsx
DataTable.stories.tsx
DataTable.module.css
useDataTable.ts Co-located hook (used only by DataTable)
dataTable.constants.ts
index.ts
DocumentUploader/
NavigationBar/
ChartPanel/
WizardContainer/
templates/ Level 4 — structural page layouts; no data, no domain logic
DashboardTemplate/
DashboardTemplate.tsx
DashboardTemplate.stories.tsx
DashboardTemplate.module.css
index.ts
WizardTemplate/
ResultsTemplate/
EmptyStateTemplate/
tokens/ Design tokens — the visual vocabulary of the library
colours.css --color-brand-primary, --color-status-error, etc.
spacing.css --space-1 through --space-16
typography.css --font-size-sm, --font-weight-semibold, etc.
borders.css --radius-sm, --radius-md, --radius-full
shadows.css --shadow-sm, --shadow-md, --shadow-focus
z-index.css --z-modal, --z-tooltip, --z-dropdown
tokens.css Master file: @import all token files above
hooks/ Shared hooks exported by the library
useDebounce.ts
useMediaQuery.ts
useLocalStorage.ts
usePrevious.ts
types/ TypeScript types exported by the library
component.types.ts Base prop types: Size, Intent, etc.
token.types.ts
utils/ Pure utility functions exported by the library
formatBytes.ts
formatDuration.ts
accessibility.ts Shared ARIA helpers
index.ts Library barrel export — the public API of the library
.storybook/
main.ts
preview.ts Injects tokens.css; global decorators
e2e/ Playwright tests for complex multi-step component interactions
package.json
tsconfig.json
vite.config.ts Also the Storybook build target
vitest.config.tsComponent Folder Rule
Every component in ol_ui_library lives in its own folder with exactly these files:
| File | Required | Purpose |
|---|---|---|
ComponentName.tsx | Yes | Implementation |
ComponentName.test.tsx | Yes | React Testing Library tests |
ComponentName.stories.tsx | Yes | Storybook stories |
ComponentName.module.css | Yes | Scoped styles (tokens only — no hardcoded values) |
index.ts | Yes | export { ComponentName } from './ComponentName' |
useComponentName.ts | If needed | Co-located hook — only if used by this component alone |
componentName.constants.ts | If needed | Constants specific to this component |
Never add a component file without all required files. A component without tests or stories is not complete.
---
File Naming Conventions
Consistent across both product applications and ol_ui_library:
| File Type | Convention | Example |
|---|---|---|
| React component | PascalCase.tsx | DocumentUploader.tsx |
| Custom hook | camelCase.ts (must start use) | useDocumentUpload.ts |
| Types file | camelCase.types.ts | document.types.ts |
| API module | camelCase.api.ts | document.api.ts |
| Constants | camelCase.constants.ts | documentUpload.constants.ts |
| CSS Module | PascalCase.module.css (matches component) | DocumentUploader.module.css |
| Unit test | PascalCase.test.tsx / camelCase.test.ts | DocumentUploader.test.tsx |
| Story file | PascalCase.stories.tsx | DocumentUploader.stories.tsx |
| Barrel export | index.ts | atoms/Button/index.ts |
| Playwright spec | kebab-case.spec.ts (named after journey) | document-upload.spec.ts |
| Folder names | kebab-case | document-upload/, pipeline-wizard/ |
No abbreviations: document-upload/ not doc-upload/, pipeline-wizard/ not pipe-wiz/.
---
What Goes Where: Decision Table
| Code | Location |
|---|---|
| Button, Input, Label | ol_ui_library/src/atoms/ |
| FormField, ProgressBar, FileDropZone | ol_ui_library/src/molecules/ |
| DataTable, DocumentUploader, NavigationBar | ol_ui_library/src/organisms/ |
| DashboardTemplate, WizardTemplate | ol_ui_library/src/templates/ |
| Design tokens (colour, spacing, typography) | ol_ui_library/src/tokens/ |
| Upload journey orchestration | frontend/src/features/document-upload/ |
| Pipeline API calls and query keys | frontend/src/entities/pipeline/pipeline.api.ts |
| Pipeline TypeScript types | frontend/src/entities/pipeline/pipeline.types.ts |
| PipelineStatusBadge (entity-level presentation) | frontend/src/entities/pipeline/ |
| Route definitions | frontend/src/app/router.tsx |
| Auth/React Query providers | frontend/src/app/providers.tsx |
| Format utility used by 2+ features | frontend/src/shared/utils/ |
| Format utility used only by one component | Co-locate in the component's folder |
| App-wide constants (routes, env config) | frontend/src/shared/constants/ |
| Domain-specific constants (file size limits) | frontend/src/features/document-upload/documentUpload.constants.ts |
Rule of thumb: If in doubt about placement, ask "which layer is this responsible to?" A component that knows about Pipeline domain types belongs in entities; a component that orchestrates the pipeline kick-off journey belongs in features.
UX Journey Design Patterns
What Is a UX Journey?
A UX journey is a named, multi-step user interaction that achieves a specific business outcome. Journeys are architectural concerns — they define component boundaries, state machine requirements, error handling strategies, and progress models.
Journey Anatomy
Every journey must specify all of these:
| Element | Description |
|---|---|
| Entry point | How the user starts: route, button, deep link, system trigger |
| Steps | Ordered sequence of actions, each with a single, clear goal |
| Decision points | Branches based on user input or system state |
| Exit states | Success (goal achieved), Abandon (user leaves), Error (unrecoverable failure) |
| Progress state | What has been completed; what remains; what the user can revisit |
Design error paths first — error states are harder than happy paths. Leaving them to implementation leads to poor UX that is expensive to fix.
---
Document Upload Journey
Use when: User uploads one or more files to trigger a downstream process.
Component Architecture
DocumentUploader (organism)
├── DropZone (molecule) drag-and-drop zone + "Browse files" button
├── FileList (molecule) selected files with status indicators + remove controls
│ └── FileItem (molecule) × n filename, size, status, per-file progress, error message
├── UploadProgress (atom) overall progress bar (optional, for bulk uploads)
└── UploadSummary (molecule) completion state: success / partial success / failedStep Design
| Step | User Goal | Key States | Error Cases |
|---|---|---|---|
| 1. Select | Choose files to upload | Empty, files selected, max count reached | Wrong type, file too large, duplicate |
| 2. Review | Confirm selection before upload | File list with remove option | — |
| 3. Upload | Submit files; monitor progress | Per-file: queued, uploading (% progress), complete, failed | Network failure, server rejection, timeout |
| 4. Result | See outcome; take next action | All success, partial success, all failed | Partial failure: which files, why, retry option |
UX Rules
- Provide both drag-drop AND a "Browse files" button — both must be equally discoverable
- Show specific error messages:
"invoice.pdf exceeds 5 MB"not"Upload failed" - Support multi-file selection; never force one-at-a-time uploads
- Show per-file progress bars, not only an overall bar
- Allow removal of individual files from the list before upload begins
- After upload: distinguish between "file received" and "file processed"
State Machine (design this explicitly)
idle → files_selected → uploading → complete
↘ ↗ (all files) → success
failed_partial → (some files) → partial_success
failed_all → error---
Pipeline Kick-Off Journey (Wizard Pattern)
Use when: User configures and initiates a data processing pipeline. Best for complex configuration that can be logically segmented into steps.
When to Use a Wizard
Use a wizard when:
- The task is long and unfamiliar to most users
- Information entry is logically segmentable
- Subsequent steps depend on earlier answers
- The process is completed infrequently (not a daily workflow)
Do NOT use a wizard for: short forms (< 9 fields total), expert daily workflows, or processes that benefit from seeing all fields simultaneously.
Component Architecture
PipelineWizard (organism)
├── StepIndicator (molecule) current step + total steps ("Step 2 of 4")
├── StepContainer (template) renders the active step component
│ ├── PipelineConfigStep parameters, run name, schedule options
│ ├── SourceSelectionStep input data selection (file, dataset, query)
│ ├── ReviewStep read-only summary of all inputs (editable via links)
│ └── SubmitStep final confirmation; submit button; SLA estimate
├── WizardNavigation (molecule) Back / Next / Submit with loading states
└── AbandonConfirmation (molecule) "Unsaved changes — are you sure?" on exitWizard Design Rules
- Maximum 5–9 fields per step; 1–2 minutes per step target
- Each step has one clear, self-contained goal — if a step is doing two things, split it
- Show clear progress:
"Step 2 of 4 — Select your data source" - Explain why information is needed — users abandon when they don't understand the value
- Always include a review/summary step before final submission
- Allow editing any previous step directly from the review step
Backnavigation never loses the current step's inputNextvalidates the current step before advancing — show inline errors, not a toast
Step States (design all of these)
| State | Description |
|---|---|
not_started | Step not yet reached |
active | Currently being filled in |
valid | Completed with valid inputs |
invalid | Attempted and has validation errors |
loading | Awaiting async validation or data fetch |
---
Pipeline Monitoring Journey
Use when: User watches the progress of a running or recently completed pipeline.
Component Architecture
PipelineDashboard (template)
├── StatusHeader (organism) pipeline name, overall status badge, elapsed time
├── StageProgressTimeline (organism) per-stage status in sequence
│ └── StageCard (molecule) × n stage name, status, duration, record count, log excerpt
├── MetricsPanel (organism) key metrics: records in/out, error rate, throughput
└── LogStream (organism) filterable, searchable log outputInformation Architecture
- F-pattern layout: most critical status in the top-left
- Priority order: Overall Status → Stage Breakdown → Metrics → Logs
- Real-time updates for in-progress pipelines; static snapshot for completed
- Error states are visually prominent — not hidden inside a log viewer
Pipeline Status States (design all explicitly)
| State | Visual Treatment | User Actions |
|---|---|---|
queued | Neutral / muted | Cancel |
running | Animated progress indicator | Cancel |
completed | Success (green) | View results |
failed | Error (red, prominent) | View error detail, Retry |
cancelled | Muted / grey | Re-run |
partial | Warning (amber) | View partial results, Retry failed stages |
Real-Time Update Architecture
See references/data-visualisation-strategy.md for the full real-time strategy. Key constraints to specify at design time:
- Update frequency: how often does the UI poll/receive updates?
- Data retention: how many historical log lines / metric points does the browser hold?
- Reconnection strategy: what does the UI show if the WebSocket drops?
---
Results Review Journey
Use when: User reviews the output of a completed pipeline or data process.
Component Architecture
ResultsDashboard (template)
├── SummaryPanel (organism) run metadata + key metrics at a glance
├── DataExplorer (organism) filterable, sortable, paginated results table
├── VisualisationPanel (organism) charts appropriate to data type (see data-visualisation-strategy.md)
└── ExportControls (molecule) download (CSV/Excel/JSON) + share optionsInformation Architecture Rules
- Lead with the answer: summary metrics before raw data
- Group related information with visual separators
- Progressive disclosure: summary → detail → raw data
- Filters appear above the content they affect, with short plain labels
- Top 3–4 metrics aligned with the user's primary objective, not what is easy to count
- Empty states are designed — "No results found" includes a reason and a recovery action
---
General UX Journey Rules
1. Design error paths alongside happy paths — both are first-class requirements 2. Every step has one goal — split steps that are doing two things 3. Progress is always visible — users know where they are and how far they have to go 4. Back never destroys input — backward navigation preserves all state 5. Abandonment is graceful — explicit confirmation before losing progress; offer resume where feasible 6. Accessibility is per-step — keyboard navigation and screen reader behaviour are specified for each step, not for the journey as a whole 7. Loading states are designed — every async operation has a designed loading state; never leave the user staring at a frozen UI