From ca642d46cc6e3739f551fafc275173629a8fec5e Mon Sep 17 00:00:00 2001 From: Wendelin <12148533+wendevlin@users.noreply.github.com> Date: Mon, 28 Apr 2025 15:04:47 +0200 Subject: [PATCH] Add typography styles (#25171) * Add typoghrapy styles * Split styles * Fix duplicated html * remove unused paper vars * Fix vars * Add vars autocompletion extension * Fix css syntax highlighting --- .devcontainer/devcontainer.json | 3 +- .vscode/extensions.json | 3 +- cast/src/launcher/entrypoint.ts | 2 +- cast/src/receiver/layout/hc-main.ts | 2 +- demo/src/entrypoint.ts | 2 +- hassio/src/entrypoint.ts | 2 +- src/common/dom/apply_themes_on_element.ts | 5 +- src/common/style/derived-css-vars.ts | 45 +++ src/entrypoints/app.ts | 2 +- src/entrypoints/authorize.ts | 2 +- src/entrypoints/onboarding.ts | 2 +- .../config/hardware/ha-config-hardware.ts | 6 +- src/panels/profile/ha-pick-theme-row.ts | 11 +- src/resources/append-ha-style.ts | 5 + src/resources/ha-style.ts | 165 -------- src/resources/particles.ts | 6 +- src/resources/roboto.ts | 2 +- src/resources/styles-data.ts | 255 ------------- src/resources/theme/color.globals.ts | 359 ++++++++++++++++++ src/resources/theme/main.globals.ts | 38 ++ src/resources/theme/theme.ts | 20 + src/resources/theme/typography.globals.ts | 40 ++ 22 files changed, 533 insertions(+), 444 deletions(-) create mode 100644 src/common/style/derived-css-vars.ts create mode 100644 src/resources/append-ha-style.ts delete mode 100644 src/resources/ha-style.ts delete mode 100644 src/resources/styles-data.ts create mode 100644 src/resources/theme/color.globals.ts create mode 100644 src/resources/theme/main.globals.ts create mode 100644 src/resources/theme/theme.ts create mode 100644 src/resources/theme/typography.globals.ts diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cb654867b5..88ccccc5aa 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,8 @@ "esbenp.prettier-vscode", "runem.lit-plugin", "github.vscode-pull-request-github", - "eamodio.gitlens" + "eamodio.gitlens", + "yeion7.styled-global-variables-autocomplete" ], "settings": { "files.eol": "\n", diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 720f06e0ba..76ef0ff7a8 100755 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -5,6 +5,7 @@ "runem.lit-plugin", "github.vscode-pull-request-github", "eamodio.gitlens", - "vitest.explorer" + "vitest.explorer", + "yeion7.styled-global-variables-autocomplete" ] } diff --git a/cast/src/launcher/entrypoint.ts b/cast/src/launcher/entrypoint.ts index f7d615d458..3ca1b1fe9e 100644 --- a/cast/src/launcher/entrypoint.ts +++ b/cast/src/launcher/entrypoint.ts @@ -1,3 +1,3 @@ import "./layout/hc-connect"; -import("../../../src/resources/ha-style"); +import("../../../src/resources/append-ha-style"); diff --git a/cast/src/receiver/layout/hc-main.ts b/cast/src/receiver/layout/hc-main.ts index 46267f715a..e733f49fb0 100644 --- a/cast/src/receiver/layout/hc-main.ts +++ b/cast/src/receiver/layout/hc-main.ts @@ -109,7 +109,7 @@ export class HcMain extends HassElement { protected firstUpdated(changedProps) { super.firstUpdated(changedProps); import("./hc-lovelace"); - import("../../../../src/resources/ha-style"); + import("../../../../src/resources/append-ha-style"); window.addEventListener("location-changed", () => { const panelPath = `/${this._urlPath || "lovelace"}/`; diff --git a/demo/src/entrypoint.ts b/demo/src/entrypoint.ts index e153eabb12..bb00790e8f 100644 --- a/demo/src/entrypoint.ts +++ b/demo/src/entrypoint.ts @@ -1,4 +1,4 @@ import "./util/is_frontpage"; import "./ha-demo"; -import("../../src/resources/ha-style"); +import("../../src/resources/append-ha-style"); diff --git a/hassio/src/entrypoint.ts b/hassio/src/entrypoint.ts index 9ba0a12b4d..7efede19d2 100644 --- a/hassio/src/entrypoint.ts +++ b/hassio/src/entrypoint.ts @@ -1,6 +1,6 @@ import "./hassio-main"; -import("../../src/resources/ha-style"); +import("../../src/resources/append-ha-style"); const styleEl = document.createElement("style"); styleEl.textContent = ` diff --git a/src/common/dom/apply_themes_on_element.ts b/src/common/dom/apply_themes_on_element.ts index 841917af68..b986e053a8 100644 --- a/src/common/dom/apply_themes_on_element.ts +++ b/src/common/dom/apply_themes_on_element.ts @@ -1,5 +1,6 @@ import type { ThemeVars } from "../../data/ws-themes"; -import { darkStyles, derivedStyles } from "../../resources/styles-data"; +import { darkColorVariables } from "../../resources/theme/color.globals"; +import { derivedStyles } from "../../resources/theme/theme"; import type { HomeAssistant } from "../../types"; import { hex2rgb, @@ -50,7 +51,7 @@ export const applyThemesOnElement = ( if (themeToApply && darkMode) { cacheKey = `${cacheKey}__dark`; - themeRules = { ...darkStyles }; + themeRules = { ...darkColorVariables }; } if (themeToApply === "default") { diff --git a/src/common/style/derived-css-vars.ts b/src/common/style/derived-css-vars.ts new file mode 100644 index 0000000000..c4eca6e022 --- /dev/null +++ b/src/common/style/derived-css-vars.ts @@ -0,0 +1,45 @@ +import type { CSSResult } from "lit"; + +const _extractCssVars = ( + cssString: string, + condition: (string) => boolean = () => true +) => { + const variables: Record = {}; + + cssString.split(";").forEach((rawLine) => { + const line = rawLine.substring(rawLine.indexOf("--")).trim(); + if (line.startsWith("--") && condition(line)) { + const [name, value] = line.split(":").map((part) => part.trim()); + variables[name.substring(2, name.length)] = value; + } + }); + return variables; +}; + +export const extractVar = (css: CSSResult, varName: string) => { + const cssString = css.toString(); + const search = `--${varName}:`; + const startIndex = cssString.indexOf(search); + if (startIndex === -1) { + return ""; + } + + const endIndex = cssString.indexOf(";", startIndex + search.length); + return cssString.substring(startIndex + search.length, endIndex).trim(); +}; + +export const extractVars = (css: CSSResult) => { + const cssString = css.toString(); + + return _extractCssVars(cssString); +}; + +export const extractDerivedVars = (css: CSSResult) => { + const cssString = css.toString(); + + if (!cssString.includes("var(")) { + return {}; + } + + return _extractCssVars(cssString, (line) => line.includes("var(")); +}; diff --git a/src/entrypoints/app.ts b/src/entrypoints/app.ts index 3fce74db5b..a54eca9d98 100644 --- a/src/entrypoints/app.ts +++ b/src/entrypoints/app.ts @@ -1,4 +1,4 @@ import "@webcomponents/scoped-custom-element-registry/scoped-custom-element-registry.min"; import "../layouts/home-assistant"; -import("../resources/ha-style"); +import("../resources/append-ha-style"); diff --git a/src/entrypoints/authorize.ts b/src/entrypoints/authorize.ts index a7ca07093a..8b2da1b74a 100644 --- a/src/entrypoints/authorize.ts +++ b/src/entrypoints/authorize.ts @@ -1,3 +1,3 @@ import "../auth/ha-authorize"; -import("../resources/ha-style"); +import("../resources/append-ha-style"); diff --git a/src/entrypoints/onboarding.ts b/src/entrypoints/onboarding.ts index 704477b49a..075b819875 100644 --- a/src/entrypoints/onboarding.ts +++ b/src/entrypoints/onboarding.ts @@ -1,6 +1,6 @@ import "../onboarding/ha-onboarding"; -import("../resources/ha-style"); +import("../resources/append-ha-style"); declare global { interface Window { diff --git a/src/panels/config/hardware/ha-config-hardware.ts b/src/panels/config/hardware/ha-config-hardware.ts index 6f420aeebe..252655c417 100644 --- a/src/panels/config/hardware/ha-config-hardware.ts +++ b/src/panels/config/hardware/ha-config-hardware.ts @@ -30,7 +30,7 @@ import { showOptionsFlowDialog } from "../../../dialogs/config-flow/show-dialog- import { showRestartDialog } from "../../../dialogs/restart/show-dialog-restart"; import "../../../layouts/hass-subpage"; import { SubscribeMixin } from "../../../mixins/subscribe-mixin"; -import { DEFAULT_PRIMARY_COLOR } from "../../../resources/styles-data"; +import { DefaultPrimaryColor } from "../../../resources/theme/color.globals"; import { haStyle } from "../../../resources/styles"; import type { HomeAssistant } from "../../../types"; import { hardwareBrandsUrl } from "../../../util/brands-url"; @@ -42,9 +42,9 @@ const DATASAMPLES = 60; const DATA_SET_CONFIG: SeriesOption = { type: "line", - color: DEFAULT_PRIMARY_COLOR, + color: DefaultPrimaryColor, areaStyle: { - color: DEFAULT_PRIMARY_COLOR + "2B", + color: DefaultPrimaryColor + "2B", }, symbolSize: 0, lineStyle: { diff --git a/src/panels/profile/ha-pick-theme-row.ts b/src/panels/profile/ha-pick-theme-row.ts index 56c30af63d..edd4cece83 100644 --- a/src/panels/profile/ha-pick-theme-row.ts +++ b/src/panels/profile/ha-pick-theme-row.ts @@ -12,9 +12,9 @@ import "../../components/ha-select"; import "../../components/ha-settings-row"; import "../../components/ha-textfield"; import { - DEFAULT_ACCENT_COLOR, - DEFAULT_PRIMARY_COLOR, -} from "../../resources/styles-data"; + DefaultAccentColor, + DefaultPrimaryColor, +} from "../../resources/theme/color.globals"; import type { HomeAssistant } from "../../types"; import { documentationUrl } from "../../util/documentation-url"; @@ -129,8 +129,7 @@ export class HaPickThemeRow extends LitElement { ${curTheme === HOME_ASSISTANT_THEME ? html`
`--${key}: ${value};`) - .join("") - )} - } -`.toString(); - -const styleElement = document.createElement("style"); -styleElement.textContent = [mainStyles, fontStyles].join(""); -document.head.append(styleElement); diff --git a/src/resources/particles.ts b/src/resources/particles.ts index 1734c99219..a2ae5912ab 100644 --- a/src/resources/particles.ts +++ b/src/resources/particles.ts @@ -1,6 +1,6 @@ import { tsParticles } from "@tsparticles/engine"; import { loadLinksPreset } from "@tsparticles/preset-links"; -import { DEFAULT_PRIMARY_COLOR } from "./styles-data"; +import { DefaultPrimaryColor } from "./theme/color.globals"; loadLinksPreset(tsParticles).then(() => { tsParticles.load({ @@ -25,11 +25,11 @@ loadLinksPreset(tsParticles).then(() => { }, particles: { color: { - value: DEFAULT_PRIMARY_COLOR, + value: DefaultPrimaryColor, }, links: { color: { - value: DEFAULT_PRIMARY_COLOR, + value: DefaultPrimaryColor, }, distance: 100, enable: true, diff --git a/src/resources/roboto.ts b/src/resources/roboto.ts index 908cebd035..f156b1fa88 100644 --- a/src/resources/roboto.ts +++ b/src/resources/roboto.ts @@ -121,4 +121,4 @@ export const fontStyles = css` font-weight: 900; font-style: italic; } -`.toString(); +`; diff --git a/src/resources/styles-data.ts b/src/resources/styles-data.ts deleted file mode 100644 index 05a3e012ec..0000000000 --- a/src/resources/styles-data.ts +++ /dev/null @@ -1,255 +0,0 @@ -export const DEFAULT_PRIMARY_COLOR = "#03a9f4" as const; -export const DEFAULT_ACCENT_COLOR = "#ff9800" as const; - -export const darkStyles = { - "primary-background-color": "#111111", - "card-background-color": "#1c1c1c", - "secondary-background-color": "#282828", - "clear-background-color": "#111111", - "primary-text-color": "#e1e1e1", - "secondary-text-color": "#9b9b9b", - "disabled-text-color": "#6f6f6f", - "app-header-text-color": "#e1e1e1", - "app-header-background-color": "#101e24", - "switch-unchecked-button-color": "#999999", - "switch-unchecked-track-color": "#9b9b9b", - "divider-color": "rgba(225, 225, 225, .12)", - "outline-color": "rgba(225, 225, 225, .12)", - "outline-hover-color": "rgba(225, 225, 225, .24)", - "mdc-ripple-color": "#AAAAAA", - "mdc-linear-progress-buffer-color": "rgba(255, 255, 255, 0.1)", - - "input-idle-line-color": "rgba(255, 255, 255, 0.42)", - "input-hover-line-color": "rgba(255, 255, 255, 0.87)", - "input-disabled-line-color": "rgba(255, 255, 255, 0.06)", - "input-outlined-idle-border-color": "rgba(255, 255, 255, 0.38)", - "input-outlined-hover-border-color": "rgba(255, 255, 255, 0.87)", - "input-outlined-disabled-border-color": "rgba(255, 255, 255, 0.06)", - "input-fill-color": "rgba(255, 255, 255, 0.05)", - "input-disabled-fill-color": "rgba(255, 255, 255, 0.02)", - "input-ink-color": "rgba(255, 255, 255, 0.87)", - "input-label-ink-color": "rgba(255, 255, 255, 0.6)", - "input-disabled-ink-color": "rgba(255, 255, 255, 0.37)", - "input-dropdown-icon-color": "rgba(255, 255, 255, 0.54)", - - "codemirror-keyword": "#C792EA", - "codemirror-operator": "#89DDFF", - "codemirror-variable": "#f07178", - "codemirror-variable-2": "#EEFFFF", - "codemirror-variable-3": "#DECB6B", - "codemirror-builtin": "#FFCB6B", - "codemirror-atom": "#F78C6C", - "codemirror-number": "#FF5370", - "codemirror-def": "#82AAFF", - "codemirror-string": "#C3E88D", - "codemirror-string-2": "#f07178", - "codemirror-comment": "#545454", - "codemirror-tag": "#FF5370", - "codemirror-meta": "#FFCB6B", - "codemirror-attribute": "#C792EA", - "codemirror-property": "#C792EA", - "codemirror-qualifier": "#DECB6B", - "codemirror-type": "#DECB6B", - "energy-grid-return-color": "#a280db", - "map-filter": - "invert(.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) saturate(.3)", - "disabled-color": "#464646", -} as const; - -export const derivedStyles = { - /* typography */ - "ha-font-size-xs": "calc(10px * var(--ha-font-size-scale))", - "ha-font-size-s": "calc(12px * var(--ha-font-size-scale))", - "ha-font-size-m": "calc(14px * var(--ha-font-size-scale))", - "ha-font-size-l": "calc(16px * var(--ha-font-size-scale))", - "ha-font-size-xl": "calc(20px * var(--ha-font-size-scale))", - "ha-font-size-2xl": "calc(24px * var(--ha-font-size-scale))", - "ha-font-size-3xl": "calc(28px * var(--ha-font-size-scale))", - "ha-font-size-4xl": "calc(32px * var(--ha-font-size-scale))", - "ha-font-size-5xl": "calc(40px * var(--ha-font-size-scale))", - - "ha-font-family-heading": "var(--ha-font-family-body)", - "ha-font-weight-body": "var(--ha-font-weight-normal)", - "ha-font-weight-heading": "var(--ha-font-weight-bold)", - "ha-font-weight-action": "var(--ha-font-weight-semibold)", - - /* Vaadin typography */ - "material-h6-font-size": "var(--ha-font-size-m)", - "material-small-font-size": "var(--ha-font-size-xs)", - "material-caption-font-size": "var(--ha-font-size-2xs)", - "material-button-font-size": "var(--ha-font-size-xs)", - - /* for label-badge */ - "label-badge-red": "var(--error-color)", - "label-badge-blue": "var(--info-color)", - "label-badge-green": "var(--success-color)", - "label-badge-yellow": "var(--warning-color)", - - /* state color */ - "state-active-color": "var(--amber-color)", - "state-inactive-color": "var(--grey-color)", - "state-unavailable-color": - "var(--state-icon-unavailable-color, var(--disabled-text-color))", - - /* state domain colors */ - "state-alarm_control_panel-armed_away-color": "var(--green-color)", - "state-alarm_control_panel-armed_custom_bypass-color": "var(--green-color)", - "state-alarm_control_panel-armed_home-color": "var(--green-color)", - "state-alarm_control_panel-armed_night-color": "var(--green-color)", - "state-alarm_control_panel-armed_vacation-color": "var(--green-color)", - "state-alarm_control_panel-arming-color": "var(--orange-color)", - "state-alarm_control_panel-disarming-color": "var(--orange-color)", - "state-alarm_control_panel-pending-color": "var(--orange-color)", - "state-alarm_control_panel-triggered-color": "var(--red-color)", - "state-alert-off-color": "var(--orange-color)", - "state-alert-on-color": "var(--red-color)", - "state-binary_sensor-active-color": "var(--amber-color)", - "state-binary_sensor-battery-on-color": "var(--red-color)", - "state-binary_sensor-carbon_monoxide-on-color": "var(--red-color)", - "state-binary_sensor-gas-on-color": "var(--red-color)", - "state-binary_sensor-heat-on-color": "var(--red-color)", - "state-binary_sensor-lock-on-color": "var(--red-color)", - "state-binary_sensor-moisture-on-color": "var(--red-color)", - "state-binary_sensor-problem-on-color": "var(--red-color)", - "state-binary_sensor-safety-on-color": "var(--red-color)", - "state-binary_sensor-smoke-on-color": "var(--red-color)", - "state-binary_sensor-sound-on-color": "var(--red-color)", - "state-binary_sensor-tamper-on-color": "var(--red-color)", - "state-climate-auto-color": "var(--green-color)", - "state-climate-cool-color": "var(--blue-color)", - "state-climate-dry-color": "var(--orange-color)", - "state-climate-fan_only-color": "var(--cyan-color)", - "state-climate-heat-color": "var(--deep-orange-color)", - "state-climate-heat-cool-color": "var(--amber-color)", - "state-cover-active-color": "var(--purple-color)", - "state-device_tracker-active-color": "var(--blue-color)", - "state-device_tracker-home-color": "var(--green-color)", - "state-fan-active-color": "var(--cyan-color)", - "state-humidifier-on-color": "var(--blue-color)", - "state-lawn_mower-error-color": "var(--red-color)", - "state-lawn_mower-mowing-color": "var(--teal-color)", - "state-light-active-color": "var(--amber-color)", - "state-lock-jammed-color": "var(--red-color)", - "state-lock-locked-color": "var(--green-color)", - "state-lock-locking-color": "var(--orange-color)", - "state-lock-unlocked-color": "var(--red-color)", - "state-lock-unlocking-color": "var(--orange-color)", - "state-lock-open-color": "var(--red-color)", - "state-lock-opening-color": "var(--orange-color)", - "state-media_player-active-color": "var(--light-blue-color)", - "state-person-active-color": "var(--blue-color)", - "state-person-home-color": "var(--green-color)", - "state-plant-active-color": "var(--red-color)", - "state-siren-active-color": "var(--red-color)", - "state-sun-above_horizon-color": "var(--amber-color)", - "state-sun-below_horizon-color": "var(--indigo-color)", - "state-switch-active-color": "var(--amber-color)", - "state-update-active-color": "var(--orange-color)", - "state-vacuum-active-color": "var(--teal-color)", - "state-valve-active-color": "var(--blue-color)", - "state-sensor-battery-high-color": "var(--green-color)", - "state-sensor-battery-low-color": "var(--red-color)", - "state-sensor-battery-medium-color": "var(--orange-color)", - "state-water_heater-eco-color": "var(--green-color)", - "state-water_heater-electric-color": "var(--orange-color)", - "state-water_heater-gas-color": "var(--orange-color)", - "state-water_heater-heat_pump-color": "var(--orange-color)", - "state-water_heater-high_demand-color": "var(--deep-orange-color)", - "state-water_heater-performance-color": "var(--deep-orange-color)", - - /* history colors */ - "history-unknown-color": "var(--dark-grey-color)", - - "state-icon-error-color": "var(--error-state-color, var(--error-color))", - "sidebar-text-color": "var(--primary-text-color)", - "sidebar-background-color": "var(--card-background-color)", - "sidebar-selected-text-color": "var(--primary-color)", - "sidebar-selected-icon-color": "var(--primary-color)", - "sidebar-icon-color": "rgba(var(--rgb-primary-text-color), 0.6)", - "switch-checked-color": "var(--primary-color)", - "switch-checked-button-color": - "var(--switch-checked-color, var(--primary-background-color))", - "switch-checked-track-color": "var(--switch-checked-color, #000000)", - "switch-unchecked-button-color": - "var(--switch-unchecked-color, var(--primary-background-color))", - "switch-unchecked-track-color": "var(--switch-unchecked-color, #000000)", - "slider-color": "var(--primary-color)", - "slider-secondary-color": "var(--light-primary-color)", - "slider-track-color": "var(--scrollbar-thumb-color)", - "label-badge-background-color": "var(--card-background-color)", - "label-badge-text-color": "rgba(var(--rgb-primary-text-color), 0.8)", - "table-header-background-color": "var(--input-fill-color)", - "table-row-background-color": "var(--primary-background-color)", - "table-row-alternative-background-color": "var(--secondary-background-color)", - "data-table-background-color": "var(--card-background-color)", - "markdown-code-background-color": "var(--primary-background-color)", - - // https://github.com/material-components/material-web/blob/master/docs/theming.md - "mdc-theme-primary": "var(--primary-color)", - "mdc-theme-secondary": "var(--accent-color)", - "mdc-theme-background": "var(--primary-background-color)", - "mdc-theme-surface": "var(--card-background-color)", - "mdc-theme-on-primary": "var(--text-primary-color)", - "mdc-theme-on-secondary": "var(--text-primary-color)", - "mdc-theme-on-surface": "var(--primary-text-color)", - "mdc-theme-text-disabled-on-light": "var(--disabled-text-color)", - "mdc-theme-text-primary-on-background": "var(--primary-text-color)", - "mdc-theme-text-secondary-on-background": "var(--secondary-text-color)", - "mdc-theme-text-hint-on-background": "var(--secondary-text-color)", - "mdc-theme-text-icon-on-background": "var(--secondary-text-color)", - "mdc-theme-error": "var(--error-color)", - "app-header-text-color": "var(--text-primary-color)", - "app-header-background-color": "var(--primary-color)", - "app-theme-color": "var(--app-header-background-color)", - "mdc-checkbox-unchecked-color": "rgba(var(--rgb-primary-text-color), 0.54)", - "mdc-checkbox-disabled-color": "var(--disabled-text-color)", - "mdc-radio-unchecked-color": "rgba(var(--rgb-primary-text-color), 0.54)", - "mdc-radio-disabled-color": "var(--disabled-text-color)", - "mdc-tab-text-label-color-default": "var(--primary-text-color)", - "mdc-button-disabled-ink-color": "var(--disabled-text-color)", - "mdc-button-outline-color": "var(--outline-color)", - "mdc-dialog-scroll-divider-color": "var(--divider-color)", - "mdc-dialog-heading-ink-color": "var(--primary-text-color)", - "mdc-dialog-content-ink-color": "var(--primary-text-color)", - - "mdc-text-field-idle-line-color": "var(--input-idle-line-color)", - "mdc-text-field-hover-line-color": "var(--input-hover-line-color)", - "mdc-text-field-disabled-line-color": "var(--input-disabled-line-color)", - "mdc-text-field-outlined-idle-border-color": - "var(--input-outlined-idle-border-color)", - "mdc-text-field-outlined-hover-border-color": - "var(--input-outlined-hover-border-color)", - "mdc-text-field-outlined-disabled-border-color": - "var(--input-outlined-disabled-border-color)", - "mdc-text-field-fill-color": "var(--input-fill-color)", - "mdc-text-field-disabled-fill-color": "var(--input-disabled-fill-color)", - "mdc-text-field-ink-color": "var(--input-ink-color)", - "mdc-text-field-label-ink-color": "var(--input-label-ink-color)", - "mdc-text-field-disabled-ink-color": "var(--input-disabled-ink-color)", - - "mdc-select-idle-line-color": "var(--input-idle-line-color)", - "mdc-select-hover-line-color": "var(--input-hover-line-color)", - "mdc-select-outlined-idle-border-color": - "var(--input-outlined-idle-border-color)", - "mdc-select-outlined-hover-border-color": - "var(--input-outlined-hover-border-color)", - "mdc-select-outlined-disabled-border-color": - "var(--input-outlined-disabled-border-color)", - "mdc-select-fill-color": "var(--input-fill-color)", - "mdc-select-disabled-fill-color": "var(--input-disabled-fill-color)", - "mdc-select-ink-color": "var(--input-ink-color)", - "mdc-select-label-ink-color": "var(--input-label-ink-color)", - "mdc-select-disabled-ink-color": "var(--input-disabled-ink-color)", - "mdc-select-dropdown-icon-color": "var(--input-dropdown-icon-color)", - "mdc-select-disabled-dropdown-icon-color": "var(--input-disabled-ink-color)", - "ha-assist-chip-filled-container-color": - "rgba(var(--rgb-primary-text-color),0.15)", - "ha-assist-chip-active-container-color": - "rgba(var(--rgb-primary-color),0.15)", - "chip-background-color": "rgba(var(--rgb-primary-text-color), 0.15)", - // Vaadin - "material-body-text-color": "var(--primary-text-color)", - "material-background-color": "var(--card-background-color)", - "material-secondary-background-color": "var(--secondary-background-color)", - "material-secondary-text-color": "var(--secondary-text-color)", -} as const; diff --git a/src/resources/theme/color.globals.ts b/src/resources/theme/color.globals.ts new file mode 100644 index 0000000000..8e588b723b --- /dev/null +++ b/src/resources/theme/color.globals.ts @@ -0,0 +1,359 @@ +import { css } from "lit"; +import { + extractDerivedVars, + extractVar, + extractVars, +} from "../../common/style/derived-css-vars"; + +export const colorStyles = css` + html { + /* text */ + --primary-text-color: #212121; + --secondary-text-color: #727272; + --text-primary-color: #ffffff; + --text-light-primary-color: #212121; + --disabled-text-color: #bdbdbd; + + /* main interface colors */ + --primary-color: #03a9f4; + --dark-primary-color: #0288d1; + --light-primary-color: #b3e5fc; + --accent-color: #ff9800; + --divider-color: rgba(0, 0, 0, 0.12); + --outline-color: rgba(0, 0, 0, 0.12); + --outline-hover-color: rgba(0, 0, 0, 0.24); + + /* rgb */ + --rgb-primary-color: 3, 169, 244; + --rgb-accent-color: 255, 152, 0; + --rgb-primary-text-color: 33, 33, 33; + --rgb-secondary-text-color: 114, 114, 114; + --rgb-text-primary-color: 255, 255, 255; + --rgb-card-background-color: 255, 255, 255; + + --scrollbar-thumb-color: rgb(194, 194, 194); + + --error-color: #db4437; + --warning-color: #ffa600; + --success-color: #43a047; + --info-color: #039be5; + + /* backgrounds */ + --card-background-color: #ffffff; + --primary-background-color: #fafafa; + --secondary-background-color: #e5e5e5; /* behind the cards on state */ + --clear-background-color: #ffffff; + + /* for label-badge */ + --label-badge-grey: #9e9e9e; + + /* states icon */ + --state-icon-color: #44739e; + /* an error state is anything that would be considered an error */ + /* --state-icon-error-color: #db4437; derived from error-color */ + + /* energy */ + --energy-grid-consumption-color: #488fc2; + --energy-grid-return-color: #8353d1; + --energy-solar-color: #ff9800; + --energy-non-fossil-color: #0f9d58; + --energy-battery-out-color: #4db6ac; + --energy-battery-in-color: #f06292; + --energy-gas-color: #8e021b; + --energy-water-color: #00bcd4; + + /* color */ + --disabled-color: #bdbdbd; + --red-color: #f44336; + --pink-color: #e91e63; + --purple-color: #926bc7; + --deep-purple-color: #6e41ab; + --indigo-color: #3f51b5; + --blue-color: #2196f3; + --light-blue-color: #03a9f4; + --cyan-color: #00bcd4; + --teal-color: #009688; + --green-color: #4caf50; + --light-green-color: #8bc34a; + --lime-color: #cddc39; + --yellow-color: #ffeb3b; + --amber-color: #ffc107; + --orange-color: #ff9800; + --deep-orange-color: #ff6f22; + --brown-color: #795548; + --light-grey-color: #bdbdbd; + --grey-color: #9e9e9e; + --dark-grey-color: #606060; + --blue-grey-color: #607d8b; + --black-color: #000000; + --white-color: #ffffff; + + /* history colors */ + --history-unavailable-color: transparent; + + /* input components */ + --input-idle-line-color: rgba(0, 0, 0, 0.42); + --input-hover-line-color: rgba(0, 0, 0, 0.87); + --input-disabled-line-color: rgba(0, 0, 0, 0.06); + --input-outlined-idle-border-color: rgba(0, 0, 0, 0.38); + --input-outlined-hover-border-color: rgba(0, 0, 0, 0.87); + --input-outlined-disabled-border-color: rgba(0, 0, 0, 0.06); + --input-fill-color: rgb(245, 245, 245); + --input-disabled-fill-color: rgb(250, 250, 250); + --input-ink-color: rgba(0, 0, 0, 0.87); + --input-label-ink-color: rgba(0, 0, 0, 0.6); + --input-disabled-ink-color: rgba(0, 0, 0, 0.37); + --input-dropdown-icon-color: rgba(0, 0, 0, 0.54); + + /* for label-badge */ + --label-badge-red: var(--error-color); + --label-badge-blue: var(--info-color); + --label-badge-green: var(--success-color); + --label-badge-yellow: var(--warning-color); + + /* state color */ + --state-active-color: var(--amber-color); + --state-inactive-color: var(--grey-color); + --state-unavailable-color: var( + --state-icon-unavailable-color, + var(--disabled-text-color) + ); + + /* state domain colors */ + --state-alarm_control_panel-armed_away-color: var(--green-color); + --state-alarm_control_panel-armed_custom_bypass-color: var(--green-color); + --state-alarm_control_panel-armed_home-color: var(--green-color); + --state-alarm_control_panel-armed_night-color: var(--green-color); + --state-alarm_control_panel-armed_vacation-color: var(--green-color); + --state-alarm_control_panel-arming-color: var(--orange-color); + --state-alarm_control_panel-disarming-color: var(--orange-color); + --state-alarm_control_panel-pending-color: var(--orange-color); + --state-alarm_control_panel-triggered-color: var(--red-color); + --state-alert-off-color: var(--orange-color); + --state-alert-on-color: var(--red-color); + --state-binary_sensor-active-color: var(--amber-color); + --state-binary_sensor-battery-on-color: var(--red-color); + --state-binary_sensor-carbon_monoxide-on-color: var(--red-color); + --state-binary_sensor-gas-on-color: var(--red-color); + --state-binary_sensor-heat-on-color: var(--red-color); + --state-binary_sensor-lock-on-color: var(--red-color); + --state-binary_sensor-moisture-on-color: var(--red-color); + --state-binary_sensor-problem-on-color: var(--red-color); + --state-binary_sensor-safety-on-color: var(--red-color); + --state-binary_sensor-smoke-on-color: var(--red-color); + --state-binary_sensor-sound-on-color: var(--red-color); + --state-binary_sensor-tamper-on-color: var(--red-color); + --state-climate-auto-color: var(--green-color); + --state-climate-cool-color: var(--blue-color); + --state-climate-dry-color: var(--orange-color); + --state-climate-fan_only-color: var(--cyan-color); + --state-climate-heat-color: var(--deep-orange-color); + --state-climate-heat-cool-color: var(--amber-color); + --state-cover-active-color: var(--purple-color); + --state-device_tracker-active-color: var(--blue-color); + --state-device_tracker-home-color: var(--green-color); + --state-fan-active-color: var(--cyan-color); + --state-humidifier-on-color: var(--blue-color); + --state-lawn_mower-error-color: var(--red-color); + --state-lawn_mower-mowing-color: var(--teal-color); + --state-light-active-color: var(--amber-color); + --state-lock-jammed-color: var(--red-color); + --state-lock-locked-color: var(--green-color); + --state-lock-locking-color: var(--orange-color); + --state-lock-unlocked-color: var(--red-color); + --state-lock-unlocking-color: var(--orange-color); + --state-lock-open-color: var(--red-color); + --state-lock-opening-color: var(--orange-color); + --state-media_player-active-color: var(--light-blue-color); + --state-person-active-color: var(--blue-color); + --state-person-home-color: var(--green-color); + --state-plant-active-color: var(--red-color); + --state-siren-active-color: var(--red-color); + --state-sun-above_horizon-color: var(--amber-color); + --state-sun-below_horizon-color: var(--indigo-color); + --state-switch-active-color: var(--amber-color); + --state-update-active-color: var(--orange-color); + --state-vacuum-active-color: var(--teal-color); + --state-valve-active-color: var(--blue-color); + --state-sensor-battery-high-color: var(--green-color); + --state-sensor-battery-low-color: var(--red-color); + --state-sensor-battery-medium-color: var(--orange-color); + --state-water_heater-eco-color: var(--green-color); + --state-water_heater-electric-color: var(--orange-color); + --state-water_heater-gas-color: var(--orange-color); + --state-water_heater-heat_pump-color: var(--orange-color); + --state-water_heater-high_demand-color: var(--deep-orange-color); + --state-water_heater-performance-color: var(--deep-orange-color); + + /* history colors */ + --history-unknown-color: var(--dark-grey-color); + + --state-icon-error-color: var(--error-state-color, var(--error-color)); + --sidebar-text-color: var(--primary-text-color); + --sidebar-background-color: var(--card-background-color); + --sidebar-selected-text-color: var(--primary-color); + --sidebar-selected-icon-color: var(--primary-color); + --sidebar-icon-color: rgba(var(--rgb-primary-text-color), 0.6); + --switch-checked-color: var(--primary-color); + --switch-checked-button-color: var( + --switch-checked-color, + var(--primary-background-color) + ); + --switch-checked-track-color: var(--switch-checked-color, #000000); + --switch-unchecked-button-color: var( + --switch-unchecked-color, + var(--primary-background-color) + ); + --switch-unchecked-track-color: var(--switch-unchecked-color, #000000); + --slider-color: var(--primary-color); + --slider-secondary-color: var(--light-primary-color); + --slider-track-color: var(--scrollbar-thumb-color); + --label-badge-background-color: var(--card-background-color); + --label-badge-text-color: rgba(var(--rgb-primary-text-color), 0.8); + --table-header-background-color: var(--input-fill-color); + --table-row-background-color: var(--primary-background-color); + --table-row-alternative-background-color: var(--secondary-background-color); + --data-table-background-color: var(--card-background-color); + --markdown-code-background-color: var(--primary-background-color); + + /* https://github.com/material-components/material-web/blob/master/docs/theming.md */ + --mdc-theme-primary: var(--primary-color); + --mdc-theme-secondary: var(--accent-color); + --mdc-theme-background: var(--primary-background-color); + --mdc-theme-surface: var(--card-background-color); + --mdc-theme-on-primary: var(--text-primary-color); + --mdc-theme-on-secondary: var(--text-primary-color); + --mdc-theme-on-surface: var(--primary-text-color); + --mdc-theme-text-disabled-on-light: var(--disabled-text-color); + --mdc-theme-text-primary-on-background: var(--primary-text-color); + --mdc-theme-text-secondary-on-background: var(--secondary-text-color); + --mdc-theme-text-hint-on-background: var(--secondary-text-color); + --mdc-theme-text-icon-on-background: var(--secondary-text-color); + --mdc-theme-error: var(--error-color); + --app-header-text-color: var(--text-primary-color); + --app-header-background-color: var(--primary-color); + --app-theme-color: var(--app-header-background-color); + --mdc-checkbox-unchecked-color: rgba(var(--rgb-primary-text-color), 0.54); + --mdc-checkbox-disabled-color: var(--disabled-text-color); + --mdc-radio-unchecked-color: rgba(var(--rgb-primary-text-color), 0.54); + --mdc-radio-disabled-color: var(--disabled-text-color); + --mdc-tab-text-label-color-default: var(--primary-text-color); + --mdc-button-disabled-ink-color: var(--disabled-text-color); + --mdc-button-outline-color: var(--outline-color); + --mdc-dialog-scroll-divider-color: var(--divider-color); + --mdc-dialog-heading-ink-color: var(--primary-text-color); + --mdc-dialog-content-ink-color: var(--primary-text-color); + + --mdc-text-field-idle-line-color: var(--input-idle-line-color); + --mdc-text-field-hover-line-color: var(--input-hover-line-color); + --mdc-text-field-disabled-line-color: var(--input-disabled-line-color); + --mdc-text-field-outlined-idle-border-color: var( + --input-outlined-idle-border-color + ); + --mdc-text-field-outlined-hover-border-color: var( + --input-outlined-hover-border-color + ); + --mdc-text-field-outlined-disabled-border-color: var( + --input-outlined-disabled-border-color + ); + --mdc-text-field-fill-color: var(--input-fill-color); + --mdc-text-field-disabled-fill-color: var(--input-disabled-fill-color); + --mdc-text-field-ink-color: var(--input-ink-color); + --mdc-text-field-label-ink-color: var(--input-label-ink-color); + --mdc-text-field-disabled-ink-color: var(--input-disabled-ink-color); + + --mdc-select-idle-line-color: var(--input-idle-line-color); + --mdc-select-hover-line-color: var(--input-hover-line-color); + --mdc-select-outlined-idle-border-color: var( + --input-outlined-idle-border-color + ); + --mdc-select-outlined-hover-border-color: var( + --input-outlined-hover-border-color + ); + --mdc-select-outlined-disabled-border-color: var( + --input-outlined-disabled-border-color + ); + --mdc-select-fill-color: var(--input-fill-color); + --mdc-select-disabled-fill-color: var(--input-disabled-fill-color); + --mdc-select-ink-color: var(--input-ink-color); + --mdc-select-label-ink-color: var(--input-label-ink-color); + --mdc-select-disabled-ink-color: var(--input-disabled-ink-color); + --mdc-select-dropdown-icon-color: var(--input-dropdown-icon-color); + --mdc-select-disabled-dropdown-icon-color: var(--input-disabled-ink-color); + --ha-assist-chip-filled-container-color: rgba( + var(--rgb-primary-text-color), + 0.15 + ); + --ha-assist-chip-active-container-color: rgba( + var(--rgb-primary-color), + 0.15 + ); + --chip-background-color: rgba(var(--rgb-primary-text-color), 0.15); + + /* Vaadin */ + --material-body-text-color: var(--primary-text-color); + --material-background-color: var(--card-background-color); + --material-secondary-background-color: var(--secondary-background-color); + --material-secondary-text-color: var(--secondary-text-color); + } +`; + +const darkColorStyles = css` + --primary-background-color: #111111; + --card-background-color: #1c1c1c; + --secondary-background-color: #282828; + --clear-background-color: #111111; + --primary-text-color: #e1e1e1; + --secondary-text-color: #9b9b9b; + --disabled-text-color: #6f6f6f; + --app-header-text-color: #e1e1e1; + --app-header-background-color: #101e24; + --switch-unchecked-button-color: #999999; + --switch-unchecked-track-color: #9b9b9b; + --divider-color: rgba(225, 225, 225, 0.12); + --outline-color: rgba(225, 225, 225, 0.12); + --outline-hover-color: rgba(225, 225, 225, 0.24); + --mdc-ripple-color: #aaaaaa; + --mdc-linear-progress-buffer-color: rgba(255, 255, 255, 0.1); + + --input-idle-line-color: rgba(255, 255, 255, 0.42); + --input-hover-line-color: rgba(255, 255, 255, 0.87); + --input-disabled-line-color: rgba(255, 255, 255, 0.06); + --input-outlined-idle-border-color: rgba(255, 255, 255, 0.38); + --input-outlined-hover-border-color: rgba(255, 255, 255, 0.87); + --input-outlined-disabled-border-color: rgba(255, 255, 255, 0.06); + --input-fill-color: rgba(255, 255, 255, 0.05); + --input-disabled-fill-color: rgba(255, 255, 255, 0.02); + --input-ink-color: rgba(255, 255, 255, 0.87); + --input-label-ink-color: rgba(255, 255, 255, 0.6); + --input-disabled-ink-color: rgba(255, 255, 255, 0.37); + --input-dropdown-icon-color: rgba(255, 255, 255, 0.54); + + --codemirror-keyword: #c792ea; + --codemirror-operator: #89ddff; + --codemirror-variable: #f07178; + --codemirror-variable-2: #eeffff; + --codemirror-variable-3: #decb6b; + --codemirror-builtin: #ffcb6b; + --codemirror-atom: #f78c6c; + --codemirror-number: #ff5370; + --codemirror-def: #82aaff; + --codemirror-string: #c3e88d; + --codemirror-string-2: #f07178; + --codemirror-comment: #545454; + --codemirror-tag: #ff5370; + --codemirror-meta: #ffcb6b; + --codemirror-attribute: #c792ea; + --codemirror-property: #c792ea; + --codemirror-qualifier: #decb6b; + --codemirror-type: #decb6b; + --energy-grid-return-color: #a280db; + --map-filter: invert(0.9) hue-rotate(170deg) brightness(1.5) contrast(1.2) + saturate(0.3); + --disabled-color: #464646; +`; +export const colorDerivedVariables = extractDerivedVars(colorStyles); +export const darkColorVariables = extractVars(darkColorStyles); + +export const DefaultPrimaryColor = extractVar(colorStyles, "primary-color"); +export const DefaultAccentColor = extractVar(colorStyles, "accent-color"); diff --git a/src/resources/theme/main.globals.ts b/src/resources/theme/main.globals.ts new file mode 100644 index 0000000000..60ae6e5731 --- /dev/null +++ b/src/resources/theme/main.globals.ts @@ -0,0 +1,38 @@ +import { css } from "lit"; +import { extractDerivedVars } from "../../common/style/derived-css-vars"; + +export const mainStyles = css` + html { + height: 100vh; + + /* for header */ + --header-height: 56px; + + /* opacity for dark text on a light background */ + --dark-divider-opacity: 0.12; + --dark-disabled-opacity: 0.38; /* or hint text or icon */ + --dark-secondary-opacity: 0.54; + --dark-primary-opacity: 0.87; + + /* opacity for light text on a dark background */ + --light-divider-opacity: 0.12; + --light-disabled-opacity: 0.3; /* or hint text or icon */ + --light-secondary-opacity: 0.7; + --light-primary-opacity: 1; + + direction: ltr; + --direction: ltr; + --float-start: left; + --float-end: right; + --margin-title-ltr: 0 0 0 24px; + --margin-title-rtl: 0 24px 0 0; + + /* Vaadin typography */ + --material-h6-font-size: var(--ha-font-size-m); + --material-small-font-size: var(--ha-font-size-xs); + --material-caption-font-size: var(--ha-font-size-2xs); + --material-button-font-size: var(--ha-font-size-xs); + } +`; + +export const mainDerivedVariables = extractDerivedVars(mainStyles); diff --git a/src/resources/theme/theme.ts b/src/resources/theme/theme.ts new file mode 100644 index 0000000000..3447bd8a6c --- /dev/null +++ b/src/resources/theme/theme.ts @@ -0,0 +1,20 @@ +import { fontStyles } from "../roboto"; +import { colorDerivedVariables, colorStyles } from "./color.globals"; +import { mainDerivedVariables, mainStyles } from "./main.globals"; +import { + typographyDerivedVariables, + typographyStyles, +} from "./typography.globals"; + +export const themeStyles = [ + fontStyles.toString(), + mainStyles.toString(), + typographyStyles.toString(), + colorStyles.toString(), +].join(""); + +export const derivedStyles = { + ...mainDerivedVariables, + ...typographyDerivedVariables, + ...colorDerivedVariables, +}; diff --git a/src/resources/theme/typography.globals.ts b/src/resources/theme/typography.globals.ts new file mode 100644 index 0000000000..c7ae6fe678 --- /dev/null +++ b/src/resources/theme/typography.globals.ts @@ -0,0 +1,40 @@ +import { css } from "lit"; +import { extractDerivedVars } from "../../common/style/derived-css-vars"; + +export const typographyStyles = css` + html { + --ha-font-family-body: Roboto, Noto, sans-serif; + --ha-font-family-code: monospace; + --ha-font-family-longform: ui-sans-serif, system-ui, sans-serif; + + font-size: 14px; + --ha-font-size-scale: 1; + --ha-font-size-xs: calc(10px * var(--ha-font-size-scale)); + --ha-font-size-s: calc(12px * var(--ha-font-size-scale)); + --ha-font-size-m: calc(14px * var(--ha-font-size-scale)); + --ha-font-size-l: calc(16px * var(--ha-font-size-scale)); + --ha-font-size-xl: calc(20px * var(--ha-font-size-scale)); + --ha-font-size-2xl: calc(24px * var(--ha-font-size-scale)); + --ha-font-size-3xl: calc(28px * var(--ha-font-size-scale)); + --ha-font-size-4xl: calc(32px * var(--ha-font-size-scale)); + --ha-font-size-5xl: calc(40px * var(--ha-font-size-scale)); + + --ha-font-weight-light: 300; + --ha-font-weight-normal: 400; + --ha-font-weight-semibold: 500; + --ha-font-weight-bold: 600; + + --ha-font-family-heading: var(--ha-font-family-body); + --ha-font-weight-body: var(--ha-font-weight-normal); + --ha-font-weight-heading: var(--ha-font-weight-bold); + --ha-font-weight-action: var(--ha-font-weight-semibold); + + --ha-line-height-condensed: 1.2; + --ha-line-height-normal: 1.6; + --ha-line-height-expanded: 2; + + --ha-font-smoothing: antialiased; + } +`; + +export const typographyDerivedVariables = extractDerivedVars(typographyStyles);