wordmark_ink: an SVG wordmark drawn in the page's own ink, following light and dark everywhere
Test / test (pull_request) Successful in 1m8s

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
This commit is contained in:
Bendik Aagaard Lynghaug
2026-10-01 09:33:27 +02:00
co-authored by Claude Opus 5.5
parent c8901558b2
commit 8376c68f8f
5 changed files with 50 additions and 4 deletions
+4
View File
@@ -4,6 +4,10 @@ One line per change, grouped by the release that shipped it. Newest
first. A release is a Cargo.toml bump plus a `v<version>` tag; the first. A release is a Cargo.toml bump plus a `v<version>` tag; the
content repos pin the tag they run (see the end of this file). content repos pin the tag they run (see the end of this file).
## 0.6.11 (2026-10-01)
- `wordmark_ink: true` in `site.yaml`: an SVG wordmark is drawn in the page's own ink, as a mask over the text colour, so it follows the page's light and dark in every browser. A wordmark shown as an `<img>` only knows the system's setting, and some browsers don't pass even that on. Opacity in the file still shows, so a lighter line stays lighter. Opt-in, for one-colour marks; a mark with a colour of its own keeps its colours.
## 0.6.10 (2026-09-30) ## 0.6.10 (2026-09-30)
- Trainer: who a business is gets a page of its own ("who are we?", `/hvem` in Norwegian), with nothing to do on it. It has one card per need that `presents` (the people, the work, each shown as picture cards) and one for the plan's `values`. The front door leads there instead of carrying it all. - Trainer: who a business is gets a page of its own ("who are we?", `/hvem` in Norwegian), with nothing to do on it. It has one card per need that `presents` (the people, the work, each shown as picture cards) and one for the plan's `values`. The front door leads there instead of carrying it all.
+1
View File
@@ -24,6 +24,7 @@ on every hot reload, and in CI through `iris check`.
```yaml ```yaml
title: Vestmark kommune # the browser title and the header title: Vestmark kommune # the browser title and the header
wordmark: /site/logo.svg # an image instead of the title wordmark: /site/logo.svg # an image instead of the title
wordmark_ink: true # a one-colour SVG mark drawn in the page's own ink
wordmark_invert: true # flip it in dark mode wordmark_invert: true # flip it in dark mode
wordmark_height: 2.4 # rem wordmark_height: 2.4 # rem
lang: no # the interface language: en or no lang: no # the interface language: en or no
+20 -1
View File
@@ -973,10 +973,29 @@ fn Hero(
} }
}); });
let has_slides = slideshow.is_some(); let has_slides = slideshow.is_some();
let mark = move || view! { // In the page's ink (`wordmark_ink`): a span the file masks, sized
// by the file's own proportions through an invisible copy of it,
// and named for screen readers as the image would have been.
let ink = site.wordmark_ink;
let mark = move || {
if ink {
let mask = format!("--wordmark-src:url(\"{}\")", wordmark.replace('"', "%22"));
view! {
<a class="wordmark wordmark-ink" href="/" aria-label=site_title.clone()>
<span class="wordmark-ink-mark" style=mask>
<img src=wordmark.clone() alt="" aria-hidden="true" style=wordmark_style.clone()/>
</span>
</a>
}
.into_any()
} else {
view! {
<a class="wordmark" class:wordmark-house=house_wordmark href="/"> <a class="wordmark" class:wordmark-house=house_wordmark href="/">
<img src=wordmark.clone() alt=site_title.clone() style=wordmark_style.clone()/> <img src=wordmark.clone() alt=site_title.clone() style=wordmark_style.clone()/>
</a> </a>
}
.into_any()
}
}; };
view! { view! {
+8
View File
@@ -767,6 +767,14 @@ pub struct SiteConfig {
/// intrinsic pixel height. /// intrinsic pixel height.
#[serde(default)] #[serde(default)]
pub wordmark_height: Option<f32>, pub wordmark_height: Option<f32>,
/// Draw an SVG wordmark in the page's own ink instead of its own
/// colours: the file becomes a mask over the text colour, so it
/// follows the page's light and dark (and any theme a site adds),
/// where an `<img>` only ever knows the system's. Opacity in the
/// file still shows, so a lighter line stays lighter. For a
/// one-colour mark; a mark with a colour of its own keeps `false`.
#[serde(default)]
pub wordmark_ink: bool,
/// BCP 47-ish language code for the portal's own chrome strings /// BCP 47-ish language code for the portal's own chrome strings
/// ("Asked by", the nav lead...) and the html lang attribute. /// ("Asked by", the nav lead...) and the html lang attribute.
/// `None` means "en"; unknown codes fall back to English per key. /// `None` means "en"; unknown codes fall back to English per key.
+14
View File
@@ -244,6 +244,20 @@ main.not-found {
display: block; display: block;
} }
/* A wordmark in the page's ink (site.yaml `wordmark_ink`): the file is a
mask over the text colour. The invisible image inside gives the span
the file's own size. */
.wordmark-ink-mark {
display: block;
background: var(--ink);
-webkit-mask: var(--wordmark-src) center / contain no-repeat;
mask: var(--wordmark-src) center / contain no-repeat;
}
.wordmark-ink-mark img {
visibility: hidden;
}
.hero-copy h1 { .hero-copy h1 {
font-size: 2.1rem; font-size: 2.1rem;
} }