feat(glossaire): polish sticky entry flow and aside navigation
This commit is contained in:
@@ -118,9 +118,10 @@ const constellationCount = relatedEntries.length;
|
||||
</Fragment>
|
||||
|
||||
<section class="dyna-page" data-dyna-page>
|
||||
<div class="dyna-hero" data-dyna-hero>
|
||||
<div class="dyna-hero glossary-page-hero" data-dyna-hero>
|
||||
<p class="dyna-kicker">Parcours du glossaire</p>
|
||||
<h1>Dynamiques archicratiques</h1>
|
||||
|
||||
<p class="dyna-intro">
|
||||
Les dynamiques archicratiques désignent les processus par lesquels une
|
||||
régulation se déplace, se ferme, se rigidifie ou se soustrait à sa
|
||||
@@ -128,12 +129,34 @@ const constellationCount = relatedEntries.length;
|
||||
d’un régime, mais aussi ses dérives, ses opacifications et ses
|
||||
pathologies.
|
||||
</p>
|
||||
<p class="dyna-intro">
|
||||
Elles décrivent ainsi le versant processuel de l’archicratie : non plus
|
||||
seulement ce qui tient, mais la manière dont cela se transforme,
|
||||
s’altère, s’autonomise ou devient de moins en moins exposable à
|
||||
l’épreuve collective.
|
||||
</p>
|
||||
|
||||
<div class="dyna-hero-collapsible">
|
||||
<div
|
||||
class="dyna-hero-more"
|
||||
id="dyna-hero-more"
|
||||
data-dyna-more
|
||||
aria-hidden="false"
|
||||
>
|
||||
<p class="dyna-intro">
|
||||
Elles décrivent ainsi le versant processuel de l’archicratie : non plus
|
||||
seulement ce qui tient, mais la manière dont cela se transforme,
|
||||
s’altère, s’autonomise ou devient de moins en moins exposable à
|
||||
l’épreuve collective.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="dyna-hero-toggle"
|
||||
id="dyna-hero-toggle"
|
||||
data-dyna-more-toggle
|
||||
type="button"
|
||||
aria-controls="dyna-hero-more"
|
||||
aria-expanded="false"
|
||||
hidden
|
||||
>
|
||||
lire la suite
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="dyna-section">
|
||||
@@ -239,7 +262,7 @@ const constellationCount = relatedEntries.length;
|
||||
|
||||
{otherEntries.length > 0 && (
|
||||
<div class="dyna-block">
|
||||
<h3>Notions et diagnostics liés</h3>
|
||||
<h3 id="notions-et-diagnostics-lies">Notions et diagnostics liés</h3>
|
||||
<div class="dyna-cards">
|
||||
{otherEntries.map((entry) => (
|
||||
<a class="dyna-card" href={hrefOf(entry)}>
|
||||
@@ -259,7 +282,7 @@ const constellationCount = relatedEntries.length;
|
||||
|
||||
{paradigmEntries.length > 0 && (
|
||||
<div class="dyna-block">
|
||||
<h3>Paradigmes mobilisés</h3>
|
||||
<h3 id="paradigmes-mobilises">Paradigmes mobilisés</h3>
|
||||
<div class="dyna-cards">
|
||||
{paradigmEntries.map((entry) => (
|
||||
<a class="dyna-card" href={hrefOf(entry)}>
|
||||
@@ -340,95 +363,225 @@ const constellationCount = relatedEntries.length;
|
||||
|
||||
<script is:inline>
|
||||
(() => {
|
||||
const body = document.body;
|
||||
const root = document.documentElement;
|
||||
const hero = document.querySelector("[data-dyna-hero]");
|
||||
|
||||
if (!body || !root || !hero) return;
|
||||
|
||||
const BODY_CLASS = "is-dynamiques-archicratiques-page";
|
||||
const FOLLOW_ON_CLASS = "dyna-follow-on";
|
||||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||||
|
||||
body.classList.add(BODY_CLASS);
|
||||
|
||||
const setRootVar = (name, value) => {
|
||||
root.style.setProperty(name, value);
|
||||
};
|
||||
|
||||
const heroHeight = () =>
|
||||
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
||||
|
||||
const stripLocalSticky = () => {
|
||||
document.querySelectorAll(".dyna-section__head").forEach((el) => {
|
||||
el.classList.remove("is-sticky");
|
||||
el.removeAttribute("data-sticky-active");
|
||||
});
|
||||
};
|
||||
|
||||
const applyLocalStickyHeight = () => {
|
||||
const h = mqMobile.matches ? 0 : heroHeight();
|
||||
|
||||
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
||||
window.__archiSetLocalStickyHeight(h);
|
||||
} else {
|
||||
setRootVar("--glossary-local-sticky-h", `${h}px`);
|
||||
}
|
||||
};
|
||||
|
||||
const syncFollowState = () => {
|
||||
const boot = () => {
|
||||
const body = document.body;
|
||||
const root = document.documentElement;
|
||||
const hero = document.querySelector("[data-dyna-hero]");
|
||||
const follow = document.getElementById("reading-follow");
|
||||
if (!follow) {
|
||||
body.classList.remove(FOLLOW_ON_CLASS);
|
||||
return;
|
||||
}
|
||||
const heroMore = document.getElementById("dyna-hero-more");
|
||||
const heroToggle = document.getElementById("dyna-hero-toggle");
|
||||
|
||||
const followOn =
|
||||
if (!body || !root || !hero || !follow) return;
|
||||
|
||||
const BODY_CLASS = "is-dynamiques-archicratiques-page";
|
||||
const FOLLOW_ON_CLASS = "dyna-follow-on";
|
||||
const EXPANDED_CLASS = "dyna-hero-expanded";
|
||||
const mqMobile = window.matchMedia("(max-width: 860px)");
|
||||
const AUTO_COLLAPSE_DELTA = 160;
|
||||
|
||||
let expandedAtY = null;
|
||||
let lastScrollY = window.scrollY || 0;
|
||||
|
||||
body.classList.add(BODY_CLASS);
|
||||
|
||||
const heroHeight = () =>
|
||||
Math.max(0, Math.round(hero.getBoundingClientRect().height || 0));
|
||||
|
||||
const stripLocalSticky = () => {
|
||||
document.querySelectorAll(".dyna-section__head").forEach((el) => {
|
||||
el.classList.remove("is-sticky");
|
||||
el.removeAttribute("data-sticky-active");
|
||||
});
|
||||
};
|
||||
|
||||
const computeFollowOn = () =>
|
||||
!mqMobile.matches &&
|
||||
follow.classList.contains("is-on") &&
|
||||
follow.style.display !== "none" &&
|
||||
follow.getAttribute("aria-hidden") !== "true";
|
||||
|
||||
body.classList.toggle(FOLLOW_ON_CLASS, followOn);
|
||||
};
|
||||
const applyLocalStickyHeight = () => {
|
||||
const h = mqMobile.matches ? 0 : heroHeight();
|
||||
|
||||
const syncAll = () => {
|
||||
stripLocalSticky();
|
||||
applyLocalStickyHeight();
|
||||
syncFollowState();
|
||||
};
|
||||
if (typeof window.__archiSetLocalStickyHeight === "function") {
|
||||
window.__archiSetLocalStickyHeight(h);
|
||||
} else {
|
||||
root.style.setProperty("--glossary-local-sticky-h", `${h}px`);
|
||||
}
|
||||
};
|
||||
|
||||
let raf = 0;
|
||||
const schedule = () => {
|
||||
if (raf) return;
|
||||
raf = requestAnimationFrame(() => {
|
||||
raf = 0;
|
||||
requestAnimationFrame(syncAll);
|
||||
const syncFollowState = () => {
|
||||
const on = computeFollowOn();
|
||||
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
||||
return on;
|
||||
};
|
||||
|
||||
const collapseHero = () => {
|
||||
if (!body.classList.contains(EXPANDED_CLASS)) return;
|
||||
|
||||
body.classList.remove(EXPANDED_CLASS);
|
||||
expandedAtY = null;
|
||||
|
||||
if (heroMore) {
|
||||
heroMore.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
|
||||
if (heroToggle) {
|
||||
heroToggle.hidden = false;
|
||||
heroToggle.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
try {
|
||||
window.__archiUpdateFollow?.();
|
||||
} catch {}
|
||||
|
||||
schedule();
|
||||
};
|
||||
|
||||
const expandHero = () => {
|
||||
body.classList.add(EXPANDED_CLASS);
|
||||
expandedAtY = window.scrollY || 0;
|
||||
|
||||
if (heroMore) {
|
||||
heroMore.setAttribute("aria-hidden", "false");
|
||||
}
|
||||
|
||||
if (heroToggle) {
|
||||
heroToggle.hidden = true;
|
||||
heroToggle.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
|
||||
try {
|
||||
window.__archiUpdateFollow?.();
|
||||
} catch {}
|
||||
|
||||
schedule();
|
||||
};
|
||||
|
||||
const syncHeroState = () => {
|
||||
const followOn = computeFollowOn();
|
||||
const expanded = body.classList.contains(EXPANDED_CLASS);
|
||||
const collapsed = followOn && !expanded;
|
||||
|
||||
if (!followOn || mqMobile.matches) {
|
||||
body.classList.remove(EXPANDED_CLASS);
|
||||
expandedAtY = null;
|
||||
|
||||
if (heroMore) {
|
||||
heroMore.setAttribute("aria-hidden", "false");
|
||||
}
|
||||
|
||||
if (heroToggle) {
|
||||
heroToggle.hidden = true;
|
||||
heroToggle.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (heroMore) {
|
||||
heroMore.setAttribute("aria-hidden", collapsed ? "true" : "false");
|
||||
}
|
||||
|
||||
if (heroToggle) {
|
||||
heroToggle.hidden = !collapsed;
|
||||
heroToggle.setAttribute("aria-expanded", expanded ? "true" : "false");
|
||||
}
|
||||
};
|
||||
|
||||
const maybeAutoCollapseOnScroll = () => {
|
||||
if (mqMobile.matches) {
|
||||
lastScrollY = window.scrollY || 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!computeFollowOn()) {
|
||||
lastScrollY = window.scrollY || 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!body.classList.contains(EXPANDED_CLASS)) {
|
||||
lastScrollY = window.scrollY || 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (expandedAtY == null) {
|
||||
lastScrollY = window.scrollY || 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const currentY = window.scrollY || 0;
|
||||
const scrollingDown = currentY > lastScrollY;
|
||||
const delta = currentY - expandedAtY;
|
||||
|
||||
if (scrollingDown && delta >= AUTO_COLLAPSE_DELTA) {
|
||||
collapseHero();
|
||||
}
|
||||
|
||||
lastScrollY = currentY;
|
||||
};
|
||||
|
||||
const syncAll = () => {
|
||||
stripLocalSticky();
|
||||
syncFollowState();
|
||||
syncHeroState();
|
||||
applyLocalStickyHeight();
|
||||
};
|
||||
|
||||
let raf = 0;
|
||||
const schedule = () => {
|
||||
if (raf) return;
|
||||
raf = requestAnimationFrame(() => {
|
||||
raf = 0;
|
||||
requestAnimationFrame(syncAll);
|
||||
});
|
||||
};
|
||||
|
||||
heroToggle?.addEventListener("click", () => {
|
||||
expandHero();
|
||||
});
|
||||
|
||||
const onScroll = () => {
|
||||
maybeAutoCollapseOnScroll();
|
||||
schedule();
|
||||
};
|
||||
|
||||
const followObserver = new MutationObserver(schedule);
|
||||
followObserver.observe(follow, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class", "style", "aria-hidden"],
|
||||
subtree: false,
|
||||
});
|
||||
|
||||
const heroResizeObserver =
|
||||
typeof ResizeObserver !== "undefined"
|
||||
? new ResizeObserver(schedule)
|
||||
: null;
|
||||
|
||||
heroResizeObserver?.observe(hero);
|
||||
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
window.addEventListener("resize", schedule);
|
||||
window.addEventListener("pageshow", schedule);
|
||||
|
||||
if (document.fonts?.ready) {
|
||||
document.fonts.ready.then(schedule).catch(() => {});
|
||||
}
|
||||
|
||||
if (mqMobile.addEventListener) {
|
||||
mqMobile.addEventListener("change", schedule);
|
||||
} else if (mqMobile.addListener) {
|
||||
mqMobile.addListener(schedule);
|
||||
}
|
||||
|
||||
schedule();
|
||||
};
|
||||
|
||||
const heroResizeObserver =
|
||||
typeof ResizeObserver !== "undefined"
|
||||
? new ResizeObserver(schedule)
|
||||
: null;
|
||||
|
||||
heroResizeObserver?.observe(hero);
|
||||
|
||||
window.addEventListener("scroll", schedule, { passive: true });
|
||||
window.addEventListener("resize", schedule);
|
||||
window.addEventListener("pageshow", schedule);
|
||||
|
||||
if (document.fonts?.ready) {
|
||||
document.fonts.ready.then(schedule).catch(() => {});
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", boot, { once: true });
|
||||
} else {
|
||||
boot();
|
||||
}
|
||||
|
||||
if (mqMobile.addEventListener) {
|
||||
mqMobile.addEventListener("change", schedule);
|
||||
} else if (mqMobile.addListener) {
|
||||
mqMobile.addListener(schedule);
|
||||
}
|
||||
|
||||
schedule();
|
||||
})();
|
||||
</script>
|
||||
</GlossaryLayout>
|
||||
@@ -451,13 +604,17 @@ const constellationCount = relatedEntries.length;
|
||||
radial-gradient(900px 240px at 20% 0%, rgba(0,217,255,0.08), transparent 60%);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
display: grid;
|
||||
row-gap: 14px;
|
||||
transition:
|
||||
margin-bottom 180ms ease,
|
||||
border-radius 180ms ease;
|
||||
border-radius 180ms ease,
|
||||
padding 180ms ease,
|
||||
row-gap 180ms ease;
|
||||
}
|
||||
|
||||
.dyna-kicker{
|
||||
margin: 0 0 10px;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
@@ -465,23 +622,75 @@ const constellationCount = relatedEntries.length;
|
||||
}
|
||||
|
||||
.dyna-hero h1{
|
||||
margin: 0 0 14px;
|
||||
margin: 0;
|
||||
font-size: clamp(2.2rem, 4vw, 3.15rem);
|
||||
line-height: 1.02;
|
||||
letter-spacing: -.04em;
|
||||
font-weight: 850;
|
||||
transition: font-size 180ms ease;
|
||||
}
|
||||
|
||||
.dyna-intro{
|
||||
max-width: 76ch;
|
||||
margin: 0;
|
||||
max-width: 72ch;
|
||||
font-size: 1.04rem;
|
||||
line-height: 1.55;
|
||||
opacity: .94;
|
||||
transition:
|
||||
font-size 180ms ease,
|
||||
line-height 180ms ease,
|
||||
max-width 180ms ease;
|
||||
}
|
||||
|
||||
.dyna-intro + .dyna-intro{
|
||||
margin-top: 14px;
|
||||
.dyna-hero-collapsible{
|
||||
display: grid;
|
||||
row-gap: 6px;
|
||||
}
|
||||
|
||||
.dyna-hero-more{
|
||||
display: grid;
|
||||
row-gap: 14px;
|
||||
max-height: 18rem;
|
||||
overflow: hidden;
|
||||
opacity: 1;
|
||||
transition:
|
||||
max-height 220ms ease,
|
||||
opacity 180ms ease;
|
||||
}
|
||||
|
||||
.dyna-hero-toggle{
|
||||
display: none;
|
||||
align-self: flex-start;
|
||||
width: fit-content;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font: inherit;
|
||||
font-size: 11px;
|
||||
line-height: 1.2;
|
||||
letter-spacing: .01em;
|
||||
text-transform: none;
|
||||
opacity: .56;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: .12em;
|
||||
text-decoration-thickness: 1px;
|
||||
}
|
||||
|
||||
.dyna-hero-toggle:hover{
|
||||
opacity: .84;
|
||||
}
|
||||
|
||||
.dyna-hero-toggle:focus-visible{
|
||||
outline: 2px solid rgba(0,217,255,0.24);
|
||||
outline-offset: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dyna-hero-toggle[hidden]{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.dyna-section{
|
||||
@@ -699,10 +908,33 @@ const constellationCount = relatedEntries.length;
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on .dyna-hero){
|
||||
margin-bottom: 0;
|
||||
padding: 12px 16px 14px;
|
||||
row-gap: 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on .dyna-hero h1){
|
||||
font-size: clamp(1.9rem, 3.2vw, 2.55rem);
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on .dyna-intro){
|
||||
max-width: 68ch;
|
||||
font-size: .98rem;
|
||||
line-height: 1.48;
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on:not(.dyna-hero-expanded) .dyna-hero-more){
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on:not(.dyna-hero-expanded) .dyna-hero-toggle){
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on #reading-follow .reading-follow__inner){
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
@@ -726,11 +958,29 @@ const constellationCount = relatedEntries.length;
|
||||
position: static;
|
||||
border-radius: 22px;
|
||||
margin-bottom: 20px;
|
||||
padding: 14px 14px 16px;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
.dyna-intro{
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.dyna-hero-more{
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.dyna-hero-toggle{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:global(body.is-dynamiques-archicratiques-page.dyna-follow-on .dyna-hero){
|
||||
border-radius: 22px;
|
||||
margin-bottom: 20px;
|
||||
padding: 14px 14px 16px;
|
||||
row-gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user