AhaSlides Design
v0.52.0React · Vue · Lit

Agent feeds · raw

design.md raw feed

Machine-readable visual language + token spec — the feed AI design/code tools read.

◆ generated — the exact file served to agents at /design.md · do not edit by hand

design.md
# AhaSlides Design System — design.md
> Machine-readable visual language for AI design + code tools. Generated from tokens.canonical.json — do not edit by hand.
> Version 0.52.0 · changelog (what changed per release): https://ahaslides-product.github.io/ahaslides-design/CHANGELOG.md

## Brand
Primary is violet purple `#6A1EBB` on near-white neutrals; ink is warm gray `#1A1A1A`.
Backgrounds are **white by default**; no gradients on fills (AI-affordance border-only exception).
Success `#16C49A` · warning `#FF7747` · error `#F5222D` · info `#9BB3E9`.

## Colour — primitive ramps
Each hue is a 10→100 scale. Semantic tokens below alias into these; **never hardcode a ramp value in a component** — bind to a semantic `--aha-*` token.
- **purple** — `5` #FCFBFF · `10` #F9F5FF · `15` #F0E4FF · `20` #E6D4FF · `25` #DCC4FF · `30` #D3B4FF · `35` #BE92F8 · `40` #A96FF0 · `45` #985AE2 · `50` #8644D4 · `55` #7831C8 · `60` #6A1EBB · `70` #621BAF · `80` #5715A0 · `90` #430379 · `100` #2B0051
- **pink** — `10` #FDF6FA · `20` #FFE3E9 · `30` #FFBACA · `40` #FF91AF · `50` #FF6996 · `60` #FF4081 · `70` #D92B6B · `80` #B31B57 · `90` #8C0E5A · `100` #660934
- **teal** — `10` #F5FFFC · `20` #D8FAEF · `30` #93F5DA · `40` #4EF1C5 · `50` #20E8B5 · `60` #16C49A · `70` #13A181 · `80` #0F6E65 · `90` #0A4C47 · `100` #062A27
- **coral** — `10` #FFF5F0 · `20` #FFE5D6 · `30` #FFCBB0 · `40` #FFAD8C · `50` #FF9068 · `60` #FF7747 · `70` #E65B29 · `80` #CC471A · `90` #993310 · `100` #661D05
- **red** — `10` #FFF1F0 · `20` #FFCCC7 · `30` #FFA39E · `40` #FF7875 · `50` #FF4D4F · `60` #F5222D · `70` #CF1322 · `80` #A8071A · `90` #820014 · `100` #5C0011
- **yellow** — `10` #FFFBE5 · `20` #FFF5B7 · `30` #FFEF88 · `40` #FFE95A · `50` #FFE32C · `60` #DBC123 · `70` #B79F1A · `80` #947D12 · `90` #705B09
- **indigo** — `0` #FFFFFF · `10` #F9F9FF · `15` #F0F4FF · `20` #E4E4F7 · `30` #C0C0E6 · `40` #9B9BCC · `50` #7777AA · `60` #5A5A91 · `70` #434373 · `80` #3E3E5A · `90` #242442 · `95` #252544 · `100` #1A1A2E
- **softIndigo** — `10` #FAFCFF · `20` #F4F8FF · `30` #EAF0FF · `40` #D9E2FF · `50` #BFD2FF · `60` #9BB3E9 · `70` #7B98D4 · `80` #5A78B5 · `90` #3E5D99 · `100` #27487A
- **lavender** — `10` #FEFBFD · `20` #FCF6FA · `30` #FAF0F6 · `40` #E9C8E0 · `50` #D6A6CB · `60` #BD7FB1 · `70` #A05D96 · `80` #88407C · `90` #69305C · `100` #4A1F3E
- **gray** — `0` #FFFFFF · `10` #FDFDFD · `15` #FAFAFA · `20` #F7F7F7 · `25` #F3F3F3 · `30` #F1F1F1 · `35` #EBEBEB · `40` #E3E3E3 · `50` #D4D4D4 · `55` #CCCCCC · `60` #B5B5B5 · `70` #8A8A8A · `80` #616161 · `90` #4A4A4A · `95` #303030 · `100` #1A1A1A

