Automatic contrast color picking (fixes #43)

This commit is contained in:
daudix
2024-12-23 22:48:34 +03:00
parent b4734dd6e1
commit 08860f5974
8 changed files with 25 additions and 98 deletions

View File

@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix build failing if social sharing button is enabled and page is missing a description (#114). - Fix build failing if social sharing button is enabled and page is missing a description (#114).
### Removed
- **[BREAKING]** Remove `fix_contrast` and `fix_contrast_dark` config/page/section variables in favor of automatic contrast color picking (#43).
## [v6.1.1](https://codeberg.org/daudix/duckquill/compare/v6.1.0...v6.1.1) ## [v6.1.1](https://codeberg.org/daudix/duckquill/compare/v6.1.0...v6.1.1)
### Fixed ### Fixed

View File

@ -99,13 +99,6 @@ accent_color = "#ff7800"
# Ditto but for the dark theme. # Ditto but for the dark theme.
# If not set regular variant will be used. # If not set regular variant will be used.
accent_color_dark = "#ffa348" accent_color_dark = "#ffa348"
# Whether to fix low contrast in text selection, checkboxes, etc.
# Use only if the default doesn't provide enough contrast, e.g. the accent color is set to yellow.
#
# fix_contrast = true
#
# Ditto but for the dark theme.
fix_contrast_dark = true
# Whether to use fonts bundled with Duckquill instead of system ones. # Whether to use fonts bundled with Duckquill instead of system ones.
# Keep in mind that it also changes the style of headings. # Keep in mind that it also changes the style of headings.
# #

View File

@ -102,8 +102,6 @@ Configuration variables from `config.toml` that can be set/overriden per page/se
- `default_theme`: Which theme should be used by default (light/dark). - `default_theme`: Which theme should be used by default (light/dark).
- `accent_color`: Sets theme and [browser theme](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color) color. - `accent_color`: Sets theme and [browser theme](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta/name/theme-color) color.
- `accent_color_dark`: Ditto but for the dark theme. If not set regular variant will be used. - `accent_color_dark`: Ditto but for the dark theme. If not set regular variant will be used.
- `fix_contrast`: Whether to fix low contrast in text selection, checkboxes, etc. Use only if the default doesn't provide enough contrast, e.g. the accent color is set to yellow.
- `fix_contrast_dark`: Ditto but for the dark theme.
- `emoji_favicon`: Use emoji as a favicon. Only one emoji is being rendered, everything else is truncated. - `emoji_favicon`: Use emoji as a favicon. Only one emoji is being rendered, everything else is truncated.
- `styles`: Additional CSS styles; expects them to be in the `./static/` directory. If you are using Sass it will be generated there automatically. - `styles`: Additional CSS styles; expects them to be in the `./static/` directory. If you are using Sass it will be generated there automatically.
- `scripts`: Additional JavaScript scripts; expects them to be in the `./static/` directory. - `scripts`: Additional JavaScript scripts; expects them to be in the `./static/` directory.

View File

@ -14,16 +14,6 @@
padding: 0.5rem; padding: 0.5rem;
} }
#color-picker-container:hover {
transform: none;
}
#color-picker-container label {
margin-inline-end: 0.25rem;
color: var(--fg-muted-4);
font-weight: bold;
}
:root[dir*="rtl"] #color-picker-container { :root[dir*="rtl"] #color-picker-container {
transform: translateX(calc(100% - 1rem)); transform: translateX(calc(100% - 1rem));
} }
@ -32,9 +22,22 @@
transform: none; transform: none;
} }
#color-picker-container:hover {
transform: none;
}
#color-picker-container > small {
display: block;
margin-block-end: 0.5rem;
font-weight: bold;
}
#color-picker-container label {
margin-inline-end: 0.25rem;
color: var(--fg-muted-5);
}
#color-picker-light, #color-picker-light,
#color-picker-dark, #color-picker-dark {
#contrast-color-light,
#contrast-color-dark {
margin-inline-end: 0.25rem; margin-inline-end: 0.25rem;
} }

View File

