diff --git a/docs/user_guide/announcements.rst b/docs/user_guide/announcements.rst index edac65ff9..2b48829aa 100644 --- a/docs/user_guide/announcements.rst +++ b/docs/user_guide/announcements.rst @@ -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: diff --git a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js index ccefaebee..dc5b44c6f 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -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 = @@ -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"); } /******************************************************************************* @@ -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); + } } } } @@ -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 = `
${data}
`; + 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); diff --git a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss index 8fbc50b3c..331014be3 100644 --- a/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss +++ b/src/pydata_sphinx_theme/assets/styles/sections/_announcement.scss @@ -1,13 +1,26 @@ +.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) { @@ -15,20 +28,11 @@ 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); diff --git a/src/pydata_sphinx_theme/locale/ca/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/ca/LC_MESSAGES/sphinx.po index cc2090fd1..8926998f2 100644 --- a/src/pydata_sphinx_theme/locale/ca/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/ca/LC_MESSAGES/sphinx.po @@ -143,7 +143,11 @@ msgstr "" "theme.readthedocs.io/en/stable/index.html\">Tema PyData Sphinx " "%(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 "" diff --git a/src/pydata_sphinx_theme/locale/cs/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/cs/LC_MESSAGES/sphinx.po index 269f014c3..91690218d 100644 --- a/src/pydata_sphinx_theme/locale/cs/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/cs/LC_MESSAGES/sphinx.po @@ -8,6 +8,7 @@ msgid "" msgstr "" + #: docs/conf.py:94 msgid "Click to expand" msgstr "" @@ -142,7 +143,11 @@ msgstr "" "theme.readthedocs.io/en/stable/index.html\">PyData Sphinx Theme " "%(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 "" diff --git a/src/pydata_sphinx_theme/locale/en/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/en/LC_MESSAGES/sphinx.po index 65bee9b24..093a8c841 100644 --- a/src/pydata_sphinx_theme/locale/en/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/en/LC_MESSAGES/sphinx.po @@ -6,6 +6,7 @@ msgid "" msgstr "" + #: docs/conf.py:94 msgid "Click to expand" msgstr "" @@ -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 "" diff --git a/src/pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po index 8cc5248bd..46adf1fa6 100644 --- a/src/pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/es/LC_MESSAGES/sphinx.po @@ -9,6 +9,7 @@ msgid "" msgstr "" + #: docs/conf.py:94 msgid "Click to expand" msgstr "" @@ -143,7 +144,11 @@ msgstr "" "theme.readthedocs.io/en/stable/index.html\">Tema PyData Sphinx " "%(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 "" diff --git a/src/pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po index 17f5dca6c..9ae92281a 100644 --- a/src/pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/fr/LC_MESSAGES/sphinx.po @@ -10,6 +10,7 @@ msgid "" msgstr "" + #: docs/conf.py:94 msgid "Click to expand" msgstr "Cliquez pour développer" @@ -144,7 +145,11 @@ msgstr "" "theme.readthedocs.io/en/stable/index.html\">Thème PyData Sphinx " "%(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" diff --git a/src/pydata_sphinx_theme/locale/ru/LC_MESSAGES/sphinx.po b/src/pydata_sphinx_theme/locale/ru/LC_MESSAGES/sphinx.po index 65d7cf2c4..de1ba6d09 100644 --- a/src/pydata_sphinx_theme/locale/ru/LC_MESSAGES/sphinx.po +++ b/src/pydata_sphinx_theme/locale/ru/LC_MESSAGES/sphinx.po @@ -8,6 +8,7 @@ msgid "" msgstr "" + #: docs/conf.py:94 msgid "Click to expand" msgstr "" @@ -142,7 +143,11 @@ msgstr "" "theme.readthedocs.io/en/stable/index.html\\\">PyData Sphinx " "%(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 "" diff --git a/src/pydata_sphinx_theme/locale/sphinx.pot b/src/pydata_sphinx_theme/locale/sphinx.pot index 69fbdc69c..11c7f142d 100644 --- a/src/pydata_sphinx_theme/locale/sphinx.pot +++ b/src/pydata_sphinx_theme/locale/sphinx.pot @@ -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 \n" "Language-Team: LANGUAGE \n" @@ -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 "" diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html index 9c577da05..9fb914b50 100644 --- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html +++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html @@ -68,9 +68,8 @@
{% include "../components/search-field.html" %}
- {%- if theme_announcement -%} - {% include "sections/announcement.html" %} - {%- endif %} + {% include "sections/announcement.html" %} + {% block docs_navbar %}