## Colour — semantic tokens
### Seed
| Token | Value |
| --- | --- |
| `--aha-color-primary` | `#6A1EBB` |
| `--aha-color-primary-hover` | `#621BAF` |
| `--aha-color-primary-active` | `#5715A0` |
| `--aha-color-success` | `#16C49A` |
| `--aha-color-warning` | `#FF7747` |
| `--aha-color-error` | `#F5222D` |
| `--aha-color-info` | `#9BB3E9` |

### Text
| Token | Value |
| --- | --- |
| `--aha-text-default` | `#1A1A1A` |
| `--aha-text-secondary` | `#4A4A4A` |
| `--aha-text-tertiary` | `#8A8A8A` |
| `--aha-text-disabled` | `#B5B5B5` |
| `--aha-text-inverse` | `#FFFFFF` |
| `--aha-text-link` | `#6A1EBB` |
| `--aha-text-link-hover` | `#A96FF0` |
| `--aha-text-primary-ink` | `#3E3E5A` |
| `--aha-text-positive` | `#13A181` |
| `--aha-text-negative` | `#F5222D` |
| `--aha-text-warning` | `#E65B29` |

### Border
| Token | Value |
| --- | --- |
| `--aha-border` | `#E3E3E3` |
| `--aha-border-secondary` | `#F1F1F1` |
| `--aha-border-strong` | `#D4D4D4` |
| `--aha-border-disabled` | `#EBEBEB` |
| `--aha-border-hover` | `#D3B4FF` |
| `--aha-border-active` | `#A96FF0` |
| `--aha-border-error` | `#F5222D` |
| `--aha-border-success` | `#16C49A` |
| `--aha-border-warning` | `#FF7747` |
| `--aha-border-info` | `#BFD2FF` |
| `--aha-checkbox-border` | `#D4D4D4` |

### Background
| Token | Value |
| --- | --- |
| `--aha-bg-base` | `#FFFFFF` |
| `--aha-bg-container` | `#FFFFFF` |
| `--aha-bg-container-secondary` | `#F7F7F7` |
| `--aha-bg-container-disabled` | `#F1F1F1` |
| `--aha-bg-elevated` | `#FFFFFF` |
| `--aha-bg-layout` | `#F7F7F7` |
| `--aha-bg-accent` | `#F9F5FF` |
| `--aha-bg-informative` | `#F4F8FF` |
| `--aha-bg-hover` | `#F7F7F7` |
| `--aha-bg-positive` | `#D8FAEF` |
| `--aha-bg-negative` | `#FFF1F0` |
| `--aha-bg-warning` | `#FFF5F0` |
| `--aha-bg-overlay` | `rgba(26,26,46,.7)` |
| `--aha-bg-dark` | `#1A1A2E` |
| `--aha-bg-dark-raised` | `#242442` |

### Icon
| Token | Value |
| --- | --- |
| `--aha-icon-default` | `#4A4A4A` |
| `--aha-icon-strong` | `#1A1A1A` |
| `--aha-icon-muted` | `#8A8A8A` |
| `--aha-icon-disabled` | `#B5B5B5` |
| `--aha-icon-inverse` | `#FFFFFF` |
| `--aha-icon-active` | `#6A1EBB` |

### Button
| Token | Value |
| --- | --- |
| `--aha-btn-primary-bg` | `#6A1EBB` |
| `--aha-btn-primary-bg-hover` | `#8644D4` |
| `--aha-btn-primary-bg-press` | `#5715A0` |
| `--aha-btn-primary-fg` | `#FDFDFD` |
| `--aha-btn-secondary-bg` | `#FFFFFF` |
| `--aha-btn-secondary-bg-hover` | `#F9F5FF` |
| `--aha-btn-secondary-border` | `#E3E3E3` |
| `--aha-btn-secondary-border-press` | `#D4D4D4` |
| `--aha-btn-tertiary-bg-hover` | `#F9F5FF` |
| `--aha-btn-disabled-bg` | `#E3E3E3` |
| `--aha-btn-disabled-fg` | `#B5B5B5` |
| `--aha-btn-danger-bg` | `#F5222D` |
| `--aha-btn-danger-bg-hover` | `#FF4D4F` |
| `--aha-btn-danger-ring` | `rgba(255,40,80,.2)` |
| `--aha-btn-encourage-bg` | `#2CB268` |
| `--aha-btn-encourage-bg-hover` | `#168C4D` |
| `--aha-btn-encourage-bg-press` | `#12733F` |

