Skip to content

Commit d8b8ac1

Browse files
authored
feat: oklch colors (#1486)
1 parent 0537273 commit d8b8ac1

File tree

7 files changed

+117
-125
lines changed

7 files changed

+117
-125
lines changed

src/unfold/settings.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,30 @@
1818
"SHOW_BACK_BUTTON": False,
1919
"COLORS": {
2020
"base": {
21-
"50": "249, 250, 251",
22-
"100": "243, 244, 246",
23-
"200": "229, 231, 235",
24-
"300": "209, 213, 219",
25-
"400": "156, 163, 175",
26-
"500": "107, 114, 128",
27-
"600": "75, 85, 99",
28-
"700": "55, 65, 81",
29-
"800": "31, 41, 55",
30-
"900": "17, 24, 39",
31-
"950": "3, 7, 18",
21+
"50": "oklch(98.5% .002 247.839)",
22+
"100": "oklch(96.7% .003 264.542)",
23+
"200": "oklch(92.8% .006 264.531)",
24+
"300": "oklch(87.2% .01 258.338)",
25+
"400": "oklch(70.7% .022 261.325)",
26+
"500": "oklch(55.1% .027 264.364)",
27+
"600": "oklch(44.6% .03 256.802)",
28+
"700": "oklch(37.3% .034 259.733)",
29+
"800": "oklch(27.8% .033 256.848)",
30+
"900": "oklch(21% .034 264.665)",
31+
"950": "oklch(13% .028 261.692)",
3232
},
3333
"primary": {
34-
"50": "250, 245, 255",
35-
"100": "243, 232, 255",
36-
"200": "233, 213, 255",
37-
"300": "216, 180, 254",
38-
"400": "192, 132, 252",
39-
"500": "168, 85, 247",
40-
"600": "147, 51, 234",
41-
"700": "126, 34, 206",
42-
"800": "107, 33, 168",
43-
"900": "88, 28, 135",
44-
"950": "59, 7, 100",
34+
"50": "oklch(97.7% .014 308.299)",
35+
"100": "oklch(94.6% .033 307.174)",
36+
"200": "oklch(90.2% .063 306.703)",
37+
"300": "oklch(82.7% .119 306.383)",
38+
"400": "oklch(71.4% .203 305.504)",
39+
"500": "oklch(62.7% .265 303.9)",
40+
"600": "oklch(55.8% .288 302.321)",
41+
"700": "oklch(49.6% .265 301.924)",
42+
"800": "oklch(43.8% .218 303.724)",
43+
"900": "oklch(38.1% .176 304.987)",
44+
"950": "oklch(29.1% .149 302.717)",
4545
},
4646
"font": {
4747
"subtle-light": "var(--color-base-500)", # text-base-500

src/unfold/sites.py

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def login_not_required(func: Callable) -> Callable:
2525

2626

2727
from unfold.settings import get_config
28-
from unfold.utils import hex_to_rgb
28+
from unfold.utils import convert_color
2929
from unfold.widgets import (
3030
BUTTON_CLASSES,
3131
CHECKBOX_CLASSES,
@@ -538,33 +538,12 @@ def _get_theme_images(
538538
def _get_colors(self, key: str, *args) -> dict[str, dict[str, str]]:
539539
colors = self._get_config(key, *args)
540540

541-
def rgb_to_values(value: str) -> str:
542-
return ", ".join(
543-
list(
544-
map(
545-
str.strip,
546-
value.removeprefix("rgb(").removesuffix(")").split(","),
547-
)
548-
)
549-
)
550-
551-
def hex_to_values(value: str) -> str:
552-
return ", ".join(str(item) for item in hex_to_rgb(value))
553-
554541
for name, weights in colors.items():
555542
weights = self._get_value(weights, *args)
556543
colors[name] = weights
557544

558545
for weight, value in weights.items():
559-
if value[0] == "#":
560-
colors[name][weight] = hex_to_values(value)
561-
elif value.startswith("rgb"):
562-
colors[name][weight] = rgb_to_values(value)
563-
elif isinstance(value, str) and all(
564-
part.isdigit() for part in value.split()
565-
):
566-
colors[name][weight] = ", ".join(value.split(" "))
567-
pass
546+
colors[name][weight] = convert_color(value)
568547

569548
return colors
570549

src/unfold/static/unfold/css/styles.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/unfold/static/unfold/js/app.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -464,9 +464,7 @@ const renderCharts = () => {
464464
.getPropertyValue("--color-base-300")
465465
.trim();
466466

467-
const borderColor = hasDarkClass
468-
? `rgb(${baseColorDark})`
469-
: `rgb(${baseColorLight})`;
467+
const borderColor = hasDarkClass ? baseColorDark : baseColorLight;
470468

471469
for (const chart of charts) {
472470
chart.options.scales.x.grid.color = borderColor;
@@ -495,7 +493,7 @@ const renderCharts = () => {
495493
const color = getComputedStyle(document.documentElement)
496494
.getPropertyValue(cssVar)
497495
.trim();
498-
dataset[colorProp] = `rgb(${color})`;
496+
dataset[colorProp] = color;
499497
}
500498
};
501499

src/unfold/styles.css

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -35,43 +35,43 @@
3535

3636
@theme {
3737
--font-sans: 'Inter', sans-serif;
38-
--shadow-raised: 0 2px 12px rgb(var(--color-base-300));
39-
--shadow-raised-dark: 0 2px 12px rgb(var(--color-base-700));
38+
--shadow-raised: 0 2px 12px var(--color-base-300);
39+
--shadow-raised-dark: 0 2px 12px var(--color-base-700);
4040
}
4141

4242
@theme inline{
4343
--radius-default: var(--border-radius, 6px);
4444

45-
--color-primary-50: rgb(var(--color-primary-50));
46-
--color-primary-100: rgb(var(--color-primary-100));
47-
--color-primary-200: rgb(var(--color-primary-200));
48-
--color-primary-300: rgb(var(--color-primary-300));
49-
--color-primary-400: rgb(var(--color-primary-400));
50-
--color-primary-500: rgb(var(--color-primary-500));
51-
--color-primary-600: rgb(var(--color-primary-600));
52-
--color-primary-700: rgb(var(--color-primary-700));
53-
--color-primary-800: rgb(var(--color-primary-800));
54-
--color-primary-900: rgb(var(--color-primary-900));
55-
--color-primary-950: rgb(var(--color-primary-950));
56-
57-
--color-base-50: rgb(var(--color-base-50));
58-
--color-base-100: rgb(var(--color-base-100));
59-
--color-base-200: rgb(var(--color-base-200));
60-
--color-base-300: rgb(var(--color-base-300));
61-
--color-base-400: rgb(var(--color-base-400));
62-
--color-base-500: rgb(var(--color-base-500));
63-
--color-base-600: rgb(var(--color-base-600));
64-
--color-base-700: rgb(var(--color-base-700));
65-
--color-base-800: rgb(var(--color-base-800));
66-
--color-base-900: rgb(var(--color-base-900));
67-
--color-base-950: rgb(var(--color-base-950));
68-
69-
--color-font-subtle-light: rgb(var(--color-font-subtle-light));
70-
--color-font-subtle-dark: rgb(var(--color-font-subtle-dark));
71-
--color-font-default-light: rgb(var(--color-font-default-light));
72-
--color-font-default-dark: rgb(var(--color-font-default-dark));
73-
--color-font-important-light: rgb(var(--color-font-important-light));
74-
--color-font-important-dark: rgb(var(--color-font-important-dark));
45+
--color-primary-50: var(--color-primary-50);
46+
--color-primary-100: var(--color-primary-100);
47+
--color-primary-200: var(--color-primary-200);
48+
--color-primary-300: var(--color-primary-300);
49+
--color-primary-400: var(--color-primary-400);
50+
--color-primary-500: var(--color-primary-500);
51+
--color-primary-600: var(--color-primary-600);
52+
--color-primary-700: var(--color-primary-700);
53+
--color-primary-800: var(--color-primary-800);
54+
--color-primary-900: var(--color-primary-900);
55+
--color-primary-950: var(--color-primary-950);
56+
57+
--color-base-50: var(--color-base-50);
58+
--color-base-100: var(--color-base-100);
59+
--color-base-200: var(--color-base-200);
60+
--color-base-300: var(--color-base-300);
61+
--color-base-400: var(--color-base-400);
62+
--color-base-500: var(--color-base-500);
63+
--color-base-600: var(--color-base-600);
64+
--color-base-700: var(--color-base-700);
65+
--color-base-800: var(--color-base-800);
66+
--color-base-900: var(--color-base-900);
67+
--color-base-950: var(--color-base-950);
68+
69+
--color-font-subtle-light: var(--color-font-subtle-light);
70+
--color-font-subtle-dark: var(--color-font-subtle-dark);
71+
--color-font-default-light: var(--color-font-default-light);
72+
--color-font-default-dark: var(--color-font-default-dark);
73+
--color-font-important-light: var(--color-font-important-light);
74+
--color-font-important-dark: var(--color-font-important-dark);
7575
}
7676

7777
@utility field-sizing-content {

src/unfold/utils.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -140,16 +140,6 @@ def display_for_field(value: Any, field: Any, empty_value_display: str) -> str:
140140
return display_for_value(value, empty_value_display)
141141

142142

143-
def hex_to_rgb(hex_color: str) -> list[int]:
144-
hex_color = hex_color.lstrip("#")
145-
146-
r = int(hex_color[0:2], 16)
147-
g = int(hex_color[2:4], 16)
148-
b = int(hex_color[4:6], 16)
149-
150-
return (r, g, b)
151-
152-
153143
def prettify_json(data: Any, encoder: Any) -> Optional[str]:
154144
try:
155145
from pygments import highlight
@@ -189,3 +179,28 @@ def parse_datetime_str(value: str) -> Optional[datetime.datetime]:
189179
return datetime.datetime.strptime(value, format)
190180
except (ValueError, TypeError):
191181
continue
182+
183+
184+
def hex_to_rgb(hex_color: str) -> list[int]:
185+
hex_color = hex_color.lstrip("#")
186+
187+
r = int(hex_color[0:2], 16)
188+
g = int(hex_color[2:4], 16)
189+
b = int(hex_color[4:6], 16)
190+
191+
return (r, g, b)
192+
193+
194+
def hex_to_values(value: str) -> str:
195+
return ", ".join(str(item) for item in hex_to_rgb(value))
196+
197+
198+
def convert_color(value: str) -> str:
199+
if value[0] == "#":
200+
return f"rgb({hex_to_values(value)})"
201+
elif value.startswith("rgb") or value.startswith("oklch"):
202+
return value
203+
elif isinstance(value, str) and all(part.isdigit() for part in value.split()):
204+
return f"rgb({', '.join(value.split(' '))})"
205+
206+
return value

tests/test_colors.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ def test_colors_hex_to_rgb():
3737
assert "colors" in context
3838
assert "primary" in context["colors"]
3939

40-
assert context["colors"]["primary"][50] == "240, 249, 255"
41-
assert context["colors"]["primary"][100] == "224, 242, 254"
42-
assert context["colors"]["primary"][200] == "186, 230, 253"
43-
assert context["colors"]["primary"][300] == "125, 211, 252"
44-
assert context["colors"]["primary"][400] == "56, 189, 248"
45-
assert context["colors"]["primary"][500] == "14, 165, 233"
46-
assert context["colors"]["primary"][600] == "2, 132, 199"
47-
assert context["colors"]["primary"][700] == "3, 105, 161"
48-
assert context["colors"]["primary"][800] == "7, 89, 133"
49-
assert context["colors"]["primary"][900] == "12, 74, 110"
50-
assert context["colors"]["primary"][950] == "8, 47, 73"
40+
assert context["colors"]["primary"][50] == "rgb(240, 249, 255)"
41+
assert context["colors"]["primary"][100] == "rgb(224, 242, 254)"
42+
assert context["colors"]["primary"][200] == "rgb(186, 230, 253)"
43+
assert context["colors"]["primary"][300] == "rgb(125, 211, 252)"
44+
assert context["colors"]["primary"][400] == "rgb(56, 189, 248)"
45+
assert context["colors"]["primary"][500] == "rgb(14, 165, 233)"
46+
assert context["colors"]["primary"][600] == "rgb(2, 132, 199)"
47+
assert context["colors"]["primary"][700] == "rgb(3, 105, 161)"
48+
assert context["colors"]["primary"][800] == "rgb(7, 89, 133)"
49+
assert context["colors"]["primary"][900] == "rgb(12, 74, 110)"
50+
assert context["colors"]["primary"][950] == "rgb(8, 47, 73)"
5151

5252

5353
@override_settings(
@@ -80,17 +80,17 @@ def test_colors_rgb():
8080
assert "colors" in context
8181
assert "primary" in context["colors"]
8282

83-
assert context["colors"]["primary"][50] == "240, 249, 255"
84-
assert context["colors"]["primary"][100] == "224, 242, 254"
85-
assert context["colors"]["primary"][200] == "186, 230, 253"
86-
assert context["colors"]["primary"][300] == "125, 211, 252"
87-
assert context["colors"]["primary"][400] == "56, 189, 248"
88-
assert context["colors"]["primary"][500] == "14, 165, 233"
89-
assert context["colors"]["primary"][600] == "2, 132, 199"
90-
assert context["colors"]["primary"][700] == "3, 105, 161"
91-
assert context["colors"]["primary"][800] == "7, 89, 133"
92-
assert context["colors"]["primary"][900] == "12, 74, 110"
93-
assert context["colors"]["primary"][950] == "8, 47, 73"
83+
assert context["colors"]["primary"][50] == "rgb(240, 249, 255)"
84+
assert context["colors"]["primary"][100] == "rgb(224, 242, 254)"
85+
assert context["colors"]["primary"][200] == "rgb(186, 230, 253)"
86+
assert context["colors"]["primary"][300] == "rgb(125, 211, 252)"
87+
assert context["colors"]["primary"][400] == "rgb(56, 189, 248)"
88+
assert context["colors"]["primary"][500] == "rgb(14, 165, 233)"
89+
assert context["colors"]["primary"][600] == "rgb(2, 132, 199)"
90+
assert context["colors"]["primary"][700] == "rgb(3, 105, 161)"
91+
assert context["colors"]["primary"][800] == "rgb(7, 89, 133)"
92+
assert context["colors"]["primary"][900] == "rgb(12, 74, 110)"
93+
assert context["colors"]["primary"][950] == "rgb(8, 47, 73)"
9494

9595

9696
@override_settings(
@@ -123,14 +123,14 @@ def test_colors_full_rgb_conversion():
123123
assert "colors" in context
124124
assert "primary" in context["colors"]
125125

126-
assert context["colors"]["primary"][50] == "240, 249, 255"
127-
assert context["colors"]["primary"][100] == "224, 242, 254"
128-
assert context["colors"]["primary"][200] == "186, 230, 253"
129-
assert context["colors"]["primary"][300] == "125, 211, 252"
130-
assert context["colors"]["primary"][400] == "56, 189, 248"
131-
assert context["colors"]["primary"][500] == "14, 165, 233"
132-
assert context["colors"]["primary"][600] == "2, 132, 199"
133-
assert context["colors"]["primary"][700] == "3, 105, 161"
134-
assert context["colors"]["primary"][800] == "7, 89, 133"
135-
assert context["colors"]["primary"][900] == "12, 74, 110"
136-
assert context["colors"]["primary"][950] == "8, 47, 73"
126+
assert context["colors"]["primary"][50] == "rgb(240, 249, 255)"
127+
assert context["colors"]["primary"][100] == "rgb(224, 242, 254)"
128+
assert context["colors"]["primary"][200] == "rgb(186, 230, 253)"
129+
assert context["colors"]["primary"][300] == "rgb(125, 211, 252)"
130+
assert context["colors"]["primary"][400] == "rgb(56, 189, 248)"
131+
assert context["colors"]["primary"][500] == "rgb(14, 165, 233)"
132+
assert context["colors"]["primary"][600] == "rgb(2, 132, 199)"
133+
assert context["colors"]["primary"][700] == "rgb(3, 105, 161)"
134+
assert context["colors"]["primary"][800] == "rgb(7, 89, 133)"
135+
assert context["colors"]["primary"][900] == "rgb(12, 74, 110)"
136+
assert context["colors"]["primary"][950] == "rgb(8, 47, 73)"

0 commit comments

Comments
 (0)