Skip to content

Commit 54c60f8

Browse files
committed
stop os/pro switch flicker on page load
1 parent a66e679 commit 54c60f8

3 files changed

Lines changed: 49 additions & 35 deletions

File tree

docs/assets/js/custom.js

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ window.ddOffcanvas = Offcanvas;
1212

1313
// Edition toggler (Open Source / Pro)
1414
//
15-
// The sidebar renders both edition menus (.version-opensource / .version-pro);
16-
// this shows one, persists the choice, and keeps every segmented control on
17-
// the page (desktop sidebar + mobile offcanvas) in sync. The sidebar and the
18-
// control start hidden (see _custom.scss) and are revealed only after the
19-
// stored edition is applied, so there is no flash of the wrong menu.
15+
// The sidebar renders both edition menus (.version-opensource / .version-pro).
16+
// Which menu shows — and which segmented-control button reads as selected —
17+
// is pure CSS keyed off html[data-dd-version] (see _custom.scss). An inline
18+
// script in custom-head.html stamps that attribute from localStorage before
19+
// first paint, so every page load renders the stored edition immediately with
20+
// no hide-then-reveal flicker. This module only handles toggling: update the
21+
// attribute, persist the choice, sync aria-checked for assistive tech.
2022
(() => {
2123
"use strict";
2224

@@ -41,26 +43,21 @@ window.ddOffcanvas = Offcanvas;
4143
};
4244

4345
const setVersion = (version) => {
44-
document.querySelectorAll(".version-opensource, .version-pro").forEach(el => {
45-
el.style.display = el.classList.contains(`version-${version}`) ? "block" : "none";
46-
});
46+
// CSS shows the matching menu and highlights the matching button
47+
document.documentElement.dataset.ddVersion = version;
4748

48-
localStorage.setItem("version", version);
49+
try {
50+
localStorage.setItem("version", version);
51+
} catch (e) {
52+
// Storage blocked (private browsing) — toggle still works this page
53+
}
4954

50-
// Sync every segmented control instance, then reveal it
51-
document.querySelectorAll(".dd-version-seg").forEach(seg => {
52-
seg.querySelectorAll("button[data-version-value]").forEach(btn => {
53-
btn.setAttribute("aria-checked", btn.dataset.versionValue === version ? "true" : "false");
54-
});
55-
seg.style.visibility = "visible";
55+
// aria-checked is for assistive tech only; visuals come from the
56+
// html[data-dd-version] attribute above
57+
document.querySelectorAll(".dd-version-seg button[data-version-value]").forEach(btn => {
58+
btn.setAttribute("aria-checked", btn.dataset.versionValue === version ? "true" : "false");
5659
});
5760

58-
// Unhide sidebar after version is applied
59-
const sidebar = document.querySelector(".docs-sidebar");
60-
if (sidebar) {
61-
sidebar.style.visibility = "visible";
62-
}
63-
6461
// Edition-aware top nav: route "Model Your Assets" to the page that
6562
// matches the selected version (see assetNavUrls above).
6663
document.querySelectorAll("a.nav-link").forEach(link => {
@@ -71,8 +68,10 @@ window.ddOffcanvas = Offcanvas;
7168
};
7269

7370
const initVersionToggle = () => {
74-
const storedVersion = localStorage.getItem("version") || "opensource";
75-
setVersion(storedVersion);
71+
// custom-head.html already stamped the stored edition on <html> before
72+
// paint; re-applying it here syncs aria-checked and the nav link on
73+
// freshly parsed (or dynamically replaced) markup.
74+
setVersion(document.documentElement.dataset.ddVersion || "opensource");
7675
};
7776

7877
// Delegated listener on body — catches every control instance

docs/assets/scss/common/_custom.scss

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -352,10 +352,6 @@ h1, h2, h3, h4, h5, h6,
352352
// Sidebar — column sizing, edition control, nav tree
353353
// ============================================================
354354

355-
.docs-sidebar {
356-
visibility: hidden; // Hide sidebar until version is resolved (JS reveals)
357-
}
358-
359355
@media (min-width: 992px) {
360356
@supports ((position: -webkit-sticky) or (position: sticky)) {
361357
.docs-sidebar {
@@ -415,7 +411,6 @@ h1, h2, h3, h4, h5, h6,
415411
background: var(--dd-surface-2);
416412
border: 1px solid var(--dd-border);
417413
border-radius: 0.625rem;
418-
visibility: hidden; // revealed by JS once the stored edition is applied
419414

420415
button {
421416
appearance: none;
@@ -433,17 +428,23 @@ h1, h2, h3, h4, h5, h6,
433428
color: var(--dd-ink);
434429
}
435430

436-
&[aria-checked='true'] {
431+
// Selected state keys off the edition stamped on <html> before first
432+
// paint (custom-head.html), not aria-checked — the static markup always
433+
// ships aria-checked="true" on Open Source, so styling from it would
434+
// flash the wrong button when Pro is stored. JS keeps aria-checked in
435+
// sync for assistive tech. :not() makes Open Source the no-JS default.
436+
html:not([data-dd-version='pro']) &[data-version-value='opensource'],
437+
html[data-dd-version='pro'] &[data-version-value='pro'] {
437438
color: #ffffff;
438439
font-weight: 600;
439440
}
440441

441-
&[data-version-value='opensource'][aria-checked='true'] {
442+
html:not([data-dd-version='pro']) &[data-version-value='opensource'] {
442443
background: var(--dd-blue);
443444
box-shadow: 0 1px 3px rgba(23, 121, 197, 0.4);
444445
}
445446

446-
&[data-version-value='pro'][aria-checked='true'] {
447+
html[data-dd-version='pro'] &[data-version-value='pro'] {
447448
background: var(--dd-orange);
448449
box-shadow: 0 1px 3px rgba(242, 86, 29, 0.4);
449450
}
@@ -455,9 +456,11 @@ h1, h2, h3, h4, h5, h6,
455456
padding-top: 0.75rem;
456457
}
457458

458-
// Hide Pro-versioned content by default (opensource is default).
459-
// JS sets explicit inline display:block/none when version is toggled.
460-
.version-pro {
459+
// Both edition menus render; html[data-dd-version] (stamped before first
460+
// paint by custom-head.html, updated by custom.js on toggle) decides which
461+
// one shows. Without JS the attribute is absent and Open Source shows.
462+
html[data-dd-version='pro'] .version-opensource,
463+
html:not([data-dd-version='pro']) .version-pro {
461464
display: none;
462465
}
463466

docs/layouts/_partials/head/custom-head.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,16 @@
44
{{ $style := resources.Get "scss/app.scss" | css.Sass $options }}
55
<link rel="stylesheet" href="{{ $style.Permalink }}">
66
{{ end -}}
7-
<meta name="docsearch:audience" content="{{ .Params.audience | default " public" }}">
7+
<meta name="docsearch:audience" content="{{ .Params.audience | default " public" }}">
8+
<script>
9+
// Stamp the stored docs edition (Open Source / Pro) on <html> before first
10+
// paint. The sidebar edition menus and the .dd-version-seg control render
11+
// their state from this attribute (see _custom.scss), so the page paints
12+
// correct immediately — no hidden-then-revealed flicker. localStorage can
13+
// throw in private-browsing/blocked-storage modes; fall back to the default.
14+
try {
15+
document.documentElement.dataset.ddVersion = localStorage.getItem('version') || 'opensource';
16+
} catch (e) {
17+
document.documentElement.dataset.ddVersion = 'opensource';
18+
}
19+
</script>

0 commit comments

Comments
 (0)