diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b32f6964c..c8381aa89 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -97,6 +97,7 @@ jobs: uses: codecov/codecov-action@v4 with: fail_ci_if_error: true + verbose: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/babel.cfg b/babel.cfg index 6d040b9b9..c835a5d51 100644 --- a/babel.cfg +++ b/babel.cfg @@ -1,4 +1,5 @@ -# See https://github.com/sphinx-doc/sphinx/blob/6.1.x/babel.cfg +# See https://github.com/python-babel/babel/blob/2a1709a7768f6f07c3d2dbfdb03d3c8a6bd80aef/docs/messages.rst#extraction-method-mapping-and-configuration +[python: **.py] [jinja2: **.html] encoding = utf-8 ignore_tags = script,style diff --git a/docs/_static/pydata-icon.js b/docs/_static/pydata-icon.js new file mode 100644 index 000000000..d111ec834 --- /dev/null +++ b/docs/_static/pydata-icon.js @@ -0,0 +1,16 @@ +/******************************************************************************* + * Set a custom icon for PyData + */ +FontAwesome.library.add( + (faListOldStyle = { + prefix: "fa-custom", + iconName: "pydata", + icon: [ + 24, // viewBox width + 24, // viewBox height + [], // ligature + "e002", // unicode codepoint - private use area + "M12.1,17.8v5.8l-5-2.9v-5.8L12.1,17.8z M12.1,12v5.8l-5-2.9V9.1L12.1,12z M17,9.1L12.1,12v5.8l4.9-2.9V9.1z M12.1,6.2L7,9.1l5,2.9L17,9.1L12.1,6.2z M17,9.1V3.3l-4.9-2.8v5.8L17,9.1z", + ], + }) +); diff --git a/docs/_static/pydata-logo.png b/docs/_static/pydata-logo.png deleted file mode 100644 index bfdf323b9..000000000 Binary files a/docs/_static/pydata-logo.png and /dev/null differ diff --git a/docs/conf.py b/docs/conf.py index cd2827596..601d99451 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,6 +13,7 @@ import pydata_sphinx_theme from sphinx.application import Sphinx +from sphinx.locale import _ sys.path.append(str(Path(".").resolve())) @@ -89,6 +90,11 @@ "jupyter": ("Jupyter", "https://jupyter.org"), } +# -- sphinx_togglebutton options --------------------------------------------- +togglebutton_hint = str(_("Click to expand")) +togglebutton_hint_hide = str(_("Click to collapse")) + + # -- Options for HTML output ------------------------------------------------- html_theme = "pydata_sphinx_theme" @@ -153,9 +159,7 @@ { "name": "PyData", "url": "https://pydata.org", - "icon": "_static/pydata-logo.png", - "type": "local", - "attributes": {"target": "_blank"}, + "icon": "fa-custom fa-pydata", }, ], # alternative way to set twitter and github header icons @@ -228,7 +232,7 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] html_css_files = ["custom.css"] -html_js_files = ["custom-icon.js"] +html_js_files = ["pydata-icon.js", "custom-icon.js"] todo_include_todos = True # -- favicon options --------------------------------------------------------- diff --git a/docs/examples/gallery.md b/docs/examples/gallery.md index 755c63661..f2a7a21e7 100644 --- a/docs/examples/gallery.md +++ b/docs/examples/gallery.md @@ -38,8 +38,8 @@ Thanks for your support! - title: Feature-engine link-alt: Feature-engine docs link: https://feature-engine.readthedocs.io/ -- title: idtracker.ai - link-alt: idtracker.ai docs +- title: idtracker.ai + link-alt: idtracker.ai docs link: https://idtracker.ai/ - title: MegEngine link-alt: MegEngine docs diff --git a/docs/index.md b/docs/index.md index 0e5562f93..c5f5d407f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -21,13 +21,11 @@ A clean, Bootstrap-based Sphinx theme by and for [the PyData community](https:// - header: "{fas}`circle-half-stroke;pst-color-primary` Light / Dark theme" content: "Users can toggle between light and dark themes interactively." - header: "{fas}`palette;pst-color-primary` Customizable UI and themes" - content: "Customize colors and branding with CSS variables, and build custom UIs with [Sphinx Design](user_guide/web-components)." + content: "Customize colors and branding with CSS variables, and build custom UIs with [Sphinx Design components](user_guide/web-components)." - header: "{fab}`python;pst-color-primary` Supports PyData and Jupyter" - content: "CSS and UI support for Jupyter extensions and PyData execution outputs." - link: "examples/pydata.html" + content: "CSS and UI support for [Jupyter extensions](examples/execution) and [PyData execution outputs](examples/pydata.ipynb)." - header: "{fas}`lightbulb;pst-color-primary` Example Gallery" - content: "See our gallery of projects that use this theme." - link: "examples/gallery.html" + content: "See [our gallery](examples/gallery.md) of projects that use this theme." ``` ```{seealso} diff --git a/docs/user_guide/accessibility.md b/docs/user_guide/accessibility.md index 13cf9b1ed..01ca24329 100644 --- a/docs/user_guide/accessibility.md +++ b/docs/user_guide/accessibility.md @@ -33,6 +33,14 @@ page that lacks metadata, please open a pull request to add it! - We have improved how we assign text colors to interactive elements such as buttons and dropdowns to ensure that they meet WCAG 2 AA or AAA contrast requirements. +### Keyboard Navigation Support + +For all buttons, dropdowns, tabbed panels, hamburger menus, modals, overlays, +links and other interactive elements, we have worked to ensure they: + +- Have a visible focus indicator (WCAG 2.4.7) +- Can be accessed via keyboard navigation (WCAG 2.1.1) + ## What You Can Do ### Site configuration diff --git a/docs/user_guide/styling.rst b/docs/user_guide/styling.rst index 3e2df90a2..22136676d 100644 --- a/docs/user_guide/styling.rst +++ b/docs/user_guide/styling.rst @@ -117,18 +117,18 @@ Here is an overview of the colors available in the theme (change theme mode to s

