From 3ee471bf39af17089f0e50d24d42f7e1316499e8 Mon Sep 17 00:00:00 2001 From: jasa Date: Wed, 23 Sep 2026 15:32:24 +0200 Subject: [PATCH] page component and filter pilles added --- README.md | 38 +++++++++---- src/demo/demo.scss | 87 +++++++--------------------- src/index.html | 50 ++++++++++++++-- src/sass/abstracts/_palette.scss | 1 + src/sass/abstracts/_tokens.scss | 4 ++ src/sass/components/_filter.scss | 93 ++++++++++++++++++++++++++++++ src/sass/components/_index.scss | 1 + src/sass/layout/_index.scss | 1 + src/sass/layout/_page.scss | 98 ++++++++++++++++++++++++++++++++ src/sass/main.scss | 2 + 10 files changed, 293 insertions(+), 82 deletions(-) create mode 100644 src/sass/components/_filter.scss create mode 100644 src/sass/layout/_index.scss create mode 100644 src/sass/layout/_page.scss diff --git a/README.md b/README.md index 7ba2552..f122c18 100644 --- a/README.md +++ b/README.md @@ -53,14 +53,14 @@ The toolbar has three controls: - **Show boxes** — outlines each component so the structure is visible. - A live viewport width and the active breakpoint. -The wood and the scroll are **demo chrome**, in `src/demo/demo.scss`, not in the -stylesheet: page layout is still on the to-do list below, and a demo is not the -place to quietly ship it. The demo is not a build input, so none of it can reach -`dist/tlig.css` — the build is checked for exactly that. +What remains demo-only, in `src/demo/demo.scss`, is the toolbar, the swatch +grid, the section scaffolding, and four `:root` declarations pointing the +frame's image tokens at this project's local mirror. The demo is not a build +input, so none of it can reach `dist/tlig.css` — the build is checked for +exactly that. -The frame is there anyway because a foundation only tells the truth on the -ground it has to work on. Brown ink at 86% looks arbitrary on white and -obviously right on papyrus. +A foundation only tells the truth on the ground it has to work on. Brown ink at +86% looks arbitrary on white and obviously right on papyrus. ## Layout @@ -76,8 +76,10 @@ obviously right on papyrus. _reset.scss _typography.scss _links.scss + layout/ + _page.scss the wood ground and the papyrus scroll components/ - _button.scss _field.scss _footer.scss + _button.scss _field.scss _filter.scss _footer.scss src/fonts/ papyrus-bold (4 scripts) and Lato, self-hosted src/demo/ demo page chrome and behaviour — never built src/index.html the demo page @@ -142,10 +144,26 @@ so the bundle resolves at whatever path it is dropped. Lato is self-hosted from the three files already in the child theme, replacing the 33 `@font-face` blocks Avada generates from its Google Fonts cache. +## The page frame + +`layout/_page.scss` carries the wood ground and the three-piece papyrus scroll. +Two things it does differently from the live CSS: + +- **The image URLs are custom properties.** Swapping the set at a breakpoint is + four declarations, where the live CSS duplicates six rules per breakpoint — + and again under `html.webp` and `html.no-webp`, for a browser that no longer + exists. A demo or a staging copy re-points the tokens instead of editing the + stylesheet. +- **The overlaps are measured, not guessed.** The foot image's top 18px ramp + from alpha 15 to its 242 plateau; butt it against the body and that fade + composites over bare wood, which reads as a hard line at the body's edge. The + overlap is `-20px`: the ramp plus a little. It has to be a margin — the + element is static, and `top` only moves a positioned box. + ## Not done yet -- Page-level layout: header, nav, the wood and papyrus backgrounds, `#main` +- Header and nav - Message typography (`.tbody`, `.vassula`, `.jc`, `.god`, the bible-reference asides) -- Menus, bookstore, search, testimonies, downloads +- Bookstore, search, testimonies, downloads - Enqueuing the built CSS from the theme, and retiring `tlig_en.css` diff --git a/src/demo/demo.scss b/src/demo/demo.scss index 77e6faf..4c59282 100644 --- a/src/demo/demo.scss +++ b/src/demo/demo.scss @@ -1,73 +1,36 @@ // ----------------------------------------------------------------------------- // Demo chrome — NOT part of the shipped stylesheet. // -// Everything here exists to frame the foundation in something that looks like -// the real site (wood ground, papyrus scroll) and to give the page its toolbar -// and swatch grid. It is reached only from src/index.html, which is not a build -// input, so none of it can reach dist/tlig.css. +// What is left here is only the page's own chrome: the toolbar, the swatch +// grid, the section scaffolding, and the four image URLs pointed at this +// project's local mirror. The scroll frame itself graduated into the +// stylesheet (`layout/_page.scss`). // -// The scroll frame is deliberately here and not in components/: page layout is -// still on the "not done" list, and a demo is not the place to quietly ship it. +// Reached only from src/index.html, which is not a build input, so none of it +// can reach dist/tlig.css. // ----------------------------------------------------------------------------- @use '../sass/abstracts' as *; $img: '/wp-content/includes/images'; -// -- The page ground --------------------------------------------------------- - -html { - background: url('#{$img}/background_planche_1920.jpg') top center / contain fixed; +// The scroll frame is a real component now (`layout/_page.scss`). All the demo +// does is point its four image tokens at the local mirror in `site/`, which is +// exactly the re-pointing the component was built to allow. +:root { + --tlig-ground: url('#{$img}/background_planche_1920.jpg'); + --tlig-scroll-head: url('#{$img}/page/background-message-entete_cnd.png.webp'); + --tlig-scroll-body: url('#{$img}/page/background-message-milieux1200x190-4_cnd.png.webp'); + --tlig-scroll-foot: url('#{$img}/page/background-message-footer-1200x114_cnd.png.webp'); } body { min-height: 100vh; } -// The scroll: a head image, a vertically repeating middle, a foot image. -.scroll { - max-width: 1200px; - margin-inline: auto; -} - -.scroll__head, -.scroll__foot { - background-repeat: no-repeat; - background-size: 100% 100%; -} - -.scroll__head { - height: 140px; - background-image: url('#{$img}/page/background-message-entete_cnd.png.webp'); - background-position: bottom; -} - -.scroll__body { - margin-block-start: -1px; - padding: 0 clamp(#{space-raw('md')}, 5vw, 5rem) space('xl'); - background: url('#{$img}/page/background-message-milieux1200x190-4_cnd.png.webp') repeat-y top / 100% auto; -} - -.scroll__foot { - // The top 18px of this image ramp from alpha 15 up to its 242 plateau — it - // fades in. Butted against the body, that ramp composites over bare wood and - // reads as a hard line at the body's bottom edge. The overlap below is the - // measured ramp height plus a little, so the whole fade lands on papyrus. - // - // `top` cannot do this: the element is static, and only a positioned box - // moves. `position`/`z-index` pin the paint order the effect depends on — - // tree order already gives it, but silently. - position: relative; - z-index: 1; - margin-block-start: -20px; - height: 114px; - background-image: url('#{$img}/page/background-message-footer-1200x114_cnd.png.webp'); - background-position: top; -} - -// Below the tablet breakpoint the site swaps in narrower scroll images, which -// are not mirrored into this project. Rather than stretch the wide ones, the -// demo falls back to a plain parchment panel. +// Only the wide cuts are mirrored into this project. Rather than stretch them, +// the demo drops the frame below the tablet breakpoint and falls back to a +// plain parchment panel. The real component swaps in the narrow cuts instead. @include down('tablet') { .scroll__head, .scroll__foot { display: none; } @@ -223,19 +186,11 @@ body { &__spacer { flex: 1; } - button { - padding: 3px 10px; - border: 1px solid rgba(240, 230, 210, 0.3); - border-radius: radius('pill'); - background: transparent; + // The toolbar's buttons are the real `.filter` component — the same pills the + // page uses. Nothing here restyles them; the dark ground is enough, because + // the pill takes its border from `currentColor`. + .filter { color: inherit; - font-size: 12px; - - &[aria-pressed='true'] { - background: #f0e6d2; - color: #1e0e0e; - border-color: #f0e6d2; - } } code { diff --git a/src/index.html b/src/index.html index 29e1817..3688879 100644 --- a/src/index.html +++ b/src/index.html @@ -13,16 +13,16 @@ Script: - - - - - + + + + + - + @@ -137,6 +137,40 @@ class with modifiers replaces them.

