27 KiB
Extrudex — Homepage (Main Hub) UI/UX Specification
Author: Sketch (Design Lead)
Date: April 20, 2026
Version: 1.0
Status: Ready for Review → Implementation Handoff
1. Objective
Who is it for?
Workshop operators and print managers who interact with Extrudex primarily on a Raspberry Pi 5 kiosk touchscreen (arm's length, greasy hands, ambient workshop lighting) and secondarily via a mobile PWA browser for remote monitoring.
What task are they completing?
The Homepage serves as the command center — the single screen where a user can, at a glance:
- Assess the fleet — See the real-time status of every printer (printing, idle, paused, error, offline).
- Spot problems fast — Instantly identify which machines need attention (errors, paused jobs, low filament).
- Take action — Navigate to a specific printer, spool, or print job with minimal taps.
- Monitor inventory — Get a quick read on filament stock levels and recent consumption.
- Recent activity — See the last few completed or failed prints for situational awareness.
Success metric: A user walking past the kiosk can determine fleet health in under 2 seconds without touching the screen.
2. Screen Inventory
The Homepage/Main Hub is a single screen that serves as the root of the navigation tree. It does not itself contain sub-screens, but it is the gateway to:
| Destination Screen | Triggered By | Priority |
|---|---|---|
| Printer Detail | Tapping any printer card | Primary |
| Spool Inventory | Nav tab "Spools" | Primary |
| Print Jobs | Nav tab "Prints" | Primary |
| Materials DB | Nav tab "Materials" | Secondary |
| Settings | Nav tab "Settings" | Secondary |
| Quick Scan | Floating action button (FAB) | Primary |
The Homepage itself contains these in-page sections (not separate screens):
- Status Summary Bar — Fleet-wide health at a glance
- Printer Fleet Grid — Live status cards for each printer
- Filament Stock Snapshot — Inventory overview with low-stock alerts
- Recent Activity Feed — Last 5 print events
3. Layout Specification
Page Title
"Extrudex" — Always visible in the top app bar. No subtitle needed; this is the root screen.
Navigation Structure
Primary Navigation: Bottom Navigation Bar (Mobile/Kiosk)
Material Design 3 bottom navigation with 5 destinations:
| Tab | Icon (Material Symbols) | Label | Badge? |
|---|---|---|---|
| Hub | dashboard |
Hub | — (active by default) |
| Printers | print |
Printers | Error count badge |
| Spools | inventory_2 |
Spools | Low-stock badge |
| Prints | receipt_long |
Prints | — |
| Settings | settings |
Settings | — |
Rationale for bottom nav:
- Touch-first: bottom nav is the easiest reach zone on a touchscreen kiosk or phone.
- 5 tabs is the MD3 maximum — keeps things scannable.
- "Hub" is the homepage; the other four are top-level destinations.
- Badges on Printers/Spools draw attention to problems without requiring navigation.
Desktop/Navigation Rail (Future)
On wider screens (browser dashboard), the bottom nav converts to a Material 3 Navigation Rail on the left edge with the same 5 destinations. This is a responsive transformation, not a separate navigation system.
Main Sections (Top to Bottom)
A. Top App Bar
- Leading: Extrudex logo mark (gear icon + "EXTRUDEX" in Inter Bold)
- Trailing:
- Connection status indicator (green dot = SignalR connected, red dot = disconnected)
- Clock (kiosk mode — always visible so users know the time without looking at their phone)
- Style: MD3 medium top app bar,
surfacecolor background, no elevation (flat) - Height: 64px kiosk / 56px mobile
B. Status Summary Bar
A horizontal strip below the app bar showing fleet-wide metrics in a single row:
| Metric | Format | Color Logic |
|---|---|---|
| Printers Active | 4 / 7 |
Text only, neutral |
| Printers in Error | 1 |
Red if > 0, hidden if 0 |
| Low Filament Spools | 2 |
Yellow if > 0, hidden if 0 |
| Prints Today | 12 |
Neutral |
- Layout: Horizontal flex row, evenly spaced, each metric in a compact chip/badge
- Kiosk override: Larger font (20px), more spacing between metrics
- Mobile: Compact chips with icons, horizontally scrollable if overflow
- Tap behavior: Tapping "Printers in Error" navigates to Printers tab filtered to errors. Tapping "Low Filament" navigates to Spools tab filtered to low stock.
C. Printer Fleet Grid
The heart of the homepage. A responsive grid of printer status cards.
Card Layout (each printer):
┌─────────────────────────────┐
│ [Status Dot] Printer Name │ ← Header row
│─────────────────────────────│
│ Current Job: Benchy #3 │ ← Job name or "Idle"
│ [████████░░] 72% │ ← Progress bar + percentage
│ Filament: PLA Silk │ ← Active material
│ Remaining: ~142g │ ← Spool remaining
│ ETA: 0h 23m │ ← Time remaining
│─────────────────────────────│
│ [View Detail →] │ ← Tap target / CTA
└─────────────────────────────┘
Status Dot Colors:
- 🟢 Green (
#4ADE70kiosk /#16A34Alight) — Printing / Active - 🟡 Yellow (
#FACC15kiosk /#CA8A04light) — Paused - 🔴 Red (
#F87171kiosk /#DC2626light) — Error / Failed - ⚪ Gray (
#64748B) — Idle / Offline
Grid Behavior:
- Kiosk (800×480 Pi 5): 2 columns, 3–4 rows (scrollable)
- Tablet (768px+): 3 columns
- Mobile (< 480px): 1 column, list view
Card Dimensions:
- Kiosk: Full-width within column, min-height 180px
- Mobile: Full-width, min-height 140px, slightly denser
Important States:
- Printing (active): Progress bar animates, card has subtle left-border accent in green
- Paused: Yellow left border, progress bar frozen, "PAUSED" badge overlaid
- Error: Red left border, card background shifts to
error-containertoken, error message shown - Idle: Gray left border, dimmed progress area, "Ready" label
- Offline: Fully dimmed card, "OFFLINE" badge, no real-time data
D. Filament Stock Snapshot
A compact section showing inventory health:
Layout: Horizontal scrolling row of small cards or a mini-list
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ PLA │ │ PETG │ │ TPU │
│ ████████░░ 80% │ │ ████░░░░░ 40% │ │ ██░░░░░░░ 20% │
│ 23 spools │ │ 8 spools │ │ 3 spools ⚠️ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
- Each card shows: Material base name, stock percentage bar, spool count
- Cards with < 25% stock get a
⚠️warning indicator and yellow-tinted background - Kiosk: 2–3 cards visible, swipe to see more
- Mobile: Horizontal scroll carousel
- Tap: Navigates to Spools tab filtered by that material
E. Recent Activity Feed
The last 5 print events in a compact list:
┌────────────────────────────────────────────────────┐
│ ✓ Benchy #3 · PLA Silk · 23g · 0h45m │
│ ✓ Gear Set v2 · PETG Basic · 87g · 2h12m │
│ ✗ Phone Case · TPU Basic · — · Failed │
│ ✓ Calibration · PLA Basic · 4g · 0h05m │
│ ✓ Bracket x4 · ASA Matte · 156g · 4h30m │
└────────────────────────────────────────────────────┘
- Each row: Status icon, job name, material, weight used, duration
- Failed prints show
✗in red with "Failed" label - Kiosk: Larger text, comfortable row height (56px)
- Mobile: Standard list density (48px rows)
- Tap a row: Navigates to that print's detail view
- "View All" link: At bottom, navigates to Prints tab
Primary CTA
Floating Action Button (FAB): "Quick Scan" — a prominent FAB in the bottom-right corner with a qr_code_scanner icon. This triggers the barcode/USB scanner workflow for spool check-in/check-out.
- Kiosk: Extended FAB with label "Scan" + icon, 56×56px minimum
- Mobile: Standard FAB, icon only, 56×56px
- Positioned above the bottom nav, with 16px margin from edges
Secondary Actions
- Tap any printer card → Printer Detail
- Tap any stock card → Spools filtered
- Tap any activity row → Print detail
- Tap error/low badges in summary bar → Filtered navigation
Key Components (MD3)
| Component | Usage | Notes |
|---|---|---|
| Bottom Navigation | Primary nav | 5 destinations |
| Top App Bar (Medium) | App header | Logo + status + clock |
| Cards (Elevated) | Printer status | Real-time content |
| Cards (Filled/outlined) | Filament stock | Compact, scrollable |
| List | Activity feed | 3-line items |
| FAB (Extended/Regular) | Quick Scan | Always accessible |
| Badge | Nav tabs, status | Error count, low stock |
| Linear Progress Indicator | Print progress | On printer cards |
| Chip | Status summary | Compact metrics |
Important States
| State | Visual Treatment |
|---|---|
| Loading (initial) | Skeleton screens for printer cards, shimmer animation |
| SignalR disconnected | Red dot in app bar, banner: "Live updates paused — reconnecting..." |
| No printers registered | Empty state illustration + "Add your first printer" CTA |
| No spools registered | Stock section shows "No inventory — add spools to start tracking" |
| All printers idle | Fleet grid shows all gray cards, summary bar shows "0 active" |
| Critical error (printer) | Card pulses red border once, then steady red left border |
4. UX Rationale
Why This Layout Supports the Task
-
Fleet health at a glance: The Status Summary Bar + Printer Fleet Grid are visible immediately on load. No scrolling required on kiosk to see if something is wrong. Color-coded status dots and left-border accents make the visual scan instantaneous.
-
Progressive detail: The homepage gives you "enough" — status, progress, material. You only tap into a printer card when you need details (temps, G-code, history). This avoids information overload while keeping critical data surface-level.
-
Inventory awareness without navigation: The Filament Stock Snapshot means operators don't need to leave the homepage to know if they're running low. The warning state (yellow + ⚠️) is visible without interpreting numbers.
-
Activity context: The Recent Activity Feed gives "what just happened" situational awareness — useful when returning to the kiosk after being away. It answers "did that print finish?" without requiring navigation.
-
Scan-first workflow: The FAB for Quick Scan is always accessible from the homepage, which is the most common action for spool check-in during workshop operations. Placed bottom-right — the natural resting thumb zone.
Hierarchy (What matters most → least)
- Printer errors (red, draws the eye immediately)
- Active printers with progress (green accent, animated progress bars)
- Paused printers (yellow accent, needs attention)
- Low filament warnings (yellow indicators in stock section)
- Idle printers (gray, calm, no action needed)
- Recent activity (informational, below the fold on mobile)
Tradeoffs
| Decision | Benefit | Cost | Mitigation |
|---|---|---|---|
| Bottom nav over side nav | Touch-friendly, MD3 standard, always visible | Takes screen space at bottom | Acceptable on touch-first device |
| Cards over table | Glanceable, status-colorable, touch-friendly | Less dense (can't see 7 printers at once) | Grid layout maximizes visible count; scroll for 6+ printers |
| Summary bar metrics | Fleet health without scrolling | Adds cognitive load if too many metrics | Keep to 4 max, hide zero-value metrics |
| Horizontal scroll for stock cards | Saves vertical space, works well for 3–6 materials | Hidden cards require swipe | First 3 most-used materials visible; swipe for rest |
| FAB for scan | Always accessible, one-tap | Covers content behind it | Standard FAB behavior; scrolls away on mobile |
| No sidebar on kiosk | Maximizes kiosk screen real estate | No persistent deep-nav | Bottom nav is sufficient for 5 top-level destinations |
5. Visual Direction
Tone
Modern Industrial/Maker — Dark mode by default on kiosk. Professional workshop vibe. High contrast. Think: a CNC control panel, not a social media app. The aesthetic should feel like a tool you trust, not an app you browse.
Dark Mode Palette (Kiosk Default)
| Token | Value | Usage |
|---|---|---|
md.sys.color.background |
#0F172A |
Page background |
md.sys.color.surface |
#1E293B |
Card backgrounds, nav bar |
md.sys.color.surface-container |
#334155 |
Elevated cards, containers |
md.sys.color.surface-container-high |
#475569 |
Hover/pressed states |
md.sys.color.primary |
#60A5FA |
Primary actions, links, active tab |
md.sys.color.on-primary |
#0F172A |
Text on primary |
md.sys.color.primary-container |
#1E3A5F |
Subtle primary tinted containers |
md.sys.color.error |
#F87171 |
Error states, failed prints |
md.sys.color.error-container |
#450A0A |
Error card backgrounds |
md.sys.color.on-error |
#FFFFFF |
Text on error |
md.sys.color.on-surface |
#F1F5F9 |
Primary text |
md.sys.color.on-surface-variant |
#94A3B8 |
Secondary text |
md.sys.color.outline |
#334155 |
Borders, dividers |
md.sys.color.outline-variant |
#1E293B |
Subtle borders |
Light Mode Palette (Dashboard/Future)
| Token | Value | Usage |
|---|---|---|
md.sys.color.background |
#F8FAFC |
Page background |
md.sys.color.surface |
#FFFFFF |
Card backgrounds |
md.sys.color.primary |
#2563EB |
Primary actions |
md.sys.color.on-surface |
#0F172A |
Primary text |
md.sys.color.on-surface-variant |
#475569 |
Secondary text |
Typography
| Role | Font | Weight | Size (Kiosk) | Size (Mobile) |
|---|---|---|---|---|
| App Title | Inter | Bold | 22px | 20px |
| Card Title (Printer Name) | Inter | SemiBold | 20px | 18px |
| Section Heading | Inter | SemiBold | 18px | 16px |
| Body Text | Inter | Regular | 18px | 16px |
| Metric Value | Inter | Bold | 28px | 24px |
| Metric Label | Inter | Medium | 14px | 12px |
| Mono Values (weight, time, %) | JetBrains Mono | Medium | 18px | 16px |
| Caption / Timestamp | Inter | Regular | 14px | 12px |
Rationale for oversized metrics: The kiosk is viewed at arm's length or further. A 28px bold metric is legible from 3–4 feet away. Monospace for numeric values ensures columns align and feels "instrument-like."
Spacing / Density
| Token | Kiosk | Mobile |
|---|---|---|
| Page padding | 24px | 16px |
| Card padding | 20px | 16px |
| Grid gap | 16px | 12px |
| Section gap | 32px | 24px |
| Row height (lists) | 56px | 48px |
| FAB margin from edge | 16px | 16px |
| Touch target minimum | 48px | 44px |
Component Behavior
- Printer cards: Update in real-time via SignalR. Progress bar animates smoothly (CSS transition 300ms). Status changes trigger a brief highlight flash (200ms background shift) to draw attention.
- Bottom nav: Active tab has
primarycolor icon + label. Inactive tabs useon-surface-variant. Badges are small circles positioned at the icon's top-right. - FAB: Elevated with shadow-3. On tap, ripple effect. Extended label appears on kiosk (wider screen), icon-only on mobile.
- Status summary bar: Metric chips are non-scrolling on kiosk (fits in one row at 800px width), horizontally scrolling on mobile if needed.
- Activity feed: List items have subtle divider lines (
outline-variant). Failed items haveerror-containerbackground tint. - Skeleton loading: Cards show shimmer placeholder during initial load (1.5s max before content appears).
Color Usage Guidelines
- Color is information, not decoration. Every colored element must communicate state.
- Red = immediate attention. Only use for errors, failures, disconnections. Never for decoration.
- Yellow = needs attention soon. Paused printers, low filament, warnings.
- Green = operating normally. Active printing, completed, connected.
- Blue = interactive. Links, buttons, active navigation, primary CTAs.
- Gray = neutral/idle. Offline printers, inactive states, secondary info.
- Never use color alone to convey meaning. Always pair with icon + text label (accessibility).
6. Responsiveness
Breakpoints
| Breakpoint | Width | Layout |
|---|---|---|
| Kiosk | 480–800px (Pi 5 typical: 800×480) | 2-col grid, bottom nav, extended FAB |
| Mobile (compact) | < 480px | 1-col list, bottom nav, standard FAB |
| Tablet | 768–1024px | 3-col grid, bottom nav, extended FAB |
| Desktop | 1024px+ | 3-col grid, nav rail, extended FAB |
Layout Changes by Device
Pi 5 Kiosk (800×480, Landscape)
- Top app bar: 64px height, clock always visible
- Status summary: 4 metrics in a single row (fits 800px)
- Printer grid: 2 columns × N rows, scrollable vertically
- Stock snapshot: 3 cards visible, no scroll needed (most common materials first)
- Activity feed: 3 rows visible, "View All" link
- Bottom nav: Full 5 tabs
- FAB: Extended with "Scan" label
Mobile PWA (< 480px, Portrait)
- Top app bar: 56px height, no clock (use phone clock)
- Status summary: 2–3 metrics visible, horizontal scroll for more
- Printer grid: 1 column list view (cards become horizontal list items)
- Stock snapshot: Horizontal carousel, 2 cards visible
- Activity feed: 3–5 rows, compact density
- Bottom nav: 5 tabs (may collapse labels on very narrow screens)
- FAB: Icon only, standard 56px
Tablet / Desktop Browser
- Bottom nav → Navigation Rail (left side, 80px wide)
- Printer grid: 3 columns
- Stock snapshot: 4–5 cards visible in row
- Activity feed: 5 rows
- Additional whitespace — dashboard mode can breathe more
Kiosk-Specific Considerations
- No hover states — all interactions are tap/click only
- No tooltips — information must be visible inline
- Larger touch targets — 48px minimum (4px above MD3 default)
- No right-click context menus — all actions are explicit buttons/links
- Screen wake — kiosk should not sleep; CSS
animationon a subtle element to prevent screen burn-in (shift a 1px element every 60s) - Overshoot scroll — prevent pull-to-refresh or browser gestures (PWA
overscroll-behavior: none)
7. Developer Handoff Notes
Reusable Components to Build
| Component | Type | Props/Inputs | Notes |
|---|---|---|---|
<ex-printer-card> |
Standalone | printer: Printer, status: PrinterStatus, job?: PrintJob |
Left-border color computed from status. SignalR drives re-renders. |
<ex-status-dot> |
Atom | status: 'active' | 'paused' | 'error' | 'idle' | 'offline' |
Small colored circle (12px) with aria-label for accessibility |
<ex-metric-chip> |
Atom | label: string, value: string | number, variant: 'default' | 'error' | 'warning' |
Used in Status Summary Bar |
<ex-stock-card> |
Standalone | material: string, percentage: number, spoolCount: number, lowStock: boolean |
Horizontal scroll child |
<ex-activity-item> |
List Item | job: PrintEvent |
3-line list item with status icon |
<ex-progress-bar> |
Atom | value: number, status: PrinterStatus |
MD3 linear progress, color matches status |
<ex-fleet-summary> |
Composite | printers: Printer[], spools: Spool[] |
Renders metric chips row |
<ex-connection-indicator> |
Atom | connected: boolean |
Green/red dot in app bar |
Angular Material Components Used
MatBottomNavigation(or custom bottom nav — MD3 bottom nav is not yet in Angular Material; implement withMatTabNav+ custom styling)MatCard→ Styled with custom dark tokensMatProgressBar→ Custom color per statusMatFabButton/MatMiniFabButtonMatBadge→ For nav tab badgesMatList→ Activity feedMatChip→ Status summary metricsMatIcon→ Material Symbols throughoutMatToolbar→ Top app bar
Interaction Notes
- SignalR subscriptions: The homepage must subscribe to
PrinterHubon mount. Each printer card re-renders on status/progress push events. Unsubscribe on navigate-away. - Optimistic updates: Progress bars should animate smoothly — use CSS transitions, not discrete jumps. If SignalR sends a progress update every 5s, interpolate between values.
- FAB scan action: On tap, immediately focus a hidden text input that captures USB HID barcode scanner output ( scanners type characters + Enter). This is a capture-only input — no keyboard should appear on mobile. Use
<input readonly>or interceptkeydownglobally. - Pull-to-refresh: Disabled on kiosk. On mobile PWA, consider enabling for manual data refresh.
- Navigation: Use Angular Router with bottom nav tabs bound to routerLinkActive. Highlight active tab. Preserve scroll position when returning to Hub.
- Skeleton screens: On initial load, show 6 skeleton printer cards (matching grid layout). Use
@angular/materialskeleton patterns or custom shimmer CSS.
Accessibility
| Requirement | Implementation |
|---|---|
| Screen reader | All status indicators have aria-label (e.g., "Printer Elegoo-1: Printing, 72% complete") |
| Color blindness | Never color-only — always icon + text + color. Status dots have aria-labels |
| Keyboard nav | Tab order: top bar → summary metrics → printer cards (grid order) → stock → activity → FAB → bottom nav |
| Focus management | After navigation, focus lands on the page title. After FAB tap, focus returns to FAB |
| Touch target | 48px minimum on kiosk, 44px minimum on mobile — all interactive elements |
| Contrast | All text on dark background meets WCAG AA (4.5:1 for body, 3:1 for large text) |
| Motion | Respect prefers-reduced-motion — disable progress bar animation and shimmer if set |
| Live regions | Printer status changes announced via aria-live="polite" on the card region |
Performance Notes
- OnPush change detection for all components receiving SignalR data
- TrackBy on printer grid
*ngForto avoid re-rendering unchanged cards - Virtual scrolling for activity feed if it grows beyond 20 items (use
@angular/cdk ScrollingModule) - Lazy load Spools, Prints, Materials, Settings tabs — only Hub is eager-loaded
- Image optimization: Use inline SVG for status icons, not raster images. Logo should be SVG.
File Structure Suggestion
src/app/
├── pages/
│ └── hub/
│ ├── hub.component.ts
│ ├── hub.component.html
│ ├── hub.component.scss
│ └── hub.component.spec.ts
├── components/
│ ├── printer-card/
│ ├── status-dot/
│ ├── metric-chip/
│ ├── stock-card/
│ ├── activity-item/
│ ├── progress-bar/
│ ├── fleet-summary/
│ └── connection-indicator/
├── layout/
│ ├── bottom-nav/
│ ├── top-app-bar/
│ └── nav-rail/
└── shared/
└── tokens/
└── _extrudex-tokens.scss
Appendix: Navigation Map
┌──────────────────────────────────────────────────────────────┐
│ EXTRUDEX │
│ │
│ ┌─ Hub (Home) ──────────────────────────────────────────┐ │
│ │ • Fleet Status Grid │ │
│ │ • Filament Snapshot │ │
│ │ • Recent Activity │ │
│ │ • [FAB: Quick Scan] │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ Printers ────────┐ ┌─ Spools ─────────────────────┐ │
│ │ Printer List │ │ Spool Inventory │ │
│ │ → Printer Detail │ │ → Spool Detail │ │
│ │ → Job History │ │ → Check-in/Check-out │ │
│ │ → Controls │ │ → Link to Printer │ │
│ └────────────────────┘ └─────────────────────────────┘ │
│ │
│ ┌─ Prints ──────────┐ ┌─ Settings ───────────────────┐ │
│ │ Print Job List │ │ System Configuration │ │
│ │ → Print Detail │ │ Printer Management │ │
│ │ → COGS Report │ │ User Preferences │ │
│ └────────────────────┘ └──────────────────────────────┘ │
│ │
│ ══════════════════════════════════════════════════════════ │
│ [Hub] [Printers] [Spools] [Prints] [Settings] │
│ ══════════════════════════════════════════════════════════ │
└──────────────────────────────────────────────────────────────┘
End of Specification — Ready for Stuart (mockup generation) and Rex (implementation handoff)