### Brand slots (categorical, Aha 1–13)
| Token | Value |
| --- | --- |
| `--aha-brand-1` | `#6A1EBB` |
| `--aha-brand-2` | `#FF4081` |
| `--aha-brand-3` | `#1A1A2E` |
| `--aha-brand-4` | `#20E8B5` |
| `--aha-brand-5` | `#434373` |
| `--aha-brand-6` | `#FF9068` |
| `--aha-brand-7` | `#93F5DA` |
| `--aha-brand-8` | `#FFBACA` |
| `--aha-brand-9` | `#D3B4FF` |
| `--aha-brand-10` | `#BFD2FF` |
| `--aha-brand-11` | `#D9E2FF` |
| `--aha-brand-12` | `#FDF6FA` |
| `--aha-brand-13` | `#F4F8FF` |

## Typography
Font **Plus Jakarta Sans** (self-hosted), weights **400 / 600** only. Base body **14** at line-height ratio **1.5**.
Size scale: 12 · 14 · 16 · 18 · 20 · 24 · 32 · 40 · 48 · 56 · 64. Letter-spacing: headings 0, body 0.2px, subtext 0.3px. No Inter.

## Shape & density
Radius scale: 4 · 6 · **8** (default) · 12 · 16; pills 999.
Control height: root **32** (Input/Select inherit); Button 28/36/40/52.
Spacing: 4-based — 0 · 2 · 4 · 6 · 8 · 10 · 12 · 14 · 16 · 20 · 24 · 28 …

## Architecture
Leaf primitives (button, checkbox, input, tag, badge, switch) = ONE shared Lit web component, same code + CSS in React and Vue.
Composites (table, form, datepicker) = antd v6 (React) + ant-design-vue v4 (Vue) themed by the shared tokens.

