Skip to content

Commit

Permalink
Animate remotely loaded banners together (#1808)
Browse files Browse the repository at this point in the history
The banner animation felt a little funky to me, even after the improvements made in #1693.

My hunch is that because the two banners are stacked on top of each other and the height of one affects the layout/position of the other, trying to animate the height of both of them at the same time causes the browser to stutter. Or maybe it was just because they could each load at different but often only slightly offset times. Whatever the case, I decided to do a little code clean up and change it so that they both come in together.

In the process of working on this PR it also made sense to address a TODO, and add "Version warning" to the list of translatable strings.

* pybabel extract . -F babel.cfg -o src/pydata_sphinx_theme/locale/sphinx.pot -k '_ __ l_ lazy_gettext'

* pybabel update -i src/pydata_sphinx_theme/locale/sphinx.pot -d src/pydata_sphinx_theme/locale -D sphinx

* Update src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html


* incorporate #1755

---------

Co-authored-by: M Bussonnier <bussonniermatthias@gmail.com>
  • Loading branch information
gabalafou and Carreau authored May 23, 2024
1 parent c42ee47 commit bbe3e57
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 131 deletions.
20 changes: 14 additions & 6 deletions docs/user_guide/announcements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,20 @@ For example, the following configuration tells the theme to load the ``custom-te
Update or remove announcement banner
------------------------------------

To update or remove the announcement banner, you can change the value of
``html_theme_options["announcement"]`` in your ``conf.py`` or you can edit the
contents of the ``custom-template.html`` file directly. For example, if you have a
temporary announcement that you want to remove without rebuilding your
documentation pages, you can use an empty ``custom-template.html`` file and the
banner will be hidden.
If you set ``html_theme_options["announcement"]`` to plain text or HTML, then to
update the announcement banner you need to modify this string and rebuild your
documentation pages. To remove the announcement banner, set this value to an
empty string and rebuild your documentation pages.

If you set ``html_theme_options["announcement"]`` to a URL string (starts with
``http``), then you can edit the file at that URL to update the announcement
banner. Saving an empty file at that URL will remove the announcement banner.
That's the main advantage of using a URL--you can change the announcement banner
without rebuilding and redeploying all of your documentation pages. For example,
if you point the announcement to the URL of a file in your repo, as we do on
this documentation site (see previous section), then you can edit, save and push
your changes to just that file (empty file = remove announcement) without
rebuilding and redeploying all your docs.

.. _version-warning-banners:

Expand Down
134 changes: 85 additions & 49 deletions src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -488,16 +488,13 @@ function showVersionWarningBanner(data) {
return;
}
// now construct the warning banner
var outer = document.createElement("aside");
// TODO: add to translatable strings
outer.setAttribute("aria-label", "Version warning");
const banner = document.querySelector(".bd-header-version-warning");
const middle = document.createElement("div");
const inner = document.createElement("div");
const bold = document.createElement("strong");
const button = document.createElement("a");
// these classes exist since pydata-sphinx-theme v0.10.0
// the init class is used for animation
outer.classList = "bd-header-version-warning container-fluid init";
middle.classList = "bd-header-announcement__content";
inner.classList = "sidebar-message";
button.classList =
Expand All @@ -522,35 +519,12 @@ function showVersionWarningBanner(data) {
} else {
bold.innerText = `version ${version}`;
}
outer.appendChild(middle);
banner.appendChild(middle);
middle.appendChild(inner);
inner.appendChild(bold);
inner.appendChild(document.createTextNode("."));
inner.appendChild(button);
const skipLink = document.getElementById("pst-skip-link");
skipLink.after(outer);
// At least 3rem height
const autoHeight = Math.max(
outer.offsetHeight,
3 * parseFloat(getComputedStyle(document.documentElement).fontSize),
);
// Set height and vertical padding to 0 to prepare the height transition
outer.style.setProperty("height", 0);
outer.style.setProperty("padding-top", 0);
outer.style.setProperty("padding-bottom", 0);
outer.classList.remove("init");
// Set height to the computed height with a small timeout to activate the transition
setTimeout(() => {
outer.style.setProperty("height", `${autoHeight}px`);
// Wait for a bit more than 300ms (the transition duration) then remove the
// forcefully set styles and let CSS take over
setTimeout(() => {
outer.style.removeProperty("padding-top");
outer.style.removeProperty("padding-bottom");
outer.style.removeProperty("height");
outer.style.setProperty("min-height", "3rem");
}, 320);
}, 10);
banner.classList.remove("d-none");
}

