Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/sections/header.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ If any of this configuration is set, then your header will show at the top of th

## Add components to the header navbar

There are three configuration options you can use in `html_theme_options`:
There are four configuration options you can use in `html_theme_options`:

**`navbar_start`**: Adds components to the beginning of the header. **Visible on all screen sizes**. Use this for adding a logo that you want to persist over time.

**`navbar_center`**: Adds components to the center of the header, or to the left if no `navbar_start` is defined. **Moved to the sizebar on mobile**. Use this for extra navigation content to external pages.

**`navbar_end`**: Adds components to the end of the header. **Moved to the sizebar on mobile**. Use this for extra social links or buttons.

**`navbar_persistent`**: Adds components to the end of the header that stay there on mobile rather than moving to the sidebar.

## An example

For example, you can add a button to the header like so:
Expand Down
12 changes: 12 additions & 0 deletions src/sphinx_book_theme/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,15 @@ def update_mode_thebe_config(app):
app.env.config.thebe_config = thebe_config


def update_navbar_defaults(app):
"""Keep the top navbar empty unless the user asks for something in it.

Without this, the pydata theme adds a search button to the navbar.
"""
theme_options = get_theme_options_dict(app)
theme_options.setdefault("navbar_persistent", [])


def check_deprecation_keys(app):
"""Warns about the deprecated keys."""

Expand Down Expand Up @@ -218,6 +227,9 @@ def setup(app: Sphinx):
app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir)

# Events
app.connect(
"builder-inited", update_navbar_defaults, priority=400
) # before pydata theme
app.connect("builder-inited", update_mode_thebe_config)
app.connect("builder-inited", check_deprecation_keys)
app.connect("builder-inited", update_sourcename)
Expand Down
8 changes: 8 additions & 0 deletions src/sphinx_book_theme/theme/sphinx_book_theme/layout.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
{% extends "pydata_sphinx_theme/layout.html" %}
{# ref: https://github.com/pydata/pydata-sphinx-theme/blob/master/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html #}

{# Skip <header> when no navbar area has any content in it. #}
{% block docs_navbar %}
{%- if theme_navbar_start or theme_navbar_center or theme_navbar_end or theme_navbar_persistent %}
{{ super() }}
{%- endif %}
{% endblock docs_navbar %}


{% block docs_main %}
{# A tiny helper pixel to detect if we've scrolled #}
<div class="sbt-scroll-pixel-helper"></div>
Expand Down
20 changes: 20 additions & 0 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,26 @@ def test_navbar_options_home_page_in_toc(sphinx_build_factory):
assert "Index with code in title" in str(li)


def test_no_navbar_by_default(sphinx_build_factory):
"""The top navbar is opt-in, so nothing should be rendered for it."""
sphinx_build = sphinx_build_factory("base").build(assert_pass=True) # type: SphinxBuild
index = sphinx_build.html_tree("index.html")
assert index.find(id="pst-header") is None
# The only search button is the one in the primary sidebar
search_buttons = index.select("button.search-button-field")
assert len(search_buttons) == 1
assert search_buttons[0].find_parent(id="pst-primary-sidebar") is not None


def test_navbar_opt_in(sphinx_build_factory):
"""Filling in any navbar area brings the top navbar back."""
sphinx_build = sphinx_build_factory(
"base",
confoverrides={"html_theme_options.navbar_center": ["navbar-nav.html"]},
).build(assert_pass=True) # type: SphinxBuild
assert sphinx_build.html_tree("index.html").find(id="pst-header") is not None


@pytest.mark.parametrize(
"option,value",
[
Expand Down
Loading