@ -10,16 +10,12 @@ slider.oninput = function() {
// Spaceship control center // Spaceship control center
const colorPickerLight = document.querySelector("#color-picker-light"); const colorPickerLight = document.querySelector("#color-picker-light");
const colorPickerDark = document.querySelector("#color-picker-dark"); const colorPickerDark = document.querySelector("#color-picker-dark");
const contrastCheckboxLight = document.querySelector("#contrast-color-light");
const contrastCheckboxDark = document.querySelector("#contrast-color-dark");
let accentColorLight = colorPickerLight.value; let accentColorLight = colorPickerLight.value;
let accentColorDark = colorPickerDark.value; let accentColorDark = colorPickerDark.value;
colorPickerLight.addEventListener("input", updateAccentColorLight); colorPickerLight.addEventListener("input", updateAccentColorLight);
colorPickerDark.addEventListener("input", updateAccentColorDark); colorPickerDark.addEventListener("input", updateAccentColorDark);
contrastCheckboxLight.addEventListener("change", updateStyles);
contrastCheckboxDark.addEventListener("change", updateStyles);
function updateAccentColorLight() { function updateAccentColorLight() {
accentColorLight = colorPickerLight.value; accentColorLight = colorPickerLight.value;
@ -32,9 +28,6 @@ function updateAccentColorDark() {
} }
function updateStyles() { function updateStyles() {
const contrastColorLight = contrastCheckboxLight.checked;
const contrastColorDark = contrastCheckboxDark.checked;
let styleElement = document.getElementById("dynamic-styles"); let styleElement = document.getElementById("dynamic-styles");
if (!styleElement) { if (!styleElement) {
@ -57,44 +50,6 @@ function updateStyles() {
} }
`; `;
if (contrastColorLight) {
styles += `
:root {
--contrast-color: rgb(0 0 0 / 0.8);
}
`;
} else {
styles += `
:root {
--contrast-color: #fff;
}
`;
}
if (contrastColorDark) {
styles += `
[data-theme="dark"] {
--contrast-color: rgb(0 0 0 / 0.8);
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--contrast-color: rgb(0 0 0 / 0.8);
}
}
`;
} else {
styles += `
[data-theme="dark"] {
--contrast-color: #fff;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--contrast-color: #fff;
}
}
`;
}
styleElement.textContent = styles; styleElement.textContent = styles;
} }

View File

@ -667,19 +667,10 @@ With `centered` and `big` classes:
<!-- For the demo purposes only --> <!-- For the demo purposes only -->
<div id="color-picker-container"> <div id="color-picker-container">
<small>Accent color:</small> <small>Accent color:</small>
<br />
<input id="color-picker-light" type="color" value="#ff7800" /> <input id="color-picker-light" type="color" value="#ff7800" />
<label for="color-picker-light">Light theme</label> <label for="color-picker-light">Light theme</label>
<br /> <br />
<input id="color-picker-dark" type="color" value="#ffa348" /> <input id="color-picker-dark" type="color" value="#ffa348" />
<label for="color-picker-dark">Dark theme</label> <label for="color-picker-dark">Dark theme</label>
<br />
<small>Fix contrast:</small>
<br />
<input id="contrast-color-light" class="switch" type="checkbox" />
<label for="contrast-color-light">Light theme</label>
<br />
<input id="contrast-color-dark" class="switch" type="checkbox" checked />
<label for="contrast-color-dark">Dark theme</label>
</div> </div>
<!-- End --> <!-- End -->

View File

@ -63,6 +63,11 @@
--yellow-bg: rgb(from var(--yellow-fg) r g b / var(--color-opacity)); --yellow-bg: rgb(from var(--yellow-fg) r g b / var(--color-opacity));
--yellow-fg: rgb(156 110 3); --yellow-fg: rgb(156 110 3);
// CONTRAST COLOR
--l: clamp(0, (l / 0.623 - 1) * -infinity, 1);
--a: calc(var(--l) + (var(--dim-opacity) * (1 - var(--l))));
--contrast-color: oklch(from var(--accent-color) var(--l) 0 h / var(--a));
// CONTAINERS // CONTAINERS
--container-width: 720px; --container-width: 720px;

View File

@ -7,16 +7,6 @@
{%- else -%} {%- else -%}
--accent-color: {{ config.extra.accent_color | default(value="#6f8396") | safe }}; --accent-color: {{ config.extra.accent_color | default(value="#6f8396") | safe }};
{%- endif -%} {%- endif -%}
{%- if page.extra.fix_contrast -%}
--contrast-color: rgb(0 0 0 / 0.8);
{%- elif section.extra.fix_contrast -%}
--contrast-color: rgb(0 0 0 / 0.8);
{%- elif config.extra.fix_contrast -%}
--contrast-color: rgb(0 0 0 / 0.8);
{%- else -%}
--contrast-color: #fff;
{%- endif -%}
} }
{%- if page.extra.accent_color_dark -%} {%- if page.extra.accent_color_dark -%}
@ -51,18 +41,6 @@
} }
{%- endif -%} {%- endif -%}
{%- if page.extra.fix_contrast_dark or section.extra.fix_contrast_dark or config.extra.fix_contrast_dark -%}
[data-theme="dark"] {
--contrast-color: rgb(0 0 0 / 0.8);
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--contrast-color: rgb(0 0 0 / 0.8);
}
}
{%- endif -%}
{%- if config.extra.debug.layout -%} {%- if config.extra.debug.layout -%}
*, *,
*::before, *::before,