Skip to content

Conversation

kirchoni
Copy link
Contributor

Proof of concept: https://stackblitz.com/edit/react-rv7ukhhw?file=app%2Fstyles.css

Add automatic color generation for native css

Introduces CSS-only automatic color generation using modern oklch() and color-mix() functions for dynamic runtime color calculations.

Distributed through the core package, where i suggest we expose a separate css file which can be imported. Nested in a utils folder:

import "@progress/kendo-theme-core/dist/utils/auto-colors.css";

Problem

Developers currently need to manually define all color variations or use build-time Sass functions that generate static values.

Proposal

New k-colors-auto mixin generates CSS formulas that automatically calculate color variations at runtime:

Usage

JavaScript:

import "@progress/kendo-theme-bootstrap/dist/all.css";
import "@progress/kendo-theme-core/dist/utils/auto-colors.css"; // <- this is the new thing

CSS:

:root {
  --kendo-color-primary: #9c27b0; 
}

Generated CSS:

    --kendo-color-primary: #9c27b0; 
    --kendo-color-primary-hover: oklch(from var(--kendo-color-primary) calc(l * var(--hover-lightness-factor)) calc(c * var(--hover-chroma-factor)) h);
    --kendo-color-primary-active: oklch(from var(--kendo-color-primary) calc(l * var(--active-lightness-factor)) calc(c * var(--active-chroma-factor)) h);
    --kendo-color-primary-subtle: 
 color-mix(in oklch, var(--kendo-color-primary) var(--subtle-mix-percent), white calc(100% - var(--subtle-mix-percent)));
    --kendo-color-primary-subtle-hover: 
 color-mix(in oklch, var(--kendo-color-primary) 12%, white 88%);
    --kendo-color-primary-subtle-active: 
 color-mix(in oklch, var(--kendo-color-primary) 20%, white 80%);
    --kendo-color-primary-emphasis: 
 color-mix(in oklch, var(--kendo-color-primary) var(--emphasis-mix-percent), white calc(100% - var(--emphasis-mix-percent)));
    --kendo-color-on-primary: oklch(from var(--kendo-color-primary) var(--contrast-l) var(--chroma-factor) h);
    --kendo-color-primary-on-surface: var(--kendo-color-primary);
    --kendo-color-primary-on-subtle: oklch(from var(--kendo-color-primary-subtle) calc(clamp(0, (l / var(--l-threshold) - 1) * -9999, 1) * 0.78 + 0.22) var(--chroma-factor) h);

Calculations

@mixin k-colors-auto() {
    :root {
        --l-threshold: 0.7;
        --contrast-l: calc(clamp(0, (l / var(--l-threshold) - 1) * -9999, 1) * 0.78 + 0.22);
        --chroma-factor: 0;
        --hover-lightness-factor: 0.92;
        --active-lightness-factor: 0.84;

        --hover-chroma-factor: 0.92;
        --active-chroma-factor: 0.83;

        --subtle-mix-percent: 8%;
        --emphasis-mix-percent: 70%;

        /* COLOR FAMILIES */
        @each $color in base, primary, secondary, tertiary, info, success, warning, error, light, dark {
            /* #{string.to-upper-case($color)} COLOR FAMILY */
            --kendo-color-#{$color}-hover: oklch(from var(--kendo-color-#{$color}) calc(l * var(--hover-lightness-factor)) calc(c * var(--hover-chroma-factor)) h);
            --kendo-color-#{$color}-active: oklch(from var(--kendo-color-#{$color}) calc(l * var(--active-lightness-factor)) calc(c * var(--active-chroma-factor)) h);
            --kendo-color-#{$color}-subtle: color-mix(in oklch, var(--kendo-color-#{$color}) var(--subtle-mix-percent), white calc(100% - var(--subtle-mix-percent)));
            --kendo-color-#{$color}-subtle-hover: color-mix(in oklch, var(--kendo-color-#{$color}) 12%, white 88%);
            --kendo-color-#{$color}-subtle-active: color-mix(in oklch, var(--kendo-color-#{$color}) 20%, white 80%);
            --kendo-color-#{$color}-emphasis: color-mix(in oklch, var(--kendo-color-#{$color}) var(--emphasis-mix-percent), white calc(100% - var(--emphasis-mix-percent)));
            --kendo-color-on-#{$color}: oklch(from var(--kendo-color-#{$color}) var(--contrast-l) var(--chroma-factor) h);
            --kendo-color-#{$color}-on-surface: var(--kendo-color-#{$color});
            --kendo-color-#{$color}-on-subtle: oklch(from var(--kendo-color-#{$color}-subtle) calc(clamp(0, (l / var(--l-threshold) - 1) * -9999, 1) * 0.78 + 0.22) var(--chroma-factor) h);
        }

        /* SERIES COLOR FAMILIES */
        @each $series in a, b, c, d, e, f {
            --kendo-color-series-#{$series}-bold: oklch(from var(--kendo-color-series-#{$series}) calc(l * 0.75) calc(c * var(--active-chroma-factor)) h);
            --kendo-color-series-#{$series}-bolder: oklch(from var(--kendo-color-series-#{$series}) calc(l * 0.5) calc(c * 0.6) h);
            --kendo-color-series-#{$series}-subtle: color-mix(in oklch, var(--kendo-color-series-#{$series}) 30%, white 70%);
            --kendo-color-series-#{$series}-subtler: color-mix(in oklch, var(--kendo-color-series-#{$series}) 50%, white 50%);
        }
    }
}

@kirchoni kirchoni requested a review from a team as a code owner July 22, 2025 12:47
Copy link

github-actions bot commented Jul 22, 2025

Packages Report

core default classic bootstrap material fluent utils
Size 29.15 KB (0.0%) 783.64 KB (0.0%) 783.65 KB (0.0%) 795.71 KB (0.0%) 929.21 KB (0.0%) 1155.10 KB (0.0%) 625.19 KB (0.0%)
Gzip Size 4.85 KB (0.0%) 101.18 KB (0.0%) 101.46 KB (0.0%) 103.68 KB (0.0%) 114.61 KB (0.0%) 136.77 KB (0.0%) 52.16 KB (0.0%)
Compile Time 1 s (0.0%) 4 s (0.0%) 4 s (0.0%) 3 s (0.0%) 4 s (0.0%) 5 s (0.0%) 4 s (0.0%)

@kirchoni kirchoni marked this pull request as draft July 22, 2025 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant