Add RTL and dark mode support for select box image (#24374)

Add rtl and dark for select box
This commit is contained in:
Paul Bottein 2025-02-25 10:38:02 +01:00 committed by GitHub
parent db5036aed3
commit d47e5c847b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 16 deletions

View File

@ -5,17 +5,27 @@ import { classMap } from "lit/directives/class-map";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import type { HaRadio } from "./ha-radio"; import type { HaRadio } from "./ha-radio";
import { fireEvent } from "../common/dom/fire_event"; import { fireEvent } from "../common/dom/fire_event";
import type { HomeAssistant } from "../types";
import { computeRTL } from "../common/util/compute_rtl";
interface SelectBoxOptionImage {
src: string;
src_dark?: string;
flip_rtl?: boolean;
}
export interface SelectBoxOption { export interface SelectBoxOption {
label?: string; label?: string;
description?: string; description?: string;
image?: string; image?: string | SelectBoxOptionImage;
value: string; value: string;
disabled?: boolean; disabled?: boolean;
} }
@customElement("ha-select-box") @customElement("ha-select-box")
export class HaSelectBox extends LitElement { export class HaSelectBox extends LitElement {
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public options: SelectBoxOption[] = []; @property({ attribute: false }) public options: SelectBoxOption[] = [];
@property({ attribute: false }) public value?: string; @property({ attribute: false }) public value?: string;
@ -40,6 +50,17 @@ export class HaSelectBox extends LitElement {
const horizontal = this.maxColumns === 1; const horizontal = this.maxColumns === 1;
const disabled = option.disabled || this.disabled || false; const disabled = option.disabled || this.disabled || false;
const selected = option.value === this.value; const selected = option.value === this.value;
const isDark = this.hass?.themes.darkMode || false;
const isRTL = this.hass ? computeRTL(this.hass) : false;
const imageSrc =
typeof option.image === "object"
? (isDark && option.image.src_dark) || option.image.src
: option.image;
const imageFlip =
typeof option.image === "object" ? isRTL && option.image.flip_rtl : false;
return html` return html`
<label <label
class="option ${classMap({ class="option ${classMap({
@ -63,7 +84,11 @@ export class HaSelectBox extends LitElement {
: nothing} : nothing}
</div> </div>
</div> </div>
${option.image ? html`<img alt="" src=${option.image} />` : nothing} ${imageSrc
? html`
<img class=${imageFlip ? "flipped" : ""} alt="" src=${imageSrc} />
`
: nothing}
</label> </label>
`; `;
} }
@ -146,6 +171,10 @@ export class HaSelectBox extends LitElement {
margin: auto; margin: auto;
} }
.flipped {
transform: scaleX(-1);
}
.option.horizontal { .option.horizontal {
flex-direction: row; flex-direction: row;
align-items: flex-start; align-items: flex-start;

View File

@ -105,6 +105,7 @@ export class HaSelectSelector extends LitElement {
.value=${this.value as string | undefined} .value=${this.value as string | undefined}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
.maxColumns=${this.selector.select?.box_max_columns} .maxColumns=${this.selector.select?.box_max_columns}
.hass=${this.hass}
></ha-select-box> ></ha-select-box>
${this._renderHelper()} ${this._renderHelper()}
`; `;

View File

@ -343,11 +343,17 @@ export interface AssistPipelineSelector {
} | null; } | null;
} }
interface SelectBoxOptionImage {
src: string;
src_dark?: string;
flip_rtl?: boolean;
}
export interface SelectOption { export interface SelectOption {
value: any; value: any;
label: string; label: string;
description?: string; description?: string;
image?: string; image?: string | SelectBoxOptionImage;
disabled?: boolean; disabled?: boolean;
} }

View File

@ -1,8 +1,9 @@
import { html, LitElement, nothing } from "lit"; import { html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { assert, assign, boolean, object, optional, string } from "superstruct";
import memoizeOne from "memoize-one"; import memoizeOne from "memoize-one";
import { assert, assign, boolean, object, optional, string } from "superstruct";
import { fireEvent } from "../../../../common/dom/fire_event"; import { fireEvent } from "../../../../common/dom/fire_event";
import type { LocalizeFunc } from "../../../../common/translations/localize";
import "../../../../components/ha-form/ha-form"; import "../../../../components/ha-form/ha-form";
import type { import type {
HaFormSchema, HaFormSchema,
@ -12,7 +13,6 @@ import type { HomeAssistant } from "../../../../types";
import type { MarkdownCardConfig } from "../../cards/types"; import type { MarkdownCardConfig } from "../../cards/types";
import type { LovelaceCardEditor } from "../../types"; import type { LovelaceCardEditor } from "../../types";
import { baseLovelaceCardConfig } from "../structs/base-card-struct"; import { baseLovelaceCardConfig } from "../structs/base-card-struct";
import type { LocalizeFunc } from "../../../../common/translations/localize";
const cardConfigStruct = assign( const cardConfigStruct = assign(
baseLovelaceCardConfig, baseLovelaceCardConfig,
@ -38,7 +38,7 @@ export class HuiMarkdownCardEditor
} }
private _schema = memoizeOne( private _schema = memoizeOne(
(localize: LocalizeFunc, text_only: boolean, isDark: boolean) => (localize: LocalizeFunc, text_only: boolean) =>
[ [
{ {
name: "style", name: "style",
@ -50,7 +50,11 @@ export class HuiMarkdownCardEditor
label: localize( label: localize(
`ui.panel.lovelace.editor.card.markdown.style_options.${style}` `ui.panel.lovelace.editor.card.markdown.style_options.${style}`
), ),
image: `/static/images/form/markdown_${style.replace("-", "_")}${isDark ? "_dark" : ""}.svg`, image: {
src: `/static/images/form/markdown_${style.replace("-", "_")}.svg`,
src_dark: `/static/images/form/markdown_${style.replace("-", "_")}_dark".svg`,
flip_rtl: true,
},
value: style, value: style,
})), })),
}, },
@ -75,8 +79,7 @@ export class HuiMarkdownCardEditor
const schema = this._schema( const schema = this._schema(
this.hass.localize, this.hass.localize,
this._config.text_only || false, this._config.text_only || false
this.hass.themes.darkMode
); );
return html` return html`

View File

@ -115,7 +115,6 @@ export class HuiTileCardEditor
localize: LocalizeFunc, localize: LocalizeFunc,
entityId: string | undefined, entityId: string | undefined,
hideState: boolean, hideState: boolean,
isDark: boolean,
displayActions: AdvancedActions[] = [] displayActions: AdvancedActions[] = []
) => ) =>
[ [
@ -185,7 +184,11 @@ export class HuiTileCardEditor
`ui.panel.lovelace.editor.card.tile.content_layout_options.${value}` `ui.panel.lovelace.editor.card.tile.content_layout_options.${value}`
), ),
value, value,
image: `/static/images/form/tile_content_layout_${value}${isDark ? "_dark" : ""}.svg`, image: {
src: `/static/images/form/tile_content_layout_${value}.svg`,
src_dark: `/static/images/form/tile_content_layout_${value}_dark.svg`,
flip_rtl: true,
},
})), })),
}, },
}, },
@ -230,7 +233,7 @@ export class HuiTileCardEditor
); );
private _featuresSchema = memoizeOne( private _featuresSchema = memoizeOne(
(localize: LocalizeFunc, vertical: boolean, isDark: boolean) => (localize: LocalizeFunc, vertical: boolean) =>
[ [
{ {
name: "features_position", name: "features_position",
@ -243,7 +246,11 @@ export class HuiTileCardEditor
`ui.panel.lovelace.editor.card.tile.features_position_options.${value}` `ui.panel.lovelace.editor.card.tile.features_position_options.${value}`
), ),
value, value,
image: `/static/images/form/tile_features_position_${value}${isDark ? "_dark" : ""}.svg`, image: {
src: `/static/images/form/tile_features_position_${value}.svg`,
src_dark: `/static/images/form/tile_features_position_${value}_dark.svg`,
flip_rtl: true,
},
disabled: vertical && value === "inline", disabled: vertical && value === "inline",
})), })),
}, },
@ -264,14 +271,12 @@ export class HuiTileCardEditor
this.hass.localize, this.hass.localize,
entityId, entityId,
this._config.hide_state ?? false, this._config.hide_state ?? false,
this.hass.themes.darkMode,
this._displayActions this._displayActions
); );
const featuresSchema = this._featuresSchema( const featuresSchema = this._featuresSchema(
this.hass.localize, this.hass.localize,
this._config.vertical ?? false, this._config.vertical ?? false
this.hass.themes.darkMode
); );
const data = { const data = {