Skill Tracer
Skills › BMAD Method › bmad-ux › experience-example-shadcn.md

experience-example-shadcn.md

133 lines · skills/bmad-ux/assets/experience-example-shadcn.md at bd70c64

Open on GitHub
1---
2name: Drift
3status: final
4sources:
5 - ../prd-drift/prd-drift.md
6updated: 2026-04-02
7---
8
9# Drift — Experience Spine
11> Illustrative example. Single-surface responsive web. shadcn/ui on Next.js + Tailwind. Paired with `design-example-shadcn.md` (Drift DESIGN.md). Demonstrates: component-library inheritance, keyboard-first interaction primitives, the "shadcn + brand-layer" pattern that covers most modern web SaaS.

Drift — Experience Spine

Illustrative example. Single-surface responsive web. shadcn/ui on Next.js + Tailwind. Paired with design-example-shadcn.md (Drift DESIGN.md). Demonstrates: component-library inheritance, keyboard-first interaction primitives, the "shadcn + brand-layer" pattern that covers most modern web SaaS.
Raw lines 1 to 12
13## Foundation
15Single-surface responsive web. shadcn/ui on Next.js 15+ with Tailwind CSS. The component library does most of the work; brand discipline is "respect the defaults except where the brand layer overrides them." `DESIGN.md` is the visual identity reference and names the override surface; this spine is the experience. Single-tenant per project; users can belong to multiple projects but each project is a self-contained workspace.

Foundation

Single-surface responsive web. shadcn/ui on Next.js 15+ with Tailwind CSS. The component library does most of the work; brand discipline is "respect the defaults except where the brand layer overrides them." DESIGN.md is the visual identity reference and names the override surface; this spine is the experience. Single-tenant per project; users can belong to multiple projects but each project is a self-contained workspace.

Raw lines 13 to 16
17## Information Architecture
19| Surface | Reached from | Purpose |
20|---|---|---|
21| Today | App open / `g t` | Current focus, in-progress tasks pulled from all projects |
22| Projects | Sidebar / `g p` | List of active and archived projects |
23| Project detail | Projects row / `g 1`–`g 9` | Tasks in this project, organized by lane |
24| Search | `⌘K` / `Ctrl+K` | Command palette — surface, navigate, act |
25| Settings | Avatar menu | Account, theme, keyboard shortcuts, billing |
27Sidebar collapses to icons on `md`; becomes a `Sheet` on `sm`. Modal stacks one level deep (e.g., open `Dialog` on top of a surface, never on top of another dialog).
29→ Composition reference: `mockups/today.html`, `mockups/project-detail.html`, `mockups/command-palette.html`. Spine wins on conflict.

Information Architecture

SurfaceReached fromPurpose
TodayApp open / g tCurrent focus, in-progress tasks pulled from all projects
ProjectsSidebar / g pList of active and archived projects
Project detailProjects row / g 1–g 9Tasks in this project, organized by lane
Search⌘K / Ctrl+KCommand palette — surface, navigate, act
SettingsAvatar menuAccount, theme, keyboard shortcuts, billing

Sidebar collapses to icons on md; becomes a Sheet on sm. Modal stacks one level deep (e.g., open Dialog on top of a surface, never on top of another dialog).

→ Composition reference: mockups/today.html, mockups/project-detail.html, mockups/command-palette.html. Spine wins on conflict.

Raw lines 17 to 30
31## Voice and Tone
33Microcopy. Brand voice and aesthetic posture live in `DESIGN.md`.
35| Do | Don't |
36|---|---|
37| "What are you working on?" | "Let's get productive! 🚀" |
38| "3 tasks in motion" | "You have 3 active items." |
39| "Closed. Nice work." | "Task completed successfully ✓" |
40| "Nothing in motion. Pick something." | "No active tasks. Click below to get started!" |
41| Manager-facing: counts and verbs. Employee-facing: same. | Different tone per audience — Drift talks to everyone the same way. |

Voice and Tone

Microcopy. Brand voice and aesthetic posture live in DESIGN.md.

