1
0
mirror of https://github.com/home-assistant/frontend.git synced 2026-04-02 00:27:49 +01:00

Add ha-input-docs (#30315)

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
This commit is contained in:
Wendelin
2026-03-25 15:46:28 +01:00
committed by GitHub
parent cc53f977a2
commit a12543fe74
7 changed files with 414 additions and 13 deletions

View File

@@ -0,0 +1,82 @@
---
title: Input
---
# Input `<ha-input>`
A text input component supporting Home Assistant theming and validation, based on webawesome input.
Supports multiple input types including text, number, password, email, search, and more.
## Implementation
### Example usage
```html
<ha-input label="Name" value="Hello"></ha-input>
<ha-input label="Email" type="email" placeholder="you@example.com"></ha-input>
<ha-input label="Password" type="password" password-toggle></ha-input>
<ha-input label="Required" required></ha-input>
<ha-input label="Disabled" disabled value="Can't touch this"></ha-input>
```
### API
This component is based on the webawesome input component.
**Slots**
- `start`: Content placed before the input (usually for icons or prefixes).
- `end`: Content placed after the input (usually for icons or suffixes).
- `label`: Custom label content. Overrides the `label` property.
- `hint`: Custom hint content. Overrides the `hint` property.
- `clear-icon`: Custom clear icon.
- `show-password-icon`: Custom show password icon.
- `hide-password-icon`: Custom hide password icon.
**Properties/Attributes**
| Name | Type | Default | Description |
| -------------------- | ---------------------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------------------------------------------- |
| appearance | "material"/"outlined" | "material" | Sets the input appearance style. "material" is the default filled style, "outlined" uses a bordered style. |
| type | "text"/"number"/"password"/"email"/"search"/"tel"/"url"/"date"/"datetime-local"/"time"/"color" | "text" | Sets the input type. |
| value | String | - | The current value of the input. |
| label | String | "" | The input's label text. |
| hint | String | "" | The input's hint/helper text. |
| placeholder | String | "" | Placeholder text shown when the input is empty. |
| with-clear | Boolean | false | Adds a clear button when the input is not empty. |
| readonly | Boolean | false | Makes the input readonly. |
| disabled | Boolean | false | Disables the input and prevents user interaction. |
| required | Boolean | false | Makes the input a required field. |
| password-toggle | Boolean | false | Adds a button to toggle the password visibility. |
| without-spin-buttons | Boolean | false | Hides the browser's built-in spin buttons for number inputs. |
| auto-validate | Boolean | false | Validates the input on blur instead of on form submit. |
| invalid | Boolean | false | Marks the input as invalid. |
| inset-label | Boolean | false | Uses an inset label style where the label stays inside the input. |
| validation-message | String | "" | Custom validation message shown when the input is invalid. |
| pattern | String | - | A regular expression pattern to validate input against. |
| minlength | Number | - | The minimum length of input that will be considered valid. |
| maxlength | Number | - | The maximum length of input that will be considered valid. |
| min | Number/String | - | The input's minimum value. Only applies to date and number input types. |
| max | Number/String | - | The input's maximum value. Only applies to date and number input types. |
| step | Number/"any" | - | Specifies the granularity that the value must adhere to. |
**CSS Custom Properties**
- `--ha-input-padding-top` - Padding above the input.
- `--ha-input-padding-bottom` - Padding below the input. Defaults to `var(--ha-space-2)`.
- `--ha-input-text-align` - Text alignment of the input. Defaults to `start`.
- `--ha-input-required-marker` - The marker shown after the label for required fields. Defaults to `"*"`.
---
## Derivatives
The following components extend or wrap `ha-input` for specific use cases:
- **`<ha-input-search>`** — A pre-configured search input with a magnify icon, clear button, and localized "Search" placeholder. Extends `ha-input`.
- **`<ha-input-copy>`** — A read-only input with a copy-to-clipboard button. Supports optional value masking with a reveal toggle.
- **`<ha-input-multi>`** — A dynamic list of text inputs for managing arrays of strings. Supports adding, removing, and drag-and-drop reordering.

View File

@@ -0,0 +1,232 @@
import { ContextProvider } from "@lit/context";
import { mdiMagnify } from "@mdi/js";
import type { TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement } from "lit/decorators";
import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element";
import "../../../../src/components/ha-card";
import "../../../../src/components/ha-svg-icon";
import "../../../../src/components/input/ha-input";
import "../../../../src/components/input/ha-input-copy";
import "../../../../src/components/input/ha-input-multi";
import "../../../../src/components/input/ha-input-search";
import { localizeContext } from "../../../../src/data/context";
const LOCALIZE_KEYS: Record<string, string> = {
"ui.common.copy": "Copy",
"ui.common.show": "Show",
"ui.common.hide": "Hide",
"ui.common.add": "Add",
"ui.common.remove": "Remove",
"ui.common.search": "Search",
"ui.common.copied_clipboard": "Copied to clipboard",
};
@customElement("demo-components-ha-input")
export class DemoHaInput extends LitElement {
constructor() {
super();
// Provides localizeContext for ha-input-copy, ha-input-multi and ha-input-search
// eslint-disable-next-line no-new
new ContextProvider(this, {
context: localizeContext,
initialValue: ((key: string) => LOCALIZE_KEYS[key] ?? key) as any,
});
}
protected render(): TemplateResult {
return html`
${["light", "dark"].map(
(mode) => html`
<div class=${mode}>
<ha-card header="ha-input in ${mode}">
<div class="card-content">
<h3>Basic</h3>
<div class="row">
<ha-input label="Default"></ha-input>
<ha-input label="With value" value="Hello"></ha-input>
<ha-input
label="With placeholder"
placeholder="Type here..."
></ha-input>
</div>
<h3>Input types</h3>
<div class="row">
<ha-input label="Text" type="text" value="Text"></ha-input>
<ha-input label="Number" type="number" value="42"></ha-input>
<ha-input
label="Email"
type="email"
placeholder="you@example.com"
></ha-input>
</div>
<div class="row">
<ha-input
label="Password"
type="password"
value="secret"
password-toggle
></ha-input>
<ha-input label="URL" type="url" placeholder="https://...">
</ha-input>
<ha-input label="Date" type="date"></ha-input>
</div>
<h3>States</h3>
<div class="row">
<ha-input
label="Disabled"
disabled
value="Disabled"
></ha-input>
<ha-input
label="Readonly"
readonly
value="Readonly"
></ha-input>
<ha-input label="Required" required></ha-input>
</div>
<div class="row">
<ha-input
label="Invalid"
invalid
validation-message="This field is required"
value=""
></ha-input>
<ha-input label="With hint" hint="This is a hint"></ha-input>
<ha-input
label="With clear"
with-clear
value="Clear me"
></ha-input>
</div>
<h3>With slots</h3>
<div class="row">
<ha-input label="With prefix">
<span slot="start">$</span>
</ha-input>
<ha-input label="With suffix">
<span slot="end">kg</span>
</ha-input>
<ha-input label="With icon">
<ha-svg-icon .path=${mdiMagnify} slot="start"></ha-svg-icon>
</ha-input>
</div>
<h3>Appearance: outlined</h3>
<div class="row">
<ha-input
appearance="outlined"
label="Outlined"
value="Hello"
></ha-input>
<ha-input
appearance="outlined"
label="Outlined disabled"
disabled
value="Disabled"
></ha-input>
<ha-input
appearance="outlined"
label="Outlined invalid"
invalid
validation-message="Required"
></ha-input>
</div>
<div class="row">
<ha-input
appearance="outlined"
placeholder="Placeholder only"
></ha-input>
</div>
</div>
</ha-card>
<ha-card header="Derivatives in ${mode}">
<div class="card-content">
<h3>ha-input-search</h3>
<ha-input-search label="Search label"></ha-input-search>
<ha-input-search appearance="outlined"></ha-input-search>
<h3>ha-input-copy</h3>
<ha-input-copy
value="my-api-token-123"
masked-value="••••••••••••••••••"
masked-toggle
></ha-input-copy>
<h3>ha-input-multi</h3>
<ha-input-multi
label="URL"
add-label="Add URL"
.value=${["https://example.com"]}
></ha-input-multi>
</div>
</ha-card>
</div>
`
)}
`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
applyThemesOnElement(
this.shadowRoot!.querySelector(".dark"),
{
default_theme: "default",
default_dark_theme: "default",
themes: {},
darkMode: true,
theme: "default",
},
undefined,
undefined,
true
);
}
static styles = css`
:host {
display: flex;
justify-content: center;
}
.dark,
.light {
display: block;
background-color: var(--primary-background-color);
padding: 0 50px;
}
ha-card {
margin: 24px auto;
}
.card-content {
display: flex;
flex-direction: column;
gap: var(--ha-space-2);
}
h3 {
margin: var(--ha-space-4) 0 var(--ha-space-1) 0;
font-size: var(--ha-font-size-l);
font-weight: var(--ha-font-weight-medium);
}
h3:first-child {
margin-top: 0;
}
.row {
display: flex;
gap: var(--ha-space-4);
}
.row > * {
flex: 1;
}
`;
}
declare global {
interface HTMLElementTagNameMap {
"demo-components-ha-input": DemoHaInput;
}
}

View File

@@ -21,7 +21,6 @@ class AliasesEditor extends LitElement {
return html` return html`
<ha-input-multi <ha-input-multi
.hass=${this.hass}
.value=${this.aliases} .value=${this.aliases}
.disabled=${this.disabled} .disabled=${this.disabled}
.sortable=${this.sortable} .sortable=${this.sortable}

View File

@@ -11,6 +11,27 @@ import "../ha-svg-icon";
import "./ha-input"; import "./ha-input";
import type { HaInput, InputType } from "./ha-input"; import type { HaInput, InputType } from "./ha-input";
/**
* Home Assistant input with copy button
*
* @element ha-input-copy
* @extends {LitElement}
*
* @summary
* A read-only input component with a copy-to-clipboard button.
* Supports optional value masking with a toggle to reveal the hidden value.
*
* @attr {string} value - The value to display and copy.
* @attr {string} masked-value - An alternative masked display value (for example, "••••••").
* @attr {string} label - Label for the copy button. Defaults to the localized "Copy" text.
* @attr {boolean} readonly - Makes the inner input readonly.
* @attr {boolean} disabled - Disables the inner input.
* @attr {boolean} masked-toggle - Shows a toggle button to reveal/hide the masked value.
* @attr {("text"|"password"|"email"|"number"|"tel"|"url"|"search"|"date"|"datetime-local"|"time"|"color")} type - Sets the input type.
* @attr {string} placeholder - Placeholder text for the input.
* @attr {string} validation-message - Custom validation message.
* @attr {boolean} auto-validate - Validates the input on blur.
*/
@customElement("ha-input-copy") @customElement("ha-input-copy")
export class HaInputCopy extends LitElement { export class HaInputCopy extends LitElement {
@property({ attribute: "value" }) public value!: string; @property({ attribute: "value" }) public value!: string;

View File

@@ -14,6 +14,23 @@ import "../ha-sortable";
import "./ha-input"; import "./ha-input";
import type { HaInput, InputType } from "./ha-input"; import type { HaInput, InputType } from "./ha-input";
/**
* Home Assistant multi-value input component
*
* @element ha-input-multi
* @extends {LitElement}
*
* @summary
* A dynamic list of text inputs that allows adding, removing, and optionally reordering values.
* Useful for managing arrays of strings such as URLs, tags, or other repeated text values.
*
* @attr {boolean} disabled - Disables all inputs and buttons.
* @attr {boolean} sortable - Enables drag-and-drop reordering of items.
* @attr {boolean} item-index - Appends a 1-based index number to each item's label.
* @attr {boolean} update-on-blur - Fires value-changed on blur instead of on input.
*
* @fires value-changed - Fired when the list of values changes. `event.detail.value` contains the new string array.
*/
@customElement("ha-input-multi") @customElement("ha-input-multi")
class HaInputMulti extends LitElement { class HaInputMulti extends LitElement {
@property({ attribute: false }) public value?: string[]; @property({ attribute: false }) public value?: string[];
@@ -22,19 +39,19 @@ class HaInputMulti extends LitElement {
@property() public label?: string; @property() public label?: string;
@property({ attribute: false }) public helper?: string; @property() public helper?: string;
@property({ attribute: false }) public inputType?: InputType; @property({ attribute: "input-type" }) public inputType?: InputType;
@property({ attribute: false }) public inputSuffix?: string; @property({ attribute: "input-suffix" }) public inputSuffix?: string;
@property({ attribute: false }) public inputPrefix?: string; @property({ attribute: "input-prefix" }) public inputPrefix?: string;
@property({ attribute: false }) public autocomplete?: string; @property() public autocomplete?: string;
@property({ attribute: false }) public addLabel?: string; @property({ attribute: "add-label" }) public addLabel?: string;
@property({ attribute: false }) public removeLabel?: string; @property({ attribute: "remove-label" }) public removeLabel?: string;
@property({ attribute: "item-index", type: Boolean }) @property({ attribute: "item-index", type: Boolean })
public itemIndex = false; public itemIndex = false;

View File

@@ -5,6 +5,16 @@ import { customElement, state } from "lit/decorators";
import { localizeContext } from "../../data/context"; import { localizeContext } from "../../data/context";
import { HaInput } from "./ha-input"; import { HaInput } from "./ha-input";
/**
* Home Assistant search input component
*
* @element ha-input-search
* @extends {HaInput}
*
* @summary
* A pre-configured search input that extends `ha-input` with a magnify icon, clear button,
* and a localized "Search" placeholder. Autocomplete is disabled by default.
*/
@customElement("ha-input-search") @customElement("ha-input-search")
export class HaInputSearch extends HaInput { export class HaInputSearch extends HaInput {
@state() @state()

View File

@@ -33,6 +33,49 @@ export type InputType =
| "color" | "color"
| "url"; | "url";
/**
* Home Assistant input component
*
* @element ha-input
* @extends {LitElement}
*
* @summary
* A text input component supporting Home Assistant theming and validation, based on webawesome input.
* Supports multiple input types including text, number, password, email, search, and more.
*
* @slot start - Content placed before the input (usually for icons or prefixes).
* @slot end - Content placed after the input (usually for icons or suffixes).
* @slot label - Custom label content. Overrides the `label` property.
* @slot hint - Custom hint content. Overrides the `hint` property.
* @slot clear-icon - Custom clear icon. Defaults to a close icon button.
* @slot show-password-icon - Custom show password icon. Defaults to an eye icon button.
* @slot hide-password-icon - Custom hide password icon. Defaults to an eye-off icon button.
*
* @csspart wa-base - The underlying wa-input base wrapper.
* @csspart wa-hint - The underlying wa-input hint container.
* @csspart wa-input - The underlying wa-input input element.
*
* @cssprop --ha-input-padding-top - Padding above the input.
* @cssprop --ha-input-padding-bottom - Padding below the input. Defaults to `var(--ha-space-2)`.
* @cssprop --ha-input-text-align - Text alignment of the input. Defaults to `start`.
* @cssprop --ha-input-required-marker - The marker shown after the label for required fields. Defaults to `"*"`.
*
* @attr {("material"|"outlined")} appearance - Sets the input appearance style. "material" is the default filled style, "outlined" uses a bordered style.
* @attr {("date"|"datetime-local"|"email"|"number"|"password"|"search"|"tel"|"text"|"time"|"color"|"url")} type - Sets the input type.
* @attr {string} label - The input's label text.
* @attr {string} hint - The input's hint/helper text.
* @attr {string} placeholder - Placeholder text shown when the input is empty.
* @attr {boolean} with-clear - Adds a clear button when the input is not empty.
* @attr {boolean} readonly - Makes the input readonly.
* @attr {boolean} disabled - Disables the input and prevents user interaction.
* @attr {boolean} required - Makes the input a required field.
* @attr {boolean} password-toggle - Adds a button to toggle the password visibility.
* @attr {boolean} without-spin-buttons - Hides the browser's built-in spin buttons for number inputs.
* @attr {boolean} auto-validate - Validates the input on blur instead of on form submit.
* @attr {boolean} invalid - Marks the input as invalid.
* @attr {boolean} inset-label - Uses an inset label style where the label stays inside the input.
* @attr {string} validation-message - Custom validation message shown when the input is invalid.
*/
@customElement("ha-input") @customElement("ha-input")
export class HaInput extends LitElement { export class HaInput extends LitElement {
@property({ reflect: true }) appearance: "material" | "outlined" = "material"; @property({ reflect: true }) appearance: "material" | "outlined" = "material";
@@ -43,10 +86,6 @@ export class HaInput extends LitElement {
@property() @property()
public value?: string; public value?: string;
/** Draws a pill-style input with rounded edges. */
@property({ type: Boolean })
public pill = false;
/** The input's label. */ /** The input's label. */
@property() @property()
public label = ""; public label = "";
@@ -484,7 +523,8 @@ export class HaInput extends LitElement {
} }
wa-input.label-raised::part(label), wa-input.label-raised::part(label),
:host(:focus-within) wa-input::part(label) { :host(:focus-within) wa-input::part(label),
:host([type="date"]) wa-input::part(label) {
padding-top: var(--ha-space-3); padding-top: var(--ha-space-3);
font-size: var(--ha-font-size-xs); font-size: var(--ha-font-size-xs);
} }