# Aihio Prompt Fragment Use this fragment when you want an AI system to generate Aihio UI quickly and correctly. It is intentionally biased toward safe, schema-backed markup over novelty. ## Strategy - Match user intent to components before thinking about visual styling. - Start from a seeded pattern when the request already resembles auth, settings, empty states, destructive confirmations, tabbed settings, inline validation, toast alerts, or a table of records. - Use native HTML for document semantics around Aihio custom elements. - When markup needs CSS of its own, use the semantic tokens below (`var(--aihio-color-muted-fg)`, `var(--aihio-spacing-stack-md)`), never raw colours or pixel values. `data-aihio-intent` annotations say what an element is for. - Adapt existing variants, sizes, slots, and compositions instead of inventing new APIs. ## Authoring Rules - Only use documented Aihio tags, related subcomponents, attributes, and pattern compositions. - Keep custom-element trees shallow and follow required slots, children, and parent relationships. - Treat boolean attributes as presence or absence, never stringified booleans. - A call to action that goes to another page is a link drawn as a button: `See pricing`. Never navigate from a click handler, and never put `href` on `aihio-button`. - A table of records is `` around a native ``: a ``, and `
` (or `aria-labelledby` pointing at the heading above it), `
` in a `
` for the cell that names each row. Make a column sortable with `data-sortable` on its ``, never with click handlers on headers, cells, or rows; link the row's name instead of making the row clickable. For more rows than a page can hold (thousands and up), show one page with `aihio-pagination` and `manual-sort`; use `aihio-data-grid`, which renders only the rows in view, when the list has to be one continuous scroll. - Open and close overlays from markup: give the overlay an `id`, and put `commandfor=""` plus one of its declared commands (such as `command="--open"`) on the `aihio-button` that controls it. Never use built-in commands like `show-modal` on an Aihio component. - When the request is ambiguous, choose the simplest accessible composition that satisfies the intent. - If a seeded pattern already fits, adapt that pattern instead of freehanding the structure. ## Component Inventory Use top-level components first, then reach for related subcomponents only inside their intended parent patterns. ### Top-Level Components - `aihio-alert` - A callout for a message the user should notice where it is shown: a failed save, a confirmation that something worked, a warning about a setting. Only the destructive variant interrupts a screen reader. Intents: `alert`, `informational`, `status`. Attributes: `variant=default|success|warning|destructive`. Slots: `default`, `title`, `description`. Methods: none. Requires: none. Related: none. - `aihio-avatar` - A round picture of a person or entity, such as the account owner in a header, falling back to initials when there is no image or it fails to load. Intents: `identity`, `labeling`. Attributes: `src=string`, `alt=string`, `fallback=string`, `size=sm|md|lg`. Slots: none. Methods: none. Requires: none. Related: none. - `aihio-badge` - A small non-interactive label for a status, count, or category, such as Live, Beta, or 3 new. Intents: `status`, `labeling`, `metadata`. Attributes: `variant=default|secondary|outline|success|warning|destructive`. Slots: `default`. Methods: none. Requires: none. Related: none. - `aihio-button` - An action the user takes: submit a form, open a dialog, run a command. Renders a real ` (`data-sortable=string`, `aria-sort=ascending|descending|none|other`, `data-numeric`), `` (`data-numeric`). Slots: none. Methods: `scrollToRow()`. Requires: children `table`. Related: none. - `aihio-dialog` - A modal dialog for a focused task or a confirmation before an irreversible action, such as deleting a project. Opens and closes from markup: commandfor plus command="--open" or command="--close". Intents: `overlay`, `modal`, `dismissible`. Attributes: `open`. Slots: none. Methods: `open()`, `close()`. Commands: `--open` (Opens the dialog modally. Focus returns to the invoking button when it closes), `--close` (Requests that the dialog close, with reason "command"; aihio-before-close can still cancel it), `--toggle` (Opens the dialog when it is closed and closes it when it is open). Requires: none. Related: `aihio-dialog-header`, `aihio-dialog-title`, `aihio-dialog-description`, `aihio-dialog-footer`. - `aihio-dropdown` - A menu of actions or links opened from a trigger button, such as an account menu or a row's More actions. Not for choosing a form value: use aihio-combobox for that. Intents: `menu`, `overlay`, `dismissible`. Attributes: `open`, `align=start|end`. Slots: `trigger`, `default`. Methods: `open()`, `close()`, `toggle()`. Requires: slots `trigger`. Related: `aihio-dropdown-item`, `aihio-dropdown-separator`. - `aihio-field` - Form field wrapper that lays out a label, control, description, and error message, and wires the accessibility relationships between them. Intents: `form-field`, `layout`, `labeling`. Attributes: `error`. Slots: `label`, `default`, `description`, `error`. Methods: none. Requires: none. Related: none. - `aihio-grid` - Layout primitive for a grid of equal columns, such as a grid of cards. Columns are never narrower than 16rem and drop away as the grid narrows, so it needs no breakpoints; columns caps how many there are. Intents: `layout`, `container`. Attributes: `columns=2|3|4`, `gap=tight|sm|md|lg`. Slots: `default`. Methods: none. Requires: none. Related: none. - `aihio-input` - A single-line text field (text, email, password, number, search, and the other native types) that submits with its form. Put it inside aihio-field to get a label, description, and error message. Intents: `form-field`, `text-entry`. Attributes: `type=string`, `size=sm|md|lg`, `placeholder=string`, `disabled`, `error`, `value=string`, `name=string`, `required`, `readonly`, `autocomplete=string`, `min=string`, `max=string`, `minlength=number`, `maxlength=number`, `pattern=string`, `step=string`, `inputmode=string`, `enterkeyhint=string`, `autocapitalize=string`, `spellcheck`, `multiple`, `accept=string`, `capture=string`, `list=string`, `form=string`. Slots: none. Methods: `checkValidity()`, `reportValidity()`, `setCustomValidity()`, `select()`, `focus()`. Requires: none. Related: none. - `aihio-pagination` - Navigation between the pages of a long list (a pager): previous and next, the first and last page, and the pages around the current one. With href each page is a link with its own address; without it each page is a button your code answers. Use it under a table, search results, or a grid of cards when the whole list is too long to show at once. Intents: `navigation`. Attributes: `page=number`, `pages=number`, `href=string`, `previous-text=string`, `next-text=string`, `page-text=string`. Slots: none. Methods: none. Requires: none. Related: none. - `aihio-stack` - Vertical layout primitive that applies the system's spacing rhythm between its children. Intents: `layout`, `container`. Attributes: `gap=tight|sm|md|lg`, `align=start|center|end|stretch`. Slots: `default`. Methods: none. Requires: none. Related: none. - `aihio-switch` - An on/off setting that submits with its form, such as Email notifications on a settings page. Renders a real . Put it inside aihio-field for a label and description; for a pressed state in a toolbar (Bold, Italic) use aihio-toggle instead. Intents: `form-field`, `toggle-state`. Attributes: `checked`, `disabled`, `required`, `name=string`, `value=string`, `form=string`. Slots: none. Methods: `click()`, `focus()`, `checkValidity()`, `reportValidity()`, `setCustomValidity()`. Requires: none. Related: none. - `aihio-table` - A data table: records in rows and columns, compared by scanning down a column. It wraps a native and gives it the system's styles, sortable columns, and a scroll box the keyboard can reach when the table is too wide for the screen. Use it for records people compare (invoices, members, deployments); use aihio-grid of cards for a few summaries, and never a table for layout. For more rows than a page can hold, show one page at a time with aihio-pagination, or use aihio-data-grid. Intents: `tabular-data`. Attributes: `density=default|compact`, `sticky-header`, `manual-sort`, `loading`, `sort-ascending-text=string`, `sort-descending-text=string`. Native elements: ` row. - `aihio-data-grid` (warn) - when a sortable header has no column name, Give each sortable header a name, data-sortable="duration", so aihio-sort says which column to sort by without depending on the header's wording. - `aihio-data-grid` (warn) - when people need to find text in the page, print every row, or read the rows in a screen reader's browse mode, Use aihio-table with aihio-pagination instead. A grid has only the rows in view in the page, and those are all that find in page, printing, and browse mode reach. - `aihio-dialog` (error) - when dialog has no aihio-dialog-title, Provide aria-label on aihio-dialog describing the dialog's purpose; otherwise screen readers announce an unnamed dialog. - `aihio-dialog` (warn) - when dialog confirms a destructive action, Label the confirming button with variant="destructive" and keep Cancel as the first focusable control. - `aihio-dropdown` (error) - when the trigger is icon-only, Provide aria-label on the trigger (e.g. aria-label="Open menu"). - `aihio-field` (error) - when the field has no slot="label" content, Provide slot="label" content, or an aria-label on the control. aihio-field wires a label but cannot invent one. - `aihio-field` (error) - when the error attribute is written on the field, Write the message in slot="error" and leave the attribute to the field, which sets it from that content. An error attribute with no message marks the field invalid with nothing to announce. - `aihio-grid` (warn) - when the grid is a list of like items, such as project cards, Give it list semantics when the count matters to the reader: role="list" on aihio-grid and role="listitem" on each item. - `aihio-input` (error) - when input has no visible row, and each row with
` (`data-sortable=string`, `aria-sort=ascending|descending|none|other`, `data-numeric`, `data-sort-value=string`), `` (`data-sort-value=string`, `data-numeric`). Slots: none. Methods: `sort()`. Requires: children `table`. Related: none. - `aihio-tabs` - Switches between sibling panels of content with a row of tabs, such as the sections of a settings page. Arrow keys move between tabs. Intents: `tabs`, `navigation`, `layout`. Attributes: `value=string`. Slots: none. Methods: none. Requires: children `aihio-tab-list`, `aihio-tab-panel`. Related: `aihio-tab-list`, `aihio-tab`, `aihio-tab-panel`. - `aihio-toggle` - A button that stays pressed or unpressed, such as Bold in a text toolbar. It renders a real
, aria-labelledby pointing at the visible heading above it, or aria-label. - `aihio-data-grid` (error) - when the table has no
cells, Name each column with a in the
as its first child, aria-labelledby pointing at the visible heading above it, or aria-label. An unnamed table is announced only as "table", and so is the scroll box it gets on a narrow screen. - `aihio-table` (error) - when the table has no
cells, Name each column with a in a
where one cell identifies it. Bold text in an ordinary cell is not a header. - `aihio-table` (error) - when a row, header, or cell responds to clicks and holds no link or button, Sort with data-sortable on the , and put a link or button in the row for anything else, such as a link in the cell that names it. A click handler on a row or cell is reachable by pointer only. - `aihio-table` (warn) - when manual-sort is set and a sortable header has no column name, Give each sortable header a name, data-sortable="amount", so aihio-sort says which column to sort by without depending on the header's wording. - `aihio-tabs` (error) - when every aihio-tab and aihio-tab-panel, Match each tab's value to exactly one panel's value. Mismatched values leave panels orphaned. - `aihio-toggle` (error) - when toggle has no visible text (icon-only), Provide aria-label describing what the toggle controls (e.g. aria-label="Bold"). - `aihio-toggle` (warn) - when the toggle turns a setting on or off, or is named by a state word (On, Enabled), Name the toggle after what it controls (e.g. "Bold"), never after its state: a toggle labelled "Enabled" is announced as "Enabled, toggle button, pressed" and never says what is enabled. For an on/off setting in a form, use aihio-switch. ## Hard Rules from Counterexamples Do not invent unsupported APIs or invalid compositions. Treat these schema-backed mistakes as hard failures. - `aihio-alert` - avoid `Oops` (aihio lint: invalid-enum-attribute) - variant="error" is not valid. Use variant="destructive" for error states. Instead: `
Could not save
` - `aihio-alert` - avoid `OK` (aihio lint: forbidden-descendant) - Alerts are non-interactive surfaces. For acknowledgeable prompts use aihio-dialog. Instead: `
Your changes were saved
` - `aihio-alert` - avoid `Saved` (aihio lint: alert-role) - role="alert" interrupts the screen reader. A confirmation should announce politely — drop the role and let the success variant set role="status". Instead: `Saved` - `aihio-avatar` - avoid `` (aihio lint: avatar-alt) - Missing alt. Screen readers will announce only the filename. Instead: `` - `aihio-avatar` - avoid `JD` (aihio lint: invalid-child) - Avatar renders its own content; passed children are replaced. Use the fallback attribute instead. Instead: `` - `aihio-badge` - avoid `Delete` (aihio lint: forbidden-descendant) - Badges are non-interactive labels. Put interactive elements outside the badge. Instead: ` Draft Delete ` - `aihio-badge` - avoid `New` (aihio lint: invalid-enum-attribute) - variant="primary" is not valid. Use variant="default" for the primary style. Instead: `New` - `aihio-button` - avoid `Save` (aihio lint: invalid-enum-attribute) - variant="primary" is not valid. The primary style is variant="default". Instead: `Save` - `aihio-button` - avoid `Save` (aihio lint: forbidden-descendant) - Buttons must not be nested. Use sibling buttons or aihio-dropdown for grouped actions. Instead: ` Cancel Save ` - `aihio-button` - avoid `✕` (aihio lint: button-accessible-name) - Icon-only button is missing an accessible name. Add aria-label="Close" (or similar). Instead: `✕` - `aihio-button` - avoid ` Sign in` (aihio lint: button-form-owner) - A submit button outside the
never submits it. Move the button inside the form element. Instead: ` Sign in
` - `aihio-button` - avoid `See pricing` (aihio lint: button-link-navigation) - A button that navigates is announced as a button, shows no URL, cannot be opened in a new tab, and does nothing without script. Put a link inside it: See pricing. Instead: `See pricing` - `aihio-button` - avoid `See pricing` (aihio lint: unknown-attribute) - aihio-button has no href; nothing reads it. Put the link inside: See pricing. Instead: `See pricing` - `aihio-card` - avoid `Hi` (aihio lint: invalid-child) - Title must live inside aihio-card-header, not directly inside aihio-card. Instead: ` Hi ` - `aihio-card` - avoid `

Open details

` (aihio lint: card-click-handler) - Clickable cards need keyboard-accessible semantics. Wrap the card in a link, or add role="button" plus keyboard handlers to the interactive surface. Instead: `

Open details

` - `aihio-cluster` - avoid `Save` (aihio lint: invalid-enum-attribute) - justify="space-between" is not valid. Use justify="between". Instead: `Save` - `aihio-cluster` - avoid `CancelSave` - A row of actions belongs in aihio-cluster. aihio-stack stacks them vertically and stretches them to full width. Instead: `CancelSave` - `aihio-cluster` - avoid ` Save ` (aihio lint: cluster-needs-grow) - justify="end" does nothing here: the cluster is a content-sized flex item inside the footer. Add grow so it fills the row. Instead: ` Save ` - `aihio-combobox` - avoid ` Finland ` (aihio lint: combobox-label) - Placeholder is not a label. Wrap it in aihio-field with a label slot, or add aria-labelledby or aria-label. Instead: ` Finland ` - `aihio-combobox` - avoid `` (aihio lint: combobox-label) - A wrapping