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:
82
gallery/src/pages/components/ha-input.markdown
Normal file
82
gallery/src/pages/components/ha-input.markdown
Normal 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.
|
||||
232
gallery/src/pages/components/ha-input.ts
Normal file
232
gallery/src/pages/components/ha-input.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,6 @@ class AliasesEditor extends LitElement {
|
||||
|
||||
return html`
|
||||
<ha-input-multi
|
||||
.hass=${this.hass}
|
||||
.value=${this.aliases}
|
||||
.disabled=${this.disabled}
|
||||
.sortable=${this.sortable}
|
||||
|
||||
@@ -11,6 +11,27 @@ import "../ha-svg-icon";
|
||||
import "./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")
|
||||
export class HaInputCopy extends LitElement {
|
||||
@property({ attribute: "value" }) public value!: string;
|
||||
|
||||
@@ -14,6 +14,23 @@ import "../ha-sortable";
|
||||
import "./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")
|
||||
class HaInputMulti extends LitElement {
|
||||
@property({ attribute: false }) public value?: string[];
|
||||
@@ -22,19 +39,19 @@ class HaInputMulti extends LitElement {
|
||||
|
||||
@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 })
|
||||
public itemIndex = false;
|
||||
|
||||
@@ -5,6 +5,16 @@ import { customElement, state } from "lit/decorators";
|
||||
import { localizeContext } from "../../data/context";
|
||||
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")
|
||||
export class HaInputSearch extends HaInput {
|
||||
@state()
|
||||
|
||||
@@ -33,6 +33,49 @@ export type InputType =
|
||||
| "color"
|
||||
| "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")
|
||||
export class HaInput extends LitElement {
|
||||
@property({ reflect: true }) appearance: "material" | "outlined" = "material";
|
||||
@@ -43,10 +86,6 @@ export class HaInput extends LitElement {
|
||||
@property()
|
||||
public value?: string;
|
||||
|
||||
/** Draws a pill-style input with rounded edges. */
|
||||
@property({ type: Boolean })
|
||||
public pill = false;
|
||||
|
||||
/** The input's label. */
|
||||
@property()
|
||||
public label = "";
|
||||
@@ -484,7 +523,8 @@ export class HaInput extends LitElement {
|
||||
}
|
||||
|
||||
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);
|
||||
font-size: var(--ha-font-size-xs);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user