+ +
+

Filter pills

+ +
+ Theme: + + + + + + +
+ +
+ Year: + + + + +
+ +

The toggle behind the message archives, the photo and + video galleries, the theme taxonomy and the year accordions. The live CSS + spells it three times — .filters-tags-frame, + .cptButtonFilter, and a bare .active that fills + whatever it lands on with rgba(145,116,85,.5) and white text. + One class with a pressed state covers all three.

+

The border is currentColor at 55%, not a + fixed brown. That is why the identical pills in the toolbar above work on + a dark ground with no second rule — the same component, inheriting a + different text colour.

+
+

Context re-points tokens

@@ -148,6 +182,10 @@ button below are all correct as a result. No dark-specific rule for any of them exists in the stylesheet.

A button, unchanged

+
+ + +

This is the mechanism that replaces the footer's 24 id selectors: a region declares what its tokens mean, and every diff --git a/src/sass/abstracts/_palette.scss b/src/sass/abstracts/_palette.scss index 355f98f..f9a6824 100644 --- a/src/sass/abstracts/_palette.scss +++ b/src/sass/abstracts/_palette.scss @@ -57,6 +57,7 @@ $sand-100: #fcf8e3; // values are what ships today and a rounding difference would be a visible // change dressed up as a refactor. $ink-86a: rgba(72, 32, 32, 0.86); // body text +$ink-55a: rgba(72, 32, 32, 0.55); // #4820208c — filter borders $ink-50a: rgba(72, 32, 32, 0.5); $wood-50a: rgba(145, 116, 85, 0.5); $wood-20a: rgba(145, 116, 85, 0.2); diff --git a/src/sass/abstracts/_tokens.scss b/src/sass/abstracts/_tokens.scss index 2c22de3..50a0881 100644 --- a/src/sass/abstracts/_tokens.scss +++ b/src/sass/abstracts/_tokens.scss @@ -49,6 +49,10 @@ $colors: ( 'button-donate-bg': $gold-700, 'button-donate-ink': $white, + // Filters — the pill toggles used across archives, galleries and the topbar + 'filter-fill': $wood-50a, // hover and selected + 'filter-ink-active': $white, + // Forms 'field-bg': $brown-300, 'field-ink': $white, diff --git a/src/sass/components/_filter.scss b/src/sass/components/_filter.scss new file mode 100644 index 0000000..ee34435 --- /dev/null +++ b/src/sass/components/_filter.scss @@ -0,0 +1,93 @@ +// ----------------------------------------------------------------------------- +// Filter pills. +// +// The toggle used wherever a list can be narrowed: message archives, the photo +// and video galleries, the theme taxonomy, the year and month accordions. The +// live CSS spells the same thing three times — `.filters-tags-frame`, +// `.cptButtonFilter` and a bare `.active` that fills anything it lands on with +// `rgba(145,116,85,0.5)` and white text. One class with a pressed state covers +// all three. +// +// The border is `currentColor` at 55%, not a fixed brown. That is what lets the +// same pill work on the papyrus page and on a dark ground without a second +// rule: re-point the text colour and the border follows. +// ----------------------------------------------------------------------------- + +@use '../abstracts' as *; + +.filter { + display: inline-flex; + align-items: center; + gap: space('2xs'); + margin: 0 space('xs') space('xs') 0; + padding: space('2xs') space('sm'); + border: 2px solid color-mix(in srgb, currentColor 55%, transparent); + border-radius: radius('sm'); + background-color: transparent; + color: color('page-ink-strong'); + font-family: font('body'); + font-size: 16px; + font-weight: weight('bold'); + line-height: 1.4; + letter-spacing: 1.5px; + text-align: center; + text-decoration: none; + cursor: pointer; + transition: background-color 120ms ease-in-out, color 120ms ease-in-out; + + &:hover, + &:focus-visible { + background-color: color('filter-fill'); + color: color('filter-ink-active'); + } + + // Pressed. `aria-pressed` is the accessible form and is what the styling + // hangs off; `.is-active` exists for markup that cannot carry the attribute. + &[aria-pressed='true'], + &.is-active { + background-color: color('filter-fill'); + color: color('filter-ink-active'); + border-color: transparent; + } + + &[disabled] { + opacity: 0.45; + cursor: not-allowed; + } + + // Compact, for a toolbar or a dense filter bar. + &--sm { + padding: space('3xs') space('xs'); + font-size: 12px; + letter-spacing: 1px; + } + + // Fully rounded, for tag-style filters. + &--pill { + border-radius: radius('pill'); + } +} + +// A row of them. Replaces `.filters-box` and `.cptFilters`. +.filter-bar { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: space('2xs'); + padding: 0; + list-style: none; + + // The pills carry their own right/bottom margin for markup that is not a + // flex container; inside the bar the gap does the work instead. + .filter { + margin: 0; + } +} + +.filter-bar__label { + margin-inline-end: space('xs'); + font-family: font('body'); + font-size: 16px; + font-weight: weight('bold'); + letter-spacing: 1.5px; +} diff --git a/src/sass/components/_index.scss b/src/sass/components/_index.scss index ffa3061..6bf0ba8 100644 --- a/src/sass/components/_index.scss +++ b/src/sass/components/_index.scss @@ -1,3 +1,4 @@ @forward 'button'; @forward 'field'; +@forward 'filter'; @forward 'footer'; diff --git a/src/sass/layout/_index.scss b/src/sass/layout/_index.scss new file mode 100644 index 0000000..e181bc3 --- /dev/null +++ b/src/sass/layout/_index.scss @@ -0,0 +1 @@ +@forward 'page'; diff --git a/src/sass/layout/_page.scss b/src/sass/layout/_page.scss new file mode 100644 index 0000000..966ef81 --- /dev/null +++ b/src/sass/layout/_page.scss @@ -0,0 +1,98 @@ +// ----------------------------------------------------------------------------- +// The page: wood ground, and the papyrus scroll the content sits on. +// +// Three stacked pieces — a head image, a vertically repeating middle, a foot +// image — which is how the live site builds it. What is different here: +// +// * The image URLs are custom properties, not literals. Swapping the set for +// a breakpoint is four declarations in one place instead of six rules +// duplicated per breakpoint, and a demo or a staging copy can re-point them +// without touching the stylesheet. +// * The live CSS states every rule twice, once under `html.webp` and once +// under `html.no-webp`. Every browser that runs this today decodes WebP, so +// there is one set. +// * The overlaps are derived from the images rather than guessed — see the +// note on `__foot`. +// ----------------------------------------------------------------------------- + +@use '../abstracts' as *; + +// Where WordPress serves these from. A project that mirrors the assets +// elsewhere overrides the custom properties below rather than this variable. +$uploads: '/wp-content/uploads' !default; + +:root { + --#{$prefix}-ground: url('#{$uploads}/2019/03/background_planche_1920-3_cnd.jpg'); + --#{$prefix}-scroll-head: url('#{$uploads}/2018/10/background-message-entete_cnd.png.webp'); + --#{$prefix}-scroll-body: url('#{$uploads}/2018/10/background-message-milieux1200x190-4_cnd.png.webp'); + --#{$prefix}-scroll-foot: url('#{$uploads}/2018/11/background-message-footer-1200x114_cnd.png.webp'); +} + +// The narrower cuts. Same four names, different files. +@include down('tablet') { + :root { + --#{$prefix}-ground: url('#{$uploads}/2019/09/background_planche_800x1300.jpg'); + --#{$prefix}-scroll-head: url('#{$uploads}/2018/11/background-message-entete750x140_cnd.png.webp'); + --#{$prefix}-scroll-body: url('#{$uploads}/2018/11/background-message-milieux750x190_cnd.png.webp'); + --#{$prefix}-scroll-foot: url('#{$uploads}/2018/11/background-message-footer-6_cnd.png.webp'); + } +} + +@include down('phone') { + :root { + --#{$prefix}-ground: url('#{$uploads}/2019/09/background_planche_600x1000.jpg'); + --#{$prefix}-scroll-head: url('#{$uploads}/2018/11/background-message-entete360x140-2_cnd.png.webp'); + --#{$prefix}-scroll-body: url('#{$uploads}/2018/11/background-message-milieux360x190_cnd.png.webp'); + --#{$prefix}-scroll-foot: url('#{$uploads}/2018/11/background-message-footer-360x114-3_cnd.png.webp'); + } +} + +// -- The wood ground --------------------------------------------------------- + +html { + background: var(--#{$prefix}-ground) top center / contain fixed; +} + +// -- The scroll -------------------------------------------------------------- + +.scroll { + max-width: var(--#{$prefix}-site-width); + margin-inline: auto; +} + +.scroll__head, +.scroll__foot { + background-repeat: no-repeat; + background-size: 100% 100%; +} + +.scroll__head { + height: 140px; + background-image: var(--#{$prefix}-scroll-head); + background-position: bottom; +} + +.scroll__body { + // Closes the hairline where the head's bottom row meets the body. + margin-block-start: -1px; + padding: 0 clamp(#{space-raw('md')}, 5vw, 5rem) space('xl'); + background: var(--#{$prefix}-scroll-body) repeat-y top / 100% auto; +} + +.scroll__foot { + // The top 18px of the foot image ramp from alpha 15 up to its 242 plateau — + // it fades in. Butted against the body, that ramp composites over bare wood + // and reads as a hard line at the body's bottom edge. The overlap is the + // measured ramp height plus a little, so the whole fade lands on papyrus. + // + // It has to be a margin: the element is static, and `top` only moves a + // positioned box. `position`/`z-index` pin the paint order the effect + // depends on — tree order already gives it, but silently, and one positioned + // ancestor added later would reverse it. + position: relative; + z-index: 1; + margin-block-start: -20px; + height: 114px; + background-image: var(--#{$prefix}-scroll-foot); + background-position: top; +} diff --git a/src/sass/main.scss b/src/sass/main.scss index a7755fe..a35041c 100644 --- a/src/sass/main.scss +++ b/src/sass/main.scss @@ -7,8 +7,10 @@ // // abstracts/ compile-time only, emits no CSS // base/ custom properties, @font-face, reset, element typography, links +// layout/ page structure: the wood ground and the papyrus scroll // components/ single-purpose blocks // ----------------------------------------------------------------------------- @use 'base'; +@use 'layout'; @use 'components';