AhaSlides Design
v0.52.0React · Vue · Lit

Patterns · Settings

Settings list

A schema-driven group of settings rows — semibold label left (with a "?" help tooltip), control right — reusing existing DS controls.

Examples

Example
Density
Schema-driven · sections → rows · reuses DS controls · "?" help tooltip · inline + stack · disabled + plan-gated (crown) rows
Slot form · a "?" help row, an inline row, a stack row (still supported)

API

PropTypeDefaultNotes
schemaobject(list, property) Settings schema { sections:[{ label, rows:[{ key, label, description?, layout?, consequence?, control }] }] } — an array is treated as one section's rows; renders rows and reuses DS controls. Also settable as a JSON `schema` attribute for the build-free HTML form A row may declare visible_if (structured `visibleIf:{key,equals?,in?,not?}` or the Shopify string `visible_if:"{{ settings.<key> }}"`) — the row is shown only when its trigger is on and hidden when off, rendered nested (indented, de-emphasised).
labelstringGroup header (a 1–3 word noun phrase); on <aha-settings-item> it is the setting name. Ignored when a schema supplies section labels
descriptionstring(item / schema row) Guidance text — rendered as the "?" HELP TOOLTIP after the label (DS <aha-tooltip help>), NOT a standing line. Default: no help glyph
consequencestring(item / schema row) RARE opt-in must-see-consequence line shown as a standing line under the label (e.g. 'This cannot be undone.') — default none
layout'inline' | 'stack'inline(item / schema row) inline = label left / control right (align-items:center, space-between, gap 12); stack = label above / control full-width (column, gap 8) for wide controls (textarea / wide select)
controlslot | schema(item) The DS control on the right — <aha-switch>, <aha-checkbox>, <aha-input>… slotted by hand, or named in a schema row's `control:{ type }` and instantiated for you
density'default' | 'compact'default(list) Row/group rhythm. compact tightens the spacing (16 between groups, 8 between siblings) — never adds lines or boxes
disabledbooleanfalse(item / schema row) Dims the label to text-disabled, disables the reused control, sets aria-disabled
lockedbooleanfalse(schema row) Plan-gates the row: stays visible, its control becomes the shared Paywall crown badge → upsell. Pair with `plan` ('essential'|'pro') and `feature` (the upsell label)

Install

# .npmrc — once: point the @ahaslides-product scope at GitHub Packages
@ahaslides-product:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}   # a GitHub token with read:packages

npm i @ahaslides-product/design
import '@ahaslides-product/design/tokens.css';   // once, at the app root
import '@ahaslides-product/design/aha-settings-list';   // registers <aha-settings-list>

Agent feed for this component (absolute, fetchable anywhere): settings-list.agent.json · settings-list.md · settings-list.llms.txt

When to use

When to use
  • Settings list — a group of related on/off or choice settings in a panel, page or drawer
  • Form — values are submitted together with validation and a submit step
  • a single Switch/Select — one setting that applies on its own
Name each setting as a noun phrase (no leading verb — the control says on/off). Use a toggle for immediate effect, a checkbox for consent/saved-together — never mix in one group. Guidance lives in the "?" help tooltip after the label — never a standing description line (reserve the rare `consequence` line for a genuine must-see, e.g. an irreversible action). Hierarchy is spacing, never lines or boxes. Use `layout:'stack'` for wide controls (textarea / wide select). See the settings pattern for grouping, sub-settings and the danger zone.
Surfaces
editor settings dashboard

Spec

Group column · 16px between sibling settings · 32px between groups · semibold (600) header (SectionHeader); member/row labels are ALSO semibold (600) per the reference SettingRow · Row (inline, default) label left, control right · align-items:center · justify-content:space-between · min-height 24 · 12px gap · Row (stack) layout=stack → label above, control full-width (flex-direction:column · 8px gap) — for wide controls (textarea / wide select) · Label 14/21 Semibold (600) #1A1A1A (name = noun phrase, no leading verb) · Help guidance = a "?" help trigger after the label (DS <aha-tooltip help>, icon system-question-mark, muted ~50% = text-tertiary #8A8A8A → brand on hover/focus) + tooltip; NO standing description line. `description` is the tooltip content · Consequence (rare) opt-in `consequence` → a standing must-see line 12/18 #8A8A8A under the label; default none · Disabled row row disabled → label dims to text-disabled #B5B5B5, control disabled, aria-disabled · Plan-gated row row locked → visible but the control is the shared Paywall crown (opens the upsell), never hidden · Density density=compact tightens the rhythm (16 between groups, 8 between siblings) — spacing, never lines · Structure no divider lines, no card/box around plain settings · Schema sections[] → rows[] { key, label, description?, layout?, consequence?, disabled?, locked?, plan?, feature?, control:{ type, …props } }; renders + reuses DS controls · visible_if a follow-up row shown only when its trigger is on (Shopify model) — nested (24 indent, tighter gap, de-emphasised label); hidden = display:none, no phantom gap (SETTINGS-19/07/14)