From f0d4c9cb72a1804e44c21426cd2ba4be06a0fbfe Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Wed, 8 Oct 2025 17:24:10 +0000 Subject: [PATCH 1/2] Introduce ha-dropdown --- .../src/pages/components/ha-dropdown.markdown | 5 + gallery/src/pages/components/ha-dropdown.ts | 133 ++++++++++++++++++ package.json | 2 +- src/components/ha-dropdown-item.ts | 23 +++ src/components/ha-dropdown.ts | 20 +++ src/panels/profile/ha-refresh-tokens-card.ts | 27 ++-- src/resources/theme/color/wa.globals.ts | 3 + src/resources/theme/wa.globals.ts | 10 +- yarn.lock | 10 +- 9 files changed, 211 insertions(+), 22 deletions(-) create mode 100644 gallery/src/pages/components/ha-dropdown.markdown create mode 100644 gallery/src/pages/components/ha-dropdown.ts create mode 100644 src/components/ha-dropdown-item.ts create mode 100644 src/components/ha-dropdown.ts diff --git a/gallery/src/pages/components/ha-dropdown.markdown b/gallery/src/pages/components/ha-dropdown.markdown new file mode 100644 index 000000000000..64381f6bb062 --- /dev/null +++ b/gallery/src/pages/components/ha-dropdown.markdown @@ -0,0 +1,5 @@ +--- +title: Dropdown +--- + +# Dropdown `` diff --git a/gallery/src/pages/components/ha-dropdown.ts b/gallery/src/pages/components/ha-dropdown.ts new file mode 100644 index 000000000000..12c467fe5c19 --- /dev/null +++ b/gallery/src/pages/components/ha-dropdown.ts @@ -0,0 +1,133 @@ +import { + mdiContentCopy, + mdiContentCut, + mdiContentPaste, + mdiDelete, +} from "@mdi/js"; +import type { TemplateResult } from "lit"; +import { css, html, LitElement } from "lit"; +import { customElement } from "lit/decorators"; +import "../../../../src/components/ha-button"; +import "../../../../src/components/ha-card"; +import "../../../../src/components/ha-svg-icon"; +import "../../../../src/components/ha-dropdown-item"; +import "@home-assistant/webawesome/dist/components/icon/icon"; +import "@home-assistant/webawesome/dist/components/button/button"; +import "@home-assistant/webawesome/dist/components/dropdown/dropdown"; +import "../../../../src/components/ha-dropdown"; +import "@home-assistant/webawesome/dist/components/popup/popup"; +import { applyThemesOnElement } from "../../../../src/common/dom/apply_themes_on_element"; +import "../../../../src/components/ha-icon-button"; + +@customElement("demo-components-ha-dropdown") +export class DemoHaDropdown extends LitElement { + protected render(): TemplateResult { + return html` + ${["light", "dark"].map( + (mode) => html` +
+ +
+ + Dropdown + + + + Cut + + + + Copy + + + + Paste + + + Show images + Show All Images + Show Thumbnails + + Emoji Shortcuts + Word Wrap + + + Delete + + +
+
+
+ ` + )} + `; + } + + 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; + } + .button { + padding: unset; + } + ha-card { + margin: 24px auto; + } + .card-content { + display: flex; + flex-direction: column; + gap: 24px; + } + .card-content div { + display: flex; + gap: 8px; + } + `; +} + +declare global { + interface HTMLElementTagNameMap { + "demo-components-ha-dropdown": DemoHaDropdown; + } +} diff --git a/package.json b/package.json index 432771aa7cdc..acad73e168c7 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "@fullcalendar/list": "6.1.19", "@fullcalendar/luxon3": "6.1.19", "@fullcalendar/timegrid": "6.1.19", - "@home-assistant/webawesome": "3.0.0-beta.6.ha.1", + "@home-assistant/webawesome": "3.0.0-beta.6.ha.2", "@lezer/highlight": "1.2.1", "@lit-labs/motion": "1.0.9", "@lit-labs/observers": "2.0.6", diff --git a/src/components/ha-dropdown-item.ts b/src/components/ha-dropdown-item.ts new file mode 100644 index 000000000000..e5002f23a3a7 --- /dev/null +++ b/src/components/ha-dropdown-item.ts @@ -0,0 +1,23 @@ +import DropdownItem from "@home-assistant/webawesome/dist/components/dropdown-item/dropdown-item"; +import { css, type CSSResultGroup } from "lit"; +import { customElement } from "lit/decorators"; + +@customElement("ha-dropdown-item") +export class HaDropdownItem extends DropdownItem { + static get styles(): CSSResultGroup { + return [ + DropdownItem.styles, + css` + :host { + min-height: 40px; + } + `, + ]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dropdown-item": HaDropdownItem; + } +} diff --git a/src/components/ha-dropdown.ts b/src/components/ha-dropdown.ts new file mode 100644 index 000000000000..96925f3b942d --- /dev/null +++ b/src/components/ha-dropdown.ts @@ -0,0 +1,20 @@ +import Dropdown from "@home-assistant/webawesome/dist/components/dropdown/dropdown"; +import type { CSSResultGroup } from "lit"; +import { customElement, property } from "lit/decorators"; + +@customElement("ha-dropdown") +export class HaDropdown extends Dropdown { + @property({ attribute: false }) dropdownTag = "ha-dropdown"; + + @property({ attribute: false }) dropdownItemTag = "ha-dropdown-item"; + + static get styles(): CSSResultGroup { + return [Dropdown.styles]; + } +} + +declare global { + interface HTMLElementTagNameMap { + "ha-dropdown": HaDropdown; + } +} diff --git a/src/panels/profile/ha-refresh-tokens-card.ts b/src/panels/profile/ha-refresh-tokens-card.ts index 7ee2b77be07d..ff10317f4b23 100644 --- a/src/panels/profile/ha-refresh-tokens-card.ts +++ b/src/panels/profile/ha-refresh-tokens-card.ts @@ -29,6 +29,8 @@ import { } from "../../dialogs/generic/show-dialog-box"; import { haStyle } from "../../resources/styles"; import type { HomeAssistant } from "../../types"; +import "../../components/ha-dropdown-item"; +import "../../components/ha-dropdown"; // Client ID used by iOS app const iOSclientId = "https://home-assistant.io/iOS"; @@ -146,19 +148,18 @@ class HaRefreshTokens extends LitElement { )}
- + - - + -
- ${this.hass.localize("ui.common.delete")} -
-
-
+ ${this.hass.localize("ui.common.delete")} + +
` diff --git a/src/resources/theme/color/wa.globals.ts b/src/resources/theme/color/wa.globals.ts index 634ead0752f4..e6e84c4a9b8e 100644 --- a/src/resources/theme/color/wa.globals.ts +++ b/src/resources/theme/color/wa.globals.ts @@ -52,6 +52,9 @@ export const waColorStyles = css` --wa-color-danger-on-normal: var(--ha-color-on-danger-normal); --wa-color-danger-on-quiet: var(--ha-color-on-danger-quiet); + --wa-color-text-normal: var(--ha-color-text-primary); + --wa-color-surface-raised: var(--ha-dialog-surface-background, var(--mdc-theme-surface, #fff)); + --wa-focus-ring-color: var(--ha-color-neutral-60); } `; diff --git a/src/resources/theme/wa.globals.ts b/src/resources/theme/wa.globals.ts index dd05b4e5547d..38ce5e7b96c5 100644 --- a/src/resources/theme/wa.globals.ts +++ b/src/resources/theme/wa.globals.ts @@ -16,7 +16,15 @@ export const waMainStyles = css` --wa-font-weight-action: var(--ha-font-weight-medium); --wa-transition-fast: 75ms; --wa-transition-easing: ease; - --wa-border-width-l: var(--ha-border-radius-l); + --wa-border-width-s: var(--ha-border-width-sm); + --wa-border-width-m: var(--ha-border-width-md); + --wa-border-width-l: var(--ha-border-width-lg); + --wa-border-radius-s: var(--ha-border-radius-sm); + --wa-border-radius-m: var(--ha-border-radius-md); + --wa-border-radius-l: var(--ha-border-radius-lg); + + --wa-line-height-condensed: 1.25; + --wa-space-xl: 32px; } diff --git a/yarn.lock b/yarn.lock index 24b0e98bcbf4..4b8c194d7d4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1942,9 +1942,9 @@ __metadata: languageName: node linkType: hard -"@home-assistant/webawesome@npm:3.0.0-beta.6.ha.1": - version: 3.0.0-beta.6.ha.1 - resolution: "@home-assistant/webawesome@npm:3.0.0-beta.6.ha.1" +"@home-assistant/webawesome@npm:3.0.0-beta.6.ha.2": + version: 3.0.0-beta.6.ha.2 + resolution: "@home-assistant/webawesome@npm:3.0.0-beta.6.ha.2" dependencies: "@ctrl/tinycolor": "npm:4.1.0" "@floating-ui/dom": "npm:^1.6.13" @@ -1955,7 +1955,7 @@ __metadata: lit: "npm:^3.2.1" nanoid: "npm:^5.1.5" qr-creator: "npm:^1.0.0" - checksum: 10/c9510e0c65b682c3868b5cbbf046f62aea30e3c5d969128d9032e0d89a8943faa4c9d78c3500446ec04cffeb0ab1939b870b60d454db657faed2aa0ac6026a3e + checksum: 10/781d3aecc7d11a13307c0be12ae6383774242abdf8ce283167665c1d85d2be8380a8a08cc16d80cfe89bdfbb01fa718c2e43cd095288bbc0ef2d06621b412866 languageName: node linkType: hard @@ -9207,7 +9207,7 @@ __metadata: "@fullcalendar/list": "npm:6.1.19" "@fullcalendar/luxon3": "npm:6.1.19" "@fullcalendar/timegrid": "npm:6.1.19" - "@home-assistant/webawesome": "npm:3.0.0-beta.6.ha.1" + "@home-assistant/webawesome": "npm:3.0.0-beta.6.ha.2" "@lezer/highlight": "npm:1.2.1" "@lit-labs/motion": "npm:1.0.9" "@lit-labs/observers": "npm:2.0.6" From 10b99433ea0712e95759f3f4af4204e5f73277d1 Mon Sep 17 00:00:00 2001 From: Simon Lamon <32477463+silamon@users.noreply.github.com> Date: Sat, 11 Oct 2025 09:52:22 +0000 Subject: [PATCH 2/2] Shadow and fixes --- src/components/ha-dropdown.ts | 19 +++++++++++++++++-- src/resources/theme/color/semantic.globals.ts | 6 ++++++ src/resources/theme/color/wa.globals.ts | 2 ++ src/resources/theme/wa.globals.ts | 1 + 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/components/ha-dropdown.ts b/src/components/ha-dropdown.ts index 96925f3b942d..76c6cbdf213f 100644 --- a/src/components/ha-dropdown.ts +++ b/src/components/ha-dropdown.ts @@ -1,5 +1,5 @@ import Dropdown from "@home-assistant/webawesome/dist/components/dropdown/dropdown"; -import type { CSSResultGroup } from "lit"; +import { css, type CSSResultGroup } from "lit"; import { customElement, property } from "lit/decorators"; @customElement("ha-dropdown") @@ -9,7 +9,22 @@ export class HaDropdown extends Dropdown { @property({ attribute: false }) dropdownItemTag = "ha-dropdown-item"; static get styles(): CSSResultGroup { - return [Dropdown.styles]; + return [ + Dropdown.styles, + css` + :host { + --wa-color-surface-border: var(--ha-color-border-normal); + --wa-color-surface-raised: var( + --card-background-color, + var(--ha-dialog-surface-background, var(--mdc-theme-surface, #fff)), + ); + } + + #menu { + --wa-shadow-m: 0px 4px 8px 0px var(--ha-color-shadow); + } + `, + ]; } } diff --git a/src/resources/theme/color/semantic.globals.ts b/src/resources/theme/color/semantic.globals.ts index d99291d83314..24eba707b851 100644 --- a/src/resources/theme/color/semantic.globals.ts +++ b/src/resources/theme/color/semantic.globals.ts @@ -152,6 +152,9 @@ export const semanticColorStyles = css` --ha-color-on-success-quiet: var(--ha-color-green-50); --ha-color-on-success-normal: var(--ha-color-green-40); --ha-color-on-success-loud: var(--white-color); + + /* shadow */ + --ha-color-shadow: rgba(0, 0, 0, 0.2); } `; @@ -280,5 +283,8 @@ export const darkSemanticColorStyles = css` --ha-color-on-success-quiet: var(--ha-color-green-70); --ha-color-on-success-normal: var(--ha-color-green-60); --ha-color-on-success-loud: var(--white-color); + + /* shadow */ + --ha-color-shadow: rgba(255, 255, 255, 0.2); } `; diff --git a/src/resources/theme/color/wa.globals.ts b/src/resources/theme/color/wa.globals.ts index e6e84c4a9b8e..d11d12d4f1c3 100644 --- a/src/resources/theme/color/wa.globals.ts +++ b/src/resources/theme/color/wa.globals.ts @@ -53,7 +53,9 @@ export const waColorStyles = css` --wa-color-danger-on-quiet: var(--ha-color-on-danger-quiet); --wa-color-text-normal: var(--ha-color-text-primary); + --wa-color-surface-default: var(--card-background-color); --wa-color-surface-raised: var(--ha-dialog-surface-background, var(--mdc-theme-surface, #fff)); + --wa-color-surface-border: var(--ha-color-border-normal); --wa-focus-ring-color: var(--ha-color-neutral-60); } diff --git a/src/resources/theme/wa.globals.ts b/src/resources/theme/wa.globals.ts index 38ce5e7b96c5..7e2651194769 100644 --- a/src/resources/theme/wa.globals.ts +++ b/src/resources/theme/wa.globals.ts @@ -16,6 +16,7 @@ export const waMainStyles = css` --wa-font-weight-action: var(--ha-font-weight-medium); --wa-transition-fast: 75ms; --wa-transition-easing: ease; + --wa-border-style: solid; --wa-border-width-s: var(--ha-border-width-sm); --wa-border-width-m: var(--ha-border-width-md); --wa-border-width-l: var(--ha-border-width-lg);