| name | ha-frontend-gallery |
| description | Home Assistant frontend gallery structure, pages, demos, content, and verification. Use when changing files under gallery/, including gallery markdown, TypeScript demos, sidebar entries, mock data, page generation, or gallery builds. |
HA Frontend Gallery
Use this skill for all work under gallery/. Follow the persistent repository guidance in AGENTS.md and load the matching specialist skills alongside this gallery-specific guidance.
Quick Reference
Run commands from the repository root unless noted otherwise:
gallery/script/develop_gallery
gallery/script/build_gallery
yarn lint
yarn lint:types
Never run yarn lint:types or tsc with file arguments. File arguments make tsc ignore tsconfig.json and can emit .js files into src/.
Purpose
The gallery is a developer and designer reference for Home Assistant frontend UI patterns. It documents component APIs, shows realistic Lovelace and more-info states, captures brand and copy guidance, and provides reproducible demos that are safe to inspect outside a running Home Assistant instance.
- Prefer demonstrating real production components from
src/ instead of creating gallery-only replacements.
- Keep fake state, sample data, and demo-only helpers inside
gallery/.
- Do not move gallery stubs or demo data into production code unless a production feature explicitly needs them.
- Do not hand-edit generated output under
gallery/build/ or gallery/dist/.
Structure
gallery/sidebar.js: Defines gallery sections, headers, and explicit page ordering.
gallery/script/develop_gallery: Wrapper for the develop-gallery gulp task.
gallery/script/build_gallery: Wrapper for the build-gallery gulp task.
gallery/src/entrypoint.js: Creates the <ha-gallery> shell.
gallery/src/ha-gallery.ts: Renders the drawer, page routing, markdown descriptions, demos, edit links, and RTL toggle.
gallery/src/html/index.html.template: HTML template used by the gallery build.
gallery/src/pages/<category>/<page>.markdown: Optional page description and frontmatter.
gallery/src/pages/<category>/<page>.ts: Optional live demo module for the same page ID.
gallery/src/components/: Gallery-only demo wrappers like demo-card, demo-cards, demo-more-info, and page-description.
gallery/src/data/: Fake hass, demo states, mock traces, and reusable sample data.
gallery/public/: Static assets copied into the gallery output.
Page Model
Gallery pages are generated by gather-gallery-pages in build-scripts/gulp/gallery.js.
- A page ID is the path under
gallery/src/pages/ without the extension, like components/ha-button.
- A
.markdown file and a .ts file with the same page ID become one gallery page.
- A page may have only markdown, only a TypeScript demo, or both.
- Markdown can contain YAML frontmatter with
title and optional subtitle.
- Markdown that contains only frontmatter contributes metadata without rendering a description block.
- TypeScript demo modules are dynamically imported for side effects when the page is opened.
- A demo module must define a custom element named
demo-${category}-${page} with slashes replaced by hyphens, like demo-components-ha-button for components/ha-button.
gallery/src/ha-gallery.ts renders that element with dynamicElement() based on the current page ID.
Sidebar
Use gallery/sidebar.js when a page needs a visible section, section header, or deterministic ordering.
category must match the first directory name under gallery/src/pages/.
header is the section label shown in the drawer.
pages is optional. When present, listed pages keep that exact order.
- Pages in a category that are not listed are appended alphabetically after the listed pages.
- New categories without a sidebar entry are appended by the generator with their category name as the header.
- If a listed page does not exist, the generator logs an error during
gather-gallery-pages.
Subsections
A section can group its pages under named subsections instead of one flat list. Use this for large categories where related pages should sit together.
subsections is an array of { header, pages }. It is mutually exclusive with a flat pages array on the same group.
- Each subsection
header is a non-collapsible label rendered inside the section's expansion panel; the section stays the only collapsible level.
- Listed pages keep their per-subsection order.
- Any pages found in the category but not listed in a subsection are collected into a generated
Other subsection, appended alphabetically. The Other subsection is omitted when there are no leftovers.
- A listed page that does not exist still logs an error during
gather-gallery-pages.
- Use sentence case for subsection headers and follow the content standards below.
Markdown Pages
Use markdown pages for explanations, design guidance, API notes, and copy standards.
- Start with frontmatter when the page needs a title or subtitle.
- Use sentence case for titles, headings, labels, and UI copy.
- Put the live example before the reference API when that makes the page easier to scan.
- Use fenced code blocks with a language tag for copyable examples.
- Keep examples short and focused on the behavior being documented.
- Prefer real component names and attributes over prose-only descriptions.
- Use Home Assistant terminology from
ha-frontend-user-facing-text.
- For remove/delete and add/create wording, follow
gallery/src/pages/misc/remove-delete-add-create.markdown.
Gallery markdown is documentation content and is not localized with localize. If demo code creates production UI strings, follow the localization and copy guidance in ha-frontend-user-facing-text.
Demo Components
Use TypeScript demo pages for interactive or stateful examples.
- Import production components from
src/ using the correct relative path from the demo file.
- Import reusable gallery helpers from
gallery/src/components/ when they already model the pattern.
- Use
demo-card and demo-cards for Lovelace card examples that render YAML card configs.
- Use
demo-more-info and demo-more-infos for more-info dialog examples.
- Use shared mock data from
gallery/src/data/ instead of repeating large fake state objects inline.
- Show meaningful states, such as loading, unavailable, empty, error, active, inactive, and disabled when relevant.
- Check responsive behavior and the gallery RTL toggle when layout or direction-sensitive UI changes.
- Keep unavoidable casts or loose demo parsing local to the demo helper or demo page.
The gallery ESLint config allows console for gallery diagnostics. Do not copy that exception into production frontend code.
Content Standards
Follow the detailed copy standards in ha-frontend-user-facing-text: use American English, sentence case, active voice, inclusive language, direct user-focused wording, and consistent Home Assistant terminology.
- Use
Home Assistant in full, not HA or HASS.
- Use
integration instead of component for product concepts.
- Use
Remove for reversible disassociation and Delete for permanent deletion.
- Use
Add for existing items and Create for something made from scratch.
- Avoid Latin abbreviations like
e.g. and i.e. in prose.
- Avoid stitching sentence fragments together in production UI examples.
Verification
- For markdown, sidebar, and page-generation changes, run
gallery/script/build_gallery.
- For TypeScript demo or gallery shell changes, run the smallest relevant check plus
yarn lint when practical.
- For type checking, run
yarn lint:types without file arguments.
- For visual changes, run
gallery/script/develop_gallery and check the affected page on desktop, narrow viewport, and RTL when relevant.
- If verification is skipped, state which command was skipped and why.