Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b621042d4e |
No files matched your search
@@ -0,0 +1,7 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="20" width="78" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="32" width="78" height="16" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 519 B |
@@ -0,0 +1,7 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="#1C1C1C"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="20" width="78" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="32" width="78" height="16" rx="4" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 521 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="12" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="24" width="78" height="10" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="23.5" y="37.5" width="47" height="13" rx="6.5" fill="white" stroke="black" stroke-opacity="0.12"/>
|
||||
<rect x="26" y="40" width="20" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="48" y="40" width="20" height="8" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 713 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="#1C1C1C"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="12" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="24" width="78" height="10" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="23.5" y="37.5" width="47" height="13" rx="6.5" fill="#1C1C1C" stroke="white" stroke-opacity="0.24"/>
|
||||
<rect x="26" y="40" width="20" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="48" y="40" width="20" height="8" rx="4" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 717 B |
@@ -0,0 +1,7 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="16" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
<rect x="8" y="28" width="78" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="40" width="78" height="8" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 519 B |
@@ -0,0 +1,7 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="#1C1C1C"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="78" height="16" rx="4" fill="white" fill-opacity="0.48"/>
|
||||
<rect x="8" y="28" width="78" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="40" width="78" height="8" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 521 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="22" height="20" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="8" y="32" width="22" height="16" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="34" y="8" width="22" height="12" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="34" y="24" width="22" height="24" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="60" y="8" width="26" height="28" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 690 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="#1C1C1C"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="22" height="20" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="8" y="32" width="22" height="16" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="34" y="8" width="22" height="12" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="34" y="24" width="22" height="24" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="60" y="8" width="26" height="28" rx="4" fill="white" fill-opacity="0.48"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 692 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="white"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="black" stroke-opacity="0.12" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="26" height="28" rx="4" fill="black" fill-opacity="0.32"/>
|
||||
<rect x="38" y="8" width="22" height="20" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="38" y="32" width="22" height="16" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="64" y="8" width="22" height="12" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
<rect x="64" y="24" width="22" height="24" rx="4" fill="black" fill-opacity="0.12"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 691 B |
@@ -0,0 +1,9 @@
|
||||
<svg width="94" height="56" viewBox="0 0 94 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="94" height="56" rx="8" fill="#1C1C1C"/>
|
||||
<rect x="0.5" y="0.5" width="93" height="55" rx="7.5" stroke="white" stroke-opacity="0.24" stroke-dasharray="4 4"/>
|
||||
<rect x="8" y="8" width="26" height="28" rx="4" fill="white" fill-opacity="0.48"/>
|
||||
<rect x="38" y="8" width="22" height="20" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="38" y="32" width="22" height="16" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="64" y="8" width="22" height="12" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
<rect x="64" y="24" width="22" height="24" rx="4" fill="white" fill-opacity="0.24"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 693 B |
@@ -48,8 +48,22 @@ export interface LovelaceViewFooterConfig {
|
||||
max_width?: number;
|
||||
}
|
||||
|
||||
export const SIDEBAR_POSITIONS = ["start", "end"] as const;
|
||||
|
||||
export type SidebarPosition = (typeof SIDEBAR_POSITIONS)[number];
|
||||
|
||||
export const DEFAULT_SIDEBAR_POSITION: SidebarPosition = "end";
|
||||
|
||||
export const SIDEBAR_MOBILE_POSITIONS = ["tabs", "top", "bottom"] as const;
|
||||
|
||||
export type SidebarMobilePosition = (typeof SIDEBAR_MOBILE_POSITIONS)[number];
|
||||
|
||||
export const DEFAULT_SIDEBAR_MOBILE_POSITION: SidebarMobilePosition = "bottom";
|
||||
|
||||
export interface LovelaceViewSidebarConfig {
|
||||
sections?: LovelaceSectionConfig[];
|
||||
position?: SidebarPosition;
|
||||
mobile_position?: SidebarMobilePosition;
|
||||
content_label?: string;
|
||||
sidebar_label?: string;
|
||||
visibility?: VisibilityCondition[];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { mdiDelete, mdiDotsVertical } from "@mdi/js";
|
||||
import { mdiDelete, mdiDotsVertical, mdiPencil } from "@mdi/js";
|
||||
import "@home-assistant/webawesome/dist/components/divider/divider";
|
||||
import { css, html, LitElement } from "lit";
|
||||
import { customElement, property } from "lit/decorators";
|
||||
import { consumeLocalize } from "../../../common/decorators/consume-context-entry";
|
||||
@@ -12,6 +13,7 @@ import type { LovelaceViewSidebarConfig } from "../../../data/lovelace/config/vi
|
||||
import { showConfirmationDialog } from "../../../dialogs/generic/show-dialog-box";
|
||||
import type { LovelacePath } from "../editor/lovelace-path";
|
||||
import { deleteAtPath, getAtPath } from "../editor/lovelace-path";
|
||||
import { showEditSidebarDialog } from "../editor/sidebar-editor/show-edit-sidebar-dialog";
|
||||
import type { Lovelace } from "../types";
|
||||
|
||||
@customElement("hui-sidebar-edit-header")
|
||||
@@ -38,6 +40,11 @@ export class HuiSidebarEditHeader extends LitElement {
|
||||
.label=${this._localize("ui.panel.lovelace.editor.sidebar.menu")}
|
||||
.path=${mdiDotsVertical}
|
||||
></ha-icon-button>
|
||||
<ha-dropdown-item value="edit">
|
||||
<ha-svg-icon slot="icon" .path=${mdiPencil}></ha-svg-icon>
|
||||
${this._localize("ui.common.edit")}
|
||||
</ha-dropdown-item>
|
||||
<wa-divider></wa-divider>
|
||||
<ha-dropdown-item value="delete" variant="danger">
|
||||
<ha-svg-icon slot="icon" .path=${mdiDelete}></ha-svg-icon>
|
||||
${this._localize("ui.common.delete")}
|
||||
@@ -49,8 +56,16 @@ export class HuiSidebarEditHeader extends LitElement {
|
||||
|
||||
private _handleDropdownSelect(ev: HaDropdownSelectEvent): void {
|
||||
const action = ev.detail?.item?.value;
|
||||
if (action === "delete") {
|
||||
this._deleteSidebar();
|
||||
switch (action) {
|
||||
case "edit":
|
||||
showEditSidebarDialog(this, {
|
||||
lovelace: this.lovelace,
|
||||
path: this.path,
|
||||
});
|
||||
break;
|
||||
case "delete":
|
||||
this._deleteSidebar();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,279 @@
|
||||
import { css, html, LitElement, nothing } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import { computeRTL } from "../../../../common/util/compute_rtl";
|
||||
import type { LocalizeFunc } from "../../../../common/translations/localize";
|
||||
import "../../../../components/ha-button";
|
||||
import "../../../../components/ha-dialog";
|
||||
import "../../../../components/ha-dialog-footer";
|
||||
import "../../../../components/ha-form/ha-form";
|
||||
import type {
|
||||
HaFormSchema,
|
||||
SchemaUnion,
|
||||
} from "../../../../components/ha-form/types";
|
||||
import "../../../../components/ha-tab-group";
|
||||
import "../../../../components/ha-tab-group-tab";
|
||||
import {
|
||||
DEFAULT_SIDEBAR_MOBILE_POSITION,
|
||||
DEFAULT_SIDEBAR_POSITION,
|
||||
SIDEBAR_MOBILE_POSITIONS,
|
||||
SIDEBAR_POSITIONS,
|
||||
type LovelaceViewSidebarConfig,
|
||||
type SidebarPosition,
|
||||
} from "../../../../data/lovelace/config/view";
|
||||
import { showAlertDialog } from "../../../../dialogs/generic/show-dialog-box";
|
||||
import type { HassDialog } from "../../../../dialogs/make-dialog-manager";
|
||||
import { DirtyStateProviderMixin } from "../../../../mixins/dirty-state-provider-mixin";
|
||||
import { haStyleDialog } from "../../../../resources/styles";
|
||||
import type { HomeAssistant, ValueChangedEvent } from "../../../../types";
|
||||
import { getAtPath, setAtPath } from "../lovelace-path";
|
||||
import "../section-editor/hui-section-visibility-editor";
|
||||
import type { EditSidebarDialogParams } from "./show-edit-sidebar-dialog";
|
||||
|
||||
const TABS = ["settings", "visibility"] as const;
|
||||
|
||||
type Tab = (typeof TABS)[number];
|
||||
|
||||
const computeSide = (position: SidebarPosition, isRTL: boolean) => {
|
||||
if (position === "start") {
|
||||
return isRTL ? "right" : "left";
|
||||
}
|
||||
return isRTL ? "left" : "right";
|
||||
};
|
||||
|
||||
@customElement("hui-dialog-edit-sidebar")
|
||||
export class HuiDialogEditSidebar
|
||||
extends DirtyStateProviderMixin<LovelaceViewSidebarConfig>()(LitElement)
|
||||
implements HassDialog<EditSidebarDialogParams>
|
||||
{
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
|
||||
@state() private _params?: EditSidebarDialogParams;
|
||||
|
||||
@state() private _config?: LovelaceViewSidebarConfig;
|
||||
|
||||
@state() private _tab: Tab = "settings";
|
||||
|
||||
@state() private _open = false;
|
||||
|
||||
@state() private _saving = false;
|
||||
|
||||
public showDialog(params: EditSidebarDialogParams): void {
|
||||
this._params = params;
|
||||
this._config =
|
||||
getAtPath<LovelaceViewSidebarConfig>(
|
||||
params.lovelace.config,
|
||||
params.path
|
||||
) ?? {};
|
||||
this._initDirtyTracking({ type: "deep" }, this._config);
|
||||
this._tab = "settings";
|
||||
this._open = true;
|
||||
}
|
||||
|
||||
public closeDialog(): boolean {
|
||||
this._open = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private _dialogClosed(): void {
|
||||
this._params = undefined;
|
||||
this._config = undefined;
|
||||
fireEvent(this, "dialog-closed", { dialog: this.localName });
|
||||
}
|
||||
|
||||
private _schema = memoizeOne(
|
||||
(localize: LocalizeFunc, isRTL: boolean) =>
|
||||
[
|
||||
{
|
||||
name: "position",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
options: SIDEBAR_POSITIONS.map((position) => ({
|
||||
value: position,
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.sidebar.position_options.${computeSide(position, isRTL)}`
|
||||
),
|
||||
image: {
|
||||
src: `/static/images/form/sidebar_position_${position}.svg`,
|
||||
src_dark: `/static/images/form/sidebar_position_${position}_dark.svg`,
|
||||
flip_rtl: true,
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mobile_position",
|
||||
required: true,
|
||||
selector: {
|
||||
select: {
|
||||
mode: "box",
|
||||
options: SIDEBAR_MOBILE_POSITIONS.map((position) => ({
|
||||
value: position,
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.sidebar.mobile_position_options.${position}`
|
||||
),
|
||||
image: {
|
||||
src: `/static/images/form/sidebar_mobile_position_${position}.svg`,
|
||||
src_dark: `/static/images/form/sidebar_mobile_position_${position}_dark.svg`,
|
||||
flip_rtl: true,
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "content_label",
|
||||
visible: { field: "mobile_position", value: "tabs" },
|
||||
selector: { text: {} },
|
||||
},
|
||||
{
|
||||
name: "sidebar_label",
|
||||
visible: { field: "mobile_position", value: "tabs" },
|
||||
selector: { text: {} },
|
||||
},
|
||||
] as const satisfies readonly HaFormSchema[]
|
||||
);
|
||||
|
||||
protected render() {
|
||||
if (!this._params || !this._config) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const data = {
|
||||
...this._config,
|
||||
position: this._config.position ?? DEFAULT_SIDEBAR_POSITION,
|
||||
mobile_position:
|
||||
this._config.mobile_position ?? DEFAULT_SIDEBAR_MOBILE_POSITION,
|
||||
};
|
||||
|
||||
const isRTL = computeRTL(
|
||||
this.hass.language,
|
||||
this.hass.translationMetadata.translations
|
||||
);
|
||||
|
||||
return html`
|
||||
<ha-dialog
|
||||
.open=${this._open}
|
||||
header-title=${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.sidebar.settings"
|
||||
)}
|
||||
.preventScrimClose=${this.isDirtyState}
|
||||
@closed=${this._dialogClosed}
|
||||
>
|
||||
<ha-tab-group @wa-tab-show=${this._tabChanged}>
|
||||
${TABS.map(
|
||||
(tab) => html`
|
||||
<ha-tab-group-tab
|
||||
slot="nav"
|
||||
.panel=${tab}
|
||||
.active=${this._tab === tab}
|
||||
>
|
||||
${this.hass.localize(
|
||||
`ui.panel.lovelace.editor.sidebar.tab_${tab}`
|
||||
)}
|
||||
</ha-tab-group-tab>
|
||||
`
|
||||
)}
|
||||
</ha-tab-group>
|
||||
${
|
||||
this._tab === "settings"
|
||||
? html`
|
||||
<ha-form
|
||||
autofocus
|
||||
.hass=${this.hass}
|
||||
.data=${data}
|
||||
.schema=${this._schema(this.hass.localize, isRTL)}
|
||||
.computeLabel=${this._computeLabel}
|
||||
@value-changed=${this._valueChanged}
|
||||
></ha-form>
|
||||
`
|
||||
: html`
|
||||
<hui-section-visibility-editor
|
||||
.hass=${this.hass}
|
||||
.config=${this._config}
|
||||
@value-changed=${this._valueChanged}
|
||||
></hui-section-visibility-editor>
|
||||
`
|
||||
}
|
||||
<ha-dialog-footer slot="footer">
|
||||
<ha-button
|
||||
slot="secondaryAction"
|
||||
appearance="plain"
|
||||
@click=${this.closeDialog}
|
||||
>
|
||||
${this.hass.localize("ui.common.cancel")}
|
||||
</ha-button>
|
||||
<ha-button
|
||||
slot="primaryAction"
|
||||
.disabled=${this._saving || !this.isDirtyState}
|
||||
.loading=${this._saving}
|
||||
@click=${this._save}
|
||||
>
|
||||
${this.hass.localize("ui.common.save")}
|
||||
</ha-button>
|
||||
</ha-dialog-footer>
|
||||
</ha-dialog>
|
||||
`;
|
||||
}
|
||||
|
||||
private _computeLabel = (
|
||||
schema: SchemaUnion<ReturnType<typeof this._schema>>
|
||||
) => this.hass.localize(`ui.panel.lovelace.editor.sidebar.${schema.name}`);
|
||||
|
||||
private _tabChanged(ev: CustomEvent<{ name: Tab }>) {
|
||||
this._tab = ev.detail.name;
|
||||
}
|
||||
|
||||
private _valueChanged(ev: ValueChangedEvent<LovelaceViewSidebarConfig>) {
|
||||
ev.stopPropagation();
|
||||
this._config = ev.detail.value;
|
||||
this._updateDirtyState(this._config);
|
||||
}
|
||||
|
||||
private async _save() {
|
||||
if (!this._params || !this._config) {
|
||||
return;
|
||||
}
|
||||
const { lovelace, path } = this._params;
|
||||
this._saving = true;
|
||||
try {
|
||||
await lovelace.saveConfig(setAtPath(lovelace.config, path, this._config));
|
||||
this.closeDialog();
|
||||
} catch (err: any) {
|
||||
showAlertDialog(this, {
|
||||
text: `${this.hass.localize(
|
||||
"ui.panel.lovelace.editor.sidebar.saving_failed"
|
||||
)}: ${err.message}`,
|
||||
});
|
||||
} finally {
|
||||
this._saving = false;
|
||||
}
|
||||
}
|
||||
|
||||
static styles = [
|
||||
haStyleDialog,
|
||||
css`
|
||||
ha-tab-group {
|
||||
display: block;
|
||||
margin-bottom: var(--ha-space-4);
|
||||
}
|
||||
ha-tab-group-tab {
|
||||
flex: 1;
|
||||
}
|
||||
ha-tab-group-tab::part(base) {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"hui-dialog-edit-sidebar": HuiDialogEditSidebar;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { fireEvent } from "../../../../common/dom/fire_event";
|
||||
import type { Lovelace } from "../../types";
|
||||
import type { LovelacePath } from "../lovelace-path";
|
||||
|
||||
export interface EditSidebarDialogParams {
|
||||
lovelace: Lovelace;
|
||||
path: LovelacePath;
|
||||
}
|
||||
|
||||
export const showEditSidebarDialog = (
|
||||
element: HTMLElement,
|
||||
params: EditSidebarDialogParams
|
||||
): void => {
|
||||
fireEvent(element, "show-dialog", {
|
||||
dialogTag: "hui-dialog-edit-sidebar",
|
||||
dialogImport: () => import("./hui-dialog-edit-sidebar"),
|
||||
dialogParams: params,
|
||||
});
|
||||
};
|
||||
@@ -23,9 +23,10 @@ import {
|
||||
DEFAULT_SECTION_COLUMN_SPAN,
|
||||
isStrategySection,
|
||||
} from "../../../data/lovelace/config/section";
|
||||
import type {
|
||||
LovelaceViewConfig,
|
||||
LovelaceViewSidebarConfig,
|
||||
import {
|
||||
DEFAULT_SIDEBAR_MOBILE_POSITION,
|
||||
type LovelaceViewConfig,
|
||||
type LovelaceViewSidebarConfig,
|
||||
} from "../../../data/lovelace/config/view";
|
||||
import { DEFAULT_MAX_COLUMNS } from "./const";
|
||||
import type { HomeAssistant } from "../../../types";
|
||||
@@ -194,14 +195,12 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
(editMode || (this._sidebarVisible && Boolean(sidebar.sections?.length)));
|
||||
const singleColumn = this._maxColumns <= 1;
|
||||
|
||||
// The tab switcher is opt-in: a sidebar enables it by labelling both tabs,
|
||||
// otherwise the sidebar stacks below the content.
|
||||
const mobilePosition =
|
||||
this._config?.sidebar?.mobile_position ?? DEFAULT_SIDEBAR_MOBILE_POSITION;
|
||||
const useSidebarTabs = Boolean(
|
||||
singleColumn &&
|
||||
hasSidebar &&
|
||||
this._config?.sidebar?.content_label &&
|
||||
this._config?.sidebar?.sidebar_label
|
||||
singleColumn && hasSidebar && mobilePosition === "tabs"
|
||||
);
|
||||
const sidebarOnTop = singleColumn && mobilePosition === "top";
|
||||
|
||||
const totalSectionCount =
|
||||
this._sectionColumnCount + (editMode ? 1 : 0) + (hasSidebar ? 1 : 0);
|
||||
@@ -227,6 +226,8 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
"has-sidebar": Boolean(hasSidebar),
|
||||
"single-column": singleColumn,
|
||||
"has-sidebar-tabs": useSidebarTabs,
|
||||
"sidebar-top": sidebarOnTop,
|
||||
"sidebar-at-start": sidebar?.position === "start",
|
||||
})}"
|
||||
style=${styleMap({
|
||||
"--column-count": columnCount,
|
||||
@@ -250,11 +251,19 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
.options=${[
|
||||
{
|
||||
value: "content",
|
||||
label: this._config!.sidebar!.content_label,
|
||||
label:
|
||||
this._config!.sidebar!.content_label ||
|
||||
this.hass.localize(
|
||||
"ui.panel.lovelace.views.sidebar_tabs.content"
|
||||
),
|
||||
},
|
||||
{
|
||||
value: "sidebar",
|
||||
label: this._config!.sidebar!.sidebar_label,
|
||||
label:
|
||||
this._config!.sidebar!.sidebar_label ||
|
||||
this.hass.localize(
|
||||
"ui.panel.lovelace.views.sidebar_tabs.sidebar"
|
||||
),
|
||||
},
|
||||
]}
|
||||
>
|
||||
@@ -654,6 +663,12 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
[content-end sidebar-start] 1fr [sidebar-end];
|
||||
}
|
||||
|
||||
.wrapper.has-sidebar.sidebar-at-start .container {
|
||||
grid-template-columns:
|
||||
[sidebar-start] 1fr [sidebar-end content-start]
|
||||
repeat(var(--content-column-count), 1fr) [content-end];
|
||||
}
|
||||
|
||||
/* With a single column, content and sidebar stack at full width */
|
||||
.wrapper.single-column.has-sidebar .container {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -677,6 +692,10 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
border-start-end-radius: 0;
|
||||
}
|
||||
|
||||
.wrapper.sidebar-top .sidebar {
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.wrapper.single-column .sidebar {
|
||||
grid-column: 1 / -1;
|
||||
}
|
||||
@@ -730,6 +749,7 @@ export class SectionsView extends LitElement implements LovelaceViewElement {
|
||||
|
||||
.wrapper.single-column .content {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: auto;
|
||||
}
|
||||
|
||||
.wrapper.has-sidebar-tabs .content {
|
||||
|
||||
@@ -398,6 +398,7 @@ export class SecurityViewStrategy extends ReactiveElement {
|
||||
],
|
||||
}
|
||||
: {}),
|
||||
mobile_position: "tabs",
|
||||
content_label: hass.localize(
|
||||
"ui.panel.lovelace.strategy.security.devices"
|
||||
),
|
||||
|
||||
@@ -10158,6 +10158,10 @@
|
||||
"saving_failed": "Saving dashboard configuration failed."
|
||||
},
|
||||
"views": {
|
||||
"sidebar_tabs": {
|
||||
"content": "Main",
|
||||
"sidebar": "Sidebar"
|
||||
},
|
||||
"unnamed_view": "Unnamed view",
|
||||
"delete_title": "Delete view",
|
||||
"delete_named_view_only": "''{name}'' view will be deleted.",
|
||||
@@ -10535,7 +10539,24 @@
|
||||
},
|
||||
"sidebar": {
|
||||
"title": "Sidebar",
|
||||
"settings": "Sidebar settings",
|
||||
"tab_settings": "[%key:ui::panel::lovelace::editor::edit_view::tab_settings%]",
|
||||
"tab_visibility": "[%key:ui::panel::lovelace::editor::edit_view::tab_visibility%]",
|
||||
"menu": "Sidebar menu",
|
||||
"saving_failed": "[%key:ui::panel::lovelace::editor::edit_view::saving_failed%]",
|
||||
"position": "On large screens",
|
||||
"position_options": {
|
||||
"left": "Left",
|
||||
"right": "Right"
|
||||
},
|
||||
"mobile_position": "On small screens",
|
||||
"mobile_position_options": {
|
||||
"tabs": "In a separate tab",
|
||||
"top": "Above the content",
|
||||
"bottom": "Below the content"
|
||||
},
|
||||
"content_label": "Main tab name",
|
||||
"sidebar_label": "Sidebar tab name",
|
||||
"delete_title": "Delete sidebar",
|
||||
"delete_text": "The sidebar and all its sections will be deleted."
|
||||
},
|
||||
|
||||