diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index bf543cb04c..a18c2f90d9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -2,6 +2,8 @@ You are an assistant helping with development of the Home Assistant frontend. The frontend is built using Lit-based Web Components and TypeScript, providing a responsive and performant interface for home automation control. +**Note**: This file contains high-level guidelines and references to implementation patterns. For detailed component documentation, API references, and usage examples, refer to the `gallery/` directory. + ## Table of Contents - [Quick Reference](#quick-reference) @@ -151,6 +153,10 @@ try { ### Styling Guidelines - **Use CSS custom properties**: Leverage the theme system +- **Use spacing tokens**: Prefer `--ha-space-*` tokens over hardcoded values for consistent spacing + - Spacing scale: `--ha-space-0` (0px) through `--ha-space-20` (80px) in 4px increments + - Defined in `src/resources/theme/core.globals.ts` + - Common values: `--ha-space-2` (8px), `--ha-space-4` (16px), `--ha-space-8` (32px) - **Mobile-first responsive**: Design for mobile, enhance for desktop - **Follow Material Design**: Use Material Web Components where appropriate - **Support RTL**: Ensure all layouts work in RTL languages @@ -159,21 +165,68 @@ try { static get styles() { return css` :host { - --spacing: 16px; - padding: var(--spacing); + padding: var(--ha-space-4); color: var(--primary-text-color); background-color: var(--card-background-color); } + .content { + gap: var(--ha-space-2); + } + @media (max-width: 600px) { :host { - --spacing: 8px; + padding: var(--ha-space-2); } } `; } ``` +### View Transitions + +The View Transitions API creates smooth animations between DOM state changes. When implementing view transitions: + +**Core Resources:** + +- **Utility wrapper**: `src/common/util/view-transition.ts` - `withViewTransition()` function with graceful fallback +- **Real-world example**: `src/util/launch-screen.ts` - Launch screen fade pattern with browser support detection +- **Animation keyframes**: `src/resources/theme/animations.globals.ts` - Global `fade-in`, `fade-out`, `scale` animations +- **Animation duration**: `src/resources/theme/core.globals.ts` - `--ha-animation-base-duration` (350ms, respects `prefers-reduced-motion`) + +**Implementation Guidelines:** + +1. Always use `withViewTransition()` wrapper for automatic fallback +2. Keep transitions simple (subtle crossfades and fades work best) +3. Use `--ha-animation-base-duration` CSS variable for consistent timing +4. Assign unique `view-transition-name` to elements (must be unique at any given time) +5. For Lit components: Override `performUpdate()` or use `::part()` for internal elements + +**Default Root Transition:** + +By default, `:root` receives `view-transition-name: root`, creating a full-page crossfade. Target with [`::view-transition-group(root)`](https://developer.mozilla.org/en-US/docs/Web/CSS/::view-transition-group) to customize the default page transition. + +**Important Constraints:** + +- Each `view-transition-name` must be unique at any given time +- Only one view transition can run at a time +- **Shadow DOM incompatibility**: View transitions operate at document level and do not work within Shadow DOM due to style isolation ([spec discussion](https://github.com/w3c/csswg-drafts/issues/10303)). For web components, set `view-transition-name` on the `:host` element or use document-level transitions + +**Current Usage & Planned Applications:** + +- Launch screen fade out (implemented) +- Automation sidebar transitions (planned - #27238) +- More info dialog content changes (planned - #27672) +- Toolbar navigation, ha-spinner transitions (planned) + +**Specification & Documentation:** + +For browser support, API details, and current specifications, refer to these authoritative sources (note: check publication dates as specs evolve): + +- [MDN: View Transition API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) - Comprehensive API reference +- [Chrome for Developers: View Transitions](https://developer.chrome.com/docs/web-platform/view-transitions) - Implementation guide and examples +- [W3C Draft Specification](https://drafts.csswg.org/css-view-transitions/) - Official specification (evolving) + ### Performance Best Practices - **Code split**: Split code at the panel/dialog level @@ -195,8 +248,9 @@ static get styles() { **Available Dialog Types:** -- `ha-md-dialog` - Preferred for new code (Material Design 3) -- `ha-dialog` - Legacy component still widely used +- `ha-wa-dialog` - Preferred for new dialogs (Web Awesome based) +- `ha-md-dialog` - Material Design 3 dialog component +- `ha-dialog` - Legacy component (still widely used) **Opening Dialogs (Fire Event Pattern - Recommended):** @@ -211,15 +265,45 @@ fireEvent(this, "show-dialog", { **Dialog Implementation Requirements:** - Implement `HassDialog` interface -- Use `createCloseHeading()` for standard headers -- Import `haStyleDialog` for consistent styling +- Use `@state() private _open = false` to control dialog visibility +- Set `_open = true` in `showDialog()`, `_open = false` in `closeDialog()` - Return `nothing` when no params (loading state) -- Fire `dialog-closed` event when closing -- Add `dialogInitialFocus` for accessibility +- Fire `dialog-closed` event in `_dialogClosed()` handler +- Use `header-title` attribute for simple titles +- Use `header-subtitle` attribute for simple subtitles +- Use slots for custom content where the standard attributes are not enough +- Use `ha-dialog-footer` with `primaryAction`/`secondaryAction` slots for footer content +- Add `autofocus` to first focusable element (e.g., ``). The component may need to forward this attribute internally. -```` +**Dialog Sizing:** + +- Use `width` attribute with predefined sizes: `"small"` (320px), `"medium"` (560px - default), `"large"` (720px), or `"full"` +- Custom sizing is NOT recommended - use the standard width presets +- Example: `` for alert/confirmation dialogs + +**Button Appearance Guidelines:** + +- **Primary action buttons**: Default appearance (no appearance attribute) or omit for standard styling +- **Secondary action buttons**: Use `appearance="plain"` for cancel/dismiss actions +- **Destructive actions**: Use `appearance="filled"` for delete/remove operations (combined with appropriate semantic styling) +- **Button sizes**: Use `size="small"` (32px height) or default/medium (40px height) +- Always place primary action in `slot="primaryAction"` and secondary in `slot="secondaryAction"` within `ha-dialog-footer` + +**Recent Examples:** + +See these files for current patterns: + +- `src/panels/config/repairs/dialog-repairs-issue.ts` +- `src/dialogs/restart/dialog-restart.ts` +- `src/panels/config/lovelace/resources/dialog-lovelace-resource-detail.ts` + +**Gallery Documentation:** + +- `gallery/src/pages/components/ha-wa-dialog.markdown` +- `gallery/src/pages/components/ha-dialogs.markdown` ### Form Component (ha-form) + - Schema-driven using `HaFormSchema[]` - Supports entity, device, area, target, number, boolean, time, action, text, object, select, icon, media, location selectors - Built-in validation with error display @@ -235,7 +319,11 @@ fireEvent(this, "show-dialog", { .computeLabel=${(schema) => this.hass.localize(`ui.panel.${schema.name}`)} @value-changed=${this._valueChanged} > -```` +``` + +**Gallery Documentation:** + +- `gallery/src/pages/components/ha-form.markdown` ### Alert Component (ha-alert) @@ -249,6 +337,35 @@ fireEvent(this, "show-dialog", { Success message ``` +**Gallery Documentation:** + +- `gallery/src/pages/components/ha-alert.markdown` + +### Keyboard Shortcuts (ShortcutManager) + +The `ShortcutManager` class provides a unified way to register keyboard shortcuts with automatic input field protection. + +**Key Features:** + +- Automatically blocks shortcuts when input fields are focused +- Prevents shortcuts during text selection (configurable via `allowWhenTextSelected`) +- Supports both character-based and KeyCode-based shortcuts (for non-latin keyboards) + +**Implementation:** + +- **Class definition**: `src/common/keyboard/shortcuts.ts` +- **Real-world example**: `src/state/quick-bar-mixin.ts` - Global shortcuts (e, c, d, m, a, Shift+?) with non-latin keyboard fallbacks + +### Tooltip Component (ha-tooltip) + +The `ha-tooltip` component wraps Web Awesome tooltip with Home Assistant theming. Use for providing contextual help text on hover. + +**Implementation:** + +- **Component definition**: `src/components/ha-tooltip.ts` +- **Usage example**: `src/components/ha-label.ts` +- **Gallery documentation**: `gallery/src/pages/components/ha-tooltip.markdown` + ## Common Patterns ### Creating a Panel @@ -289,11 +406,19 @@ export class DialogMyFeature @state() private _params?: MyDialogParams; + @state() + private _open = false; + public async showDialog(params: MyDialogParams): Promise { this._params = params; + this._open = true; } public closeDialog(): void { + this._open = false; + } + + private _dialogClosed(): void { this._params = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -304,23 +429,27 @@ export class DialogMyFeature } return html` - - - - ${this.hass.localize("ui.common.cancel")} - - - ${this.hass.localize("ui.common.save")} - - +

Dialog content

+ + + ${this.hass.localize("ui.common.cancel")} + + + ${this.hass.localize("ui.common.save")} + + + `; } diff --git a/AGENTS.md b/AGENTS.md new file mode 120000 index 0000000000..02dd134122 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1 @@ +.github/copilot-instructions.md \ No newline at end of file