mirror of
https://github.com/home-assistant/frontend.git
synced 2025-10-15 06:39:46 +00:00
Compare commits
5 Commits
loading-an
...
clock-date
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a6a83258ab | ||
![]() |
01889de462 | ||
![]() |
a8f8d197f8 | ||
![]() |
4fcac79047 | ||
![]() |
42ddacd41a |
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* Trigger a view transition if supported by the browser
|
||||
* @param updateCallback - Callback function that updates the DOM
|
||||
* @returns Promise that resolves when the transition is complete
|
||||
*/
|
||||
export const startViewTransition = async (
|
||||
updateCallback: () => void | Promise<void>
|
||||
): Promise<void> => {
|
||||
// Check if View Transitions API is supported
|
||||
if (
|
||||
!document.startViewTransition ||
|
||||
window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
||||
) {
|
||||
// Fallback: just run the update without transition
|
||||
await updateCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the view transition
|
||||
const transition = document.startViewTransition(async () => {
|
||||
await updateCallback();
|
||||
});
|
||||
|
||||
try {
|
||||
await transition.finished;
|
||||
} catch (error) {
|
||||
// Transitions can be skipped, which is fine
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug("View transition skipped or failed:", error);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to apply view transition on first render
|
||||
* @param _element - The element to observe (unused, kept for API consistency)
|
||||
* @param callback - Callback when element is first rendered
|
||||
*/
|
||||
export const applyViewTransitionOnLoad = (
|
||||
_element: HTMLElement,
|
||||
callback?: () => void
|
||||
): void => {
|
||||
if (!document.startViewTransition) {
|
||||
callback?.();
|
||||
return;
|
||||
}
|
||||
|
||||
// Use requestAnimationFrame to ensure DOM is ready
|
||||
requestAnimationFrame(() => {
|
||||
startViewTransition(() => {
|
||||
callback?.();
|
||||
});
|
||||
});
|
||||
};
|
@@ -17,7 +17,7 @@ export class HaTooltip extends Tooltip {
|
||||
css`
|
||||
:host {
|
||||
--wa-tooltip-background-color: var(--secondary-background-color);
|
||||
--wa-tooltip-color: var(--primary-text-color);
|
||||
--wa-tooltip-content-color: var(--primary-text-color);
|
||||
--wa-tooltip-font-family: var(
|
||||
--ha-tooltip-font-family,
|
||||
var(--ha-font-family-body)
|
||||
|
@@ -77,80 +77,84 @@ class MoreInfoMediaPlayer extends LitElement {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
if (!stateActive(this.stateObj)) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
const supportsMute = supportsFeature(
|
||||
this.stateObj,
|
||||
MediaPlayerEntityFeature.VOLUME_MUTE
|
||||
);
|
||||
const supportsSliding = supportsFeature(
|
||||
const supportsSet = supportsFeature(
|
||||
this.stateObj,
|
||||
MediaPlayerEntityFeature.VOLUME_SET
|
||||
);
|
||||
|
||||
return html`${(supportsFeature(
|
||||
this.stateObj!,
|
||||
MediaPlayerEntityFeature.VOLUME_SET
|
||||
) ||
|
||||
supportsFeature(this.stateObj!, MediaPlayerEntityFeature.VOLUME_STEP)) &&
|
||||
stateActive(this.stateObj!)
|
||||
? html`
|
||||
<div class="volume">
|
||||
${supportsMute
|
||||
? html`
|
||||
<ha-icon-button
|
||||
.path=${this.stateObj.attributes.is_volume_muted
|
||||
? mdiVolumeOff
|
||||
: mdiVolumeHigh}
|
||||
.label=${this.hass.localize(
|
||||
`ui.card.media_player.${
|
||||
this.stateObj.attributes.is_volume_muted
|
||||
? "media_volume_unmute"
|
||||
: "media_volume_mute"
|
||||
}`
|
||||
)}
|
||||
@click=${this._toggleMute}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: ""}
|
||||
${supportsFeature(
|
||||
this.stateObj,
|
||||
MediaPlayerEntityFeature.VOLUME_STEP
|
||||
) && !supportsSliding
|
||||
? html`
|
||||
<ha-icon-button
|
||||
action="volume_down"
|
||||
.path=${mdiVolumeMinus}
|
||||
.label=${this.hass.localize(
|
||||
"ui.card.media_player.media_volume_down"
|
||||
)}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>
|
||||
<ha-icon-button
|
||||
action="volume_up"
|
||||
.path=${mdiVolumePlus}
|
||||
.label=${this.hass.localize(
|
||||
"ui.card.media_player.media_volume_up"
|
||||
)}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
${supportsSliding
|
||||
? html`
|
||||
${!supportsMute
|
||||
? html`<ha-svg-icon .path=${mdiVolumeHigh}></ha-svg-icon>`
|
||||
: nothing}
|
||||
<ha-slider
|
||||
labeled
|
||||
id="input"
|
||||
.value=${Number(this.stateObj.attributes.volume_level) *
|
||||
100}
|
||||
@change=${this._selectedValueChanged}
|
||||
></ha-slider>
|
||||
`
|
||||
: nothing}
|
||||
</div>
|
||||
`
|
||||
: nothing}`;
|
||||
const supportsStep = supportsFeature(
|
||||
this.stateObj,
|
||||
MediaPlayerEntityFeature.VOLUME_STEP
|
||||
);
|
||||
|
||||
if (!supportsMute && !supportsSet && !supportsStep) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="volume">
|
||||
${supportsMute
|
||||
? html`
|
||||
<ha-icon-button
|
||||
.path=${this.stateObj.attributes.is_volume_muted
|
||||
? mdiVolumeOff
|
||||
: mdiVolumeHigh}
|
||||
.label=${this.hass.localize(
|
||||
`ui.card.media_player.${
|
||||
this.stateObj.attributes.is_volume_muted
|
||||
? "media_volume_unmute"
|
||||
: "media_volume_mute"
|
||||
}`
|
||||
)}
|
||||
@click=${this._toggleMute}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
${supportsStep
|
||||
? html` <ha-icon-button
|
||||
action="volume_down"
|
||||
.path=${mdiVolumeMinus}
|
||||
.label=${this.hass.localize(
|
||||
"ui.card.media_player.media_volume_down"
|
||||
)}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>`
|
||||
: nothing}
|
||||
${supportsSet
|
||||
? html`
|
||||
${!supportsMute && !supportsStep
|
||||
? html`<ha-svg-icon .path=${mdiVolumeHigh}></ha-svg-icon>`
|
||||
: nothing}
|
||||
<ha-slider
|
||||
labeled
|
||||
id="input"
|
||||
.value=${Number(this.stateObj.attributes.volume_level) * 100}
|
||||
@change=${this._selectedValueChanged}
|
||||
></ha-slider>
|
||||
`
|
||||
: nothing}
|
||||
${supportsStep
|
||||
? html`
|
||||
<ha-icon-button
|
||||
action="volume_up"
|
||||
.path=${mdiVolumePlus}
|
||||
.label=${this.hass.localize(
|
||||
"ui.card.media_player.media_volume_up"
|
||||
)}
|
||||
@click=${this._handleClick}
|
||||
></ha-icon-button>
|
||||
`
|
||||
: nothing}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
protected _renderSourceControl() {
|
||||
|
@@ -34,12 +34,16 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
|
||||
@state() private _dateTimeFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _dateFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _hourOffsetSec?: number;
|
||||
|
||||
@state() private _minuteOffsetSec?: number;
|
||||
|
||||
@state() private _secondOffsetSec?: number;
|
||||
|
||||
@state() private _date?: string;
|
||||
|
||||
private _initDate() {
|
||||
if (!this.config || !this.hass) {
|
||||
return;
|
||||
@@ -60,6 +64,17 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
resolveTimeZone(locale.time_zone, this.hass.config?.time_zone),
|
||||
});
|
||||
|
||||
if (this.config.date_format === "day") {
|
||||
this._dateFormat = new Intl.DateTimeFormat(this.hass.locale.language, {
|
||||
day: "2-digit",
|
||||
timeZone:
|
||||
this.config.time_zone ||
|
||||
resolveTimeZone(locale.time_zone, this.hass.config?.time_zone),
|
||||
});
|
||||
} else {
|
||||
this._dateFormat = undefined;
|
||||
}
|
||||
|
||||
this._computeOffsets();
|
||||
}
|
||||
|
||||
@@ -111,6 +126,13 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
this._secondOffsetSec = secondsWithMs;
|
||||
this._minuteOffsetSec = minute * 60 + secondsWithMs;
|
||||
this._hourOffsetSec = hour12 * 3600 + minute * 60 + secondsWithMs;
|
||||
|
||||
if (this._dateFormat) {
|
||||
const dateParts = this._dateFormat.formatToParts();
|
||||
this._date = dateParts.find((part) => part.type === "day")?.value;
|
||||
} else {
|
||||
this._date = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -231,6 +253,9 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
}s;`}
|
||||
></div>`
|
||||
: nothing}
|
||||
${this._date !== undefined
|
||||
? html`<div class="date ${sizeClass}">${this._date}</div>`
|
||||
: nothing}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -399,6 +424,36 @@ export class HuiClockCardAnalog extends LitElement {
|
||||
animation-timing-function: steps(60, end);
|
||||
}
|
||||
|
||||
.date {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 25%;
|
||||
transform: translate(50%, -50%);
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
color: var(--primary-text-color);
|
||||
opacity: 0.6;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
padding: 1px 3px;
|
||||
border-radius: 2px;
|
||||
box-shadow:
|
||||
inset 0 1px 2px rgba(0, 0, 0, 0.15),
|
||||
inset 0 -1px 1px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.date.size-medium {
|
||||
font-size: var(--ha-font-size-l);
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.date.size-large {
|
||||
font-size: var(--ha-font-size-xl);
|
||||
padding: 2px 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
@keyframes ha-clock-rotate {
|
||||
from {
|
||||
transform: translate(-50%, 0) rotate(0deg);
|
||||
|
@@ -16,6 +16,8 @@ export class HuiClockCardDigital extends LitElement {
|
||||
|
||||
@state() private _dateTimeFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _dateFormat?: Intl.DateTimeFormat;
|
||||
|
||||
@state() private _timeHour?: string;
|
||||
|
||||
@state() private _timeMinute?: string;
|
||||
@@ -24,6 +26,8 @@ export class HuiClockCardDigital extends LitElement {
|
||||
|
||||
@state() private _timeAmPm?: string;
|
||||
|
||||
@state() private _date?: string;
|
||||
|
||||
private _tickInterval?: undefined | number;
|
||||
|
||||
private _initDate() {
|
||||
@@ -48,6 +52,17 @@ export class HuiClockCardDigital extends LitElement {
|
||||
resolveTimeZone(locale.time_zone, this.hass.config?.time_zone),
|
||||
});
|
||||
|
||||
if (this.config?.date_format === "day") {
|
||||
this._dateFormat = new Intl.DateTimeFormat(this.hass.locale.language, {
|
||||
day: "2-digit",
|
||||
timeZone:
|
||||
this.config?.time_zone ||
|
||||
resolveTimeZone(locale.time_zone, this.hass.config?.time_zone),
|
||||
});
|
||||
} else {
|
||||
this._dateFormat = undefined;
|
||||
}
|
||||
|
||||
this._tick();
|
||||
}
|
||||
|
||||
@@ -93,6 +108,13 @@ export class HuiClockCardDigital extends LitElement {
|
||||
? parts.find((part) => part.type === "second")?.value
|
||||
: undefined;
|
||||
this._timeAmPm = parts.find((part) => part.type === "dayPeriod")?.value;
|
||||
|
||||
if (this._dateFormat) {
|
||||
const dateParts = this._dateFormat.formatToParts();
|
||||
this._date = dateParts.find((part) => part.type === "day")?.value;
|
||||
} else {
|
||||
this._date = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -113,6 +135,9 @@ export class HuiClockCardDigital extends LitElement {
|
||||
? html`<div class="time-part am-pm">${this._timeAmPm}</div>`
|
||||
: nothing}
|
||||
</div>
|
||||
${this._date !== undefined
|
||||
? html`<div class="date ${sizeClass}">${this._date}</div>`
|
||||
: nothing}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -121,6 +146,26 @@ export class HuiClockCardDigital extends LitElement {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: var(--ha-font-size-m);
|
||||
font-weight: var(--ha-font-weight-medium);
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
direction: ltr;
|
||||
margin-top: 4px;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.date.size-medium {
|
||||
font-size: var(--ha-font-size-l);
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.date.size-large {
|
||||
font-size: var(--ha-font-size-xl);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.time-parts {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
|
@@ -381,6 +381,7 @@ export interface ClockCardConfig extends LovelaceCardConfig {
|
||||
seconds_motion?: "continuous" | "tick";
|
||||
time_format?: TimeFormat;
|
||||
time_zone?: string;
|
||||
date_format?: "none" | "day";
|
||||
no_background?: boolean;
|
||||
// Analog clock options
|
||||
border?: boolean;
|
||||
|
@@ -37,6 +37,9 @@ const cardConfigStruct = assign(
|
||||
),
|
||||
time_format: optional(enums(Object.values(TimeFormat))),
|
||||
time_zone: optional(enums(Object.keys(timezones))),
|
||||
date_format: optional(
|
||||
defaulted(union([literal("none"), literal("day")]), literal("none"))
|
||||
),
|
||||
show_seconds: optional(boolean()),
|
||||
no_background: optional(boolean()),
|
||||
// Analog clock options
|
||||
@@ -117,6 +120,20 @@ export class HuiClockCardEditor
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "date_format",
|
||||
selector: {
|
||||
select: {
|
||||
mode: "dropdown",
|
||||
options: ["none", "day"].map((value) => ({
|
||||
value,
|
||||
label: localize(
|
||||
`ui.panel.lovelace.editor.card.clock.date_formats.${value}`
|
||||
),
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
{ name: "show_seconds", selector: { boolean: {} } },
|
||||
{ name: "no_background", selector: { boolean: {} } },
|
||||
...(clockStyle === "digital"
|
||||
@@ -265,6 +282,7 @@ export class HuiClockCardEditor
|
||||
clock_size: "small",
|
||||
time_zone: "auto",
|
||||
time_format: "auto",
|
||||
date_format: "none",
|
||||
show_seconds: false,
|
||||
no_background: false,
|
||||
// Analog clock options
|
||||
@@ -359,6 +377,10 @@ export class HuiClockCardEditor
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.clock.time_zone`
|
||||
);
|
||||
case "date_format":
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.clock.date_format`
|
||||
);
|
||||
case "show_seconds":
|
||||
return this.hass!.localize(
|
||||
`ui.panel.lovelace.editor.card.clock.show_seconds`
|
||||
|
@@ -25,10 +25,6 @@ import { ifDefined } from "lit/directives/if-defined";
|
||||
import memoizeOne from "memoize-one";
|
||||
import { isComponentLoaded } from "../../common/config/is_component_loaded";
|
||||
import { fireEvent } from "../../common/dom/fire_event";
|
||||
import {
|
||||
applyViewTransitionOnLoad,
|
||||
startViewTransition,
|
||||
} from "../../common/dom/view_transition";
|
||||
import { shouldHandleRequestSelectedEvent } from "../../common/mwc/handle-request-selected-event";
|
||||
import { goBack, navigate } from "../../common/navigate";
|
||||
import type { LocalizeKeys } from "../../common/translations/localize";
|
||||
@@ -76,7 +72,7 @@ import {
|
||||
} from "../../dialogs/quick-bar/show-dialog-quick-bar";
|
||||
import { showShortcutsDialog } from "../../dialogs/shortcuts/show-shortcuts-dialog";
|
||||
import { showVoiceCommandDialog } from "../../dialogs/voice-command-dialog/show-ha-voice-command-dialog";
|
||||
import { haStyle, haStyleViewTransitions } from "../../resources/styles";
|
||||
import { haStyle } from "../../resources/styles";
|
||||
import type { HomeAssistant, PanelInfo } from "../../types";
|
||||
import { documentationUrl } from "../../util/documentation-url";
|
||||
import { showToast } from "../../util/toast";
|
||||
@@ -322,7 +318,7 @@ class HUIRoot extends LitElement {
|
||||
menu-corner="END"
|
||||
>
|
||||
<ha-icon-button
|
||||
.label=${label}
|
||||
.id="button-${index}"
|
||||
.path=${item.icon}
|
||||
slot="trigger"
|
||||
></ha-icon-button>
|
||||
@@ -344,6 +340,9 @@ class HUIRoot extends LitElement {
|
||||
`
|
||||
)}
|
||||
</ha-button-menu>
|
||||
<ha-tooltip placement="bottom" .for="button-${index}">
|
||||
${label}
|
||||
</ha-tooltip>
|
||||
`
|
||||
: html`
|
||||
<ha-icon-button
|
||||
@@ -623,9 +622,6 @@ class HUIRoot extends LitElement {
|
||||
window.addEventListener("scroll", this._handleWindowScroll, {
|
||||
passive: true,
|
||||
});
|
||||
|
||||
// Trigger view transition on initial load
|
||||
applyViewTransitionOnLoad(this);
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
@@ -1165,45 +1161,43 @@ class HUIRoot extends LitElement {
|
||||
// Recreate a new element to clear the applied themes.
|
||||
const root = this._viewRoot;
|
||||
|
||||
startViewTransition(() => {
|
||||
if (root.lastChild) {
|
||||
root.removeChild(root.lastChild);
|
||||
}
|
||||
if (root.lastChild) {
|
||||
root.removeChild(root.lastChild);
|
||||
}
|
||||
|
||||
if (viewIndex === "hass-unused-entities") {
|
||||
const unusedEntities = document.createElement("hui-unused-entities");
|
||||
// Wait for promise to resolve so that the element has been upgraded.
|
||||
import("./editor/unused-entities/hui-unused-entities").then(() => {
|
||||
unusedEntities.hass = this.hass!;
|
||||
unusedEntities.lovelace = this.lovelace!;
|
||||
unusedEntities.narrow = this.narrow;
|
||||
});
|
||||
root.appendChild(unusedEntities);
|
||||
return;
|
||||
}
|
||||
if (viewIndex === "hass-unused-entities") {
|
||||
const unusedEntities = document.createElement("hui-unused-entities");
|
||||
// Wait for promise to resolve so that the element has been upgraded.
|
||||
import("./editor/unused-entities/hui-unused-entities").then(() => {
|
||||
unusedEntities.hass = this.hass!;
|
||||
unusedEntities.lovelace = this.lovelace!;
|
||||
unusedEntities.narrow = this.narrow;
|
||||
});
|
||||
root.appendChild(unusedEntities);
|
||||
return;
|
||||
}
|
||||
|
||||
let view;
|
||||
const viewConfig = this.config.views[viewIndex];
|
||||
let view;
|
||||
const viewConfig = this.config.views[viewIndex];
|
||||
|
||||
if (!viewConfig) {
|
||||
this.lovelace!.setEditMode(true);
|
||||
return;
|
||||
}
|
||||
if (!viewConfig) {
|
||||
this.lovelace!.setEditMode(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!force && this._viewCache![viewIndex]) {
|
||||
view = this._viewCache![viewIndex];
|
||||
} else {
|
||||
view = document.createElement("hui-view");
|
||||
view.index = viewIndex;
|
||||
this._viewCache![viewIndex] = view;
|
||||
}
|
||||
if (!force && this._viewCache![viewIndex]) {
|
||||
view = this._viewCache![viewIndex];
|
||||
} else {
|
||||
view = document.createElement("hui-view");
|
||||
view.index = viewIndex;
|
||||
this._viewCache![viewIndex] = view;
|
||||
}
|
||||
|
||||
view.lovelace = this.lovelace;
|
||||
view.hass = this.hass;
|
||||
view.narrow = this.narrow;
|
||||
view.lovelace = this.lovelace;
|
||||
view.hass = this.hass;
|
||||
view.narrow = this.narrow;
|
||||
|
||||
root.appendChild(view);
|
||||
});
|
||||
root.appendChild(view);
|
||||
}
|
||||
|
||||
private _openShortcutDialog(ev: Event) {
|
||||
@@ -1214,7 +1208,6 @@ class HUIRoot extends LitElement {
|
||||
static get styles(): CSSResultGroup {
|
||||
return [
|
||||
haStyle,
|
||||
haStyleViewTransitions,
|
||||
css`
|
||||
:host {
|
||||
-ms-user-select: none;
|
||||
@@ -1269,7 +1262,6 @@ class HUIRoot extends LitElement {
|
||||
padding: 0px 12px;
|
||||
font-weight: var(--ha-font-weight-normal);
|
||||
box-sizing: border-box;
|
||||
view-transition-name: lovelace-toolbar;
|
||||
}
|
||||
.narrow .toolbar {
|
||||
padding: 0 4px;
|
||||
@@ -1418,7 +1410,6 @@ class HUIRoot extends LitElement {
|
||||
hui-view-container > * {
|
||||
flex: 1 1 100%;
|
||||
max-width: 100%;
|
||||
view-transition-name: lovelace-view;
|
||||
}
|
||||
/**
|
||||
* In edit mode we have the tab bar on a new line *
|
||||
|
@@ -196,58 +196,3 @@ export const baseEntrypointStyles = css`
|
||||
width: 100vw;
|
||||
}
|
||||
`;
|
||||
|
||||
export const haStyleViewTransitions = css`
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
/* Toolbar fade in */
|
||||
::view-transition-group(lovelace-toolbar) {
|
||||
animation-duration: var(--ha-animation-duration);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
::view-transition-new(lovelace-toolbar) {
|
||||
animation: fade-in var(--ha-animation-duration) ease-out;
|
||||
animation-delay: var(--ha-animation-delay-base);
|
||||
}
|
||||
|
||||
/* View slide down */
|
||||
::view-transition-group(lovelace-view) {
|
||||
animation-duration: var(--ha-animation-duration);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
::view-transition-new(lovelace-view) {
|
||||
animation: fade-in-slide-down var(--ha-animation-duration) ease-out;
|
||||
animation-delay: var(--ha-animation-delay-base);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in-slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in-slide-down {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@@ -42,24 +42,6 @@ export const coreStyles = css`
|
||||
--ha-space-18: 72px;
|
||||
--ha-space-19: 76px;
|
||||
--ha-space-20: 80px;
|
||||
|
||||
/* Animation timing */
|
||||
--ha-animation-duration: 350ms;
|
||||
--ha-animation-delay-base: 50ms;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html {
|
||||
--ha-animation-duration: 150ms;
|
||||
--ha-animation-delay-base: 20ms;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable View Transitions API for supported browsers */
|
||||
@supports (view-transition-name: none) {
|
||||
:root {
|
||||
view-transition-name: root;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
@@ -7809,6 +7809,11 @@
|
||||
"time_zones": {
|
||||
"auto": "Use user settings"
|
||||
},
|
||||
"date_format": "Date format",
|
||||
"date_formats": {
|
||||
"none": "None",
|
||||
"day": "Day"
|
||||
},
|
||||
"no_background": "No background",
|
||||
"border": {
|
||||
"label": "Border",
|
||||
|
Reference in New Issue
Block a user