# Add Item Button > Generated from add-item-button.contract.json — do not edit by hand. The full-width "+ Add" affordance that sits under a settings list (OptionRow / QuestionList) — a dashed, tertiary add row that appends a new item. Tier: **leaf-lit**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3. Surfaces: editor, settings, dashboard. ## Props | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `label` | string | `Add` | The add-affordance text; carries the accessible name | | `disabled` | boolean | `false` | Non-interactive (e.g. at the max item count); muted, no hover, sets aria-disabled | | `add` | CustomEvent<{}> | `—` | Composed event fired on click when enabled — the host appends a new item | ## Visual standard (measured) - Box: full width (100%) · height 40 · radius 8 · padding 0 12 - Border: 1px dashed #E3E3E3 (rest) - Content: centered — system-plus 16px + label, 8px gap - Text: Plus Jakarta 14/600, #4A4A4A (secondary) - Hover: border + text → #6A1EBB, #F9F5FF fill (animated) - Focus: #6A1EBB border + 2px soft ring - Disabled: #B5B5B5 text, #EBEBEB border, not-allowed, no hover, aria-disabled ## When to use - **Add Item Button** — append a new row to an editable settings list — options, questions, list items - **Button (tertiary)** — a standalone action that isn't 'add another row to this list' Place it directly under the list it grows, full-width so it reads as part of the stack. Label it with the item noun — 'Add option', 'Add question' — not a bare 'Add' when the context needs it. Disable (don't hide) it at the max count so the ceiling stays discoverable; pair with a tooltip or helper line explaining the limit. --- # Alert > Generated from alert.contract.json — do not edit by hand. 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. Tier: **leaf-lit**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3. Surfaces: editor, dashboard, settings, audience. ## Props | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `type` | info | success | warning | error | branding | `info` | Tone + status icon + surface/border tokens | | `heading` | string | `—` | Optional bold title above the message | | `size` | regular | small | `regular` | Compact padding + type scale | | `banner` | boolean | `false` | Full-width, square-cornered edge-to-edge page notice | | `closable` | boolean | `false` | Shows a dismiss control (✕ chrome) | | `hide-icon` | boolean | `false` | Suppresses the leading status icon (the showIcon toggle) | | `slot="action"` | slot | `—` | Trailing action — a button or link | | `close` | CustomEvent | `—` | Composed event when the banner is dismissed | ## Visual standard (measured) - Box: flex row, gap 10 · padding 10 14 · radius 8 · 1px tonal border - Text: Plus Jakarta 14/1.5; heading SemiBold 600 - Info: bg #F4F8FF, border #BFD2FF, icon #9BB3E9 - Success: bg #D8FAEF, border #16C49A, icon/text #13A181 - Warning: bg #FFF5F0, border #FF7747, icon/text #E65B29 - Error: bg #FFF1F0, border #F5222D, icon/text #F5222D - Branding: bg-accent #F9F5FF, border-focus #D3B4FF, icon/text color-primary #6A1EBB - Small: padding 6 10 · gap 8 · 13px text · 16px glyph - Banner: full-width, square (radius 0), border on the bottom edge only - Action: trailing slot="action" for a button/link - Icon: status glyph via (system-info / system-check-circle / system-warning-circle / system-x-circle / system-sparkle) ## When to use - **Alert** — a persistent, inline message tied to a region of the page (a form warning, a page-level notice) - **Toast** — a brief, transient confirmation of an action that then disappears - **Notification** — a richer, stacking message with a title + description, often from a background event Keep the message to one or two lines; lead with what happened, then what to do. Reserve error for real failures — over-using red trains people to ignore it. --- # AutoComplete > Generated from autocomplete.contract.json — do not edit by hand. Free-text input with suggestions as you type — search boxes, tag entry, known-but-open fields — rendered through the shared AutoComplete. Tier: **composite-antd**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3. Surfaces: editor, dashboard, settings. ## Props | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `options` | { value, label? }[] | { label, options }[] | `[]` | Suggestions shown as the user types — flat, or grouped ({ label, options }) for section headers | | `value` | string | `—` | Current free-text value | | `size` | 'small' | 'default' | 'large' | `'default'` | Control height — 24 / 32 / 40, matching the DS V3 Input size set | | `status` | 'error' | 'warning' | `—` | Validation state — red / amber border, same as the DS V3 Input | | `disabled` | boolean | `false` | Non-interactive, muted control | | `allowClear` | boolean | `false` | Shows a clear (×) affordance once there's a value | | `onSearch` | (text) => void | `—` | Fires as the query changes — fetch/filter suggestions | | `onSelect` | (value) => void | `—` | Fires when a suggestion is chosen | | `filterOption` | boolean | (input, option) => boolean | `true` | Client-side filter; set false when onSearch fetches server-side | | `placeholder` | string | `—` | Hint shown when empty | ## Visual standard (measured) - Control: height 32 · radius 8 · 1px #E3E3E3 border - Sizes: small 24 · default 32 · large 40 (DS V3 Input set) - Status: error #F5222D · warning #FAAD14 border - Focus: brand #6A1EBB border - Active option: #F7F7F7 (gray-20) row - Selected option: brand-tint #F9F5FF row - Placeholder: #8A8A8A ## When to use - **AutoComplete** — free text where suggestions help but the user may type their own value - **Select** — the value MUST come from a known set — don't allow free text - **Input** — free text with no suggestions to offer Filter suggestions on the query, don't dump the whole list. AutoComplete allows values outside the options — if the value must be from the set, use Select instead. --- # Avatar > Generated from avatar.contract.json — do not edit by hand. Represent a person or entity with a photo, initials, or an icon — solo or in a stacked group. Tier: **leaf-lit**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3. Surfaces: editor, dashboard, settings, audience. ## Props | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `name` | string | `—` | Full name; initials are derived when no src/icon. Also the alt/aria-label | | `src` | string | `—` | Image URL; the photo content mode (overrides icon/initials) | | `icon` | string | `—` | DS icon name (e.g. 'system-user'); the glyph content mode when no src | | `size` | 'small' | 'default' | 'large' | number | `default` | 24 / 40 / 64 named steps, or any numeric px | | `shape` | circle | square | `circle` | Clip shape | | `color` | token name | `—` | Ground tint — an --aha-* token suffix, e.g. 'bg-positive' | | `max` | number | `—` | (aha-avatar-group) collapse children past this count into a +N chip | ## Visual standard (measured) - Size: small 24 · default 40 · large 64 (named), or any numeric px via `size` - Shape: circle (pill radius) · square (radius 8) - Initials: bg-accent #F9F5FF, purple-60 #6A1EBB, SemiBold 600 - Image: object-fit cover, clipped to shape - Icon: glyph by name, ~half the avatar diameter, currentColor - Color: ground tint from an --aha-* token via `color` (default brand tint) - Group: stacked overlap (-10px), 2px container-white ring, +N chip past `max` ## When to use - **Avatar** — identifying a person or entity — a presenter, a participant, an author - **Icon** — a generic symbol, not a specific identity - **Tag** — labelling with a category rather than an identity Always provide `name` even when `src` is set — it becomes the alt text and the initials fallback if the image fails. Prefer initials or a photo over a generic icon for a real identity; reserve the icon mode for a placeholder/guest slot. In a group, keep sizes uniform and set `max` so the +N chip stays legible. --- # Badge > Generated from badge.contract.json — do not edit by hand. A small count or status marker — notification counts, unread dots, a standalone status label. Tier: **leaf-lit**. Frameworks: HTML (paste-and-run, no build step) · React · Vue 3. Surfaces: editor, dashboard, settings, audience. ## Props | Prop | Type | Default | Notes | | --- | --- | --- | --- | | `count` | number | `0` | The number shown in the bubble; 0 hides it unless showZero | | `overflowCount` | number | `99` | Cap; above it renders as N+ (alias: max) | | `showZero` | boolean | `false` | Keep the bubble visible when count is 0 | | `dot` | boolean | `false` | Render a bare marker, no number | | `status` | success | processing | error | warning | default | primary | `error` | Semantic colour; with `text` (no count/dot) renders a standalone dot + label | | `text` | string | `—` | Label for a standalone status badge | | `color` | CSS colour | `—` | Custom colour overriding the semantic default | | `ribbon` | boolean | `false` | Wrap the slotted child (a card) with a corner ribbon banner; `text` is the label, colour from color/status (default primary) | | `placement` | start | end | `end` | Ribbon corner: end = top-right (default), start = top-left | | `tone` | danger | success | positive | essential | pro | branding | primary-alt | `—` | Filled/tinted LABEL chip; each tone binds bg + fg to an --aha-* token | | `plan` | free | edu | essential | pro | enterprise | `—` | Plan preset chip (solid brand fill); pro/enterprise lead with a crown glyph | | `cycle` | monthly | yearly | `—` | Appended to a plan chip's default label (e.g. "Pro · Yearly") | | `rank` | 1 | 2 | 3 | 4 | `—` | Leaderboard rank chip; medal-tinted (gold/silver/bronze) with a leading system-Medal glyph | | `session` | string | `—` | Renders a "Session N" chip; the value is N (slotted content / `text` overrides the label) | | `href` | URL | `—` | Makes a tone/plan/rank/session chip a clickable LINK — renders (native focusable, animates on hover), never a