Next.js dashboard with git statistics, AI-powered summaries via Ollama, and research documents for project planning. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
59 KiB
stepsCompleted, inputDocuments, workflowType, project_name, user_name, date, lastStep, status, completedAt
| stepsCompleted | inputDocuments | workflowType | project_name | user_name | date | lastStep | status | completedAt | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
ux-design | GitPulse | Ramez | 2025-04-25 | 14 | complete | 2025-04-25 |
UX Design Specification GitPulse
Author: Ramez Date: 2025-04-25
Executive Summary
Project Vision
GitPulse is an open source desktop dashboard that solves multi-repo chaos: a developer launches the app and instantly sees the state of all their Git repositories — status, branches, pending commits, and alerts. The vision is the "command center" for the local code ecosystem.
Fundamental UX Constraints:
- Zero-config, zero-login — user sees dashboard in < 30 seconds after download
- Offline-first — no feature depends on network
- Native performance — ~15 MB binary, <200 MB RAM, 60fps
- Cross-platform — same experience on Windows, macOS, Linux
Target Users
Persona 1 — Sarah, Indie Dev Poly-Project (primary) Freelancer with 10-50+ repos across clients, OSS, personal. Daily context-switching. Loses track of unpushed commits, stale branches. Wants instant visibility, zero configuration. Tool budget: $0-10/month.
Persona 2 — Leo, Power User / Tech Lead (secondary) Senior dev in microservices architecture, 12-30+ repos. Uses CLI + GUI hybrid. Wants batch ops, cross-repo visibility, configures cloud API keys for advanced analysis.
Persona 3 — Max, Maker / Side-Project Builder (tertiary) Creative developer with 20+ side projects, many dormant. Needs dormancy detection and cleanup prompts.
Persona 4 — Jay, New Dev (onboarding) < 10 repos. Experience must remain valuable — no "empty" feeling with a small number of repositories.
Key Design Challenges
-
Information density vs readability — Each repo displays branch, status (clean/dirty/ahead/behind), last commit, stash count, and optionally an AI summary. For 5 to 100+ repos, the challenge is instant pattern recognition without visual overload.
-
Consistent multi-view navigation — Card Grid ↔ List View toggle must maintain a consistent visual status language (colors, badges, icons) and preserve selection when switching views (useful for batch ops).
-
Trust through transparency — The privacy indicator (FR27) is a key differentiator. Users must always know whether data stays local or transits to cloud, without being intrusive.
-
"5-Second Wow" — The conversion moment: first launch → auto-scan → full dashboard in < 30 seconds. The empty experience (0 repos) and small experience (< 10 repos, Jay) must also be engaging.
-
Platform-specific integration — System tray, notifications, auto-launch have different native behaviors on Windows, macOS, Linux. UX must be consistent while respecting each platform's conventions.
-
Progressive AI enhancement — Smart Status is an enrichment, never a dependency. The interface must be complete without AI, and naturally enriched when a provider is configured.
Design Opportunities
-
Unified visual status language — A consistent color/badge system (green = clean, orange = ahead/behind, red = dirty, grey = dormant) that works across Card Grid, List View, system tray, and notifications. This is the #1 UX lever for instant pattern recognition.
-
Batch ops with granular feedback — Selecting 15 repos and seeing results appear in real-time (success/failure per repo) is a major functional differentiator. The partial success UX can transform a tedious task into a satisfying interaction.
-
Trust as a feature — The Privacy Badge and local-first default can become a visual selling point. "Your code never leaves your machine" as a design element, not just text.
-
Smart Status as subtle enrichment — Rather than a separate AI panel, health summaries can appear naturally in RepoCards as an additional text line, with a discreet "AI" badge indicating the source.
Core User Experience
Defining Experience
Core loop: Scan → See → Act
The central action is the "visual status check" — the user opens GitPulse and immediately knows which repos need attention. It's a "check-in tool" like a weather app or monitoring dashboard: open, visually scan, act if needed, close.
Usage frequency varies by persona:
- Sarah: 2-3x/day (morning check, post-commit check, end-of-day check)
- Leo: 1-2x/day + occasional batch ops
- Max: 1x/week + monthly cleanup
- Jay: 1x/day to build familiarity
The one interaction to nail: The Card Grid visual scan. If the user can open GitPulse and in 2 seconds identify the 3 repos that need attention among 30+ repos, everything else follows.
Platform Strategy
Platform: Native Desktop (Tauri v2)
- Windows, macOS, Linux — same codebase, same UX
- Interaction: mouse + keyboard (desktop-first, no touch)
- Native WebView per platform (WebView2/WebKit/WebKitGTK)
Two interaction surfaces:
- Main Dashboard — Full desktop window with Card Grid / List View. The complete experience.
- System Tray — Always-present background agent. Push notifications + quick actions (pull, push, status). Functions with dashboard closed.
Platform constraints:
- Tray behavior differs by OS (Windows: taskbar, macOS: menu bar, Linux: D-Bus). UX must be functionally identical but visually native.
- OS notifications must respect each platform's system settings.
- Keyboard + shortcuts for all core operations (NFR25).
Effortless Interactions
Zero-effort by design:
- Launch → auto-scan (no action required)
- Scan results → persistent cache (instant reload on next launch)
- Repo status → updated via background batch fetch
One-effort:
- Batch pull/push: multi-select → one click → streaming results
- Rescan: single button (or keyboard shortcut)
- View toggle: one click or shortcut (Ctrl/Cmd+G grid, Ctrl/Cmd+L list)
What should disappear vs competitors:
- No login/password (vs GitKraken)
- No manual repo config (vs gita)
- No repo-by-repo navigation (vs lazygit)
- No setup wizard — dashboard appears directly
Critical Success Moments
Moment 1 — "5-Second Wow" (first launch) User downloads, launches, sees full dashboard in < 30 seconds. If repos appear with clear visual status, they instantly understand the value.
Moment 2 — First status check (first minute) User visually identifies a forgotten repo (behind, dirty, or dormant). The "oh, I forgot about that one!" reaction is instant product validation.
Moment 3 — First batch op (first session) Select 5-10 repos → batch pull → see results stream in real-time. Time savings are tangible and measurable.
Moment 4 — First Smart Status (first week) Configure Ollama → see an AI summary appear on a repo. The enrichment is subtle but rewarding.
Break moment — Empty state or error Empty dashboard (0 repos found) or failed scan. If the empty state isn't engaging with a clear call-to-action, the user abandons.
Experience Principles
-
Instant Visibility — All repo states visible at a glance. No navigation, no loading, no setup. Open = know.
-
Zero Friction Entry — No obstacles between download and value. No account, no config, no wizard. First scan starts automatically.
-
Progressive Power — Base interface is simple (visual status). Power (batch ops, AI, filters) reveals itself as needed, without overwhelming the initial user.
-
Trust by Default — Privacy is the default mode. The Privacy Badge isn't an intrusive notification but a reassuring design element, always visible but never blocking.
-
Native Feel — No "web app in a window." Native desktop behavior: keyboard shortcuts, system tray, OS notifications, fluid resizing, responsive performance.
Desired Emotional Response
Primary Emotional Goals
Emotion #1 — Relief The immediate feeling: "I don't have to check 30 repos manually anymore." GitPulse eliminates the anxiety of the unknown — the developer knows exactly where things stand. This is the emotion that drives recommendations: "You have to try this, it saved me."
Emotion #2 — Control The lasting feeling: "I dominate my code ecosystem." The user feels organized, informed, proactive rather than reactive. The Card Grid is the visual projection of this mastery.
Emotion #3 — Trust The underlying feeling: "My code stays on my machine." Trust isn't a feature but an absence of doubt. The Privacy Badge silently reinforces this confidence with every use.
Emotional Journey Mapping
Discovery → First Launch (curiosity → relief) User arrives with curiosity ("a free multi-repo tool?") and leaves with relief ("wow, I had 3 repos I forgot about"). The auto-scan is the emotional trigger.
Daily check-in (routine → confidence) After adoption, the daily check becomes routine. The target emotion is quiet confidence — user opens, confirms all is well, closes. No alerts = success.
Batch operation (hesitation → satisfaction) First batch op: user hesitates ("will this work on 15 repos at once?"). Result: tangible satisfaction. Partial failures must inspire confidence ("the failed ones are clearly flagged, I know what to do").
AI discovery (intrigue → delight) First Smart Status: curiosity ("what will the AI say about my repo?"). Result: subtle delight if the summary is relevant. AI must never disappoint — a useless summary is worse than no summary.
Empty/error state (confusion → clarity) 0 repos found or scan error. Emotion must shift quickly from confusion to clarity through a clear message/action ("Add directories to scan" with direct button to Settings).
Micro-Emotions
| Micro-Emotion | GitPulse Context | Design Response |
|---|---|---|
| Confidence vs Confusion | Scan results appearing | Progressive results, never a blank screen without feedback |
| Trust vs Skepticism | AI/Cloud data flow | Privacy Badge always visible, explicit opt-in for cloud |
| Accomplishment vs Frustration | Batch operations | Per-repo success/failure visual, no endless spinners |
| Delight vs Indifference | Smart Status summaries | Relevant, concise summaries, no generic filler text |
| Control vs Overwhelm | 50+ repos dashboard | Instant filters/sorts, status colors for pattern recognition |
| Belonging vs Isolation | Open source community | Discreet GitHub link, contributing hints |
Design Implications
-
Relief → Visible instant scan: Scan must show progressive results (repo count climbing), never a blank screen with spinner. Each appearing repo reinforces relief.
-
Control → Immediate visual status: Colors and badges must be interpretable in < 1 second without a legend. The color pattern must be instinctive (green = ok, red = problem).
-
Trust → Privacy as architecture: The Privacy Badge isn't a popup or banner but a permanent interface element, like the padlock in a browser. Present, discreet, reassuring.
-
Satisfaction → Streaming batch results: Each successful repo appears in green as it completes. Failures appear in red with detail. No "all or nothing" — progress is visible.
-
Delight → Subtle AI: Smart Status appears as a natural text line in the RepoCard, not a separate panel. A micro-badge "AI" indicates the source. If no AI is configured, the slot doesn't exist as an empty hole — it simply isn't there.
Emotional Design Principles
-
Show, don't tell — Value is visible at first glance. No text onboarding, no explanatory tooltips. The dashboard is visually self-explanatory.
-
Silent reassurance — Trust is built through absence of problems, not through messages. The Privacy Badge is like the HTTPS padlock — noticed when sought, never intrusive.
-
Celebrate progress, isolate failure — Batch ops show each success in real-time. Failures are isolated and actionable, never blocking the whole.
-
Calm competence — GitPulse doesn't try to impress. It is competent, reliable, understated. The design reflects this: no flashy animations, no sounds, no confetti. Just a tool that works.
UX Pattern Analysis & Inspiration
Inspiring Products Analysis
Linear (project management) The gold standard for developer tools. Keyboard-first interface, clean design, instant performance. Every interaction is fast and predictable. Information density is high without overload. Command palette (Cmd+K) for everything. Transferable: the "fast by default, power on demand" principle matches GitPulse's experience exactly.
Raycast (productivity launcher) Master of "zero-friction entry." Opens instantly, real-time results, closes fast. The "check-in tool" model is identical to GitPulse: open → see → act → close. Silent trust (no unnecessary notifications, no bloat) is a model for the system tray.
Docker Desktop (container dashboard) Multi-item dashboard with colored status indicators (green/yellow/red). Similar to GitPulse: multiple "entities" with visual states, possible batch actions. Their weakness: heavy, slow, Electron. GitPulse can adopt the dashboard pattern but with native lightness.
1Password (security app) The security padlock as a permanent, reassuring design element. Exactly the analogy for GitPulse's Privacy Badge. Trust is integrated into the interface, not added on top. The visual lock/unlock is a model for the local/cloud indicator.
lazygit (terminal git UI) The reference git TUI. Instant, keyboard-driven, all info visible on one screen. Proves developers want speed and density. Its limitation: single repo only. GitPulse extends this pattern to multiple repos.
Transferable UX Patterns
Navigation Patterns:
- Command palette (Linear/Raycast) — Cmd/Ctrl+K for quick access to any action (rescan, toggle view, batch pull). Scales without complicating the interface.
- Single-page dashboard — No tab-based hierarchical navigation. Everything visible on one page with filters/toggles to change perspective.
Interaction Patterns:
- Inline batch selection — Checkbox on each card/row for multi-select. Context toolbar appears when items are selected (batch pull/push/fetch).
- Streaming progress — Batch results appearing one by one (like Docker Desktop pull progress), no blocking until completion.
- Zero-setup first experience — Like Raycast: launch → immediate action, no wizard.
Visual Patterns:
- Status color system (Docker Desktop) — Green/yellow/red/grey for status with legend integrated into badge (icon + color, not color alone for accessibility).
- Trust indicator (1Password) — Permanent badge in a corner of the interface. Small, discreet, always present. Visually changes state when mode changes.
- Skeleton loading — Instead of spinners, placeholder cards showing structure while awaiting data.
Anti-Patterns to Avoid
-
Mandatory login for local features (GitKraken) — Users must use 100% of local features without an account. Login does not exist in GitPulse.
-
Blocking modal wizards — No "setup wizard" on first launch. Scan starts automatically, results appear directly.
-
Global spinners without feedback — Never a central spinner without progress indication. Always show advancement (repo count, progress bar, streaming results).
-
Web-like chrome in a desktop app — No web app sidebar navigation, no breadcrumbs, no hamburger menu header. The interface is a native dashboard.
-
Excessive notifications — System tray alerts only when relevant (repo behind, unpushed commits older than X days). No "tip of the day" or marketing notifications.
-
AI as intrusive feature — No "Configure AI!" popup on launch. AI is discoverable via Settings, and Smart Status appears naturally once configured.
-
Color as sole status indicator — Status badges use color + icon + label text for accessibility (NFR26-27). Never color alone.
Design Inspiration Strategy
What to Adopt:
- Command palette (Cmd/Ctrl+K) — supports keyboard-first developer workflow
- Status color + icon system (green/yellow/red/grey) — instant pattern recognition
- Streaming batch results — tangible progress visibility
- Privacy Badge as permanent element — trust through consistent presence
- Skeleton loading — no layout shift during loading
What to Adapt:
- Card Grid layout — adapt Docker Desktop's multi-entity grid for repo context (branch, status, ahead/behind, stash)
- System tray — adapt Raycast's "silent but present" background model with quick actions
- Empty state — create an engaging first experience for Jay (0-10 repos) that encourages exploration rather than feeling sparse
What to Avoid:
- Web navigation patterns (sidebars, breadcrumbs, hamburger menus)
- Setup wizards and mandatory configuration steps
- Modal-heavy workflows
- Notification spam
- AI-first messaging or aggressive AI onboarding
Design System Foundation
Design System Choice
Approach: Tailwind CSS + Radix UI Primitives (Headless)
GitPulse uses a hybrid approach: Tailwind CSS for styling and the token system, combined with Radix UI for accessible component primitives (Dialog, Select, Tooltip, Dropdown). No full design system like Material/Ant — too heavy and too opinionated for a solo project with a custom visual identity.
Component Stack:
| Concern | Solution | Rationale |
|---|---|---|
| Styling & tokens | Tailwind CSS | Already chosen in architecture. Utility-first, fast for solo dev |
| Component primitives | Radix UI | Accessible by default, unstyled (Tailwind controls visuals), lightweight |
| Icons | Lucide React | Open source, tree-shakeable, consistent linear style |
| Animations | Tailwind transitions + prefers-reduced-motion | Minimal, no animation library |
| Virtualization | @tanstack/react-virtual | For rendering 100+ repos (FR14/NFR6 gap identified in architecture) |
Rationale for Selection
Why not a full design system (Material, Ant, Chakra):
- GitPulse has a specific visual identity (status colors, Privacy Badge, card grid) that doesn't match Material/Ant conventions
- Complete design systems add 50-100 KB to bundle — contradicts ~15 MB binary target
- A solo developer doesn't benefit from full system velocity — customization takes longer than building from scratch with Tailwind
- Desktop native architecture (Tauri webview) benefits from lean CSS
Why Radix UI over Headless UI or alternatives:
- Built-in accessibility (ARIA, keyboard nav) — directly addresses NFR25-27
- Unstyled: no CSS override battles, Tailwind controls 100% of visuals
- Exact components GitPulse needs: Dialog (settings), Select (filters), Tooltip (status details), Dropdown (tray menu), Checkbox (batch select)
- Maintained by Radix team, used in production by Linear, Vercel
Why Lucide React:
- Linear icon style consistent with "calm competence" aesthetic
- Tree-shakeable — only used icons are included
- Open source (ISC), no license constraints
- 1000+ icons covering git, status, settings, AI
Implementation Approach
Design tokens via Tailwind config:
Status colors (core visual language):
- status-clean: green-500 (clean repo)
- status-dirty: red-500 (uncommitted changes)
- status-ahead: blue-500 (ahead of remote)
- status-behind: orange-500 (behind remote)
- status-dormant: gray-400 (no activity > threshold)
Neutrals:
- bg-primary, bg-secondary, bg-surface
- text-primary, text-secondary, text-muted
Privacy indicator:
- privacy-local: green-600 (Ollama / no AI)
- privacy-cloud: amber-500 (cloud API active)
Component architecture:
components/ui/— Tailwind-styled primitives (Button, Badge, Card, Input, Dialog, Select, Skeleton, Tooltip)- Each primitive wraps a Radix component with Tailwind styling
- Business components (RepoCard, PrivacyBadge, BatchToolbar) compose from primitives
- No runtime theming — tokens are compiled into CSS
Customization Strategy
Custom components (not in Radix, to be built):
RepoCard/RepoRow— Card with status badge, branch label, ahead/behind counter, AI summary linePrivacyBadge— Permanent local/cloud indicator with icon and labelStatusBadge— Colored badge with icon for each status (clean/dirty/ahead/behind/dormant)BatchProgress— Repo list with streaming success/failureViewToggle— Grid/list toggle with iconsEmptyState— Illustration + CTA for 0 repos and < 10 repos
Accessibility in each custom component:
- StatusBadge: color + icon + aria-label (never color alone)
- RepoCard: role="article", tabindex for keyboard nav
- PrivacyBadge: aria-live="polite" when mode changes
- BatchProgress: role="list", aria-label per repo result
Core User Experience
Defining Experience
"Launch and Know" — Open and immediately know.
The defining experience is the moment the user opens GitPulse and sees the state of all repos at a glance. No navigation, no setup, no searching. The Card Grid is GitPulse's "swipe" — the interaction that, if perfected, makes everything else natural.
What the user describes to a friend: "You launch it and you immediately see which repos are dirty, which are behind, which are dormant. No more checking one by one."
The equation: Repo count × info per repo = instant pattern recognition. If the Card Grid lets Sarah see in 2 seconds that 3 out of 30 repos need attention, the experience succeeds.
User Mental Model
How developers currently think:
- Existing mental model:
cd repo && git status— one repo at a time, mental stack limited to ~5 repos - Frustration: "I know I forgot to push something but I don't remember where"
- Workarounds: shell scripts (fragile), mental notes (imperfect), growing anxiety with repo count
Expectations for GitPulse:
- Expects an "overview" — not a per-repo tool
- Expects to understand status without reading text — visual recognition
- Expects to act directly from the view — no additional navigation
- Expects it to "just work" without config — like
lsin a terminal
Potential confusion points:
- "Where are my repos?" if scan doesn't cover the right directories → Empty State with clear CTA
- "What does this color mean?" if status system isn't instinctive → icons + labels, not color alone
- "How do I act on a repo?" if actions aren't discoverable → right-click + command palette
Success Criteria
The "Launch and Know" interaction succeeds when:
- 2-second scan — User identifies problematic repos in < 2 seconds visually
- Zero learning curve — First use without documentation, status meanings are instinctive
- Pattern recognition — User perceives patterns ("3 repos behind", "all clean") without individual reading
- Action proximity — User can act on a repo in < 2 clicks from the Card Grid
- Scale gracefully — Experience is equally satisfying with 5 repos (Jay) as with 50+ (Sarah)
Success feedback:
- Status badges immediately interpretable (color + icon + count)
- Ahead/behind counts visible directly on cards
- "All clean" is a satisfying visual state — all green = peace of mind
- Dirty/dormant repos "pop" visually — the eye is naturally drawn to problems
Novel UX Patterns
Established patterns adopted:
- Card Grid (Docker Desktop, Trello) — familiar, adapted for multi-entity
- Status color system (traffic lights, Docker) — universally understood
- Multi-select + batch actions (email clients, file managers) — known pattern
- Command palette (VS Code, Linear) — developers know it
GitPulse's unique twist:
- The Privacy Badge is a novel pattern in git tools. No competitor offers a privacy indicator. It's a visual differentiator — the green "local" padlock becomes GitPulse's visual signature.
- Smart Status inline — AI summaries aren't in a separate panel but integrated directly into cards as natural content. A discreet "AI" badge indicates the source. This "invisible AI augmentation" pattern is new in git tools.
- Dormancy glow — Dormant repos get subtle visual treatment (reduced opacity, "sleeping" badge) that signals inactivity without being alarmist. No red — it's information, not a problem.
Experience Mechanics
Flow: Launch and Know
1. Initiation:
- Double-click exe/dmg → window opens directly (no splash screen)
- First launch: auto-scan of home directory. Results appear progressively.
- Subsequent launches: cache loaded instantly, then background rescan for updates.
2. Visual scan (2-second pattern recognition):
- Eye scans Card Grid left-to-right, top-to-bottom
- Status badges (color + icon) are first fixation point — brain automatically filters by color
- "Problematic" cards (red, orange) attract attention first
- "Clean" cards (green) form a reassuring background
- "Dormant" cards (grey, reduced opacity) blend into the background
3. Action proximity:
- Click on card → expand detail (branch, last commit, stash, AI summary)
- Right-click → context menu (pull, push, fetch, open in terminal)
- Multi-select (checkbox or Shift/Ctrl+click) → batch toolbar appears
- Cmd/Ctrl+K → command palette for quick actions
4. Feedback loop:
- Batch op in progress → each repo visually transitions (grey → spinner → green/red)
- Results visible in real-time — no need to wait for batch completion
- Errors displayed inline on the concerned repo's card (no global error modal)
5. Completion:
- "All clean" is the resting state — user closes dashboard, confident
- System tray continues passive monitoring
- Notification only if a repo changes state (new behind, dirty detected)
Visual Design Foundation
Color System
Philosophy: GitPulse is a developer desktop tool. Dark mode is the default (developer preference), with full light mode support. Status colors are the heart of the visual system.
Dark Mode (default):
| Token | Value | Usage |
|---|---|---|
bg-primary |
gray-950 (#0a0a0a) |
Main background |
bg-surface |
gray-900 (#171717) |
Card backgrounds |
bg-elevated |
gray-800 (#262626) |
Hovered cards, dropdowns |
border |
gray-700 (#404040) |
Card borders, dividers |
text-primary |
gray-50 (#fafafa) |
Main text |
text-secondary |
gray-300 (#d4d4d4) |
Secondary text, labels |
text-muted |
gray-500 (#737373) |
Muted text, timestamps |
Status Colors (shared dark/light):
| Status | Color | Icon | Tailwind |
|---|---|---|---|
| Clean | Green | CheckCircle | text-green-500 / bg-green-500/10 |
| Dirty | Red | AlertCircle | text-red-500 / bg-red-500/10 |
| Ahead | Blue | ArrowUpCircle | text-blue-500 / bg-blue-500/10 |
| Behind | Orange | ArrowDownCircle | text-orange-500 / bg-orange-500/10 |
| Dormant | Gray | Moon | text-gray-400 / bg-gray-400/10 |
Privacy Indicator:
- Local:
text-green-600+ shield icon + label "Local" - Cloud:
text-amber-500+ cloud icon + label provider name
Accessibility: All text/background combos meet WCAG AA contrast ratio (4.5:1 normal text, 3:1 large text). Status badges always use color + icon + label, never color alone.
Typography System
Principle: "Native feel" = system fonts by default.
GitPulse uses platform system fonts for native rendering. No web fonts to load — instant performance and OS consistency.
Font stack:
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
Helvetica, Arial, sans-serif;
- macOS: San Francisco
- Windows: Segoe UI
- Linux: Noto Sans
Code/monospace (branch names, commit hashes):
font-family: "SF Mono", "Cascadia Code", "Fira Code", "Consolas", monospace;
Type Scale:
| Role | Size | Weight | Usage |
|---|---|---|---|
text-xl |
20px | Semibold (600) | Window title, empty state heading |
text-lg |
18px | Medium (500) | Section headings |
text-base |
16px | Regular (400) | Card repo name, primary content |
text-sm |
14px | Regular (400) | Branch names, status text, AI summaries |
text-xs |
12px | Medium (500) | Timestamps, badges, counts, muted info |
Line heights: 1.5 for body text, 1.2 for headings, 1.0 for single-line data (counts, badges).
Spacing & Layout Foundation
Base unit: 4px. All spacing is a multiple of 4px for consistency.
Spacing Scale:
| Token | Value | Usage |
|---|---|---|
space-1 |
4px | Inline gaps, icon padding |
space-2 |
8px | Tight component spacing, badge padding |
space-3 |
12px | Card internal padding |
space-4 |
16px | Standard padding, card gaps |
space-6 |
24px | Section spacing |
space-8 |
32px | Major section breaks |
Card Grid Layout:
- Grid gap: 16px (
space-4) - Card min-width: 280px, max-width: 360px
- Responsive: auto-fill with
minmax(280px, 1fr) - Cards per row: adapts to window width (2-5 cards)
List View Layout:
- Row height: 56px
- Columns: checkbox | status icon | repo name | branch | ahead/behind | last commit | actions
- Column widths: fixed for status (32px), flexible for name, fixed for counts
Window Layout:
- Min window size: 800×600
- Default window size: 1200×800
- Top bar: 48px (title + view toggle + filters + Privacy Badge)
- No sidebar — single-page dashboard
Accessibility Considerations
- Contrast: All text/background combos meet WCAG AA (4.5:1 normal, 3:1 large text)
- Status identification: Never color alone — always color + icon + text label
- Focus indicators: Visible focus rings (2px ring, offset 2px) on all interactive elements
- Keyboard navigation: Tab order logical (top bar → cards → actions), arrow keys within card grid
- Screen readers: ARIA labels on all status badges, live regions for batch results and privacy mode changes
- Reduced motion:
prefers-reduced-motionrespected — no animations when OS setting is active - High contrast: OS high contrast mode triggers fallback to system colors with enhanced borders
Design Direction Decision
Design Directions Explored
Six design directions were generated and evaluated as interactive HTML mockups (ux-design-directions.html):
- Compact Grid — Maximum density, tight cards, status badges pop
- Spacious Cards — Breathing room, metric boxes, AI summaries prominent
- List-First — Table layout, batch-native, power user focus
- Stats Dashboard + Grid — Summary metrics bar above card grid
- Hybrid Detail Panel — Split view with left list + right detail panel
- Minimal Zen — Ultra-clean status dots, click-to-expand
Chosen Direction
D1 Compact Grid + D4 Stats Bar (combined)
The compact card grid delivers the 2-second pattern recognition that defines GitPulse's core experience. The collapsible stats bar adds "mission control" context without sacrificing grid density.
Layout structure (top to bottom):
- Top bar (48px) — Title, Grid/List toggle, filter pills with counts, rescan button, Privacy Badge
- Stats bar (collapsible, ~60px) — 5 metric cards: Clean / Dirty / Ahead / Behind / Dormant counts
- Card Grid (main area) — Compact repo cards with status badge, branch, ahead/behind/stash, last commit time
- Batch toolbar (appears on multi-select) — Pull, Push, Fetch, Status actions with count
Card Grid is default view. List View (D3 table) available via toggle for batch operations and power-user sorting/filtering.
Design Rationale
Why Compact Grid (not Spacious):
- GitPulse's core value is seeing ALL repos at once. More cards visible = better pattern recognition.
- Sarah (30+ repos) needs density. Jay (< 10 repos) doesn't need spaciousness — the empty space would feel worse, not better.
- AI Smart Status fits as a subtle one-liner in the card footer. It enriches without requiring card expansion.
Why Stats Bar (collapsible):
- "7 clean, 1 dirty, 2 behind" visible without scanning cards = instant health overview.
- Collapsible because power users (Leo) may find it redundant after the first week.
- Stats bar doubles as a filter — clicking a stat card filters the grid to that status.
Why not Hybrid Panel (D5):
- Only one repo visible in detail at a time contradicts GitPulse's "see everything at a glance" principle.
- Detail info (commits, AI summary) accessible via click-to-expand on individual cards instead.
Why not Minimal Zen (D6):
- Too minimal for a tool users rely on daily. Branch names and counts are essential, not optional.
- Risks perception of "incomplete" rather than "elegant."
Implementation Approach
Component hierarchy:
App
├── TopBar
│ ├── ViewToggle (Grid/List)
│ ├── FilterPills (All, Dirty, Behind, Dormant) with counts
│ ├── RescanButton
│ └── PrivacyBadge
├── StatsBar (collapsible)
│ └── StatCard × 5 (Clean, Dirty, Ahead, Behind, Dormant)
├── CardGrid (default view, virtualized)
│ └── RepoCard × N
│ ├── StatusBadge
│ ├── BranchLabel
│ ├── CountStats (ahead/behind/stash)
│ ├── SmartStatusLine (optional, when AI configured)
│ └── LastCommitTime
├── ListView (toggled view)
│ ├── ListHeader (sortable columns)
│ └── RepoRow × N (with checkboxes)
└── BatchToolbar (appears on multi-select)
├── SelectionCount
└── ActionButtons (Pull, Push, Fetch, Status)
User Journey Flows
Journey 1: First Launch (Jay's Journey — 5-Second Wow)
Goal: Jay downloads GitPulse, launches, and sees a full dashboard in < 30 seconds. Zero config, zero login.
flowchart TD
A[Download binary] --> B[Launch GitPulse]
B --> C{First launch?}
C -->|Yes| D[Auto-scan home directory]
C -->|No| E[Load cached repos instantly]
D --> F[Show scan progress: repo count climbing]
F --> G{Repos found?}
G -->|0 repos| H[Empty State: Add scan directories CTA]
G -->|1-9 repos| I[Card Grid + Stats Bar]
G -->|10+ repos| I
E --> I
H --> J[User adds scan root]
J --> D
I --> K[User sees status badges at a glance]
K --> L{Problem repos visible?}
L -->|Yes| M[Click dirty/behind card for detail]
L -->|No| N[All clean = peace of mind]
M --> O[Right-click context menu: Pull / Open terminal]
N --> P[Close dashboard or minimize to tray]
Entry points: Double-click binary, system tray icon click Success criteria: Dashboard visible with repo statuses in < 30 seconds from launch Error recovery: 0 repos → Empty State with clear CTA to add scan directories Feedback: Scan progress shows repo count climbing, skeleton cards during load
Journey 2: Daily Status Check (Sarah's Journey — Morning Check-in)
Goal: Sarah opens GitPulse in the morning, identifies in 2 seconds the 3 repos needing attention among 30+ repos.
flowchart TD
A[Launch GitPulse] --> B[Cache loads instantly]
B --> C[Background rescan starts]
C --> D[Stats Bar: 24 clean, 3 dirty, 2 behind, 1 dormant]
D --> E[Sarah scans Card Grid visually]
E --> F[Eye drawn to red/orange cards]
F --> G[auth-service: Dirty, 3 uncommitted]
F --> H[shared-libs: Behind 12 commits]
F --> I[old-experiment: Dormant, 3 months]
G --> J[Click auth-service card]
J --> K[Card expands: branch, stash, AI summary]
K --> L[Right-click: Open in terminal]
H --> M[Select shared-libs checkbox]
M --> N[Batch toolbar appears]
N --> O[Click Pull]
O --> P[Streaming results: green checkmark appears]
I --> Q[Note: will clean up later]
L --> R[Commit and push in terminal]
P --> S[Stats Bar updates: behind count drops to 0]
R --> T[Rescan: auth-service turns green]
T --> U[All clean. Close dashboard. Tray continues monitoring.]
Entry points: App launch, system tray click Success criteria: Problem repos identified in < 2 seconds, action taken in < 30 seconds Feedback: Stats bar provides numeric context, card colors provide instant pattern recognition Error recovery: Pull fails on shared-libs → red X with error detail inline, other repos unaffected
Journey 3: Batch Operations (Leo's Journey — Sprint Start)
Goal: Leo batch-pulls 12 microservice repos at sprint start, then uses Smart Status to verify overall health.
flowchart TD
A[Leo opens GitPulse] --> B[Switch to List View]
B --> C[Click column header: Sort by Behind]
C --> D[12 repos behind remote]
D --> E[Select All behind]
E --> F[Batch toolbar: 12 repos selected]
F --> G[Click Pull]
G --> H[Streaming results appear row by row]
H --> I{Per-repo result}
I -->|Success| J[Row turns green, checkmark]
I -->|Auth error| K[Row turns red, error detail inline]
I -->|Conflict| L[Row turns red, merge conflict message]
J --> M[10/12 succeeded]
K --> N[2/12 failed: api-auth, payment-svc]
L --> N
M --> O[Click failed repo for error detail]
N --> O
O --> P[Resolve in terminal or retry]
P --> Q[Rescan: all green]
Q --> R[Configure DeepSeek API key in Settings]
R --> S[Privacy Badge: Local changes to Cloud DeepSeek]
S --> T[Smart Status summaries appear on cards]
T --> U[AI: All microservices synced. Shared auth library version mismatch in 2 repos.]
Entry points: App launch, Monday morning routine Success criteria: 12 repos pulled in < 30 seconds, partial failures clearly reported Feedback: Streaming per-repo results, success count updating in real-time Error recovery: Failed repos show specific error (auth, conflict), successful repos complete independently
Journey 4: Dormancy Cleanup (Max's Journey — Monthly Review)
Goal: Max discovers 8 dormant repos and decides which to archive.
flowchart TD
A[Max opens GitPulse] --> B[Filter: Dormant]
B --> C[8 repos shown with reduced opacity]
C --> D[Stats Bar: 8 dormant more than 90 days]
D --> E[Scan cards: old-prototype, tutorial-clone...]
E --> F[Click old-prototype card]
F --> G[Smart Status: Last commit 6 months ago. Safe to archive.]
G --> H{Action?}
H -->|Archive| I[Right-click: Open in file manager]
H -->|Keep| J[Move on to next]
I --> K[Manually archive/move directory]
J --> L[Rescan: dormant repos update]
K --> L
L --> M[Check remaining repos]
M --> N[3 repos have uncommitted changes from weeks ago]
N --> O[Select 3 then Batch status]
O --> P[Review uncommitted changes]
P --> Q[Decide: commit and push or discard]
Entry points: Weekly/monthly review, tray notification ("3 repos dormant for 90+ days") Success criteria: Identify and action dormant repos in a single session Feedback: Dormant filter shows only relevant repos, reduced opacity visually deprioritizes them Error recovery: No destructive actions in GitPulse — "archive" opens file manager, user decides
Journey Patterns
Navigation Pattern — Filter then Act:
- User applies a filter (status, or click stat card) → grid shows only matching repos
- User scans filtered results → identifies targets
- User selects and acts → batch toolbar appears
- Results stream in → grid updates in real-time
Feedback Pattern — Streaming Progress:
- Action triggered → all selected items show "loading" state (grey spinner)
- Each item completes → transitions to success (green) or failure (red + detail)
- Progress counter in toolbar: "10/12 complete"
- Stats bar updates after all items finish
Error Pattern — Isolate and Report:
- Error occurs on one item → only that item affected
- Item shows inline error detail (not modal)
- User clicks error for expanded detail
- Other items continue processing unaffected
Flow Optimization Principles
- Minimize steps to value — Every journey starts with "open and see." No intermediate screens between launch and dashboard.
- Progressive disclosure — Card shows essential info. Click expands detail. Right-click offers actions. No information overload on first glance.
- Batch by default — Multi-select and batch toolbar make acting on multiple repos as natural as acting on one.
- Error isolation — Failures never block successes. Every batch operation shows per-item results independently.
- Stats as navigation — Clicking a stat card (e.g., "3 dirty") filters the grid, combining overview and action in one interaction.
Component Strategy
Design System Components
From Radix UI (styled with Tailwind tokens):
| Radix Primitive | GitPulse Usage | Styling |
|---|---|---|
Dialog |
Settings panels, AI config | Tailwind: bg-surface, border, rounded-xl |
Select |
Sort dropdown, filter selector | Tailwind: custom trigger, status-colored options |
Tooltip |
Status badge hover details, counts | Tailwind: bg-elevated, text-sm, delay-300 |
DropdownMenu |
Right-click context on cards/rows | Tailwind: bg-surface, items with icons |
Checkbox |
Batch selection in List View | Tailwind: border, rounded, checked:bg-blue-500 |
ToggleGroup |
Grid/List view switch | Tailwind: border, rounded-lg, active:bg-elevated |
Popover |
Card detail expansion on click | Tailwind: bg-surface, shadow-xl |
Separator |
Stats bar dividers, card sections | Tailwind: bg-border |
From Lucide React (icons):
| Icon | Usage | Component |
|---|---|---|
| CheckCircle | Clean status | StatusBadge |
| AlertCircle | Dirty status | StatusBadge |
| ArrowUpCircle | Ahead status | StatusBadge |
| ArrowDownCircle | Behind status | StatusBadge |
| Moon | Dormant status | StatusBadge |
| Shield | Privacy local | PrivacyBadge |
| Cloud | Privacy cloud | PrivacyBadge |
| RefreshCw | Rescan | TopBar |
| Grid / List | View toggle | ViewToggle |
| GitBranch | Branch label | RepoCard |
| Clock | Last commit | RepoCard |
| Inbox | Stash count | RepoCard |
Custom Components
RepoCard
Purpose: Display a single repository's status in the Card Grid. The fundamental unit of the GitPulse dashboard.
Anatomy:
+------------------------------+
| repo-name [Badge] | header: name + StatusBadge
| branch-name | monospace branch label
| Ahead: 3 Behind: 0 S: 0 | count stats
| --------------------------- | subtle divider
| 2h ago 3 unpushed | footer: time + action badge
| AI: 3 unpushed commits... | SmartStatusLine (optional)
+------------------------------+
States: default, hover (border-lighten, bg-elevated), selected (border-blue), loading (skeleton), error (border-red), dormant (opacity-50)
Accessibility: role="article", tabindex=0, aria-label="Repository {name}: {status}, {ahead} ahead, {behind} behind", Enter/Space opens detail popover
RepoRow
Purpose: Table row for List View with sortable columns and checkbox selection.
Anatomy:
[checkbox] [icon] repo-name branch up:3 down:0 2h ago [menu]
States: default, hover (bg-elevated), selected (bg-blue/5), loading, error (bg-red/5)
Accessibility: role="row", aria-selected, checkbox keyboard accessible
StatusBadge
Purpose: Compact visual indicator for repository status. Always uses color + icon + label text.
Variants:
| Variant | Color | Icon | Label |
|---|---|---|---|
| clean | green-500 | CheckCircle | "Clean" |
| dirty | red-500 | AlertCircle | "Dirty" |
| ahead | blue-500 | ArrowUpCircle | "Ahead" |
| behind | orange-500 | ArrowDownCircle | "Behind" |
| dormant | gray-400 | Moon | "Dormant" |
Sizes: sm (10px text, compact cards), md (12px text, default), lg (14px text, stats bar)
Accessibility: aria-label="{status} repository", never relies on color alone
StatsBar
Purpose: Summary metrics bar at top of dashboard. Collapsible. Each stat card is clickable to filter grid.
Anatomy:
+--------+ +--------+ +--------+ +--------+ +--------+
| 7 | | 1 | | 3 | | 2 | | 1 |
| Clean | | Dirty | | Ahead | | Behind | |Dormant |
+--------+ +--------+ +--------+ +--------+ +--------+
States: Each stat card: default, hover (cursor-pointer, bg-elevated), active/filtered (border-status-color)
Accessibility: Each card has aria-label="{count} {status} repositories", role="button", click filters grid
PrivacyBadge
Purpose: Permanent indicator showing local vs cloud data processing mode. Always visible in TopBar.
Variants:
| Mode | Icon | Color | Label |
|---|---|---|---|
| local/no AI | Shield | green-600 | "Local" |
| Ollama | Shield | green-600 | "Local" |
| Cloud provider | Cloud | amber-500 | "{Provider}" |
States: Transition animation when mode changes (subtle color crossfade), aria-live="polite" announces change to screen readers
BatchToolbar
Purpose: Appears when repos are selected. Shows count and action buttons.
Anatomy:
| 3 selected [Pull] [Push] [Fetch] [Status] [Cancel] |
States: Appears with slide-down animation, disappears when selection clears, buttons disabled during active operation, progress counter replaces selection count during operation
Accessibility: role="toolbar", aria-label="{count} repositories selected", each button has aria-label with action + count
SmartStatusLine
Purpose: AI-generated one-line health summary. Appears in RepoCard footer when AI is configured.
Anatomy:
| AI: 3 unpushed commits on feature branch. Ready for PR. |
Blue left border (2px), text-sm, text-secondary, italic, optional "AI" micro-badge
States: loading (skeleton pulse), loaded (text), error (hidden — no error shown, graceful absence)
Accessibility: aria-label="AI summary: {text}", visually indicated by left border color
EmptyState
Purpose: Displayed when no repos are found. Engaging CTA to add scan directories.
Anatomy:
+----------------------------------+
| [Git illustration] |
| No repositories found |
| Add directories to scan |
| [Open Settings] |
| |
| Tip: GitPulse scans for |
| .git folders recursively |
+----------------------------------+
Accessibility: role="status", aria-live="polite", CTA button keyboard focusable
Component Implementation Strategy
Layer 1 — Radix + Tailwind Primitives (components/ui/):
- Button, Card, Dialog, Select, Tooltip, DropdownMenu, Checkbox, ToggleGroup, Input, Skeleton
- Each wraps Radix with Tailwind styling. No custom logic.
Layer 2 — GitPulse Domain Components (components/dashboard/, components/batch/, components/ai/):
- RepoCard, RepoRow, StatusBadge, StatsBar, PrivacyBadge, BatchToolbar, SmartStatusLine, EmptyState
- Composed from Layer 1 primitives + domain logic (Tauri IPC calls via hooks)
Layer 3 — Feature Compositions (App.tsx):
- TopBar, CardGrid, ListView
- Wire Layer 2 components together with stores and hooks
Implementation Roadmap
Phase 1 — Core Dashboard (FR1-FR13):
- StatusBadge — foundation for all visual status
- RepoCard — core card component
- CardGrid — virtualized grid with @tanstack/react-virtual
- StatsBar — summary metrics
- EmptyState — 0 repos experience
Phase 2 — Batch Operations (FR15-FR21): 6. RepoRow — list view row with checkbox 7. BatchToolbar — selection actions 8. ListView — sortable table with virtualization
Phase 3 — AI & Settings (FR22-FR41): 9. PrivacyBadge — trust indicator 10. SmartStatusLine — AI summary in cards 11. Settings panels — using Radix Dialog + primitives
UX Consistency Patterns
Button Hierarchy
| Priority | Style | Usage | Example |
|---|---|---|---|
| Primary | bg-blue-500, text-white, rounded-lg | Main action per context | "Pull", "Save Settings" |
| Secondary | bg-elevated, border, text-primary | Alternative actions | "Push", "Fetch", "Cancel" |
| Destructive | bg-red-500/10, text-red-500, border-red | Irreversible actions | "Reset All Settings" |
| Ghost | transparent, text-secondary, hover:bg-elevated | Low-priority, toolbar | "Rescan", view toggle icons |
| Disabled | opacity-50, cursor-not-allowed | Unavailable action | Batch buttons during active op |
Rules:
- Only one primary button visible per context
- Destructive actions always require confirmation (Radix Dialog)
- Button text is always a verb ("Pull", not "OK")
- Icon + text for primary, icon-only for ghost/toolbar with tooltip
Feedback Patterns
Success:
- Repo-level: card/row transitions to green checkmark, brief green flash on status badge
- Batch-level: counter updates "10/12 complete", stats bar numbers animate
- No toast/notification for success — the visual state change IS the feedback
Error:
- Repo-level: card/row shows red border + inline error text (e.g., "Auth failed", "Merge conflict")
- Batch-level: failed repos highlighted, successful repos remain green. "2/12 failed" in toolbar
- Error detail: click failed repo → popover with full error message + suggested action
- Never modal for batch errors — always inline
Warning:
- Privacy mode change: PrivacyBadge transitions with amber flash + aria-live announcement
- Dormancy: reduced opacity + dormant badge, no red/orange alarm
Info:
- Scan progress: repo count climbs in real-time ("Scanning... 12 repos found")
- Background rescan: subtle progress indicator in top bar, non-blocking
Loading States
Skeleton loading (initial load):
- Card grid shows skeleton cards (grey rectangles matching RepoCard shape) during first scan
- No central spinner — skeleton cards communicate layout and progress simultaneously
- Skeleton count matches cached repo count if available, otherwise show 6 skeletons
Streaming loading (batch operations):
- Each repo transitions individually: default → spinner overlay → green/red result
- Other repos remain interactive during batch — user can still click and explore
- Batch toolbar shows progress counter: "Pulling... 7/12"
Inline loading (AI queries):
- SmartStatusLine shows skeleton pulse animation while AI generates summary
- Other card content remains visible and interactive during AI load
- If AI fails or times out: SmartStatusLine simply doesn't appear (graceful absence)
Never:
- Never a full-page spinner blocking all interaction
- Never a modal "Loading..." dialog
- Never disable the entire UI during an operation
Empty States
0 repos found:
- Center of dashboard: Git illustration, "No repositories found", "Add directories to scan"
- Primary CTA button: "Open Settings" → opens Settings to Scan Roots tab
- Secondary text: "GitPulse scans for .git folders recursively"
- Stats bar hidden (no data to show)
0 results after filter:
- Center of grid area: "No {status} repositories" with filter icon
- Ghost button: "Clear filter" → resets filter to "All"
- Suggestion: "Try a different filter or rescan"
First launch scanning:
- "Scanning your directories..." with animated repo count
- First repo appears immediately as skeleton → fills in as discovered
- Transition from empty state to card grid is seamless (cards appear progressively)
Navigation Patterns
Primary navigation — single page:
- No sidebar, no tabs, no routing. The dashboard IS the app.
- Content changes via: filters, view toggle, card expansion
Context menus — right-click:
[Repo name]
─────────────
Pull
Push
Fetch
─────────────
Open in Terminal
Open in File Manager
Copy Path
─────────────
Refresh Status
- Dividers separate action groups (git ops / system / utility)
- Actions use Lucide icons + text label
- Disabled items shown greyed, not hidden
Command palette — Cmd/Ctrl+K:
+----------------------------------+
| Search commands... |
+----------------------------------+
| Rescan All Repositories |
| Toggle Grid / List View |
| Filter: Dirty Repos |
| Filter: Behind Repos |
| Batch Pull Selected |
| Open Settings |
| Open AI Configuration |
| Check for Updates |
+----------------------------------+
- Fuzzy search on command names
- Keyboard navigable (arrow keys + Enter)
- Esc to close
Additional Patterns
Toastless design:
- GitPulse does not use toast notifications in the dashboard
- All feedback is inline (card states, toolbar counters, stats bar)
- System tray uses native OS notifications for background alerts only
Keyboard shortcuts:
| Shortcut | Action |
|---|---|
| Cmd/Ctrl+K | Command palette |
| Cmd/Ctrl+G | Switch to Grid view |
| Cmd/Ctrl+L | Switch to List view |
| Cmd/Ctrl+R | Rescan |
| Cmd/Ctrl+, | Open Settings |
| Cmd/Ctrl+A | Select all repos |
| Escape | Clear selection / close palette |
| Space (on card) | Toggle selection |
| Enter (on card) | Expand detail |
Confirmation patterns:
- Destructive actions (Reset Settings): Radix Dialog with "This cannot be undone" + Cancel/Confirm
- Batch operations on 10+ repos: no confirmation — progress is visible, user can cancel mid-operation
- Privacy mode change: no confirmation needed — PrivacyBadge updates, user can revert in Settings
Window behavior:
- Closing window → minimizes to system tray (app continues running)
- Cmd/Ctrl+Q or tray Quit → actually quits
- Window position/size remembered across launches
Responsive Design & Accessibility
Responsive Strategy
Desktop-only — no mobile, no tablet.
GitPulse is a native desktop application (Tauri v2). Responsive design is limited to adapting the desktop window between minimum size (800x600) and large screens (2560x1440+).
No mobile/tablet strategy:
- No touch interactions
- No bottom navigation
- No hamburger menu
- No mobile breakpoints
- System tray handles the "minimal" context when dashboard is closed
Window resize adaptation:
| Window Width | Card Grid Behavior | Stats Bar | Top Bar |
|---|---|---|---|
| < 900px | 2 cards per row | Collapsed (icon counts only) | Filters hidden in dropdown |
| 900-1200px | 3 cards per row | Expanded (5 stat cards) | Full top bar |
| 1200-1600px | 4 cards per row | Expanded | Full top bar |
| > 1600px | 5+ cards per row | Expanded | Full top bar, more breathing room |
Window height adaptation:
- < 600px (minimum): stats bar auto-collapsed, grid scrollable
- 600-800px: stats bar visible, grid fits ~3 rows of cards
-
800px: full experience, 4+ rows visible without scroll
Resize behavior:
- Card grid reflows immediately (CSS Grid auto-fill)
- Stats bar collapse/expand is smooth, no content jump
- Window position and size persisted via
tauri-plugin-store - Min window size enforced: 800x600
Breakpoint Strategy
Desktop breakpoints only (CSS media queries within Tauri webview):
| Breakpoint | Width | Layout Change |
|---|---|---|
sm |
< 900px | 2-col grid, collapsed stats, compact top bar |
md |
900-1199px | 3-col grid, full stats, full top bar |
lg |
1200-1599px | 4-col grid (default) |
xl |
>= 1600px | 5+ col grid, max-width container optional |
Implementation: Tailwind breakpoints (sm:, md:, lg:, xl:) applied directly in component classes. No CSS-in-JS, no runtime theme switching.
Accessibility Strategy
Target: WCAG 2.1 Level AA (industry standard, addresses NFR25-27)
1. Color & Contrast (NFR26):
- All text meets 4.5:1 contrast ratio (normal text), 3:1 (large text/UI components)
- Status indicators never rely on color alone — always color + icon + text label
- StatusBadge tested against: protanopia, deuteranopia, tritanopia, achromatopsia
- High contrast mode: OS setting triggers fallback to system colors + enhanced borders
2. Keyboard Navigation (NFR25):
- All interactive elements reachable via Tab
- Arrow keys navigate within card grid (2D grid navigation pattern)
- Enter/Space activates focused element
- Escape closes popovers/command palette
- Focus trap in Dialog (settings) — Tab cycles within dialog
- Visible focus indicators: 2px ring, offset 2px, blue-500 color
- Skip-to-content: Cmd/Ctrl+K serves as universal keyboard entry point
3. Screen Reader Compatibility (NFR27):
- ARIA landmarks: main (dashboard), navigation (top bar), toolbar (batch)
- ARIA labels on all status badges: "Repository auth-service: Dirty, 7 commits ahead"
- aria-live="polite" for dynamic content: batch results, privacy mode changes, scan progress
- RepoCard: role="article" with descriptive aria-label
- StatsBar: each stat card has role="button" with aria-label
- SmartStatusLine: aria-label="AI summary: {text}"
- Error states: aria-live="assertive" for critical errors
4. Motion & Animation:
prefers-reduced-motionmedia query respected- All transitions use
motion-safe:Tailwind prefix - No auto-playing animations
- Skeleton loading: static when reduced-motion preferred
5. Focus Management:
- Dialog opens → focus trapped in dialog, first interactive element focused
- Dialog closes → focus returns to trigger element
- Command palette → focus trapped in palette list
- Card expansion → focus moves to expanded content
- Tab order: top bar → stats bar → card grid → batch toolbar
Testing Strategy
Automated testing:
- Playwright e2e tests with
@axe-core/playwrightfor automated WCAG checks - Run on every PR via CI
- Key scenarios: dashboard load, card grid rendering, batch operations, settings dialog
Manual testing (per release):
- Keyboard-only navigation: complete all core journeys without mouse
- Screen reader testing: macOS VoiceOver (primary), Windows NVDA
- Color blindness simulation: Chrome DevTools color vision deficiency
- High contrast mode: Windows High Contrast, macOS Increase Contrast
Test matrix:
| Platform | Screen Reader | Test Focus |
|---|---|---|
| macOS | VoiceOver | Card grid nav, batch ops, settings |
| Windows | NVDA | Full journey: scan → dashboard → batch |
| Linux | Orca | Basic dashboard navigation |
Implementation Guidelines
For AI agents implementing components:
- All status indicators must use StatusBadge component — never ad-hoc colored elements
- All interactive elements must have focus-visible styles and keyboard handlers
- All dynamic content must have aria-live region for announcements
- All dialogs must use Radix Dialog (handles focus trap and aria automatically)
- All icons must have accompanying text or aria-label — never icon-only meaning
- All batch operations must emit per-repo events with accessible status updates
- Window resize must use Tailwind responsive classes, never JavaScript resize listeners
- Reduced motion must use Tailwind
motion-safe:prefix for all transitions/animations