figma-component-specs.json.The revised file carries one explicit designer callout ("Documentation Note", node 5397:33328) on the Components board:
"This tab should include an all components on a single website grid, as an overview. Each component should also have its own page for more details, variations, and developer notes."
Implication: The designer wants a per-component page structure (details + variations + developer notes) — which is exactly what docs/component-specifications/<component>/ already provides. New masters currently have no such page; tracked in new-components-2026-06-10.html.
Per-component developer notes were extracted from the local .fig archive (kiwi schema = deflate, data tree = zstd). The verbatim notes are in §6 — several are architecture-level.
| # | Figma master | Node id | In prior 19-spec? | Status |
|---|---|---|---|---|
| 1 | card-md | 4718:11125 | ✅ | Card (size variant) |
| 2 | card-btn | 4737:13038 | ✅ | Button (D3) |
| 3 | card-notification | 4864:31901 | ✅ | Card layout variant |
| 4 | flight segment card | 4555:7483 | ✅ | Domain control (FTDT) |
| 5 | horizontal scrolling feed | 4047:4230 | ✅ | Carousel |
| 6 | listy card generic | 5172:15482 | ✅ | List |
| 7 | main-feed slot | 4038:891 | ✅ | Feed Template |
| 8 | navBar-bottom | 4038:1037 | ✅ | Bottom Navigation |
| 9 | profile | 4153:8817 | ✅ | Screen (out of library) |
| 10 | profile info block | 4128:7690 | ✅ | Info Block atom |
| 11 | section title | 4596:11818 | ✅ | Section Title primitive |
| 12 | slider | 4317:5239 | ✅ | Carousel scroll indicator (not Carousel) |
| 13 | tab group | 4361:8479 | ✅ | Segmented Control (D9 amended) |
| 14 | topNav | 5419:34168 | ✅ | Top Navigation |
| 15 | button-sm | 4128:7717 | ✅ | Button (size variant) |
| 16 | NavItem-primary | 4020:3429 | ❌ NEW | NavItem atom (Primary) |
| 17 | NavItem-top | 4038:3300 | ❌ NEW | NavItem atom (Top) |
| 18 | navItem hamburger | 4057:7542 | ❌ NEW | NavItem atom (Drawer) |
| 19 | nav controls | 4084:2871 | ❌ NEW | Nav Controls |
| 20 | navBar-bottom-tablet | 5419:34086 | ❌ NEW | Deferred-responsive |
| 21 | hamburger menu | 4084:2712 | ❌ NEW | Navigation Drawer |
| 22 | menu-hamburger | 4153:8871 | ❌ NEW | Screen (out of library) |
| 23 | main view-interior | 4245:5027 | ❌ NEW | Interior Template |
| 24 | template | 4436:5299 | ❌ NEW | Page Template |
| 25 | template-tablet | 5419:34171 | ❌ NEW | Deferred-responsive |
| 26 | flight detail flight info | 4325:6399 | ❌ NEW | Domain control (FTDT) |
| 27 | progress bar & labels | 4537:14830 | ❌ NEW | Progress Bar primitive |
| 28 | status | 4325:6332 | ❌ NEW | Badge atom |
| 29 | endpoint | 4322:5706 | ❌ NEW | Endpoint domain atom |
| 30 | horizontal button with icon | 4128:7799 | ❌ NEW | Button variant |
| 31 | btn-pulldown | 4555:6510 | ❌ NEW | Button variant (pulldown) |
| 32 | btn-sort&filter | 4358:4501 | ❌ NEW | Button variant (icon+label) |
| 33 | alpa logo | 4023:780 | ❌ NEW | Logo brand-asset atom |
| 34 | back | 4431:4432 | ❌ NEW | Back control atom |
Retained (15): card-md · card-btn · card-notification · flight segment card · horizontal scrolling feed · listy card generic · main-feed slot · navBar-bottom · profile · profile info block · section title · slider · tab group · topNav · button-sm
Dropped (3) — 0 occurrences in revised file: mobile hero (→ CardHero) · mobile nav (→ nav controls / navBar-bottom / topNav) · search bar (→ Search screen + search secondary buttons)
Still live but master outside this canvas: card-lg (17× instances; → Card Large + CardHero) · card-sm (28× instances; → CardSmall, D4)
New masters (19): NavItem-primary · NavItem-top · navItem hamburger · nav controls · navBar-bottom-tablet · hamburger menu · menu-hamburger · main view-interior · template · template-tablet · flight detail flight info · progress bar & labels · status · endpoint · horizontal button with icon · btn-pulldown · btn-sort&filter · alpa logo · back
When importing a Figma revision, resolve every Figma master against these, in order, before flagging anything as "new":
-property-mapping.html — each carries the exact Figma node refCarousel ← horizontal scrolling feed (4047:4230). The current carousel-property-mapping.html mapped onto slider (4317:5239, 313×63) — a scroll-position indicator (scroll-track + thumb + min/max label rows), not the card collection. slider reclassified as the Carousel's scroll-indicator sub-control, not the Carousel itself.
| Node | Size | What it is | Name | ViewModel |
|---|---|---|---|---|
navBar-bottom 4038:1037 | 393×88 | Global bottom nav — main-section switcher (HOME · JUMPSEAT · KCM · FTDT · MY MEC) | Bottom Navigation | BottomNavigationViewModel |
tab group 4361:8479 | 345×31 | In-screen single-select segment (NONSTOP · ONE STOP · MULTILEG; Notifications FF/Comms) | Segmented Control | SegmentedControlViewModel |
D9 amended (2026-06-10): "Segmented Control" adopted as a deliberate scoped exception — it is the clearest name, already the design system's own token vocabulary (Miscellaneous/Segmented Control - Selected Fill), and disambiguates from Bottom Navigation.
card-md/card-lg → Card + CardVariant { Small, Medium, Large }; button-sm → Button + size variant. Variant becomes remotely-configurable data, not a separate component. Aligns with Path 2 (Hybrid SDUI).Concrete types, no magic strings: CardVariant = a closed enum (SDUI deserializes to it — never a loose string). ComponentStyle = a typed value object of design-token types (ThemeColor, typed scale units) — no CSS strings on the domain VM. MEC theme = IOptionsMonitor<MecThemeOptions> (live-reload). Raw CSS string exists only at the view edge — an IThemeResolver maps (component type, Variant, Style, active MEC theme) → the CSS class a Razor component binds. No free-form inline-Style escape hatch on the VM.
| Bucket | Strategy |
|---|---|
| Design-system primitives (Figma library, MEC-themeable) | Build from scratch — own DOM + CSS variables |
| Complex generic controls (date/time pickers, combobox, dialog, virtualization) | Vendor allowed — but wrapped behind own component + typed VM |
| Theming | One vector: CSS custom properties from typed tokens |
MudBlazor: keep as an option for complex controls (wrapped); do not adopt MudTheme as the theming system (would fracture MEC theming into two systems). Bridge tokens → Mud palette at the wrapper if needed. Remove Mud from the core design-system path.
Card-family naming (D4 revised): type-first — Card, CardSmall, CardHero, CardText. Dirs renamed: hero-card/→card-hero/, text-card/→card-text/, small-card/→card-small/.
The design system is a library, not app-shell — a Razor Class Library targeting plain net10.0 (no UseMaui). Nav chrome, page templates, primitives, and their ViewModels all live in it. This is Feature AB#2087 (Presentation Extraction).
Constraints to stay MAUI-free: Typed tokens are library-defined (ThemeColor/ComponentStyle must be our types, not Microsoft.Maui.Graphics.Color) · Platform concerns are injected interfaces (navigation, storage: interface in library, implementation in MAUI host via DI) · Vendor/MudBlazor stays host-side (D19).
| Figma master | Name | ViewModel | Notes |
|---|---|---|---|
Master Form Field | Form Field | FormFieldViewModel | "Master" = Figma main-component artifact, not part of the name. Validated by design tokens (Font Family/Form Field). Unified field: text input / select / expanding textarea / ±icons / states. |
card-notification | Card (layout variant) | CardViewModel | Not a separate component. Differences are image placement + proportion = visual, not structural. Folds into Card as a layout/presentation variant. Axes orthogonal: Size ⟂ Layout ⟂ state. |
progress bar & labels | Progress Bar | ProgressBarViewModel | Gradient fill = a CSS gradient design token, MEC-themeable (D18/D19); not a VM property. VM holds data (value/min/max + label text), not the fill look. |
status | Badge | BadgeViewModel | Shared generic atom: Label + State/Severity variant → CSS token styling. Domain controls compose it via D11. Same Badge used for flight-status and duty-period-status. |
profile (4153:8817) | Screen (out of library) | — | Full Profile screen — outside the component library per D20. |
profile info block | Info Block | InfoBlockViewModel : ComponentViewModel | Generic label + value pair ("MEMBER NUMBER" / value), no surface chrome. Domain-neutral; distinct from CardText (which is on a surface). |
endpoint | Endpoint | — | Flight endpoint atom (airport/time), composed into flight card / flight segment card by their factories (D11). Not a library primitive. |
All four are domain controls that compose generic scaffolds + atoms (D11) — none is a new library primitive.
| Domain control | Node | Composes (verified) | Variants |
|---|---|---|---|
| flight card | 4348:4002 | base Card scaffold + Endpoint ×2 + leg/layover collection (DL 302 · AA 1753 · AA 1186) + icons | 5 (Default/swipe/expanded/Variant4/5) = states, not components |
| flight segment card | 4555:7483 | Endpoint atoms (DEN ✈ MIA) + date/time + carrier/equipment (DL 302 · 757) | — |
| flight detail flight info | 4325:6399 | Badge ("Delayed 34m") + Info Block (Gate H14) + Buttons (KCM › · Jumpseat Policy ›) | Departure/Arrival |
| card-duty period-alt | 4617:13876 | Progress Bar (Max Duty 14:00) + Info Block (Ends/Duty) + Button (Manage Flights & Details) | 3 (Default/Variant2/delete-demo) = states |
The *-tablet masters (navBar-bottom-tablet, template-tablet) and *— TABLET screen frames are non-optimized responsive designs, not distinct components. Handled at implementation time via responsive layout (CSS breakpoints / adaptive layout in Blazor). Do not create separate *Tablet ViewModels/components.
| Figma master | Node | Size | What it is | Name / Tier |
|---|---|---|---|---|
topNav | 5419:34168 | 834×110 | Top utility bar — profile · heart · bell · search + hamburger | Top Navigation — nav chrome |
nav controls | 4084:2871 | 193×38 | In-screen header row (back/home · title · filter) | Nav Controls — nav chrome |
hamburger menu | 4084:2712 | 300×570 | Slide-out drawer: back/home + nav rows | Navigation Drawer — nav chrome |
menu-hamburger | 4153:8871 | 393×852 | Full hamburger overlay screen | Screen — out of library (D20) |
NavItem-primary | 4020:3429 | 50×80 | Bottom-nav item (vertical icon+label) | NavItem atom — variant: Primary |
NavItem-top | 4038:3300 | 38×54 | Top-nav item (icon) | NavItem atom — variant: Top |
navItem hamburger | 4057:7542 | 280×48 | Drawer row (label + chevron) | NavItem atom — variant: Drawer |
template | 4436:5299 | 393×852 | Base page scaffold (status bar · nav · content slot) | Page Template — template tier |
main view-interior | 4245:5027 | 300×570 | Interior screen scaffold (nav controls + title + content slot) | Interior Template — template tier |
main-feed slot | 4038:891 | 393×852 | Home/feed scaffold with content slot | Feed Template — template tier |
section title | 4596:11818 | 313×38 | Section header + optional "View All ›" | Section Title — primitive |
alpa logo | 4023:780 | 60×60 | ALPA brand mark | Logo — brand-asset atom |
back | 4431:4432 | 69×22 | Back affordance (caret + label) | Back — control atom |
btn-pulldown | 4555:6510 | 320×39 | "VIEW DETAILS ⌄" expandable outlined button | Button variant (pulldown) per D3 |
btn-sort&filter | 4358:4501 | 131×18 | "⇄ SORT & FILTER" icon+label | Button variant (icon+label, small) per D3 |
Full tier model: atoms (NavItem, Badge, Info Block, Endpoint, Logo, Back, icons) → primitives (Card, Button, Form Field, Progress Bar, Section Title) → containers (Carousel, List, Button Group) → nav chrome (Top Navigation, Bottom Navigation, Nav Controls, Navigation Drawer, Segmented Control) → page templates (Page/Interior/Feed Template) → domain controls (flight card, flight segment, flight detail, duty period). Screens (profile, menu-hamburger, *— TABLET) compose the above and are out of the library (D20).
Extracted from the local .fig archive. Several are architecture-level.
topNavnavBar-bottomOpen designer question: "Hide top navbar in lower levels > reveal on swipe down?" — unresolved interaction proposal.
detail frame is the card's expanded view, hidden by default. Toggle its visibility to see the expanded content; every flight card carries one. Hidden here means an alternate state stored in place, not an unused layer."comms (Comms-tab styling vs. flight-status styling). One card component serves both notification tabs; comms is the variant used on the Comms side." → card-notificationdefault / selected, single-choice. Drives in-screen tab switching (e.g. the Notifications tabs)." → tab group → Segmented Control"Note: gradient style for all progress bar fills" → progress bar & labels
Variants = interaction states: "Default / expanded are the card's states. Variant4 / Variant5 are generically named — map these by appearance; the labels don't describe them."
overlay- are modal sheets layered over a base screen (filter / sort / notification-filter), shown on invocation and dismissed back to the screen beneath. Build as overlays, not separate routes. Applies to all overlay- frames (flight finder filter, notification filters, KCM filter)."comms variant on the Comms side). One screen, two filtered feeds — not two screens."All audit items resolved 2026-06-10:
Cross-checks passed: Counts reconcile: 15 retained + 19 new = 34 masters · D18 vs D10 (typed chrome → ComponentStyle tokens) ✓ · D19 vs D11 (vendor-free like domain-free) ✓ · D20 vs D6 (greenfield, MAUI-free) ✓ · atoms deriving from ComponentViewModel ✓.
Capture is decision-complete. Applied to COMPONENT-CHANGES.html and figma-component-specs.json (_resync manifest). Per-component spec pages gated on AB#2087.