Findings comparing our component names against the Figma reference and industry conventions. For review — no changes applied. Goal: agree on a naming convention before the component library is implemented.
This report is the analysis that led to the decisions. The adopted naming and rationale are recorded in the Component Decisions Record. Renames have been applied across the docs.
Figma names components by size/shape (card-lg, card-md, card-sm, card-btn) — a designer's presentation vocabulary, not a semantic one. Our names are a mix of semantic (Hero, Text), size (Small), and generic (Card). Neither set is internally consistent. The two highest-value fixes: (1) rename Slider Card → Carousel (the word "slider" means a range input in industry UI vocabulary), and (2) stop suffixing container components ("Slider", "Stack") with "Card" — they hold cards, they aren't cards.
| Our Component | ViewModel | Figma Component | Industry-Conventional Term | Alignment |
|---|---|---|---|---|
| Card (base) | CardViewModel |
card-lg |
Card / Content Card | Aligned |
| Hero Card | HeroCardViewModel |
card-lg (shared) · mobile hero |
Hero Card / Feature Card | Aligned |
| Text Card | TextCardViewModel |
card-md |
Text Card / Content Tile | Aligned |
| Small Card | SmallCardViewModel |
card-sm |
List Row / List Item / Nav Tile | Size-based |
| Button Card | ButtonCardViewModel |
card-btn (shared) · button-sm |
Button / Action Button | Conflated |
| Icon Button Card | IconButtonCardViewModel |
card-btn (shared) |
Icon Button / Icon Tile | Shared key |
| Multi Button Card | MultiButtonCardViewModel |
3 × card-btn (shared) · button-sm |
Button Group / Action Grid / Segmented | Non-standard |
| Slider Card | SliderCardViewModel |
slider · horizontal scrolling feed · section title |
Carousel / Horizontal Scroll | Name collision |
| Stack Card | StackCardViewModel |
listy card generic |
List / List View / Vertical Stack | Container, not card |
In mainstream UI vocabulary (HTML <input type="range">, Material, iOS, Figma's own component sets), "Slider" denotes a draggable value selector — volume, brightness, price range. Our "Slider Card" is a horizontally scrolling carousel of cards. A developer or designer reading "Slider" will expect the wrong control.
Figma's own naming here is also loose: the slider node is just the pagination-dot control, while the actual scroller is horizontal scrolling feed.
Rename to Carousel (CarouselViewModel). It's the unambiguous industry term for a horizontally paged collection. Reserve "Slider" for any future range-input control.
Slider Card and Stack Card are not cards — they are layout containers that hold an Items collection of other cards. Naming a container "Card" is a category error that blurs the line between content and layout. Every other "Card" in the set is an actual content surface; these two are arrangement primitives.
Drop the "Card" suffix on containers: Carousel (horizontal) and List or Stack (vertical). Keep "Card" only for components that render a single content surface.
Figma uses a size/shape suffix convention: card-lg, card-md, card-sm, card-btn, button-sm. That is a designer's layout vocabulary — it says nothing about purpose or data. Our names mix three axes:
card-sm)Industry component libraries (Material, Fluent, Carbon, Polaris) name by function, not size — "ListItem", "Carousel", "Card", "Button" — and express size as a variant/prop (size="sm"), not a separate component.
Adopt function-based names for the public component library and treat Figma's size suffixes as variant props. e.g. card-lg / card-md become one Card with a size variant, not two components.
The mapping is many-to-one, which suggests our component count is higher than the design actually requires:
card-lg → Card + Hero Card (2 of ours)card-btn → Button Card + Icon Button Card + Multi Button Card (3 of ours)In Figma these are a single component (often with variants/properties). Our split into distinct ViewModels may be the right code decomposition, but the names should make the shared lineage obvious (e.g. a Button family with a layout variant), rather than reading as unrelated components.
Model card-btn as a single Tile Button with variants (text, icon, group), and card-lg as a single Card with a hero variant — or, if kept separate, name them as an explicit family.
No mainstream library uses "Multi Button Card". The pattern — a row of equal action tiles — is universally called a Button Group, Action Grid, or Segmented control. "Multi Button Card" also re-triggers the container-vs-card issue (it's a group of buttons, not a card).
Rename to Button Group (or Action Grid if the layout is a grid rather than a single row).
card-btn (tile) and button-sm (button) are conflated under "Button Card"Figma has two distinct things our "Button Card" references: card-btn is a 116×106 tile (icon + title), while button-sm is a 151×36 filled button (the actual call-to-action, e.g. "Emergency Hotline" / "Member Number"). These are different controls with different affordances.
Separate the concepts: Button (the button-sm filled CTA, e.g. Primary Button) vs Tile Button / Icon Tile (the card-btn square). Don't let one name cover both.
card-sm is a home-screen navigation row (image + title + chevron/heart, tap-through to a destination). "Small Card" describes its size, not what it does. Industry would call this a List Row, List Item, or Navigation Tile.
Consider List Row or Nav Tile. If the library keeps size-based names elsewhere, "Small Card" is acceptable but is the weakest semantic name in the set.
A function-based set that stays recognisable to both the design and engineering sides. Nothing here is applied — it's a strawman to react to.
| Current Name | Proposed Name | Type | Rationale | Priority |
|---|---|---|---|---|
| Card | Card | Content surface | Already conventional. Keep as the base. | Keep |
| Hero Card | Hero Card | Content surface | Industry-standard term for a featured card. | Keep |
| Text Card | Text Card | Content surface | Clear and conventional. | Keep |
| Slider Card | Carousel | Container (horizontal) | Removes the range-input collision; standard term. | Rename |
| Stack Card | List (or Stack) | Container (vertical) | It's a vertical list container, not a card. | Rename |
| Multi Button Card | Button Group | Control group | Universal name for a row of action tiles. | Rename |
| Button Card | Button | Control (CTA) | Maps to button-sm filled button. | Clarify |
| Icon Button Card | Icon Tile (or Tile Button) | Control (tile) | Maps to card-btn square tile. | Clarify |
| Small Card | List Row (or Nav Tile) | List item | Names by function, not size. | Consider |
card-btn's three uses (Button / Icon Button / Multi Button) collapse into one Button family with variants, or stay as separate ViewModels?listy card generic, card-btn, etc. are informal.)The Text Card has three layouts, named by their leading element. The small label above the title was initially called Eyebrow — an editorial/web term that reads as jargon. Reviewed against mobile conventions and our own property surface:
| Element | Figma | Web dev | Mobile context | Our property | Adopted |
|---|---|---|---|---|---|
| Small label above title | eyebrow (frame) |
MUI / Material Web overline · common CSS class .eyebrow / .kicker · (editorial: eyebrow/kicker) |
Material 3 label typography role · MAUI Label control · (Material 2 "overline" is deprecated; iOS has no equivalent) |
Label (IsLabelVisible) |
Label |
| Primary heading | title | Heading (<h2>/<h3>) · MUI h6 / subtitle1 |
Title (universal) | Title |
Title |
| Body text | description / body | Body (<p>) · MUI body1 / body2 |
Supporting text (Material) · Description | Description |
Description |
Renamed the Eyebrow variant/element to Label. It aligns with Material 3's label role and the MAUI Label control, and — decisively — it matches the existing Label property in our spec, so the variant name and the code stop diverging. The three variants (simplest → richest) are now Description · Title · Label, mapping to TextCardVariant { Description, Title, Label }. "Eyebrow" is retained only as the Figma layer name (provenance) and the --font-eyebrow-* token (its Figma token id is other/eyebrow).
Where each adopted component name sits on the web↔mobile spectrum. Most are universal or web-leaning; almost none are mobile-specific. Decision (D9): keep universal naming for now — the platform direction (native MAUI/XAML vs Blazor/Razor) is unsettled (Blazor Hybrid work restarted in a separate branch, 2026-06-05). Universal names work under either stack with ~zero change; refactor only if a strict axis is later chosen.
| Component | Web term | Mobile term | Sits | If mobile axis → | If web axis → |
|---|---|---|---|---|---|
| Card | Card (Bootstrap/MUI) | Card (Material/SwiftUI) | Universal | Card | Card |
| Hero Card | Hero / hero unit | Feature / Featured | Web-leaning | Feature Card | Hero Card |
| Text Card | — | — | Neutral | Text Card | Text Card |
| Small Card | list item | List item / cell | Neutral | List Item / Cell | Small Card |
| Button | Button | Button | Universal | Button | Button |
| Button Group | Button Group (Bootstrap/MUI) | Segmented Button (M3) / Segmented Control (iOS) | Web-leaning | Segmented Control | Button Group |
| Carousel | Carousel (Bootstrap/MUI) | Carousel (M3) / Page Control (iOS) | Web-leaning | Page Control | Carousel |
| List | List (<ul>) | List (UITableView) | Universal | List | List |
| Text Card label elem | Overline (MUI) | Label (M3 role) | Label = both | Label | Overline? |
The current set is already universal or web-leaning, so "universal for now" requires essentially no change. A strict mobile axis would force the most renames (Hero, Button Group, Carousel) for little gain; a strict web axis fits the Blazor/Razor signal but is premature while the direction is unsettled. Hold universal; refactor the few platform-leaning names only if the direction settles to a strict axis. Recorded as D9 in the Component Decisions Record.