hozen: add new color system

This commit is contained in:
ooks-io 2024-11-08 16:35:01 +11:00
parent 723bf4d367
commit 11bd9a3671
6 changed files with 332 additions and 373 deletions

View file

@ -3,17 +3,14 @@
types,
translate,
}: let
# base modification function
# Base modification functions
modifyHSL = hexStr: modifications: let
# convert hex to HSL
hslSet = translate.hex.toHSL.set hexStr;
# apply modifications to get new HSL values
newHSL = types.hsl.set {
inherit (hslSet) h; # keep hue
inherit (hslSet) h;
l = math.clamp 0.0 1.0 (hslSet.l + (modifications.l or 0.0));
s = math.clamp 0.0 1.0 (hslSet.s + (modifications.s or 0.0));
};
# convert back to hex
rgbSet = translate.hsl.toRGB.set newHSL;
in
translate.rgb.toHex.string rgbSet;
@ -30,6 +27,8 @@
desaturate = amount: hexStr:
modifyHSL hexStr {s = (amount * -1) / 100.0;};
# opinionated scale generators for light/dark themes
# lighter/darker shades always desaturate
mkDarkColorScale = base: {
up4 = desaturate 24 (lighten 12 base);
up3 = desaturate 18 (lighten 9 base);
@ -54,10 +53,11 @@
up4 = desaturate 24 (darken 12 base);
};
mkDarkColorScheme = {
shades,
# core color scheme generator
mkColorScheme = {
type ? "dark",
neutrals ? {},
primary,
secondary,
red,
orange,
yellow,
@ -69,54 +69,252 @@
purple,
pink,
brown,
} @ args: {
shade-50 = args.shades."50";
shade-100 = args.shades."100";
shade-150 = args.shades."150";
shade-200 = args.shades."200";
shade-250 = args.shades."250";
shade-300 = args.shades."300";
shade-350 = args.shades."350";
shade-400 = args.shades."400";
shade-450 = args.shades."450";
shade-500 = args.shades."500";
shade-550 = args.shades."550";
shade-600 = args.shades."600";
shade-650 = args.shades."650";
shade-700 = args.shades."700";
shade-750 = args.shades."750";
shade-800 = args.shades."800";
shade-850 = args.shades."850";
shade-900 = args.shades."900";
} @ args: let
# Select scale function based on theme type
colorScale =
if type == "dark"
then mkDarkColorScale
else mkLightColorScale;
primary = mkDarkColorScale args.primary;
secondary = {
up-1 = args.shade."550";
up-2 = args.shade."500";
up-3 = args.shade."450";
up-4 = args.shade."400";
up-5 = args.shade."350";
up-6 = args.shade."300";
up-7 = args.shade."250";
up-8 = args.shade."200";
up-9 = args.shade."150";
up-10 = args.shade."100";
base = args.shade."700";
down-1 = args.shade."650";
down-2 = args.shade."700";
# Generate color scales
colorScales = {
red = colorScale args.red;
orange = colorScale args.orange;
yellow = colorScale args.yellow;
olive = colorScale args.olive;
green = colorScale args.green;
teal = colorScale args.teal;
blue = colorScale args.blue;
violet = colorScale args.violet;
purple = colorScale args.purple;
pink = colorScale args.pink;
brown = colorScale args.brown;
};
red = mkDarkColorScale args.red;
orange = mkDarkColorScale args.orange;
yellow = mkDarkColorScale args.yellow;
olive = mkDarkColorScale args.olive;
green = mkDarkColorScale args.green;
teal = mkDarkColorScale args.teal;
blue = mkDarkColorScale args.blue;
violet = mkDarkColorScale args.violet;
purple = mkDarkColorScale args.purple;
pink = mkDarkColorScale args.pink;
brown = mkDarkColorScale args.brown;
# Theme-specific configurations
themeConfig =
if type == "dark"
then {
semantic = {
body = args.neutrals."700";
header = args.neutrals."800";
footer = args.neutrals."800";
menu = args.neutrals."800";
border = args.neutrals."150";
border-active = args.neutrals."150";
border-inactive = args.neutrals."600";
text = args.neutrals."150";
text-bright = args.neutrals."100";
subtext = args.neutrals."300";
};
secondary = {
up-4 = args.neutrals."400";
up-3 = args.neutrals."450";
up-2 = args.neutrals."500";
up-1 = args.neutrals."550";
base = args.neutrals."700";
down-1 = args.neutrals."750";
down-2 = args.neutrals."800";
down-3 = args.neutrals."850";
down-4 = args.neutrals."900";
};
base00 = args.neutrals."800";
base01 = args.neutrals."700";
base02 = args.neutrals."600";
base03 = args.neutrals."450";
base04 = args.neutrals."300";
base05 = args.neutrals."150";
base06 = args.neutrals."100";
base07 = args.neutrals."50";
base10 = args.neutrals."850";
base11 = args.neutrals."900";
}
else {
semantic = {
body = args.neutrals."50";
header = args.neutrals."150";
footer = args.neutrals."150";
menu = args.neutrals."150";
border = args.neutrals."800";
border-active = args.neutrals."800";
border-inactive = args.neutrals."300";
text = args.neutrals."800";
text-bright = args.neutrals."850";
subtext = args.neutrals."600";
};
secondary = {
up-4 = args.neutrals."400";
up-3 = args.neutrals."350";
up-2 = args.neutrals."300";
up-1 = args.neutrals."250";
base = args.neutrals."200";
down-1 = args.neutrals."150";
down-2 = args.neutrals."100";
down-3 = args.neutrals."50";
down-4 = args.neutrals."50";
};
base00 = args.neutrals."150";
base01 = args.neutrals."250";
base02 = args.neutrals."450";
base03 = args.neutrals."550";
base04 = args.neutrals."650";
base05 = args.neutrals."800";
base06 = args.neutrals."850";
base07 = args.neutrals."900";
base10 = args.neutrals."100";
base11 = args.neutrals."50";
};
in {
# Common structure for both themes
neutrals = {
inherit
(args.neutrals)
"50"
"100"
"150"
"200"
"250"
"300"
"350"
"400"
"450"
"500"
"550"
"600"
"650"
"700"
"750"
"800"
"850"
"900"
;
};
inherit
(colorScales)
red
orange
yellow
olive
green
teal
blue
violet
purple
pink
brown
;
primary = colorScale args.primary;
inherit (themeConfig) semantic secondary;
# Status colors (same structure for both themes)
error = {
bg = "${colorScales.red.base}";
bg-active = "${colorScales.red.down1}";
bg-hover = "${colorScales.red.down2}";
text = "${themeConfig.semantic.text-bright}";
border = "${colorScales.red.up2}";
};
success = {
bg = "${colorScales.green.base}";
bg-active = "${colorScales.green.down1}";
bg-hover = "${colorScales.green.down2}";
text = "${themeConfig.semantic.text-bright}";
border = "${colorScales.green.up2}";
};
warning = {
bg = "${colorScales.yellow.base}";
bg-active = "${colorScales.yellow.down1}";
bg-hover = "${colorScales.yellow.down2}";
text = "${themeConfig.semantic.text-bright}";
border = "${colorScales.yellow.up2}";
};
info = {
bg = "${colorScales.blue.base}";
bg-active = "${colorScales.blue.down1}";
bg-hover = "${colorScales.blue.down2}";
text = "${themeConfig.semantic.text-bright}";
border = "${colorScales.blue.up2}";
};
tip = {
bg = "${colorScales.teal.base}";
bg-active = "${colorScales.teal.down1}";
bg-hover = "${colorScales.teal.down2}";
text = "${themeConfig.semantic.text-bright}";
border = "${colorScales.teal.up2}";
};
# Syntax highlighting (same for both themes)
syntax = {
string = args.green;
number = args.purple;
float = args.purple;
boolean = args.purple;
type = args.yellow;
structure = args.orange;
statement = args.red;
label = args.orange;
operator = args.orange;
identifier = args.blue;
function = args.green;
storageClass = args.orange;
constant = args.teal;
exception = args.red;
preproc = args.purple;
include = args.purple;
define = args.purple;
macro = args.teal;
preCondit = args.purple;
special = args.yellow;
specialChar = args.yellow;
comment = "${themeConfig.semantic.subtext}";
todo = args.purple;
tag = args.teal;
};
# Base16/24 colors
inherit
(themeConfig)
base00
base01
base02
base03
base04
base05
base06
base07
base10
base11
;
# Generated base colors
base08 = args.red;
base09 = args.orange;
base0A = args.yellow;
base0B = args.green;
base0C = args.teal;
base0D = args.blue;
base0E = args.purple;
base0F = args.brown;
base12 = "${colorScales.red.up2}";
base13 = "${colorScales.yellow.up2}";
base14 = "${colorScales.green.up2}";
base15 = "${colorScales.teal.up2}";
base16 = "${colorScales.blue.up2}";
base17 = "${colorScales.purple.up2}";
};
# wrappers
mkDarkColorScheme = args: mkColorScheme (args // {type = "dark";});
mkLightColorScheme = args: mkColorScheme (args // {type = "light";});
in {
inherit lighten darken saturate desaturate mkLightColorScale mkDarkColorScale mkDarkColorScheme;
inherit lighten darken saturate desaturate;
inherit mkDarkColorScale mkLightColorScale;
inherit mkColorScheme mkDarkColorScheme mkLightColorScheme;
}