AhaSlides Design
v0.52.0React · Vue · Lit

Patterns · composition guide

Settings pattern

How to organise a settings surface — group ordering, help-text vs tooltip, sub-settings, plan-gating, and the danger zone — built from existing components.

◆ generated from guidelines/settings.json + parts/settings.guide.md — do not edit by hand

Settings is the most-repeated surface in the product, so it drifts fastest without shared rules. This pattern ships NO new component: it reuses Checkbox, Button, Icon and the --aha-size* spacing scale, and documents the CONVENTIONS that make every settings panel read as one product. The narrative 'why' lives in the aha-design-settings skill; this artifact carries only what the repo can enforce.

Based on

The rationale, worked examples, and the full assertion set live in the design skill — this pattern distils the enforceable subset and links each rule back to it.

build aha-design:aha-design-settings judge aha-design:aha-design-settings-judge

Choose the surface

SurfaceUse forExample
Inline panel (editor right pane)per-object settings, immediate effect on canvasblock required toggle, choice count
Settings page (route)workspace/account-level, affects a whole scopeworkspace name, billing, permissions
Modalone-time action or short flow, not independently persistedexport options, one-time import config
Drawersupplements a primary view, 3–8 settingsdistribution settings, results filter

Composed of

What a compliant settings surface reuses from this design system — the pattern's link into the component graph.

ReusesKindForIn DS?
checkboxcomponentgrouped options saved together; consentavailable
buttoncomponentthe danger-zone CTA (danger variant → colorError)available
iconcomponentthe ? help glyph, drag handle, per-option image, delete — functional icons onlyavailable
--aha-size*tokenthe whole spacing hierarchy (4/8/16/32/48) — separation comes from spacing, never dividersavailable
--aha-color-errortokendanger CTA colour — never hardcode a hexavailable
switchcomponenta single setting that takes effect immediately (toggle rows)available
selectcomponentduration/unit/mode dropdowns; recommended default pre-selectedavailable
inputcomponenttext/number fields; NumberWithUnit for a number + unitavailable
tooltipcomponentthe ? help tooltip (HelpTooltip) — shared dark-navy tooltip, arrow anchored to the ? iconavailable
settings-listcomponentthe reusable form of this pattern — SectionHeader (semibold group header) + SettingRow (label left / control right, or stacked) rendered from a schema over DS controls; spacing-only hierarchyavailable
dropdowncomponentDropdownMenu — themed action menu (aha-dropdown + aha-menu) for image Change/Edit/Delete and Improve-style menusavailable
menucomponentthe aha-menu inside DropdownMenu's action menu — neutral-grey item hoveravailable
mode-fieldcomponentModeField — a labelled field whose input swaps with an inline exclusive mode control (outline radio group / segmented); only the active mode's body is liveavailable
counted-inputcomponentCountedInput — single-line field with a focus-only char counter (counter is a persistent sibling revealed via :focus-within, never a remount-on-focus)available
counted-textareacomponentCountedTextarea — multi-line sibling of CountedInput; grows between minRows/maxRows, same focus-only counteravailable
card-selectcomponentCardSelect — single-select as an icon+label card grid; the one selection shape Ant has no built-in foravailable
number-with-unitcomponentNumberWithUnit — digit input + hover stepper (clamped, maxDigits) + unit-in-full + optional error line, at an 8px corner; for durations/numbers-with-a-unitavailable
option-rowcomponentOptionRow — repeatable option/answer row: drag handle, optional correct toggle, borderless textarea with hover counter, optional image control, floating deleteavailable
numbered-itemcomponentNumberedItem — repeatable numbered SECTION wrapper for composite items (chip + '<Label> N' header + hover delete + grey container); body is a slotavailable
question-listcomponentQuestionList — editable list of collapsible questions (prompt field + OptionRow choices); composes NumberedItem/OptionRowavailable
image-dropzonecomponentImageDropzone — full-width settings-only image field (dashed card, empty/loading/filled) emitting intents; the host runs the upload modals, never a self-built uploaderavailable
image-action-buttoncomponentImageActionButton — per-option image control with empty/loading/thumbnail states + Change/Edit/Delete menu; emits intentsavailable
info-boxcomponentInfoBox — settings-only tinted callout (information/success/warning/error), optionally dismissible with persisted state; bespoke, not Ant Alertavailable

Rules

The shippable checklist — each rule traces to an assertion in aha-design:aha-design-settings.

RuleSkill assertion
Setting name is a short noun phrase — no leading verb (Enable/Allow/Show/Turn on). The control communicates the action; the label names what is acted on.SETTINGS-01 SETTINGS-40
Toggle when the change takes effect immediately; checkbox when options are saved together as a group or express consent. Never mix toggles and checkboxes in one group.SETTINGS-11
Help text only for a must-see consequence that is hard to undo (≤90 chars, states the consequence). Default is ZERO help lines per panel; everything else is a ? tooltip or nothing. Never both channels on one setting.SETTINGS-02 SETTINGS-28 SETTINGS-29
The help trigger is a question-mark (?) glyph from the shared Icon — never an info circle (ⓘ). Every ? in a panel is the same glyph, size, and tooltip placement; the tooltip is the shared dark-navy tooltip with its arrow anchored to the icon.SETTINGS-26 SETTINGS-30 SETTINGS-35
Hierarchy and separation come from --aha-size* spacing tokens (4 name→help, 8 sub→parent, 16 sibling, 32 group, 48 danger zone) — never divider lines, never raw px.SETTINGS-13
Plain settings and groups sit directly on the panel surface, separated by spacing — never wrapped in a card or tinted/bordered container. Card styling is reserved for genuinely selectable items and the repeatable composite-item wrapper.SETTINGS-15
A group has 2–6 settings. Header is a 1–3 word noun phrase, sentence case, no colon. Only the group header carries weight — semibold (600, the SectionHeader weight); member/single-control labels are regular weight (400).SETTINGS-05 SETTINGS-06 SETTINGS-37
Build a settings surface by reusing the canonical composed controls — SectionHeader, SettingRow, SubSettingGroup, HelpTooltip, ModeField, CountedInput/CountedTextarea, NumberWithUnit, CardSelect, OptionRow, NumberedItem, QuestionList, ImageDropzone/ImageActionButton, InfoBox, DropdownMenu — mapped to their DS form (parts/settings.guide.md). Never hand-roll a settings control that already exists in the library; a control the DS does not yet ship is a tracked backlog gap (composedOf), not licence to re-implement it privately.SETTINGS-15 SETTINGS-33
A dependent sub-setting is HIDDEN (not disabled) when its parent is off. When shown it reads as nested — indented and de-emphasised — never as a top-level peer and never bracketed by its own separators.SETTINGS-07 SETTINGS-14
A plan-gated setting stays visible but locked (crown badge) — never hidden. The badge opens the shared Paywall popover (owned by aha-design-paywall), not a bespoke one.SETTINGS-08
Dangerous/irreversible settings sit last, set apart by the largest gap (48). The CTA is the danger Button (colorError, no hardcoded hex); red never on the label. Any irreversible action requires a confirmation modal.SETTINGS-09 SETTINGS-10 SETTINGS-12
A narrow control sits inline with its label (label left / control right); a wide control (textarea, wide select, radio group, image dropzone) drops below it. Never stack a narrow control or cram a wide one inline.SETTINGS-47
Every object occupies only its real content height. A container that renders nothing visible is removed or collapsed to zero — never left holding space (the #1 source of editor mystery-gaps).SETTINGS-19

Composition code

Doc-only — this pattern ships no wrapper from this repo. Doc-only pattern — ships no composition wrapper from this repo. The canonical composed settings controls live in slide-type-creator's @/iframe/settings library (ui-standard.json → settingsLibrary is their source of truth); parts/settings.guide.md carries the explicit, one-per-component mapping from each library control to its DS form (a DS contract, a documented convention, or a tracked backlog gap in composedOf). As each backlog control graduates into this DS it gets a contract + reuse block and is gated like a composite; when the DS ships it, flip its composedOf entry from missing→available and move the mapping row to 'mapped'.

Guide

Settings — composition guide

Distilled from aha-design-settings. The skill holds the full rationale, worked BAD/GOOD examples, and all 52 SETTINGS-xx assertions; this guide is the shippable checklist. When the two ever disagree, the skill wins and this file is regenerated.

Settings panels are the most-repeated surface in the product. They reuse existing components — Checkbox, Button, Icon, the spacing scale — so this pattern adds no new control; it defines the conventions that keep every panel reading as one product.

Pick the surface first

SurfaceUse for
Inline panel (editor right pane)Per-object settings, immediate effect on the canvas
Settings page (route)Workspace / account-level settings that affect a whole scope
ModalA one-time action or short flow, not persisted on its own
Drawer3–8 settings that supplement a primary view

A single-block panel growing past 8–10 settings is a signal to re-group or split, not to keep adding.

Name and control

  • Name = short noun phrase. No leading verb. "Progress bar", not "Show progress bar". The control already says on/off; the label names what is acted on. (Narrow exception: a manual/automatic *mode* toggle may keep its verb — "Show results manually".)
  • No decorative leading icon. Panel icons are functional only — drag handle, image, delete, ? help. A trophy on "Leaderboard" is decorative and comes out, however on-topic.
  • Toggle vs checkbox: toggle when the change takes effect immediately; checkbox when options are saved together or express consent. Never mix the two in one group.
  • Placement: narrow control inline (label left, control right); wide control (textarea, wide select, radio group, image dropzone) drops below the label.

Explanation: name → tooltip → help text

This is the single most common AI failure — do not give every setting a description line.

1. Name only — the default; carries most settings. 2. ? tooltip — the home for any "what/why/how it interacts" elaboration. Costs no standing weight. The glyph is a question-mark from the shared Icon (never an info circle), same glyph/size/placement across the panel, shared dark-navy tooltip with the arrow on the icon. 3. Help text — only a must-see consequence that is hard to undo (≤90 chars, states the consequence, ends with a period). Default zero per panel. Never a ? and a help line on the same setting.

Ship gate: count the help-text lines. More than one is almost always the anti-pattern.

One home for guidance. The canonical SettingRow puts *all* "what/why/how it interacts" elaboration in the ? tooltip — it has no separate always-visible description line. AhaSlides keeps one narrow addition on top of that: the rare must-see consequence help line (tier 3 above), which is near-zero per panel and states a hard-to-undo consequence, not a description. Everything else is a tooltip or nothing. Never run a ? tooltip *and* a help line on the same setting.

Grouping — spacing, never lines or boxes

Hierarchy comes from the gap size, on the --aha-size* scale — monotonic so whitespace alone reads as structure:

RelationshipTokenpx
Name → its help textsizeXXS4
Sub-setting → parentsizeXS8
Between sibling settingssize / sizeMS16
Between groupssizeXL32
Danger zonesizeXXL48
  • Never a divider line between settings, groups, or the danger zone — more distance means a wider gap.
  • Never a card/tinted/bordered container around plain settings or a lone toggle; a filled box signals a *selectable* object. Reserve it for real selectable items and the repeatable composite-item wrapper.
  • Group shape: 2–6 settings; header is a 1–3 word noun phrase, sentence case, no colon; only the header carries weight — semibold (600) (the SectionHeader weight), member/single-control labels regular (400).
  • Order: most-used first; a dependent sub-setting directly under its parent; dangerous last.

Sub-settings

A setting that only applies when a parent is on is hidden when the parent is off — not shown disabled. When visible it reads as *nested*: indented (sizeLG), tighter gap above (sizeXS), and de-emphasised label — never a top-level peer, never bracketed by its own separators.

Plan-gated and dangerous settings

  • Plan-gated: stays visible but locked (crown badge) — never hidden. The badge opens the shared Paywall popover (owned by aha-design-paywall).
  • Danger zone: dangerous/irreversible settings sit last, set apart by the largest gap (48). CTA is the danger Button (colorError, no hardcoded hex); red never on the label. Any irreversible action requires a confirmation modal (per aha-design-overlays) — never a bare toggle flip.

No empty height

Every object occupies only its real content height. A container that renders nothing visible — an empty section, an empty list wrapper, an empty-body settings iframe — is removed or collapsed to zero, never left holding space. This is the top source of editor "mystery gaps".

Mapping the settings-lab library to the DS

The composed settings controls have one source of truth — slide-type-creator's @/iframe/settings library (ui-standard.json → settingsLibrary). This is the canonical, one-per-component mapping from each library control to its AhaSlides-design form. A control resolves to one of three homes: a DS component you reuse today; a DS convention this pattern documents (no dedicated element needed); or a backlog gap — a composite the DS does not yet ship, tracked in composedOf (status: missing) so a fully-compliant surface is buildable by reuse once it lands. Never hand-roll a control the library already defines.

settings-lab controlDS formHome
SectionHeader<aha-settings-list> group header — semibold (600), optional ? tooltip + action slotconvention (in settings-list)
SettingRow<aha-settings-item> / a settings-list schema row — label left / control right, or stackedmappedsettings-list
SubSettingGroup*sub-settings* rule — indent-only, hidden (not disabled) when the parent is offconvention
HelpTooltip<aha-tooltip> + <aha-icon> ? glyph (the *help-glyph* rule)mappedtooltip
DropdownMenu<aha-dropdown> + <aha-menu> — themed action menumappeddropdown
ModeField*label + inline exclusive mode control (outline radio / segmented), body swaps in place*mappedmode-field
CountedInput*single-line field + focus-only char counter (persistent sibling, no remount)*mappedcounted-input
CountedTextarea*multi-line CountedInput; grows minRows–maxRows*mappedcounted-textarea
CardSelect*single-select icon+label card grid*mappedcard-select
NumberWithUnit*digit input + hover stepper (clamped, maxDigits) + unit-in-full + optional error line*mappednumber-with-unit
OptionRow*repeatable option row: drag handle, correct toggle, borderless textarea + counter, image, delete*mappedoption-row
NumberedItem*numbered composite-item wrapper: chip + <Label> N header + hover delete + grey container*mappednumbered-item
QuestionList*collapsible questions (prompt + OptionRow choices); composes NumberedItem/OptionRow*mappedquestion-list
ImageDropzone*full-width settings-only image field; emits intents, host runs the upload modals*mappedimage-dropzone
ImageActionButton*per-option image control (empty/loading/thumbnail + Change/Edit/Delete)*mappedimage-action-button
InfoBox*settings-only tinted callout; bespoke, not Ant Alert*mappedinfo-box

Backlog controls are real gaps, not licence to re-implement: author each here (contract + lib/ + parts + conformance), then flip its composedOf entry from missing → available and move its row to mapped. Until then, a surface needing one composes the closest DS primitives and follows the rules above.


*Full detail, screenshots, and the slide-type config specifics (§10) live in the

aha-design-settings skill. Self-check any built surface with aha-design-settings-judge and fix every FAIL before shipping.*