DoDon't
"What are you working on?""Let's get productive! 🚀"
"3 tasks in motion""You have 3 active items."
"Closed. Nice work.""Task completed successfully ✓"
"Nothing in motion. Pick something.""No active tasks. Click below to get started!"
Manager-facing: counts and verbs. Employee-facing: same.Different tone per audience — Drift talks to everyone the same way.
Raw lines 31 to 42
43## Component Patterns
45Behavioral. Visual specs live in `DESIGN.md.Components` (or in shadcn defaults, when inherited).
47| Component | Use | Behavioral rules |
48|---|---|---|
49| Task row | Projects, Today | Click anywhere on row opens edit dialog. Checkbox toggles done state with optimistic update. Hover reveals quick-actions (`focus`, `defer`, `archive`). |
50| Focus card | Today, Project detail | At most one focus card per surface — the task or project marked with `focus` state. `f` keyboard shortcut sets focus on the active row. |
51| Command palette | Global (⌘K) | Fuzzy search across all projects, tasks, and commands. `Enter` fires the highlighted result. `→` previews a result. Escape closes. |
52| Project header | Project detail | Inline-editable title (click to edit, blur to save). Status pill: active / archived / done. |
53| Empty state | Anywhere | shadcn's empty pattern + one Drift-specific sentence. `display-sm` for the headline, body text below, single primary action. |

Component Patterns

Behavioral. Visual specs live in DESIGN.md.Components (or in shadcn defaults, when inherited).