/*******************************************************************************
Expand Down Expand Up @@ -584,27 +558,29 @@ function initRTDObserver() {
observer.observe(document.body, config);
}

// fetch the JSON version data (only once), then use it to populate the version
// switcher and maybe show the version warning bar
var versionSwitcherBtns = document.querySelectorAll(
".version-switcher__button",
);
const hasSwitcherMenu = versionSwitcherBtns.length > 0;
const hasVersionsJSON = DOCUMENTATION_OPTIONS.hasOwnProperty(
"theme_switcher_json_url",
);
const wantsWarningBanner = DOCUMENTATION_OPTIONS.show_version_warning_banner;

if (hasVersionsJSON && (hasSwitcherMenu || wantsWarningBanner)) {
const data = await fetchVersionSwitcherJSON(
DOCUMENTATION_OPTIONS.theme_switcher_json_url,
async function fetchAndUseVersions() {
// fetch the JSON version data (only once), then use it to populate the version
// switcher and maybe show the version warning bar
var versionSwitcherBtns = document.querySelectorAll(
".version-switcher__button",
);
const hasSwitcherMenu = versionSwitcherBtns.length > 0;
const hasVersionsJSON = DOCUMENTATION_OPTIONS.hasOwnProperty(
"theme_switcher_json_url",
);
// TODO: remove the `if(data)` once the `return null` is fixed within fetchVersionSwitcherJSON.
// We don't really want the switcher and warning bar to silently not work.
if (data) {
populateVersionSwitcher(data, versionSwitcherBtns);
if (wantsWarningBanner) {
showVersionWarningBanner(data);
const wantsWarningBanner = DOCUMENTATION_OPTIONS.show_version_warning_banner;

if (hasVersionsJSON && (hasSwitcherMenu || wantsWarningBanner)) {
const data = await fetchVersionSwitcherJSON(
DOCUMENTATION_OPTIONS.theme_switcher_json_url,
);
// TODO: remove the `if(data)` once the `return null` is fixed within fetchVersionSwitcherJSON.
// We don't really want the switcher and warning bar to silently not work.
if (data) {
populateVersionSwitcher(data, versionSwitcherBtns);
if (wantsWarningBanner) {
showVersionWarningBanner(data);
}
}
}
}
Expand Down Expand Up @@ -718,10 +694,70 @@ function debounce(callback, wait) {
};
}

/*******************************************************************************
* Announcement banner - fetch and load remote HTML
*/
async function setupAnnouncementBanner() {
const banner = document.querySelector(".bd-header-announcement");
const { pstAnnouncementUrl } = banner.dataset;

if (!pstAnnouncementUrl) {
return;
}

try {
const response = await fetch(pstAnnouncementUrl);
if (!response.ok) {
throw new Error(
`[PST]: HTTP response status not ok: ${response.status} ${response.statusText}`,
);
}
const data = await response.text();
if (data.length === 0) {
console.log(`[PST]: Empty announcement at: ${pstAnnouncementUrl}`);
return;
}
banner.innerHTML = `<div class="bd-header-announcement__content">${data}</div>`;
banner.classList.remove("d-none");
} catch (_error) {
console.log(`[PST]: Failed to load announcement at: ${pstAnnouncementUrl}`);
console.error(_error);
}
}

/*******************************************************************************
* Reveal (and animate) the banners (version warning, announcement) together
*/
async function fetchRevealBannersTogether() {
// Wait until finished fetching and loading banners
await Promise.allSettled([fetchAndUseVersions(), setupAnnouncementBanner()]);

// The revealer element should have CSS rules that set height to 0, overflow
// to hidden, and an animation transition on the height (unless the user has
// turned off animations)
const revealer = document.querySelector(".pst-async-banner-revealer");

// Remove the d-none (display-none) class to calculate the children heights.
revealer.classList.remove("d-none");

// Add together the heights of the element's children
const height = Array.from(revealer.children).reduce(
(height, el) => height + el.offsetHeight,
0,
);

// Use the calculated height to give the revealer a non-zero height (if
// animations allowed, the height change will animate)
revealer.style.setProperty("height", `${height}px`);
}

/*******************************************************************************
* Call functions after document loading.
*/