## Components
- **Add Item Button** (leaf-lit) — The full-width "+ Add" affordance that sits under a settings list (OptionRow / QuestionList) — a dashed, tertiary add row that appends a new item.
- **Alert** (leaf-lit) — An inline, contextual feedback banner — info, success, warning, error, or branding — in regular/small sizes, with an optional full-width banner mode and a trailing action.
- **AutoComplete** (composite-antd) — Free-text input with suggestions as you type — search boxes, tag entry, known-but-open fields — rendered through the shared AutoComplete.
- **Avatar** (leaf-lit) — Represent a person or entity with a photo, initials, or an icon — solo or in a stacked group.
- **Badge** (leaf-lit) — A small count or status marker — notification counts, unread dots, a standalone status label.
- **Breadcrumb** (leaf-lit) — A trail of ancestor links ending in the current page — and, at size=page-title, the page heading itself (there is no separate page-title component).
- **Button** (leaf-lit) — Trigger an action or navigation — the primary interactive control.
- **Card** (leaf-lit) — A surface that groups related content — cover, title, body and footer actions — in default/small size, bordered or flat, with a hover lift and a loading skeleton.
- **Card select** (leaf-lit) — Single-select as an icon+label card grid — pick one of N options each shown as its own visual card, with roving radiogroup keyboard navigation. Two layouts: labelled tiles (stretch to fill `columns`) or compact 44px icon-only squares.
- **Carousel** (composite-antd) — A swipeable set of slides — onboarding, a feature tour, a gallery — rendered through the shared Carousel.
- **Checkbox** (leaf-lit) — Let a user turn one or more independent options on or off.
- **Collapse** (leaf-lit) — A single expandable panel that hides secondary content until asked.
- **Color picker** (leaf-lit) — Pick a colour from a selectable palette of presets.
- **Counted input** (leaf-lit) — A single-line settings field whose character counter shows only while the field is focused and is hidden at rest — the shared CountedInput pattern for option/answer text.
- **Counted textarea** (leaf-lit) — The multi-line settings field — a CountedInput that wraps to several lines, grows from minRows to maxRows then scrolls, with the same focus-only character counter.
- **CSAT** (leaf-lit) — The shared thumbs up/down satisfaction prompt — the one CSAT control, not a bespoke rating.
- **DatePicker** (composite-antd) — Pick a date or a date range from a calendar — schedules, deadlines, filters — rendered through the shared DatePicker.
- **Descriptions** (leaf-lit) — A read-only label/value grid summarising one entity's fields — N columns, bordered or plain, horizontal or vertical, with per-item span.
- **Divider** (leaf-lit) — A thin rule that separates blocks of content — full-width, with a label, or a vertical hairline.
- **Drawer** (composite-antd) — A side panel that slides in for a longer edit or detail view — rendered through the shared Drawer.
- **Dropdown** (leaf-lit) — A trigger button that reveals a floating overlay of actions — with leading icons, dividers, disabled rows and a red danger action.
- **Empty** (leaf-lit) — The placeholder for a surface that has no data yet.
- **Flex** (leaf-lit) — A flexbox container with the DS spacing scale baked into `gap` — direction, align, justify, wrap.
- **Form** (composite-antd) — A labelled, validated set of fields — sign-in, settings, create dialogs — rendered through the shared Form.
- **Grid** (leaf-lit) — A CSS-grid container — a fixed column count or a responsive auto-fit, with the DS gutter scale, track justify/align, and a responsive collapse.
- **Icon** (leaf-lit) — One glyph set, called by name — 259 icons imported from Figma, rendered by the shared <aha-icon>, never inline SVG.
- **Illustration** (leaf-lit) — One spot-art set, called by name — 20 multi-colour illustrations imported from Figma, rendered by the shared <aha-illustration>, never inline SVG.
- **Image** (leaf-lit) — A framed image with rounded corners, a hover preview mask, a loading placeholder and a broken-src fallback.
- **Image action button** (leaf-lit) — The compact per-option image control — an image icon button with empty / loading / thumbnail states and a Change/Edit/Delete menu; it emits intents, the host owns the modals.
- **Image dropzone** (leaf-lit) — The full-width settings image field where the image IS the field — a dashed upload card with empty / loading / filled states and a Change/Edit/Delete overlay; it emits intents, the host owns the modals (SETTINGS-44).
- **Info box** (leaf-lit) — A settings-only tinted callout in four tones (information / success / warning / error), optionally dismissible — a bespoke component, not Ant Alert.
- **Input** (leaf-lit) — A single-line text field — names, search, numbers, short free text — with sizes, error/warning status, affixes, a clear ✕ and a password reveal.
- **InputNumber** (composite-antd) — Enter a number with steppers, min/max and precision — quantities, limits, durations — rendered through the shared InputNumber.
- **List** (leaf-lit) — A vertical list of uniform rows — avatar + title/description meta and trailing actions, with size, bordered and split options.
- **Loader** (leaf-lit) — The full-surface branded loading screen shown while a new environment boots — workspace → editor, or editor → presenting.
- **Menu** (leaf-lit) — A list of selectable options — a side nav, a settings list, an overflow menu — with icons, groups, submenus and danger actions.
- **Modal** (composite-antd) — A focused, blocking dialog in two types — a Confirmation (yes/no decision) and an Action (a task surface) — rendered through the shared Modal.
- **Mode field** (leaf-lit) — A labelled field with an inline exclusive mode control whose body swaps in place — the settings field for a control that has two-or-more mutually-exclusive modes.
- **Notification** (composite-antd) — A richer, stacking message with a title + description — rendered through antd's notification API.
- **Number with unit** (leaf-lit) — A fixed-width digit input with the unit written IN FULL inline (rendered exactly as passed — "seconds", "points" — muted grey), a hover ▲/▼ stepper, a hard digit cap, clamp-on-change, and an error line — the settings field for a number that carries a unit.
- **Numbered item** (leaf-lit) — The numbered wrapper for a repeatable composite item — a grey card with a muted number chip, a "<Label> N" header, a hover delete, and a body slot (SETTINGS-43).
- **Option row** (leaf-lit) — The repeatable option/answer row — one bordered row with an inside drag handle, a borderless counted textarea, an optional correct toggle (circle or square) and per-option image, and a floating hover delete; marking correct paints the whole card success-green (SETTINGS-20/34/23/39).
- **Pagination** (leaf-lit) — A page selector for a paged list or table — prev / numbered pages with ellipsis / next; two sizes, a simple mode, and a whole-control disabled state.
- **Paywall** (leaf-lit) — Wrap a pro-gated affordance; the shared upsell renders itself — the crown upgrade mark, title, one-sentence body, the fixed unlock line, and Upgrade + See all plans CTAs are baked in.
- **Popconfirm** (composite-antd) — A lightweight inline confirmation popover anchored to the trigger — confirm/cancel a low-risk action.
- **Popover** (leaf-lit) — Anchor a floating card of rich content — a title, a body, and an optional arrow — to a trigger.
- **Progress** (leaf-lit) — A determinate progress indicator — completion, upload, a quiz timer — as a line, segmented steps, or a circle.
- **QR code** (composite-antd) — A scannable QR code — a join link, a deck URL, a Wi-Fi handoff — rendered through the shared QRCode.
- **Question list** (leaf-lit) — An editable list of collapsible questions — each a prompt field plus its OptionRow choices — with a full-width "+ Add question" that disables at max; composes NumberedItem + OptionRow (SETTINGS-31/36).
- **Radio** (leaf-lit) — Pick exactly one option from a small mutually-exclusive set, all shown at once.
- **Rate** (leaf-lit) — Capture or display a score as a row of stars.
- **Result** (leaf-lit) — A full-block outcome state — success, error, info, warning, 404, 403 or 500 — with an icon, title and actions.
- **Screen heading** (leaf-lit) — A product page header — a title/greeting or a breadcrumb trail on the left, action buttons on the right, responsive across desktop / tablet / phone.
- **Section Header** (leaf-lit) — A settings GROUP header — the hierarchy parent that a stack of setting rows sits under: a noun-phrase label, an optional "?" help, and a right-aligned action slot (a master switch, a count, a link).
- **Segmented** (leaf-lit) — Switch between a few mutually-exclusive options inline — labels, leading icons, or icon-only, in three sizes.
- **Select** (composite-antd) — Pick one value (or several) from a known set — with type-to-search — rendered through the shared Select.
- **Select field** (leaf-lit) — Pick one value from a short, known set — a lightweight native-select-backed field that embeds anywhere.
- **Setting group** (leaf-lit) — The settings GROUP container — an optional semibold header (with a "?" help and an action slot) over a column of rows — that bakes in the panel spacing scale so gaps come out right automatically.
- **Setting Row** (leaf-lit) — ONE setting — a label (with an optional "?" help) plus a slotted DS control; inline (label-left / control-right) by default, or stacked (label above, control full-width) for a wide control.
- **Settings list** (leaf-lit) — A schema-driven group of settings rows — semibold label left (with a "?" help tooltip), control right — reusing existing DS controls.
- **Skeleton** (leaf-lit) — A greyed placeholder that holds a component's shape while its content loads.
- **Slider** (composite-antd) — Drag to set a value across a known range — volume, opacity, thresholds, ranges — rendered through the shared Slider.
- **Space** (leaf-lit) — An even, DS-scale gap between a small inline set of items — buttons, tags, inline controls.
- **Spin** (leaf-lit) — A brand-coloured spinner for an indeterminate wait — loading a page, a panel, or results.
- **Statistic** (leaf-lit) — A single headline number with a caption, prefix/suffix (text or icon), precision, trend colour and a loading skeleton.
- **Status badge** (leaf-lit) — A glanceable lifecycle pill for a domain object — draft, published, closed, archived, active, inactive.
- **Steps** (composite-antd) — Show progress through a sequence of ordered stages — wizards, onboarding, checkouts — rendered through the shared Steps.
- **Sub setting group** (leaf-lit) — The dependent (child) settings wrapper — indents a cluster of sub-settings under one parent toggle with a tight gap, spacing only (no border, no card).
- **Switch** (leaf-lit) — A single setting that takes effect immediately — on or off.
- **Table** (composite-antd) — A data grid — results, leaderboard, participant/admin list — rendered through the shared DataTable.
- **Tabs** (leaf-lit) — Switch between sibling content panels from a tab bar — line, primary or card, in two sizes, with per-tab icons.
- **Tag** (leaf-lit) — A small label chip for a category, keyword, or state — filled or bordered, with an icon, a dismiss ×, or a checkable toggle.
- **Textarea** (composite-antd) — Enter multi-line free text — descriptions, messages, notes — with autosize and char count, rendered through the shared Textarea.
- **TimePicker** (composite-antd) — Pick a time of day from scrolling hour/minute/second columns — schedules, reminders, durations — rendered through the shared TimePicker.
- **Toast** (composite-antd) — A brief, auto-dismissing confirmation of an action — rendered through antd's message API.
- **Tooltip** (leaf-lit) — A short, transient hint shown on hover or focus of its trigger.
- **Upload** (leaf-lit) — Select files by clicking a drop zone or dragging onto it — then manage them as rows or picture tiles with per-item state.
- **User info** (leaf-lit) — A person/identity row — an avatar next to a name, with an optional email underneath.