Files
Extrudex/design/01-filament-inventory-list.md
cubecraft-agents[bot] 230c3b295d initial commit
2026-04-25 18:51:05 +00:00

344 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Filament Inventory List — Screen Specification
> **Screen ID:** FIL-001
> **Source of Truth:** [Material Design 3](https://m3.material.io/)
> **Tone:** Modern Industrial/Maker
> **Theme:** Dark Mode, High-Contrast
> **Last Updated:** 2026-04-20
---
## 1. Objective
Provide a single, scannable view of all filament spools in inventory. Users (shop operators) must be able to:
- Rapidly assess stock levels at a glance (which spools are low/critical).
- Search by material type, brand, color, or internal tracking ID.
- Filter by status (Available, In Use, Low Stock, Depleted).
- Navigate to spool detail or initiate the Smart Intake workflow.
This is the **primary landing screen** for both the kiosk and the mobile PWA.
---
## 2. Screen Inventory
| Element | MD3 Component | Notes |
|---------|--------------|-------|
| Top App Bar | `md-top-app-bar` (medium) | Title + search toggle + intake FAB |
| Search Bar | `md-search-bar` | Expandable on tap; collapses to icon on kiosk |
| Filter Chips | `md-chip-set` (filter) | Status filters: All / Available / In Use / Low / Depleted |
| Inventory List | `md-list` (3-line) | Spool cards as list items |
| Low-Stock Badge | `md-badge` | Tonal badge on list items |
| Extended FAB | `md-fab` (extended) | "Smart Intake" CTA |
| Navigation Rail | `md-navigation-rail` | Kiosk only — Inventory / Printers / Jobs / Settings |
| Bottom Navigation | `md-navigation-bar` | Mobile only — same destinations |
| Empty State | Illustration + `md-text-button` | When no spools match filter |
---
## 3. Layout Specification
### Title
**"Filament Inventory"** — displayed in the Top App Bar headline slot.
### Sections
#### A. Top App Bar (56dp mobile / 64dp kiosk)
- **Leading:** Menu icon (kiosk) / Back arrow (mobile, if deep-linked)
- **Title:** "Filament Inventory"
- **Trailing actions:** Search icon (toggles search bar), Overflow menu (Sort by, Export)
#### B. Search Bar (0dp collapsed → 56dp expanded)
- Triggered by search icon tap or pull-down gesture on mobile
- Placeholder: "Search spools, brands, colors…"
- Auto-focus on expand; dismiss on back/clear
- Real-time filtering as user types
#### C. Filter Chip Row (52dp height, horizontal scroll)
- Chips: `All` | `Available` | `In Use` | `Low Stock` | `Depleted`
- Default selection: `All`
- Multi-select disabled — single filter active at a time
- Chip styling: Tonal variants per status color
- Available: `green` tonal
- In Use: `blue` tonal (primary)
- Low Stock: `yellow` tonal (warning)
- Depleted: `red` tonal (error)
#### D. Inventory List (flex, scrollable)
- Each item is a **3-line list item** with leading/trailing elements:
```
┌──────────────────────────────────────────────────┐
│ [Color Swatch] PLA Basic - Matte Black │
│ Bambu Lab • Slot A3 • 842g left │
│ ▓▓▓▓▓▓▓▓▓▓░░ 67% [Low] badge │
├──────────────────────────────────────────────────┤
│ [Color Swatch] PETG Basic - Transparent │
│ Polymaker • Shelf B2 • 210g left │
│ ▓▓▓░░░░░░░░░ 21% [Critical] ⚠ │
└──────────────────────────────────────────────────┘
```
- **Leading:** Circular color swatch (40dp) — matches filament color
- **Line 1:** Material name (MaterialBase + Finish + Modifier) — `titleMedium`, `onSurface`
- **Line 2:** Brand • Location • Remaining weight — `bodyMedium`, `onSurfaceVariant`
- **Line 3:** Linear progress indicator + percentage text — `labelSmall`, `onSurfaceVariant`
- **Trailing:** Status badge (tonal chip) + chevron icon
- **Divider:** Full-width between items
**Sort order (default):** Low stock first, then alphabetical by material name.
#### E. Extended FAB (Bottom-end, mobile; Bottom-end, kiosk)
- Label: **"Smart Intake"** + `qr_code_scanner` icon
- Container: `primaryContainer` color
- On tap → navigates to Smart Intake Scan State
#### F. Navigation (Screen-level)
- **Kiosk:** Navigation Rail on leading edge (80dp wide)
- Destinations: Inventory (active), Printers, Jobs, Settings
- **Mobile:** Bottom Navigation Bar (80dp height)
- Same destinations
### Primary CTA
**Smart Intake** (Extended FAB) — always visible, anchored bottom-end.
### Secondary Actions
- Tap list item → Spool Detail View
- Overflow → Sort options (Name A-Z, Name Z-A, Weight Low→High, Weight High→Low, Recently Used)
- Overflow → Export inventory (CSV)
### Key Components
- Search bar with real-time filtering
- Filter chip set (single-select)
- 3-line list items with progress indicators
- Color swatch leading element
- Status tonal badges
- Extended FAB
### States
| State | Visual |
|-------|--------|
| **Loading** | `md-circular-progress` centered, list skeleton (shimmer) |
| **Empty (no spools)** | Spool icon illustration + "No spools in inventory" + "Add your first spool" text button |
| **Empty (no filter matches)** | "No spools match your filter" + Clear filter chip button |
| **Error** | Error illustration + "Couldn't load inventory" + Retry button |
| **Low Stock item** | Yellow tonal badge "Low" + progress bar < 25% yellow |
| **Critical item** | Red tonal badge "Critical" + progress bar < 10% red + pulsing dot |
| **Depleted item** | Red tonal badge "Depleted" + progress bar 0% + strikethrough title |
---
## 4. UX Rationale
1. **Progress bars beat numbers alone.** A visual progress indicator communicates remaining spool life faster than parsing "210g / 1000g" — critical in a busy workshop where decisions are made in seconds.
2. **Low stock first (default sort).** Operators need to see what's running out before what's plentiful. This prevents the "surprise empty spool" problem mid-print.
3. **Color swatches as leading elements.** Filament identification is primarily visual — operators scan for color before reading text. The swatch leverages pre-attentive processing.
4. **Single-select filters over multi-select.** Workshop operators don't construct complex queries. They want one quick filter tap. Multi-select adds cognitive load for minimal practical benefit.
5. **Smart Intake FAB, not a menu item.** Intake is the most frequent action (new spools arrive regularly). It deserves the highest-affordance control on screen — a FAB is unmissable.
6. **Search collapses by default.** On kiosk, screen space is precious. The search icon expands the bar only when needed, preserving vertical list space.
7. **Empty states with action.** An empty inventory list should immediately offer the path forward — "Add your first spool" links directly to Smart Intake.
---
## 5. Visual Direction
### Typography (MD3 Type Scale)
| Role | Token | Size | Weight | Line Height |
|------|-------|------|--------|-------------|
| App Bar Title | `titleLarge` | 22sp | 400 | 28sp |
| List Item Line 1 | `titleMedium` | 16sp | 500 | 24sp |
| List Item Line 2 | `bodyMedium` | 14sp | 400 | 20sp |
| List Item Line 3 | `labelSmall` | 11sp | 500 | 16sp |
| Filter Chip Text | `labelLarge` | 14sp | 500 | 20sp |
| FAB Label | `labelLarge` | 14sp | 500 | 20sp |
| Empty State Title | `headlineSmall` | 24sp | 400 | 32sp |
| Empty State Body | `bodyMedium` | 14sp | 400 | 20sp |
### Spacing (MD3 8dp grid)
| Element | Spacing |
|---------|---------|
| App Bar internal padding | 16dp horizontal, 12dp vertical |
| Filter chip row padding | 16dp horizontal, 8dp vertical |
| Chip gap | 8dp |
| List item padding | 16dp horizontal, 12dp vertical (top/bottom of 3-line) |
| List item internal gap | 16dp (leading to content), 16dp (content to trailing) |
| FAB margin | 16dp from edges |
| Content area padding | 0dp (list is edge-to-edge with dividers) |
### Color (MD3 Dark Theme — "Industrial Maker")
Based on a **blue-grey** primary seed for the industrial feel, with **teal** as secondary (maker accent).
| Role | Token | Value (Dark) | Usage |
|------|-------|-------------|-------|
| Background | `surface` | `#1C1B1F` | Screen background |
| On Background | `onSurface` | `#E6E1E5` | Primary text |
| Surface Variant | `surfaceContainer` | `#211F26` | App bar, list items |
| On Surface Variant | `onSurfaceVariant` | `#CAC4D0` | Secondary text, chip outlines |
| Primary | `primary` | `#A8CEDA` | FAB container, active states |
| On Primary | `onPrimary` | `#00303E` | FAB label text |
| Primary Container | `primaryContainer` | `#004D63` | FAB container (tonal), active chip fill |
| On Primary Container | `onPrimaryContainer` | `#A8CEDA` | Active chip text |
| Secondary | `secondary` | `#B1CCC7` | Navigation rail active icon |
| Tertiary | `tertiary` | `#EFB8C8` | Accent (not used here) |
| Error | `error` | `#F2B8B5` | Depleted badge, critical states |
| Error Container | `errorContainer` | `#8C1D18` | Critical badge background |
| On Error Container | `onErrorContainer` | `#F2B8B5` | Critical badge text |
| **Custom: Warning** | — | `#FFD580` | Low stock indicator |
| **Custom: Warning Container** | — | `#5D4200` | Low stock badge background |
| **Custom: Success** | — | `#8BD0A0` | Available badge text |
| **Custom: Success Container** | — | `#00522E` | Available badge background |
| Outline | `outline` | `#938F99` | Dividers, chip outlines |
| Outline Variant | `outlineVariant` | `#49454F` | Subtle borders |
### Color Swatches
Spool color swatches use the actual filament color as a circular filled element (40dp diameter) with a 2dp `outlineVariant` border for visibility on dark backgrounds. For transparent/clear filaments, use a diagonal hatch pattern fill.
---
## 6. Responsiveness
### Kiosk (800×480, Raspberry Pi 5 Touchscreen)
```
┌──────┬──────────────────────────────────────────────┐
│ NAV │ Filament Inventory [🔍] [⋮] │
│ RAIL │──────────────────────────────────────────────│
│ │ [All] [Available] [In Use] [Low] [Depleted] │
│ 📦 │──────────────────────────────────────────────│
│ 🖨️ │ ● PLA Basic - Matte Black │
│ 📋 │ Bambu Lab • Slot A3 • 842g │
│ ⚙️ │ ▓▓▓▓▓▓▓▓▓▓░░ 67% [Low] │
│ │──────────────────────────────────────────────│
│ │ ● PETG Basic - Transparent │
│ │ Polymaker • Shelf B2 • 210g │
│ │ ▓▓▓░░░░░░░░░ 21% [Critical] │
│ │──────────────────────────────────────────────│
│ │ ● ABS Basic - White │
│ │ eSUN • Slot B1 • 950g │
│ │ ▓▓▓▓▓▓▓▓▓▓▓▓ 95% [Available] │
│ │ [+ Smart │
│ │ Intake] ↗ │
└──────┴──────────────────────────────────────────────┘
```
- **Navigation Rail:** 80dp wide, pinned left
- **List area:** 720dp × 420dp usable
- **Visible items:** ~4-5 spools without scrolling
- **Touch targets:** All interactive elements ≥ 48dp (exceeds 44dp minimum for workshop glove use)
- **FAB:** Bottom-right, 16dp margin from rail and screen edge
### Mobile PWA (375×812, e.g., iPhone 14)
```
┌──────────────────────────────────┐
│ Filament Inventory [🔍] [⋮] │
│──────────────────────────────────│
│ [All] [Avail] [In Use] [Low] [×]│
│──────────────────────────────────│
│ ● PLA Basic - Matte Black │
│ Bambu Lab • Slot A3 • 842g │
│ ▓▓▓▓▓▓▓▓▓▓░░ 67% [Low] │
│──────────────────────────────────│
│ ● PETG Basic - Transparent │
│ Polymaker • Shelf B2 • 210g │
│ ▓▓▓░░░░░░░░░ 21% [Critical] │
│──────────────────────────────────│
│ ● ABS Basic - White │
│ eSUN • Slot B1 • 950g │
│ ▓▓▓▓▓▓▓▓▓▓▓▓ 95% [Avail] │
│──────────────────────────────────│
│ │
│ [+ Smart Intake] ↗ │
│──────────────────────────────────│
│ 📦 🖨️ 📋 ⚙️ │
│ Inventory Printers Jobs Settings │
└──────────────────────────────────┘
```
- **Bottom Navigation:** 80dp, pinned bottom
- **List area:** 375dp × ~600dp usable
- **Visible items:** ~5-6 spools without scrolling
- **FAB:** Floating above bottom nav, right-aligned
- **Filter chips:** Horizontally scrollable when more than screen width
### Key Adaptations
| Property | Kiosk (800×480) | Mobile (375×812) |
|----------|-----------------|-------------------|
| Navigation | Rail (left) | Bottom bar |
| Search | Collapsed icon by default | Same, but swipe-down gesture also expands |
| List item density | Comfortable (3-line, 72dp) | Same density |
| FAB position | Bottom-right, above list | Bottom-right, above nav bar |
| Filter chips | All visible at once | Horizontally scrollable |
| Sort access | Overflow menu | Overflow menu |
---
## 7. Developer Handoff Notes
### Angular Material Components
| UI Element | Angular Material Component | Notes |
|-----------|--------------------------|-------|
| Top App Bar | `<mat-toolbar>` | Use `@angular/material/toolbar`. Medium emphasis variant. |
| Search | Custom wrapper + `<input matInput>` | No native mat-search-bar in Angular Material; implement custom expandable search with `@ViewChild` animation. |
| Filter Chips | `<mat-chip-listbox>` | Use `mat-chip-option` with `selected` binding. Single-select: deselect others on select. |
| List Items | `<mat-list>` + `<mat-list-item>` | 3-line variant with `matListItemTitle`, `matListItemLine`, `matListItemMeta`. |
| Progress Bar | `<mat-progress-bar>` | Use `mode="determinate"` with `[value]` binding. Custom color classes for warning/error thresholds. |
| Badge | `<mat-badge>` | Overlay on list items. Use `matBadgeColor` for status colors. |
| Extended FAB | `<button mat-fab extended>` | Use `@angular/material/button`. `extended` attribute for label. |
| Nav Rail | `<mat-sidenav>` styled as rail | No native nav-rail in Angular Material yet; implement as styled sidenav with icon buttons. |
| Bottom Nav | `<mat-bottom-nav>` or custom | Use `<nav mat-tab-nav-bar>` positioned at bottom as a workaround. |
| Empty State | Custom component | Illustration (SVG) + `<button mat-button>`. |
| Loading | `<mat-spinner>` | Use `mode="indeterminate"` centered in list area. |
### Interaction Notes
1. **Search expansion:** Animate height from 0→56dp with `@angular/animations` (`expandCollapse` trigger, 200ms ease-out).
2. **Filter chip selection:** Single-select logic in component — on chip click, set `selectedChip = chip.value`, deselect all others.
3. **List item tap → navigation:** Use `routerLink="/spools/:id"` on each `mat-list-item`.
4. **FAB → Smart Intake:** Navigates to `/intake/scan`.
5. **Progress bar color:** Dynamically set based on percentage:
- ≥ 25%: `primary` (teal-blue)
- 10-24%: Custom `warn-yellow` class
- < 10%: `warn` (red)
6. **Skeleton loading:** Use `@angular/material` skeleton pattern or custom shimmer CSS animation on list items during initial load.
7. **Pull-to-refresh (mobile):** Implement with Angular CDK `@cdk/drag-drop` or a custom gesture handler to refresh inventory data.
8. **Infinite scroll / pagination:** Load 20 spools initially, load more on scroll-to-bottom.
### Accessibility
| Requirement | Implementation |
|-------------|---------------|
| Screen reader | Each list item: `aria-label="PLA Basic Matte Black, Bambu Lab, Slot A3, 842 grams remaining, 67 percent, Low stock"` |
| Color swatch | `aria-label="Color: Matte Black"` + `role="img"` |
| Progress bar | `aria-valuenow`, `aria-valuemin="0"`, `aria-valuemax="100"`, `aria-label="Remaining filament: 67 percent"` |
| Filter chips | `role="listbox"`, each chip `role="option"` + `aria-selected` |
| Search | `role="search"`, `aria-label="Search filament inventory"` |
| FAB | `aria-label="Smart Intake: scan new spool"` |
| Keyboard nav | Tab through list items, Enter to select. Escape to dismiss search. |
| Focus management | On search expand, auto-focus input. On search collapse, return focus to search icon. |
| Motion reduction | Respect `prefers-reduced-motion` — disable shimmer, use opacity fade for loading. |
| Contrast | All text meets WCAG AA (4.5:1) against dark surface. Verified: `onSurface` (#E6E1E5) on `surface` (#1C1B1F) = 11.2:1 ✓ |
### SignalR Integration
- Subscribe to `SpoolUpdated` hub event on screen init.
- On event: update the corresponding list item in-place (no full refresh).
- On `SpoolAdded`: insert at sorted position with highlight animation (300ms `primaryContainer` background flash).
- On `SpoolDepleted`: move to Depleted filter group, show toast notification.
### Performance Notes
- Use `TrackByFunction` on `*ngFor` to prevent full list re-render on updates.
- Virtual scrolling via `<cdk-virtual-scroll-viewport>` if inventory exceeds 100 spools.
- Debounce search input at 300ms.