- primary - secondary - accent - success - info - warning - danger - background - on-background - surface - on-surface - target + primary + secondary + accent + success + info + warning + danger + background + on-background + surface + on-surface + target

diff --git a/docs/user_guide/web-components.rst b/docs/user_guide/web-components.rst index 8527d5e20..4df92256d 100644 --- a/docs/user_guide/web-components.rst +++ b/docs/user_guide/web-components.rst @@ -4,16 +4,31 @@ Sphinx Design Components ======================== -The PyData Sphinx Theme uses `sphinx-design `__ -to add several UI components and provide extra flexibility for content creation. -These include badges, buttons, cards, and tabs, among other components. -This theme provides custom CSS to ensure that `sphinx-design `__ elements look and feel consistent with this theme. +On this page, you will find user interface components such as badges, buttons, +cards, and tabs. + +The components on this page are **not provided by PyData Theme**. They are +provided by `Sphinx Design _` (a Sphinx extension). This means that if you wish +to use the components on this page, you must install Sphinx Design separately and add it to your `conf.py`. .. seealso:: - For more information about how to use these extensions, see `the sphinx-design documentation `_. + To add the Sphinx Design extension to your Sphinx project, refer to `Sphinx + Design - Getting Started + `_. + +Contributors to both projects have worked to ensure compatible styling so that +Sphinx Design components look and feel consistent with the PyData Theme. + +This page shows you how the Sphinx Design components would look on your site if +you were to use them in combination with the PyData Theme. Sphinx Design also +provides a `PyData-themed version of the Sphinx Design site +`__; however, their site +use an older version of this theme. -Below you can find some examples of the components created with the :code:`sphinx-design` extension. +Any customizations you make to the theme could affect how these components +appear on your site. So what you see on this page might not match exactly what +you see on your site even if your site uses this theme. .. _badges-buttons: diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index f2d227130..77ab0dc11 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -194,6 +194,18 @@ def update_and_remove_templates( if asset_path == theme_css_name: del context["css_files"][i] break + # Add links for favicons in the topbar + for favicon in context.get("theme_favicons", []): + icon_type = Path(favicon["href"]).suffix.strip(".") + opts = { + "rel": favicon.get("rel", "icon"), + "sizes": favicon.get("sizes", "16x16"), + "type": f"image/{icon_type}", + } + if "color" in favicon: + opts["color"] = favicon["color"] + # Sphinx will auto-resolve href if it's a local file + app.add_css_file(favicon["href"], **opts) # Add metadata to DOCUMENTATION_OPTIONS so that we can re-use later # Pagename to current page 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 0dcc6ae42..e15194550 100644 --- a/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js +++ b/src/pydata_sphinx_theme/assets/scripts/pydata-sphinx-theme.js @@ -489,7 +489,7 @@ function showVersionWarningBanner(data) { middle.classList = "bd-header-announcement__content"; inner.classList = "sidebar-message"; button.classList = - "sd-btn sd-btn-danger sd-shadow-sm sd-text-wrap font-weight-bold ms-3 my-1 align-baseline"; + "btn text-wrap font-weight-bold ms-3 my-1 align-baseline pst-button-link-to-stable-version"; button.href = `${preferredURL}${DOCUMENTATION_OPTIONS.pagename}.html`; button.innerText = "Switch to stable version"; button.onclick = checkPageExistsAndRedirect; @@ -609,6 +609,89 @@ function fixMoreLinksInMobileSidebar() { } } +/******************************************************************************* + * Add keyboard functionality to mobile sidebars. + * + * Wire up the hamburger-style buttons using the click event which (on buttons) + * handles both mouse clicks and the space and enter keys. + */ +function setupMobileSidebarKeyboardHandlers() { + // These are hidden checkboxes at the top of the page whose :checked property + // allows the mobile sidebars to be hidden or revealed via CSS. + const primaryToggle = document.getElementById("pst-primary-sidebar-checkbox"); + const secondaryToggle = document.getElementById( + "pst-secondary-sidebar-checkbox" + ); + const primarySidebar = document.querySelector(".bd-sidebar-primary"); + const secondarySidebar = document.querySelector(".bd-sidebar-secondary"); + + // Toggle buttons - + // + // These are the hamburger-style buttons in the header nav bar. When the user + // clicks, the button transmits the click to the hidden checkboxes used by the + // CSS to control whether the sidebar is open or closed. + const primaryClickTransmitter = document.querySelector(".primary-toggle"); + const secondaryClickTransmitter = document.querySelector(".secondary-toggle"); + [ + [primaryClickTransmitter, primaryToggle, primarySidebar], + [secondaryClickTransmitter, secondaryToggle, secondarySidebar], + ].forEach(([clickTransmitter, toggle, sidebar]) => { + if (!clickTransmitter) { + return; + } + clickTransmitter.addEventListener("click", (event) => { + event.preventDefault(); + event.stopPropagation(); + toggle.checked = !toggle.checked; + + // If we are opening the sidebar, move focus to the first focusable item + // in the sidebar + if (toggle.checked) { + // Note: this selector is not exhaustive, and we may need to update it + // in the future + const tabStop = sidebar.querySelector("a, button"); + // use setTimeout because you cannot move focus synchronously during a + // click in the handler for the click event + setTimeout(() => tabStop.focus(), 100); + } + }); + }); + + // Escape key - + // + // When sidebar is open, user should be able to press escape key to close the + // sidebar. + [ + [primarySidebar, primaryToggle, primaryClickTransmitter], + [secondarySidebar, secondaryToggle, secondaryClickTransmitter], + ].forEach(([sidebar, toggle, transmitter]) => { + if (!sidebar) { + return; + } + sidebar.addEventListener("keydown", (event) => { + if (event.key === "Escape") { + event.preventDefault(); + event.stopPropagation(); + toggle.checked = false; + transmitter.focus(); + } + }); + }); + + // When the