// Call this one first to kick off the network request for the version warning
// and announcement banner data as early as possible.
documentReady(fetchRevealBannersTogether);
documentReady(addModeListener);
documentReady(scrollToActive);
documentReady(addTOCInteractivity);
Expand Down
26 changes: 15 additions & 11 deletions src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
.pst-async-banner-revealer {
// Setting height to 0 and overflow to hidden allows us to add up the heights
// of this element's children before revealing them.
height: 0;
overflow: hidden;

// Height to be set by JavaScript, which should trigger the following
// transition rule (unless the user has set their system to reduce motion).
transition: height 300ms ease-in-out;
@media (prefers-reduced-motion) {
transition: none;
}
}

.bd-header-version-warning,
.bd-header-announcement {
min-height: 3rem;
width: 100%;
display: flex;
position: relative;
align-items: center;
justify-content: center;
text-align: center;
transition: height 300ms ease-in-out;
overflow-y: hidden;
padding: 0.5rem 12.5%; // Horizontal padding so the width is 75%
// One breakpoint less than $breakpoint-sidebar-primary. See variables/_layout.scss for more info.
@include media-breakpoint-down(lg) {
// Announcements can take a bit more width on mobile
padding: 0.5rem 2%;
}

&.init {
position: fixed;
visibility: hidden;
}

p {
font-weight: bold;
margin: 0;
}

&:empty {
display: none;
}

// Ensure there is enough contrast against the background
a {
color: var(--pst-color-inline-code-links);
Expand Down
6 changes: 5 additions & 1 deletion src/pydata_sphinx_theme/locale/ca/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,11 @@ msgstr ""
"theme.readthedocs.io/en/stable/index.html\">Tema PyData Sphinx</a> "
"%(theme_version)s."

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
7 changes: 6 additions & 1 deletion src/pydata_sphinx_theme/locale/cs/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
msgid ""
msgstr ""


#: docs/conf.py:94
msgid "Click to expand"
msgstr ""
Expand Down Expand Up @@ -142,7 +143,11 @@ msgstr ""
"theme.readthedocs.io/en/stable/index.html\">PyData Sphinx Theme</a> "
"%(theme_version)s."

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
7 changes: 6 additions & 1 deletion src/pydata_sphinx_theme/locale/en/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
msgid ""
msgstr ""


#: docs/conf.py:94
msgid "Click to expand"
msgstr ""
Expand Down Expand Up @@ -135,7 +136,11 @@ msgid ""
"%(theme_version)s."
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
7 changes: 6 additions & 1 deletion src/pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
msgid ""
msgstr ""


#: docs/conf.py:94
msgid "Click to expand"
msgstr ""
Expand Down Expand Up @@ -143,7 +144,11 @@ msgstr ""
"theme.readthedocs.io/en/stable/index.html\">Tema PyData Sphinx</a> "
"%(theme_version)s."

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
7 changes: 6 additions & 1 deletion src/pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
msgid ""
msgstr ""


#: docs/conf.py:94
msgid "Click to expand"
msgstr "Cliquez pour développer"
Expand Down Expand Up @@ -144,7 +145,11 @@ msgstr ""
"theme.readthedocs.io/en/stable/index.html\">Thème PyData Sphinx</a> "
"%(theme_version)s."

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr "Annonce"

Expand Down
7 changes: 6 additions & 1 deletion src/pydata_sphinx_theme/locale/ru/LC_MESSAGES/sphinx.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
msgid ""
msgstr ""


#: docs/conf.py:94
msgid "Click to expand"
msgstr ""
Expand Down Expand Up @@ -142,7 +143,11 @@ msgstr ""
"theme.readthedocs.io/en/stable/index.html\\\">PyData Sphinx</a> "
"%(theme_version)s."

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
8 changes: 6 additions & 2 deletions src/pydata_sphinx_theme/locale/sphinx.pot
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2024-04-29 13:43+0200\n"
"POT-Creation-Date: 2024-05-10 18:43+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down Expand Up @@ -146,7 +146,11 @@ msgid ""
"%(theme_version)s."
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:1
#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:4
msgid "Version warning"
msgstr ""

#: src/pydata_sphinx_theme/theme/pydata_sphinx_theme/sections/announcement.html:6
msgid "Announcement"
msgstr ""

Expand Down
Loading

0 comments on commit bbe3e57

Please sign in to comment.