ComponentUseBehavioral rules
Task rowProjects, TodayClick anywhere on row opens edit dialog. Checkbox toggles done state with optimistic update. Hover reveals quick-actions (focus, defer, archive).
Focus cardToday, Project detailAt most one focus card per surface — the task or project marked with focus state. f keyboard shortcut sets focus on the active row.
Command paletteGlobal (⌘K)Fuzzy search across all projects, tasks, and commands. Enter fires the highlighted result. → previews a result. Escape closes.
Project headerProject detailInline-editable title (click to edit, blur to save). Status pill: active / archived / done.
Empty stateAnywhereshadcn's empty pattern + one Drift-specific sentence. display-sm for the headline, body text below, single primary action.
Raw lines 43 to 54
55## State Patterns
57| State | Surface | Treatment |
58|---|---|---|
59| Cold app load | Today | shadcn `Skeleton` rows (4-6) match expected layout. Resolves on data. |
60| No focus | Today | `display-sm`: "Nothing in motion. Pick something." Below: list of in-progress tasks from all projects. |
61| Empty project | Project detail | `display-sm`: "{Project title} is empty." Body: "Add a first task to get going." Single primary button. |
62| Command palette no matches | ⌘K | "No matches. Start typing a task or project name, or pick an action below." Followed by 4-5 common commands. |
63| Offline | Global (status bar) | shadcn `Toast` once: "You're offline. Changes will sync when you reconnect." Local writes continue. |
64| Permission denied | Projects (others' private) | Surface hidden from sidebar. No "blocked" screen. |
65| Stale data | Project detail | If background refresh detects changes, shadcn `Toast`: "Updated by {collaborator_name}. Refresh." Manual refresh, no auto. |

State Patterns

StateSurfaceTreatment
Cold app loadTodayshadcn Skeleton rows (4-6) match expected layout. Resolves on data.
No focusTodaydisplay-sm: "Nothing in motion. Pick something." Below: list of in-progress tasks from all projects.
Empty projectProject detaildisplay-sm: "{Project title} is empty." Body: "Add a first task to get going." Single primary button.
Command palette no matches⌘K"No matches. Start typing a task or project name, or pick an action below." Followed by 4-5 common commands.
OfflineGlobal (status bar)shadcn Toast once: "You're offline. Changes will sync when you reconnect." Local writes continue.
Permission deniedProjects (others' private)Surface hidden from sidebar. No "blocked" screen.
Stale dataProject detailIf background refresh detects changes, shadcn Toast: "Updated by {collaborator_name}. Refresh." Manual refresh, no auto.
Raw lines 55 to 66
67## Interaction Primitives
69**Keyboard-first.** Drift's primary audience is developers and power users; the keyboard surface is the product, the mouse is fallback.
71- `⌘K` / `Ctrl+K` — Command palette (universal)
72- `g t` / `g p` — Go to Today / Projects (vim-style)
73- `g 1`–`g 9` — Go to project by sidebar position
74- `f` — Set focus on highlighted task/project
75- `c` — Create new task (context-aware: in the active project)
76- `Esc` — Close dialogs, exit edit mode, clear command palette
77- `/` — Focus search in current surface
79**Mouse:** click to act, drag deferred to v2. Hover reveals row actions on `md+` (touch users tap to reveal).
81**Banned everywhere:** infinite scroll (pagination only), drag-to-reorder in v1, hover-only affordances on `sm` viewports, modal stacks > 1 level deep.

Interaction Primitives

Keyboard-first. Drift's primary audience is developers and power users; the keyboard surface is the product, the mouse is fallback.

  • ⌘K / Ctrl+K — Command palette (universal)
  • g t / g p — Go to Today / Projects (vim-style)
  • g 1–g 9 — Go to project by sidebar position
  • f — Set focus on highlighted task/project
  • c — Create new task (context-aware: in the active project)
  • Esc — Close dialogs, exit edit mode, clear command palette
  • / — Focus search in current surface

Mouse: click to act, drag deferred to v2. Hover reveals row actions on md+ (touch users tap to reveal).

Banned everywhere: infinite scroll (pagination only), drag-to-reorder in v1, hover-only affordances on sm viewports, modal stacks > 1 level deep.

Raw lines 67 to 82
83## Accessibility Floor
85Behavioral. Visual contrast lives in `DESIGN.md` (inherits shadcn's WCAG AA-compliant defaults; brand overrides verified to maintain ratios).
87- WCAG 2.2 AA across the responsive web surface.
88- Screen reader announces page surface on navigation: "Today, focus surface" / "Project: {name}, task list, {N} tasks."
89- Keyboard shortcuts available without modifier on most surfaces (vim-style `g t` etc.) — users with motor-control limitations get the same surface as power users.
90- `Tab` order matches reading order on every surface. `Esc` always closes the topmost modal/popover.
91- Command palette is fully keyboard-operable; results announce as they update via `aria-live`.
92- Focus rings inherit shadcn's `ring` token — visible at AA contrast against `background`.

Accessibility Floor

Behavioral. Visual contrast lives in DESIGN.md (inherits shadcn's WCAG AA-compliant defaults; brand overrides verified to maintain ratios).

  • WCAG 2.2 AA across the responsive web surface.
  • Screen reader announces page surface on navigation: "Today, focus surface" / "Project: {name}, task list, {N} tasks."
  • Keyboard shortcuts available without modifier on most surfaces (vim-style g t etc.) — users with motor-control limitations get the same surface as power users.
  • Tab order matches reading order on every surface. Esc always closes the topmost modal/popover.
  • Command palette is fully keyboard-operable; results announce as they update via aria-live.
  • Focus rings inherit shadcn's ring token — visible at AA contrast against background.
Raw lines 83 to 93
94## Responsive & Platform
96| Breakpoint | Behavior |
97|---|---|
98| `≥ lg` (1024px+) | Sidebar visible. Today is a 2-column layout: focus + in-motion list. |
99| `md` (768–1023px) | Sidebar collapses to icons. Today stacks to single column. |
100| `< md` (`sm`) | Sidebar becomes a `Sheet` triggered from top bar. Command palette opens fullscreen. |
102Drift is responsive web, not a native mobile app. The product works on phones for read + simple-edit, but the primary surface is desktop / laptop.

Responsive & Platform

BreakpointBehavior
≥ lg (1024px+)Sidebar visible. Today is a 2-column layout: focus + in-motion list.
md (768–1023px)Sidebar collapses to icons. Today stacks to single column.
< md (sm)Sidebar becomes a Sheet triggered from top bar. Command palette opens fullscreen.

Drift is responsive web, not a native mobile app. The product works on phones for read + simple-edit, but the primary surface is desktop / laptop.

Raw lines 94 to 103
104## Inspiration & Anti-patterns
106- **Lifted from Linear:** the keyboard-first discipline. `⌘K` is the command center; vim-style nav (`g t`); no drag for primary navigation; status pill vocabulary.
107- **Lifted from Notion:** inline-editable titles. Click-to-edit on project header, blur to save. No edit/view mode toggle.
108- **Lifted from shadcn:** the entire surface vocabulary. Drift's brand is *what we add to shadcn*, not a from-scratch design system. This is a deliberate posture, not a shortcut.
109- **Rejected — Streaks, badges, achievement notifications:** Drift is a tool, not a habit app. Task closure is its own reward; no celebratory animation, no "🎉 5-day streak!" toast.
110- **Rejected — AI-suggested next tasks:** Drift surfaces what's in motion, doesn't tell the user what to work on. The user picks focus; the tool surfaces consequences.
111- **Rejected — Multi-column kanban as default project view:** lists are linear; kanban hides progress behind columns. Optional v2; not the default.

Inspiration & Anti-patterns

  • Lifted from Linear: the keyboard-first discipline. ⌘K is the command center; vim-style nav (g t); no drag for primary navigation; status pill vocabulary.
  • Lifted from Notion: inline-editable titles. Click-to-edit on project header, blur to save. No edit/view mode toggle.
  • Lifted from shadcn: the entire surface vocabulary. Drift's brand is what we add to shadcn, not a from-scratch design system. This is a deliberate posture, not a shortcut.
  • Rejected — Streaks, badges, achievement notifications: Drift is a tool, not a habit app. Task closure is its own reward; no celebratory animation, no "🎉 5-day streak!" toast.
  • Rejected — AI-suggested next tasks: Drift surfaces what's in motion, doesn't tell the user what to work on. The user picks focus; the tool surfaces consequences.
  • Rejected — Multi-column kanban as default project view: lists are linear; kanban hides progress behind columns. Optional v2; not the default.
Raw lines 104 to 112
113## Key Flows
115### Flow 1 — Morning focus (Sarah, solo founder, 8:45am Tuesday)
1171. Sarah opens Drift in a browser tab.
1182. App loads Today. `display-sm`: "Welcome back, Sarah." Focus card shows yesterday's marked task — "Finish landing page hero copy" — still in motion.
1193. She hits `⌘K`, types "ship hero", sees the matching task and presses Enter to open it.
1204. Inline edit: she updates the task description with two new bullets. Tab + Tab triggers save.
1215. **Climax:** Sarah closes the dialog. Today re-renders: focus card still shows the hero task, but now with the updated body text visible at a glance. She doesn't have to navigate anywhere — the surface that greeted her now reflects the work she just did. She picks up her coffee and starts writing.
123Failure: data save fails → shadcn `Toast` (destructive variant): "Couldn't save. Trying again." Inline edit retained; another `Enter` retries.

Flow 1 — Morning focus (Sarah, solo founder, 8:45am Tuesday)

  1. Sarah opens Drift in a browser tab.
  2. App loads Today. display-sm: "Welcome back, Sarah." Focus card shows yesterday's marked task — "Finish landing page hero copy" — still in motion.
  3. She hits ⌘K, types "ship hero", sees the matching task and presses Enter to open it.
  4. Inline edit: she updates the task description with two new bullets. Tab + Tab triggers save.
  5. Climax: Sarah closes the dialog. Today re-renders: focus card still shows the hero task, but now with the updated body text visible at a glance. She doesn't have to navigate anywhere — the surface that greeted her now reflects the work she just did. She picks up her coffee and starts writing.

Failure: data save fails → shadcn Toast (destructive variant): "Couldn't save. Trying again." Inline edit retained; another Enter retries.

Raw lines 115 to 124
125### Flow 2 — Async handoff (Devon and Mara, small remote team, mid-afternoon)
1271. Devon finishes wiring up the auth flow and marks the task `done`.
1282. Mara, time-zoned three hours ahead and online during overlap, opens Drift.
1293. Today loads; her focus is on her own front-end work, but the in-motion list shows Devon's auth task now marked done and one task below it newly assigned to her — "Wire up post-auth redirect" — that Devon set during checkout.
1304. She hits `f` on the row to mark it as her focus, then `Enter` to open it.
1315. **Climax:** The focus card swaps. Her surface now shows the post-auth redirect task as the live thing she's working on; the projects sidebar shows the Auth project highlighted; the command palette `⌘K` defaults its first result to "Go to Auth project." The state of the team's progress is *embedded in her surface* — no Slack thread to scroll, no status doc to read.
133Failure: Devon hadn't actually assigned the follow-up — Mara mis-assigned to herself. She hits `Esc`, `f` again to unfocus, and reassigns to Devon. No "are you sure" dialog; Drift trusts the user.

Flow 2 — Async handoff (Devon and Mara, small remote team, mid-afternoon)

  1. Devon finishes wiring up the auth flow and marks the task done.
  2. Mara, time-zoned three hours ahead and online during overlap, opens Drift.
  3. Today loads; her focus is on her own front-end work, but the in-motion list shows Devon's auth task now marked done and one task below it newly assigned to her — "Wire up post-auth redirect" — that Devon set during checkout.
  4. She hits f on the row to mark it as her focus, then Enter to open it.
  5. Climax: The focus card swaps. Her surface now shows the post-auth redirect task as the live thing she's working on; the projects sidebar shows the Auth project highlighted; the command palette ⌘K defaults its first result to "Go to Auth project." The state of the team's progress is embedded in her surface — no Slack thread to scroll, no status doc to read.

Failure: Devon hadn't actually assigned the follow-up — Mara mis-assigned to herself. She hits Esc, f again to unfocus, and reassigns to Devon. No "are you sure" dialog; Drift trusts the user.

Raw lines 125 to 133