Add color palettes (#26271)

This commit is contained in:
Wendelin 2025-07-30 13:51:14 +02:00 committed by GitHub
parent 641e406502
commit 3e67d91d1a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 643 additions and 56 deletions

View File

@ -101,6 +101,7 @@
"comlink": "4.4.2",
"core-js": "3.44.0",
"cropperjs": "1.6.2",
"culori": "4.0.2",
"date-fns": "4.1.0",
"date-fns-tz": "3.2.0",
"deep-clone-simple": "1.1.1",
@ -164,6 +165,7 @@
"@types/chromecast-caf-receiver": "6.0.22",
"@types/chromecast-caf-sender": "1.0.11",
"@types/color-name": "2.0.0",
"@types/culori": "4",
"@types/html-minifier-terser": "7.0.2",
"@types/js-yaml": "4.0.9",
"@types/leaflet": "1.9.20",

115
src/common/color/palette.ts Normal file
View File

@ -0,0 +1,115 @@
import { formatHex, oklch, wcagLuminance, type Oklch } from "culori";
const MIN_LUMINANCE = 0.3;
const MAX_LUMINANCE = 0.6;
/**
* Normalizes the luminance of a given color to ensure it falls within the specified minimum and maximum luminance range.
* This helps to keep everything readable and accessible, especially for text and UI elements.
*
* This function converts the input color to the OKLCH color space, calculates its luminance,
* and adjusts the lightness component if the luminance is outside the allowed range.
* The adjustment is performed using a binary search to find the appropriate lightness value.
* If the color is already within the range, it is returned unchanged.
*
* @param color - css color string
* @returns The normalized color as a hex string, or the original color if normalization is not needed.
* @throws If the provided color is invalid or cannot be parsed.
*/
export const normalizeLuminance = (color: string): string => {
const baseOklch = oklch(color);
if (baseOklch === undefined) {
throw new Error("Invalid color provided");
}
const luminance = wcagLuminance(baseOklch);
if (luminance >= MIN_LUMINANCE && luminance <= MAX_LUMINANCE) {
return color;
}
const targetLuminance =
luminance < MIN_LUMINANCE ? MIN_LUMINANCE : MAX_LUMINANCE;
function findLightness(lowL = 0, highL = 1, iterations = 10) {
if (iterations <= 0) {
return (lowL + highL) / 2;
}
const midL = (lowL + highL) / 2;
const testColor = { ...baseOklch, l: midL } as Oklch;
const testLuminance = wcagLuminance(testColor);
if (Math.abs(testLuminance - targetLuminance) < 0.01) {
return midL;
}
if (testLuminance < targetLuminance) {
return findLightness(midL, highL, iterations--);
}
return findLightness(lowL, midL, iterations--);
}
baseOklch.l = findLightness();
return formatHex(baseOklch) || color;
};
/**
* Generates a color palette based on a base color using the OKLCH color space.
*
* The palette consists of multiple shades, both lighter and darker than the base color,
* calculated by adjusting the lightness and chroma values. Each shade is labeled and
* returned as a tuple containing the shade name and its hexadecimal color value.
*
* @param baseColor - The base color in a HEX format.
* @param label - A string label used to name each color variant in the palette.
* @param steps - An array of numbers representing the percentage steps for generating shades (default: [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95]).
* @returns An array of tuples, each containing the shade name and its corresponding hex color value.
* @throws If the provided base color is invalid or cannot be parsed by the `oklch` function.
*/
export const generateColorPalette = (
baseColor: string,
label: string,
steps = [5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95]
) => {
const baseOklch = oklch(baseColor);
if (baseOklch === undefined) {
throw new Error("Invalid base color provided");
}
return steps.map((step) => {
const name = `color-${label}-${step}`;
// Base color at 50%
if (step === 50) {
return [name, formatHex(baseOklch)];
}
// For darker shades (below 50%)
if (step < 50) {
const darkFactor = step / 50;
// Adjust lightness and chroma to create darker variants
const darker = {
...baseOklch,
l: baseOklch.l * darkFactor, // darkening
c: baseOklch.c * (0.9 + 0.1 * darkFactor), // Slightly adjust chroma
};
return [name, formatHex(darker)];
}
// For lighter shades (above 50%)
const lightFactor = (step - 50) / 45; // Normalized from 0 to 1
// Adjust lightness and reduce chroma for lighter variants
const lighter = {
...baseOklch,
l: Math.min(1, baseOklch.l + (1 - baseOklch.l) * lightFactor), // Increase lightness
c: baseOklch.c * Math.max(0, 1 - lightFactor * 0.7), // Gradually reduce chroma
};
return [name, formatHex(lighter)];
});
};

View File

@ -1,5 +1,5 @@
import type { ThemeVars } from "../../data/ws-themes";
import { darkColorVariables } from "../../resources/theme/color.globals";
import { darkColorVariables } from "../../resources/theme/color";
import { derivedStyles } from "../../resources/theme/theme";
import type { HomeAssistant } from "../../types";
import {
@ -11,6 +11,7 @@ import {
} from "../color/convert-color";
import { hexBlend } from "../color/hex";
import { labBrighten, labDarken } from "../color/lab";
import { generateColorPalette } from "../color/palette";
import { rgbContrast } from "../color/rgb";
interface ProcessedTheme {
@ -75,6 +76,11 @@ export const applyThemesOnElement = (
const labPrimaryColor = rgb2lab(rgbPrimaryColor);
themeRules["primary-color"] = primaryColor;
const rgbLightPrimaryColor = lab2rgb(labBrighten(labPrimaryColor));
generateColorPalette(primaryColor, "primary").forEach(([key, color]) => {
themeRules[key] = color;
});
themeRules["light-primary-color"] = rgb2hex(rgbLightPrimaryColor);
themeRules["dark-primary-color"] = lab2hex(labDarken(labPrimaryColor));
themeRules["text-primary-color"] =

View File

@ -18,7 +18,43 @@ const _extractCssVars = (
return variables;
};
export const extractVar = (css: CSSResult, varName: string) => {
/**
* Recursively resolves a CSS variable reference from a base variable map.
*
* If the value of the specified variable in `baseVars` is itself a CSS variable reference
* (i.e., starts with `var(`), this function will recursively resolve the reference until
* it finds a concrete value or reaches an undefined variable.
*
* @param varName - The name of the CSS variable to resolve.
* @param baseVars - A record mapping variable names to their values or references.
* @returns The resolved value of the variable, or `undefined` if not found.
*/
const extractVarFromBase = (
varName: string,
baseVars: Record<string, string>
): string | undefined => {
if (baseVars[varName] && baseVars[varName].startsWith("var(")) {
const baseVarName = baseVars[varName]
.substring(6, baseVars[varName].length - 1)
.trim();
return extractVarFromBase(baseVarName, baseVars);
}
return baseVars[varName];
};
/**
* Extracts the value of a CSS custom property (CSS variable) from a given CSSResult object.
*
* @param css - The CSSResult object containing the CSS string to search.
* @param varName - The name of the CSS variable (without the leading '--') to extract.
* @param baseVars - (Optional) A record of base variable names and their values, used to resolve variables that reference other variables via `var()`.
* @returns The value of the CSS variable if found, otherwise an empty string. If the variable references another variable and `baseVars` is provided, attempts to resolve it from `baseVars`.
*/
export const extractVar = (
css: CSSResult,
varName: string,
baseVars?: Record<string, string>
) => {
const cssString = css.toString();
const search = `--${varName}:`;
const startIndex = cssString.indexOf(search);
@ -27,10 +63,17 @@ export const extractVar = (css: CSSResult, varName: string) => {
}
const endIndex = cssString.indexOf(";", startIndex + search.length);
return cssString
const value = cssString
.substring(startIndex + search.length, endIndex)
.replaceAll("}", "")
.trim();
if (baseVars && value.startsWith("var(")) {
const baseVarName = value.substring(6, value.length - 1).trim();
return extractVarFromBase(baseVarName, baseVars) || value;
}
return value;
};
export const extractVars = (css: CSSResult) => {

View File

@ -29,7 +29,7 @@ import { formatTimeLabel } from "./axis-label";
import { ensureArray } from "../../common/array/ensure-array";
import "../chips/ha-assist-chip";
import { downSampleLineData } from "./down-sample";
import { colorVariables } from "../../resources/theme/color.globals";
import { colorVariables } from "../../resources/theme/color/color.globals";
export const MIN_TIME_BETWEEN_UPDATES = 60 * 5 * 1000;
const LEGEND_OVERFLOW_LIMIT = 10;

View File

@ -1,9 +1,9 @@
import { mdiPower } from "@mdi/js";
import type { SeriesOption } from "echarts/types/dist/shared";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import type { SeriesOption } from "echarts/types/dist/shared";
import memoizeOne from "memoize-one";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { round } from "../../../common/number/round";
@ -12,9 +12,9 @@ import "../../../components/buttons/ha-progress-button";
import "../../../components/chart/ha-chart-base";
import "../../../components/ha-alert";
import "../../../components/ha-card";
import "../../../components/ha-md-list-item";
import "../../../components/ha-icon-button";
import "../../../components/ha-icon-next";
import "../../../components/ha-md-list-item";
import "../../../components/ha-settings-row";
import type { ConfigEntry } from "../../../data/config_entries";
import { subscribeConfigEntries } from "../../../data/config_entries";
@ -23,6 +23,7 @@ import type {
SystemStatusStreamMessage,
} from "../../../data/hardware";
import { BOARD_NAMES } from "../../../data/hardware";
import { extractApiErrorMessage } from "../../../data/hassio/common";
import type { HassioHassOSInfo } from "../../../data/hassio/host";
import { fetchHassioHassOsInfo } from "../../../data/hassio/host";
import { scanUSBDevices } from "../../../data/usb";
@ -30,13 +31,12 @@ 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 { DefaultPrimaryColor } from "../../../resources/theme/color.globals";
import type { ECOption } from "../../../resources/echarts";
import { haStyle } from "../../../resources/styles";
import { DefaultPrimaryColor } from "../../../resources/theme/color/color.globals";
import type { HomeAssistant } from "../../../types";
import { hardwareBrandsUrl } from "../../../util/brands-url";
import { showhardwareAvailableDialog } from "./show-dialog-hardware-available";
import { extractApiErrorMessage } from "../../../data/hassio/common";
import type { ECOption } from "../../../resources/echarts";
const DATASAMPLES = 60;

View File

@ -1,18 +1,20 @@
import { html, LitElement, css } from "lit";
import type { CSSResultGroup } from "lit";
import { customElement, property, state } from "lit/decorators";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type {
CallbackDataParams,
TopLevelFormatterParams,
} from "echarts/types/dist/shared";
import type { UnsubscribeFunc } from "home-assistant-js-websocket";
import type { CSSResultGroup } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import type { HomeAssistant, Route } from "../../../../../types";
import { relativeTime } from "../../../../../common/datetime/relative_time";
import { navigate } from "../../../../../common/navigate";
import { throttle } from "../../../../../common/util/throttle";
import "../../../../../components/chart/ha-network-graph";
import type {
NetworkData,
NetworkNode,
NetworkLink,
NetworkNode,
} from "../../../../../components/chart/ha-network-graph";
import type {
BluetoothDeviceData,
@ -24,11 +26,9 @@ import {
} from "../../../../../data/bluetooth";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import "../../../../../layouts/hass-subpage";
import { colorVariables } from "../../../../../resources/theme/color.globals";
import { navigate } from "../../../../../common/navigate";
import { colorVariables } from "../../../../../resources/theme/color/color.globals";
import type { HomeAssistant, Route } from "../../../../../types";
import { bluetoothAdvertisementMonitorTabs } from "./bluetooth-advertisement-monitor";
import { relativeTime } from "../../../../../common/datetime/relative_time";
import { throttle } from "../../../../../common/util/throttle";
const UPDATE_THROTTLE_TIME = 10000;

View File

@ -1,26 +1,26 @@
import "@material/mwc-button";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { mdiRefresh } from "@mdi/js";
import type {
CallbackDataParams,
TopLevelFormatterParams,
} from "echarts/types/dist/shared";
import { mdiRefresh } from "@mdi/js";
import type { CSSResultGroup, PropertyValues } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { navigate } from "../../../../../common/navigate";
import "../../../../../components/chart/ha-network-graph";
import type {
NetworkData,
NetworkNode,
NetworkLink,
NetworkNode,
} from "../../../../../components/chart/ha-network-graph";
import type { ZHADevice } from "../../../../../data/zha";
import { fetchDevices, refreshTopology } from "../../../../../data/zha";
import "../../../../../layouts/hass-tabs-subpage";
import { colorVariables } from "../../../../../resources/theme/color/color.globals";
import type { HomeAssistant, Route } from "../../../../../types";
import { formatAsPaddedHex } from "./functions";
import { zhaTabs } from "./zha-config-dashboard";
import { colorVariables } from "../../../../../resources/theme/color.globals";
import { navigate } from "../../../../../common/navigate";
@customElement("zha-network-visualization-page")
export class ZHANetworkVisualizationPage extends LitElement {

View File

@ -1,33 +1,33 @@
import { customElement, property, state } from "lit/decorators";
import { css, html, LitElement } from "lit";
import memoizeOne from "memoize-one";
import type {
CallbackDataParams,
TopLevelFormatterParams,
} from "echarts/types/dist/shared";
import type { HomeAssistant, Route } from "../../../../../types";
import { configTabs } from "./zwave_js-config-router";
import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { navigate } from "../../../../../common/navigate";
import { debounce } from "../../../../../common/util/debounce";
import "../../../../../components/chart/ha-network-graph";
import type {
NetworkData,
NetworkLink,
NetworkNode,
} from "../../../../../components/chart/ha-network-graph";
import "../../../../../components/chart/ha-network-graph";
import "../../../../../layouts/hass-tabs-subpage";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import type {
ZWaveJSNodeStatisticsUpdatedMessage,
ZWaveJSNodeStatus,
} from "../../../../../data/zwave_js";
import {
fetchZwaveNetworkStatus,
NodeStatus,
subscribeZwaveNodeStatistics,
} from "../../../../../data/zwave_js";
import type {
ZWaveJSNodeStatisticsUpdatedMessage,
ZWaveJSNodeStatus,
} from "../../../../../data/zwave_js";
import { colorVariables } from "../../../../../resources/theme/color.globals";
import type { DeviceRegistryEntry } from "../../../../../data/device_registry";
import { debounce } from "../../../../../common/util/debounce";
import { navigate } from "../../../../../common/navigate";
import "../../../../../layouts/hass-tabs-subpage";
import { SubscribeMixin } from "../../../../../mixins/subscribe-mixin";
import { colorVariables } from "../../../../../resources/theme/color/color.globals";
import type { HomeAssistant, Route } from "../../../../../types";
import { configTabs } from "./zwave_js-config-router";
@customElement("zwave_js-network-visualization")
export class ZWaveJSNetworkVisualization extends SubscribeMixin(LitElement) {

View File

@ -3,6 +3,7 @@ import "@material/mwc-button/mwc-button";
import type { PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators";
import { normalizeLuminance } from "../../common/color/palette";
import { fireEvent } from "../../common/dom/fire_event";
import "../../components/ha-formfield";
import "../../components/ha-list-item";
@ -14,7 +15,7 @@ import "../../components/ha-textfield";
import {
DefaultAccentColor,
DefaultPrimaryColor,
} from "../../resources/theme/color.globals";
} from "../../resources/theme/color/color.globals";
import type { HomeAssistant } from "../../types";
import { documentationUrl } from "../../util/documentation-url";
@ -171,6 +172,12 @@ export class HaPickThemeRow extends LitElement {
private _handleColorChange(ev: CustomEvent) {
const target = ev.target as any;
// normalize primary color if needed for contrast
if (target.name === "primaryColor") {
target.value = normalizeLuminance(target.value);
}
fireEvent(this, "settheme", { [target.name]: target.value });
}

View File

@ -1,6 +1,6 @@
import { tsParticles } from "@tsparticles/engine";
import { loadLinksPreset } from "@tsparticles/preset-links";
import { DefaultPrimaryColor } from "./theme/color.globals";
import { DefaultPrimaryColor } from "./theme/color/color.globals";
loadLinksPreset(tsParticles).then(() => {
tsParticles.load({

View File

@ -1,21 +1,21 @@
import { css } from "lit";
import {
extractDerivedVars,
extractVar,
extractVars,
} from "../../common/style/derived-css-vars";
} from "../../../common/style/derived-css-vars";
import { coreColorVariables } from "./core.globals";
export const colorStyles = css`
html {
/* text */
--primary-text-color: #212121;
--secondary-text-color: #727272;
--primary-text-color: var(--color-text-primary);
--secondary-text-color: var(--color-text-secondary);
--text-primary-color: #ffffff;
--text-light-primary-color: #212121;
--disabled-text-color: #bdbdbd;
/* main interface colors */
--primary-color: #03a9f4;
--primary-color: var(--color-primary-40);
--dark-primary-color: #0288d1;
--light-primary-color: #b3e5fc;
--accent-color: #ff9800;
@ -24,7 +24,7 @@ export const colorStyles = css`
--outline-hover-color: rgba(0, 0, 0, 0.24);
/* rgb */
--rgb-primary-color: 3, 169, 244;
--rgb-primary-color: 0, 154, 199;
--rgb-accent-color: 255, 152, 0;
--rgb-primary-text-color: 33, 33, 33;
--rgb-secondary-text-color: 114, 114, 114;
@ -303,7 +303,7 @@ export const colorStyles = css`
}
`;
const darkColorStyles = css`
export const darkColorStyles = css`
html {
--primary-background-color: #111111;
--card-background-color: #1c1c1c;
@ -359,9 +359,11 @@ const darkColorStyles = css`
--disabled-color: #464646;
}
`;
export const colorDerivedVariables = extractDerivedVars(colorStyles);
export const colorVariables = extractVars(colorStyles);
export const darkColorVariables = extractVars(darkColorStyles);
export const DefaultPrimaryColor = extractVar(colorStyles, "primary-color");
export const DefaultPrimaryColor = extractVar(
colorStyles,
"primary-color",
coreColorVariables
);
export const DefaultAccentColor = extractVar(colorStyles, "accent-color");

View File

@ -0,0 +1,77 @@
import { css } from "lit";
import { extractVars } from "../../../common/style/derived-css-vars";
export const coreColorStyles = css`
html {
--white: #ffffff;
--black: #000000;
--transparent-none: rgba(255, 255, 255, 0);
/* primary */
--color-primary-05: #001721;
--color-primary-10: #002e3e;
--color-primary-20: #004156;
--color-primary-30: #006787;
--color-primary-40: #009ac7;
--color-primary-50: #18bcf2;
--color-primary-60: #37c8fd;
--color-primary-70: #7bd4fb;
--color-primary-80: #b9e6fc;
--color-primary-90: #b9e6fc;
--color-primary-95: #eff9fe;
/* neutral */
--color-neutral-05: #101219;
--color-neutral-10: #1b1d26;
--color-neutral-20: #2f323f;
--color-neutral-30: #424554;
--color-neutral-40: #545868;
--color-neutral-50: #717584;
--color-neutral-60: #9194a2;
--color-neutral-70: #abaeb9;
--color-neutral-80: #c7c9d0;
--color-neutral-90: #e4e5e9;
--color-neutral-95: #f1f2f3;
/* orange */
--color-orange-05: #280700;
--color-orange-10: #3b0f00;
--color-orange-20: #5e1c00;
--color-orange-30: #7e2900;
--color-orange-40: #9d3800;
--color-orange-50: #c94e00;
--color-orange-60: #f36d00;
--color-orange-70: #ff9342;
--color-orange-80: #ffbb89;
--color-orange-90: #ffe0c8;
--color-orange-95: #fff0e4;
/* red */
--color-red-05: #2a040b;
--color-red-10: #3e0913;
--color-red-20: #631323;
--color-red-30: #8a132c;
--color-red-40: #b30532;
--color-red-50: #dc3146;
--color-red-60: #f3676c;
--color-red-70: #fd8f90;
--color-red-80: #ffb8b6;
--color-red-90: #ffdedc;
--color-red-95: #fff0ef;
/* green */
--color-green-05: #031608;
--color-green-10: #052310;
--color-green-20: #0a3a1d;
--color-green-30: #0a5027;
--color-green-40: #036730;
--color-green-50: #00883c;
--color-green-60: #00ac49;
--color-green-70: #5dc36f;
--color-green-80: #93da98;
--color-green-90: #c2f2c1;
--color-green-95: #e3f9e3;
}
`;
export const coreColorVariables = extractVars(coreColorStyles);

View File

@ -0,0 +1,26 @@
import {
extractDerivedVars,
extractVars,
} from "../../../common/style/derived-css-vars";
import { colorStyles, darkColorStyles } from "./color.globals";
import { coreColorStyles } from "./core.globals";
import {
darkSemanticColorStyles,
semanticColorStyles,
} from "./semantic.globals";
export const darkColorVariables = {
...extractVars(darkColorStyles),
...extractVars(darkSemanticColorStyles),
};
export const colorDerivedVariables = {
...extractDerivedVars(colorStyles),
...extractDerivedVars(semanticColorStyles),
};
export const colorStylesCollection = [
coreColorStyles.toString(),
semanticColorStyles.toString(),
colorStyles.toString(),
];

View File

@ -0,0 +1,293 @@
import { css } from "lit";
export const semanticColorStyles = css`
html {
--color-overlay-modal: rgba(0, 0, 0, 0.25);
--color-focus: var(--color-orange-60);
/* surface */
--color-surface-lower: var(--color-neutral-90);
--color-surface-low: var(--color-neutral-95);
--color-surface-default: var(--white);
/* text */
--color-text-primary: var(--color-neutral-05);
--color-text-secondary: var(--color-neutral-40);
--color-text-disabled: var(--color-neutral-60);
--color-text-link: var(--color-primary-40);
/* border primary */
--color-border-quiet: var(--color-primary-80);
--color-border-normal: var(--color-primary-70);
--color-border-loud: var(--color-primary-40);
/* border neutral */
--color-border-neutral-quiet: var(--color-neutral-80);
--color-border-neutral-normal: var(--color-neutral-60);
--color-border-neutral-loud: var(--color-neutral-40);
/* border danger */
--color-border-danger-quiet: var(--color-red-80);
--color-border-danger-normal: var(--color-red-70);
--color-border-danger-loud: var(--color-red-40);
/* border warning */
--color-border-warning-quiet: var(--color-orange-80);
--color-border-warning-normal: var(--color-orange-70);
--color-border-warning-loud: var(--color-orange-40);
/* border success */
--color-border-success-quiet: var(--color-green-80);
--color-border-success-normal: var(--color-green-70);
--color-border-success-loud: var(--color-green-40);
/* fill primary quiet */
--color-fill-primary-quiet-resting: var(--color-primary-95);
--color-fill-primary-quiet-hover: var(--color-primary-90);
--color-fill-primary-quiet-active: var(--color-primary-95);
/* fill primary normal */
--color-fill-primary-normal-resting: var(--color-primary-90);
--color-fill-primary-normal-hover: var(--color-primary-80);
--color-fill-primary-normal-active: var(--color-primary-90);
/* fill primary loud */
--color-fill-primary-loud-resting: var(--color-primary-40);
--color-fill-primary-loud-hover: var(--color-primary-30);
--color-fill-primary-loud-active: var(--color-primary-40);
/* fill neutral quiet */
--color-fill-neutral-quiet-resting: var(--color-neutral-95);
--color-fill-neutral-quiet-hover: var(--color-neutral-90);
--color-fill-neutral-quiet-active: var(--color-neutral-95);
/* fill neutral normal */
--color-fill-neutral-normal-resting: var(--color-neutral-90);
--color-fill-neutral-normal-hover: var(--color-neutral-80);
--color-fill-neutral-normal-active: var(--color-neutral-90);
/* fill neutral loud */
--color-fill-neutral-loud-resting: var(--color-neutral-40);
--color-fill-neutral-loud-hover: var(--color-neutral-30);
--color-fill-neutral-loud-active: var(--color-neutral-40);
/* fill disabled quiet */
--color-fill-disabled-quiet-resting: var(--color-neutral-95);
/* fill disabled normal */
--color-fill-disabled-normal-resting: var(--color-neutral-95);
/* fill disabled loud */
--color-fill-disabled-loud-resting: var(--color-neutral-80);
/* fill danger quiet */
--color-fill-danger-quiet-resting: var(--color-red-95);
--color-fill-danger-quiet-hover: var(--color-red-90);
--color-fill-danger-quiet-active: var(--color-red-95);
/* fill danger normal */
--color-fill-danger-normal-resting: var(--color-red-90);
--color-fill-danger-normal-hover: var(--color-red-80);
--color-fill-danger-normal-active: var(--color-red-90);
/* fill danger loud */
--color-fill-danger-loud-resting: var(--color-red-50);
--color-fill-danger-loud-hover: var(--color-red-40);
--color-fill-danger-loud-active: var(--color-red-50);
/* fill warning quiet */
--color-fill-warning-quiet-resting: var(--color-orange-95);
--color-fill-warning-quiet-hover: var(--color-orange-90);
--color-fill-warning-quiet-active: var(--color-orange-95);
/* fill warning normal */
--color-fill-warning-normal-resting: var(--color-orange-90);
--color-fill-warning-normal-hover: var(--color-orange-80);
--color-fill-warning-normal-active: var(--color-orange-90);
/* fill warning loud */
--color-fill-warning-loud-resting: var(--color-orange-70);
--color-fill-warning-loud-hover: var(--color-orange-50);
--color-fill-warning-loud-active: var(--color-orange-70);
/* fill success quiet */
--color-fill-success-quiet-resting: var(--color-green-95);
--color-fill-success-quiet-hover: var(--color-green-90);
--color-fill-success-quiet-active: var(--color-green-95);
/* fill success normal */
--color-fill-success-normal-resting: var(--color-green-90);
--color-fill-success-normal-hover: var(--color-green-80);
--color-fill-success-normal-active: var(--color-green-90);
/* fill success loud */
--color-fill-success-loud-resting: var(--color-green-50);
--color-fill-success-loud-hover: var(--color-green-40);
--color-fill-success-loud-active: var(--color-green-50);
/* on primary */
--color-on-primary-quiet: var(--color-primary-50);
--color-on-primary-normal: var(--color-primary-40);
--color-on-primary-loud: var(--white);
/* on neutral */
--color-on-neutral-quiet: var(--color-neutral-50);
--color-on-neutral-normal: var(--color-neutral-40);
--color-on-neutral-loud: var(--white);
/* on disabled */
--color-on-disabled-quiet: var(--color-neutral-80);
--color-on-disabled-normal: var(--color-neutral-70);
--color-on-disabled-loud: var(--color-neutral-95);
/* on danger */
--color-on-danger-quiet: var(--color-red-50);
--color-on-danger-normal: var(--color-red-40);
--color-on-danger-loud: var(--white);
/* on warning */
--color-on-warning-quiet: var(--color-orange-50);
--color-on-warning-normal: var(--color-orange-40);
--color-on-warning-loud: var(--white);
/* on success */
--color-on-success-quiet: var(--color-green-50);
--color-on-success-normal: var(--color-green-40);
--color-on-success-loud: var(--white);
/* logo */
--color-logo-primary: var(--color-primary-50);
}
`;
export const darkSemanticColorStyles = css`
html {
/* surface */
--color-surface-lower: var(--black);
--color-surface-low: var(--color-neutral-05);
--color-surface-default: var(--color-neutral-10);
/* text */
--color-text-primary: var(--white);
--color-text-secondary: var(--color-neutral-80);
--color-text-link: var(--color-primary-60);
/* border primary */
--color-border-normal: var(--color-primary-50);
/* border neutral */
--color-border-neutral-quiet: var(--color-neutral-40);
--color-border-neutral-normal: var(--color-neutral-50);
--color-border-neutral-loud: var(--color-neutral-70);
/* border danger */
--color-border-danger-normal: var(--color-red-50);
--color-border-danger-loud: var(--color-red-50);
/* border warning */
--color-border-warning-normal: var(--color-orange-50);
--color-border-warning-loud: var(--color-orange-50);
/* fill primary quiet */
--color-fill-primary-quiet-resting: var(--color-primary-05);
--color-fill-primary-quiet-hover: var(--color-primary-10);
--color-fill-primary-quiet-active: var(--color-primary-05);
/* fill primary normal */
--color-fill-primary-normal-resting: var(--color-primary-10);
--color-fill-primary-normal-hover: var(--color-primary-20);
--color-fill-primary-normal-active: var(--color-primary-10);
/* fill neutral quiet */
--color-fill-neutral-quiet-resting: var(--color-neutral-05);
--color-fill-neutral-quiet-hover: var(--color-neutral-10);
--color-fill-neutral-quiet-active: var(--color-neutral-00);
/* fill neutral normal */
--color-fill-neutral-normal-resting: var(--color-neutral-10);
--color-fill-neutral-normal-hover: var(--color-neutral-20);
--color-fill-neutral-normal-active: var(--color-neutral-10);
/* fill disabled quiet */
--color-fill-disabled-quiet-resting: var(--color-neutral-10);
/* fill disabled normal */
--color-fill-disabled-normal-resting: var(--color-neutral-20);
/* fill disabled loud */
--color-fill-disabled-loud-resting: var(--color-neutral-30);
/* fill danger quiet */
--color-fill-danger-quiet-resting: var(--color-red-05);
--color-fill-danger-quiet-hover: var(--color-red-10);
--color-fill-danger-quiet-active: var(--color-red-05);
/* fill danger normal */
--color-fill-danger-normal-resting: var(--color-red-10);
--color-fill-danger-normal-hover: var(--color-red-20);
--color-fill-danger-normal-active: var(--color-red-10);
/* fill danger loud */
--color-fill-danger-loud-resting: var(--color-red-40);
--color-fill-danger-loud-hover: var(--color-red-30);
--color-fill-danger-loud-active: var(--color-red-40);
/* fill warning quiet */
--color-fill-warning-quiet-resting: var(--color-orange-05);
--color-fill-warning-quiet-hover: var(--color-orange-10);
--color-fill-warning-quiet-active: var(--color-orange-05);
/* fill warning normal */
--color-fill-warning-normal-resting: var(--color-orange-10);
--color-fill-warning-normal-hover: var(--color-orange-20);
--color-fill-warning-normal-active: var(--color-orange-10);
/* fill warning loud */
--color-fill-warning-loud-resting: var(--color-orange-40);
--color-fill-warning-loud-hover: var(--color-orange-30);
--color-fill-warning-loud-active: var(--color-orange-40);
/* fill success quiet */
--color-fill-success-quiet-resting: var(--color-green-05);
--color-fill-success-quiet-hover: var(--color-green-10);
--color-fill-success-quiet-active: var(--color-green-05);
/* fill success normal */
--color-fill-success-normal-resting: var(--color-green-10);
--color-fill-success-normal-hover: var(--color-green-20);
--color-fill-success-normal-active: var(--color-green-10);
/* fill success loud */
--color-fill-success-loud-resting: var(--color-green-40);
--color-fill-success-loud-hover: var(--color-green-30);
--color-fill-success-loud-active: var(--color-green-40);
/* on primary */
--color-on-primary-quiet: var(--color-primary-70);
--color-on-primary-normal: var(--color-primary-80);
/* on neutral */
--color-on-neutral-quiet: var(--color-neutral-70);
--color-on-neutral-normal: var(--color-neutral-60);
--color-on-neutral-loud: var(--white);
/* on disabled */
--color-on-disabled-quiet: var(--color-neutral-40);
--color-on-disabled-normal: var(--color-neutral-50);
--color-on-disabled-loud: var(--color-neutral-50);
/* on danger */
--color-on-danger-quiet: var(--color-red-70);
--color-on-danger-normal: var(--color-red-60);
--color-on-danger-loud: var(--white);
/* on warning */
--color-on-warning-quiet: var(--color-orange-70);
--color-on-warning-normal: var(--color-orange-60);
--color-on-warning-loud: var(--white);
/* on success */
--color-on-success-quiet: var(--color-green-70);
--color-on-success-normal: var(--color-green-60);
--color-on-success-loud: var(--white);
}
`;

View File

@ -1,5 +1,5 @@
import { fontStyles } from "../roboto";
import { colorDerivedVariables, colorStyles } from "./color.globals";
import { colorDerivedVariables, colorStylesCollection } from "./color";
import { mainDerivedVariables, mainStyles } from "./main.globals";
import {
typographyDerivedVariables,
@ -9,7 +9,7 @@ import {
export const themeStyles = [
mainStyles.toString(),
typographyStyles.toString(),
colorStyles.toString(),
...colorStylesCollection,
fontStyles.toString(),
].join("");

View File

@ -4474,6 +4474,13 @@ __metadata:
languageName: node
linkType: hard
"@types/culori@npm:4":
version: 4.0.0
resolution: "@types/culori@npm:4.0.0"
checksum: 10/62a9058d6125fe489ca1e7df27ac9837ea7a34c772b8bed8e5e00177b141574830efaa0c93363e9532878490d3245a9c9c8183ebee181a450097584af0cfefc1
languageName: node
linkType: hard
"@types/deep-eql@npm:*":
version: 4.0.2
resolution: "@types/deep-eql@npm:4.0.2"
@ -7040,6 +7047,13 @@ __metadata:
languageName: node
linkType: hard
"culori@npm:4.0.2":
version: 4.0.2
resolution: "culori@npm:4.0.2"
checksum: 10/9d297ca5c6fc86b2637200e1d9edb5a7d1015a2e978a6748781ef53c9577269ce1df96dc0925b0002239c85665ba881a3d580564dfd2807c65ee65dc2e829849
languageName: node
linkType: hard
"data-urls@npm:^5.0.0":
version: 5.0.0
resolution: "data-urls@npm:5.0.0"
@ -9388,6 +9402,7 @@ __metadata:
"@types/chromecast-caf-receiver": "npm:6.0.22"
"@types/chromecast-caf-sender": "npm:1.0.11"
"@types/color-name": "npm:2.0.0"
"@types/culori": "npm:4"
"@types/html-minifier-terser": "npm:7.0.2"
"@types/js-yaml": "npm:4.0.9"
"@types/leaflet": "npm:1.9.20"
@ -9417,6 +9432,7 @@ __metadata:
comlink: "npm:4.4.2"
core-js: "npm:3.44.0"
cropperjs: "npm:1.6.2"
culori: "npm:4.0.2"
date-fns: "npm:4.1.0"
date-fns-tz: "npm:3.2.0"
deep-clone-simple: "npm:1.1.1"