feat(glossaire): polish sticky entry flow and aside navigation
This commit is contained in:
@@ -66,21 +66,44 @@ const paradigmesCount = paradigmes.length;
|
||||
</Fragment>
|
||||
|
||||
<section class="theo-page" data-theo-page>
|
||||
<div class="theo-hero" data-theo-hero>
|
||||
<div class="theo-hero glossary-page-hero" data-theo-hero>
|
||||
<p class="theo-kicker">Cartographie théorique</p>
|
||||
<h1>Paradigmes et doctrines</h1>
|
||||
|
||||
<p class="theo-intro">
|
||||
L’archicratie ne se déploie pas dans le vide. Elle s’inscrit dans un
|
||||
paysage intellectuel plus large où se croisent des doctrines
|
||||
fondatrices de l’ordre et des paradigmes de régulation des collectifs.
|
||||
</p>
|
||||
<p class="theo-intro">
|
||||
On appellera ici <strong>doctrines fondatrices</strong> les formulations
|
||||
qui posent un principe premier de légitimité, de souveraineté ou d’ordre
|
||||
politique. On appellera <strong>paradigmes régulateurs</strong> les
|
||||
cadres théoriques qui décrivent des modes de tenue, de conflictualité,
|
||||
d’administration, de reproduction ou de transformation des sociétés.
|
||||
</p>
|
||||
|
||||
<div class="theo-hero-collapsible">
|
||||
<div
|
||||
class="theo-hero-more"
|
||||
id="theo-hero-more"
|
||||
data-theo-more
|
||||
aria-hidden="false"
|
||||
>
|
||||
<p class="theo-intro">
|
||||
On appellera ici <strong>doctrines fondatrices</strong> les formulations
|
||||
qui posent un principe premier de légitimité, de souveraineté ou d’ordre
|
||||
politique. On appellera <strong>paradigmes régulateurs</strong> les
|
||||
cadres théoriques qui décrivent des modes de tenue, de conflictualité,
|
||||
d’administration, de reproduction ou de transformation des sociétés.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="theo-hero-toggle"
|
||||
id="theo-hero-toggle"
|
||||
data-theo-more-toggle
|
||||
type="button"
|
||||
aria-controls="theo-hero-more"
|
||||
aria-expanded="false"
|
||||
hidden
|
||||
>
|
||||
lire la suite
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{doctrines.length > 0 && (
|
||||
@@ -227,12 +250,20 @@ const paradigmesCount = paradigmes.length;
|
||||
const body = document.body;
|
||||
const root = document.documentElement;
|
||||
const hero = document.querySelector("[data-theo-hero]");
|
||||
const follow = document.getElementById("reading-follow");
|
||||
const heroMore = document.getElementById("theo-hero-more");
|
||||
const heroToggle = document.getElementById("theo-hero-toggle");
|
||||
|
||||
if (!body || !root || !hero) return;
|
||||
if (!body || !root || !hero || !follow) return;
|
||||
|
||||
const BODY_CLASS = "is-paradigmes-page";
|
||||
const FOLLOW_ON_CLASS = "theo-follow-on";
|
||||
const EXPANDED_CLASS = "theo-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);
|
||||
|
||||
@@ -246,6 +277,12 @@ const paradigmesCount = paradigmes.length;
|
||||
});
|
||||
};
|
||||
|
||||
const computeFollowOn = () =>
|
||||
!mqMobile.matches &&
|
||||
follow.classList.contains("is-on") &&
|
||||
follow.style.display !== "none" &&
|
||||
follow.getAttribute("aria-hidden") !== "true";
|
||||
|
||||
const applyLocalStickyHeight = () => {
|
||||
const h = mqMobile.matches ? 0 : heroHeight();
|
||||
|
||||
@@ -257,22 +294,121 @@ const paradigmesCount = paradigmes.length;
|
||||
};
|
||||
|
||||
const syncFollowState = () => {
|
||||
const follow = document.getElementById("reading-follow");
|
||||
const on = computeFollowOn();
|
||||
body.classList.toggle(FOLLOW_ON_CLASS, on);
|
||||
return on;
|
||||
};
|
||||
|
||||
const followOn =
|
||||
!mqMobile.matches &&
|
||||
!!follow &&
|
||||
follow.classList.contains("is-on") &&
|
||||
follow.style.display !== "none" &&
|
||||
follow.getAttribute("aria-hidden") !== "true";
|
||||
const collapseHero = () => {
|
||||
if (!body.classList.contains(EXPANDED_CLASS)) return;
|
||||
|
||||
body.classList.toggle(FOLLOW_ON_CLASS, followOn);
|
||||
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();
|
||||
applyLocalStickyHeight();
|
||||
syncFollowState();
|
||||
syncHeroState();
|
||||
applyLocalStickyHeight();
|
||||
};
|
||||
|
||||
let raf = 0;
|
||||
@@ -284,13 +420,17 @@ const paradigmesCount = paradigmes.length;
|
||||
});
|
||||
};
|
||||
|
||||
const follow = document.getElementById("reading-follow");
|
||||
const followObserver =
|
||||
follow
|
||||
? new MutationObserver(schedule)
|
||||
: null;
|
||||
heroToggle?.addEventListener("click", () => {
|
||||
expandHero();
|
||||
});
|
||||
|
||||
followObserver?.observe(follow, {
|
||||
const onScroll = () => {
|
||||
maybeAutoCollapseOnScroll();
|
||||
schedule();
|
||||
};
|
||||
|
||||
const followObserver = new MutationObserver(schedule);
|
||||
followObserver.observe(follow, {
|
||||
attributes: true,
|
||||
attributeFilter: ["class", "style", "aria-hidden"],
|
||||
subtree: false,
|
||||
@@ -303,6 +443,7 @@ const paradigmesCount = paradigmes.length;
|
||||
|
||||
heroResizeObserver?.observe(hero);
|
||||
|
||||
window.addEventListener("scroll", onScroll, { passive: true });
|
||||
window.addEventListener("resize", schedule);
|
||||
window.addEventListener("pageshow", schedule);
|
||||
|
||||
@@ -346,13 +487,17 @@ const paradigmesCount = paradigmes.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;
|
||||
}
|
||||
|
||||
.theo-kicker{
|
||||
margin: 0 0 10px;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
@@ -360,23 +505,75 @@ const paradigmesCount = paradigmes.length;
|
||||
}
|
||||
|
||||
.theo-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;
|
||||
}
|
||||
|
||||
.theo-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;
|
||||
}
|
||||
|
||||
.theo-intro + .theo-intro{
|
||||
margin-top: 14px;
|
||||
.theo-hero-collapsible{
|
||||
display: grid;
|
||||
row-gap: 6px;
|
||||
}
|
||||
|
||||
.theo-hero-more{
|
||||
display: grid;
|
||||
row-gap: 14px;
|
||||
max-height: 18rem;
|
||||
overflow: hidden;
|
||||
opacity: 1;
|
||||
transition:
|
||||
max-height 220ms ease,
|
||||
opacity 180ms ease;
|
||||
}
|
||||
|
||||
.theo-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;
|
||||
}
|
||||
|
||||
.theo-hero-toggle:hover{
|
||||
opacity: .84;
|
||||
}
|
||||
|
||||
.theo-hero-toggle:focus-visible{
|
||||
outline: 2px solid rgba(0,217,255,0.24);
|
||||
outline-offset: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.theo-hero-toggle[hidden]{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.theo-section{
|
||||
@@ -521,10 +718,33 @@ const paradigmesCount = paradigmes.length;
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on .theo-hero){
|
||||
margin-bottom: 0;
|
||||
padding: 12px 16px 14px;
|
||||
row-gap: 10px;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on .theo-hero h1){
|
||||
font-size: clamp(1.9rem, 3.2vw, 2.55rem);
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on .theo-intro){
|
||||
max-width: 68ch;
|
||||
font-size: .98rem;
|
||||
line-height: 1.48;
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on:not(.theo-hero-expanded) .theo-hero-more){
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on:not(.theo-hero-expanded) .theo-hero-toggle){
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on #reading-follow .reading-follow__inner){
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
@@ -548,11 +768,29 @@ const paradigmesCount = paradigmes.length;
|
||||
position: static;
|
||||
border-radius: 22px;
|
||||
margin-bottom: 20px;
|
||||
padding: 14px 14px 16px;
|
||||
row-gap: 12px;
|
||||
}
|
||||
|
||||
.theo-intro{
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.theo-hero-more{
|
||||
max-height: none;
|
||||
opacity: 1;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.theo-hero-toggle{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
:global(body.is-paradigmes-page.theo-follow-on .theo-hero){
|
||||
border-radius: 22px;
|
||||
margin-bottom: 20px;
|
||||
padding: 14px 14px 16px;
|
||||
row-gap: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user