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.