Skip to content

Commit 0596d44

Browse files
committed
ENH: Standardize header buttons
1 parent 056d66e commit 0596d44

36 files changed

+991
-457
lines changed

.github/workflows/tests.yml

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ jobs:
111111
--exclude 'someurl'
112112
--exclude 'mailto:docutils-develop'
113113
--exclude 'pathto\('
114+
--exclude 'deepnote.com'
114115
115116
- name: Audit with Lighthouse
116117
uses: treosh/lighthouse-ci-action@v8

ARCHITECTURE.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ This folder contains all of the source files for this theme, and most changes to
1717
This module does things like load in Sphinx's default HTML for the sidebar, and modify it in order to have dropdown nested lists.
1818
It also inserts several variables into the Jinja template context that are then used in our HTML templates.
1919

20-
`launch.py`
20+
`header_buttons/`
21+
: Scripts to generate metadata for buttons in the header. We use [Jinja Macros](https://jinja.palletsprojects.com/en/3.0.x/templates/) (in the `macros/` folder) to generate the HTML for header buttons. The scripts in `header_buttons/` generate the data structure that is used to generate buttons with these macros (in the `header-article.html` template).
22+
23+
`header_buttons/launch.py`
2124
: Logic to create the correct URLs for our launch buttons. This basically means building the URL for a given launch service in a proper fashion.
2225

2326
The other folders in this section are described in the next few sections.
@@ -31,6 +34,9 @@ These follow the [`sphinx-basic-ng` template structure](https://sphinx-basic-ng.
3134

3235
- `layout.html` inherits from the [pydata sphinx theme](https://pydata-sphinx-theme.readthedocs.io/) and modifies several sections.
3336
- `theme.conf` contains the Sphinx configuration file for this theme.
37+
- `macros/` contains HTML templates that define Jinja macros
38+
- `sections/` contains HTML templates for major sections of the page.
39+
- `components/` contains HTML templates for smaller, self-contained parts of the page.
3440

3541
### `/assets/scripts` - JavaScript assets
3642

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ This updates to the latest PyData Sphinx Theme, which re-works some of the HTML
160160
### New features added
161161

162162
- Added tag for cell-input [#259](https://github.com/executablebooks/sphinx-book-theme/pull/259) ([@AakashGfude](https://github.com/AakashGfude))
163-
- Add a shadow to topbar, on scroll [#255](https://github.com/executablebooks/sphinx-book-theme/pull/255) ([@pradyunsg](https://github.com/pradyunsg))
163+
- Add a shadow to header, on scroll [#255](https://github.com/executablebooks/sphinx-book-theme/pull/255) ([@pradyunsg](https://github.com/pradyunsg))
164164
- Add CSS to center align images with class [#292](https://github.com/executablebooks/sphinx-book-theme/pull/292) ([@DrDrij](https://github.com/DrDrij))
165165

166166
### Enhancements made

docs/customize/index.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ The following options are available via `html_theme_options`
2626
- Branch of the repository for the documentation (e.g., `master`, `main`, `docs`). See [](source-files:repository).
2727
* - `use_issues_button`
2828
- bool
29-
- Add an button in the topbar with a link to issues for the repository (used in conjunction with `repository_url` and `repository_branch`). See [](source-files:repository).
29+
- Add an button in the header with a link to issues for the repository (used in conjunction with `repository_url` and `repository_branch`). See [](source-files:repository).
3030
* - `use_download_button`
3131
- bool
32-
- Add a button in the topbar to download the source file of the page. See [](customize:source-files).
32+
- Add a button in the header to download the source file of the page. See [](customize:source-files).
3333
* - `use_fullscreen_button`
3434
- bool
35-
- Add a button in the topbar to trigger full-screen mode.
35+
- Add a button in the header to trigger full-screen mode.
3636
* - `use_repository_button`
3737
- bool
38-
- Add a button in the topbar that links to the repository of the documentation.See [](source-files:repository).
38+
- Add a button in the header that links to the repository of the documentation.See [](source-files:repository).
3939
* - `launch_buttons`
4040
- bool
4141
- Include Binder launch buttons for pages that were built from Jupyter Notebooks. See [](customize:launch).

docs/customize/sidebar-secondary.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Customize the secondary sidebar
22

33
The secondary sidebar contains information about the current page.
4-
It begins at the top of the page (in the topbar), and extends downwards (by default, from the right side of the page).
4+
It begins at the top of the page (in the header), and extends downwards (by default, from the right side of the page).
55
This page describes ways to control and customize the secondary sidebar.
66

77
## Rename the in-page Table of Contents

docs/tutorials/get-started.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ html_theme_options = {
5959
}
6060
```
6161

62-
When you build your documentation, your topbar should now include a small GitHub logo that has a link to the repository.
62+
When you build your documentation, your header should now include a small GitHub logo that has a link to the repository.
6363

6464

6565
:::{seealso}

src/sphinx_book_theme/__init__.py

+12-53
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
from sphinx.locale import get_translation
99
from sphinx.util import logging
1010

11-
from .launch import add_hub_urls
11+
from .header_buttons import prep_header_buttons, add_header_buttons
12+
from .header_buttons.launch import add_launch_buttons
1213

1314
__version__ = "0.2.0"
1415
"""sphinx-book-theme version"""
@@ -24,8 +25,8 @@ def get_html_theme_path():
2425
return theme_path
2526

2627

27-
def add_to_context(app, pagename, templatename, context, doctree):
28-
28+
def add_metadata_to_page(app, pagename, templatename, context, doctree):
29+
"""Adds some metadata about the page that we re-use later."""
2930
# Add the site title to our context so it can be inserted into the navbar
3031
if not context.get("root_doc"):
3132
# TODO: Sphinx renamed master to root in 4.x, deprecate when we drop 3.x
@@ -49,43 +50,7 @@ def add_to_context(app, pagename, templatename, context, doctree):
4950
if app.config.author != "unknown":
5051
context["author"] = app.config.author
5152

52-
# Add HTML context variables that the pydata theme uses that we configure elsewhere
53-
# For some reason the source_suffix sometimes isn't there even when doctree is
54-
if doctree and context.get("page_source_suffix"):
55-
config_theme = app.config.html_theme_options
56-
repo_url = config_theme.get("repository_url", "")
57-
# Only add the edit button if `repository_url` is given
58-
if repo_url:
59-
branch = config_theme.get("repository_branch")
60-
if not branch:
61-
# Explicitly check in cae branch is ""
62-
branch = "master"
63-
relpath = config_theme.get("path_to_docs", "")
64-
org, repo = repo_url.strip("/").split("/")[-2:]
65-
context.update(
66-
{
67-
"github_user": org,
68-
"github_repo": repo,
69-
"github_version": branch,
70-
"doc_path": relpath,
71-
}
72-
)
73-
else:
74-
# Disable using the button so we don't get errors
75-
context["theme_use_edit_page_button"] = False
76-
77-
# Make sure the context values are bool
78-
btns = [
79-
"theme_use_edit_page_button",
80-
"theme_use_repository_button",
81-
"theme_use_issues_button",
82-
"theme_use_download_button",
83-
"theme_use_fullscreen_button",
84-
]
85-
for key in btns:
86-
if key in context:
87-
context[key] = _string_or_bool(context[key])
88-
53+
# Translations
8954
translation = get_translation(MESSAGE_CATALOG_NAME)
9055
context["translate"] = translation
9156
# this is set in the html_theme
@@ -128,15 +93,6 @@ def update_thebe_config(app):
12893
app.env.config.thebe_config = thebe_config
12994

13095

131-
def _string_or_bool(var):
132-
if isinstance(var, str):
133-
return var.lower() == "true"
134-
elif isinstance(var, bool):
135-
return var
136-
else:
137-
return var is None
138-
139-
14096
class Margin(Sidebar):
14197
"""Goes in the margin to the right of the page."""
14298

@@ -159,16 +115,19 @@ def run(self):
159115
def setup(app: Sphinx):
160116
app.connect("builder-inited", update_thebe_config)
161117

162-
# Configuration for Juypter Book
163-
app.connect("html-page-context", add_hub_urls)
164-
165118
# add translations
166119
theme_dir = get_html_theme_path()
167120
locale_dir = os.path.join(theme_dir, "static", "locales")
168121
app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir)
169122

170123
app.add_html_theme("sphinx_book_theme", theme_dir)
171-
app.connect("html-page-context", add_to_context)
124+
app.connect("html-page-context", add_metadata_to_page)
125+
126+
# Header buttons
127+
app.connect("html-page-context", prep_header_buttons)
128+
app.connect("html-page-context", add_launch_buttons)
129+
# Bump priority by 1 so that it runs after the pydata theme sets up the edit URL.
130+
app.connect("html-page-context", add_header_buttons, priority=501)
172131

173132
app.add_directive("margin", Margin)
174133

src/sphinx_book_theme/_compile_translations.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,18 @@
1111
}
1212

1313

14-
def convert_json():
14+
def convert_json(folder=None):
15+
"""Convert JSON translations into .mo/.po files for Sphinx.
16+
17+
folder:
18+
the source folder of the JSON translations. This function will put the
19+
compiled .mo/.po files in a specific folder relative to this source
20+
folder. This parameter is just provided to make testing easier.
21+
"""
1522
# Raw translation JSONs that are hand-edited
16-
folder = Path(__file__).parent / "assets" / "translations"
23+
folder = folder or Path(__file__).parent / "assets" / "translations"
1724
# Location of compiled static translation assets
18-
out_folder = Path(__file__).parent / "theme" / "sphinx_book_theme" / "static"
25+
out_folder = folder / ".." / ".." / "theme" / "sphinx_book_theme" / "static"
1926

2027
# compile po
2128
for path in (folder / "jsons").glob("*.json"):

src/sphinx_book_theme/assets/scripts/index.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ var initThebeSBT = () => {
176176
*/
177177
var initTooltips = () => {
178178
$(document).ready(function () {
179-
$('[data-toggle="tooltip"]').tooltip({ trigger: "hover" });
179+
$('[data-toggle="tooltip"]').tooltip({
180+
trigger: "hover",
181+
delay: { show: 500, hide: 100 },
182+
});
180183
});
181184
};
182185

src/sphinx_book_theme/assets/styles/abstracts/_variables.scss

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ $grey--medium: #aaa;
1313
$grey--light: #ccc;
1414
$non-content-grey: $grey--dark;
1515

16-
$topbar-height: 3em;
16+
$header-article-height: 3em;
1717
$leftbar-width-mobile: 75%;
1818
$leftbar-width-wide: 275px;
1919
$toc-width-mobile: 75%;
@@ -58,7 +58,7 @@ $border-thin: 1px solid rgba(0, 0, 0, 0.1);
5858

5959
// Variables for this theme
6060
--sbt-sidebar-font-size: var(--sbt-font-size-small-1);
61-
--sbt-topbar-font-size: var(--sbt-font-size-small-1);
61+
--sbt-header-article-font-size: var(--sbt-font-size-small-1);
6262
--sbt-prevnext-font-size: var(--sbt-font-size-small-1);
6363
--sbt-footer-font-size: var(--sbt-font-size-small-1);
6464
}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
11
/*********************************************
2-
* Buttons, mostly for the topbar *
2+
* Buttons, mostly for the headers *
33
*********************************************/
4-
.topbarbtn,
5-
.topbarbtn--wide {
4+
/**
5+
* Basic button style
6+
*/
7+
.headerbtn {
68
display: flex;
79
align-items: center;
810
justify-content: center;
911

10-
img {
11-
height: 1.15em;
12-
padding-right: 6px;
13-
margin-left: -5px;
14-
}
15-
16-
// Icon inside the button
17-
i {
18-
vertical-align: baseline;
19-
line-height: 1;
20-
}
21-
}
22-
23-
.topbarbtn {
2412
background-color: white;
2513
color: $non-content-grey;
2614
cursor: pointer;
@@ -35,47 +23,94 @@
3523
color: black;
3624
background-color: white;
3725
box-shadow: none;
26+
text-decoration: none;
27+
}
28+
29+
span {
30+
display: flex;
31+
align-items: center;
32+
}
33+
34+
img,
35+
i {
36+
margin: auto;
3837
}
3938
}
4039

41-
// Buttons with a dropdown list underneath
42-
div.dropdown-buttons-trigger {
43-
div.dropdown-buttons {
44-
display: none;
45-
position: absolute;
46-
max-width: 130px;
47-
margin-top: 0;
48-
z-index: 1000;
49-
transform: translate(-70%);
50-
51-
// Create extra spacing for these icons since they have
52-
i {
53-
margin-right: 0.5em;
54-
}
40+
/**
41+
* Dropdown groups of buttons
42+
*/
43+
.menu-dropdown__trigger:hover + .menu-dropdown__content,
44+
.menu-dropdown__content:hover {
45+
visibility: visible;
46+
opacity: 1;
47+
transform: translate(-70%); // To achieve a slight shift effect
48+
}
49+
50+
.menu-dropdown__content {
51+
// Hide by default, we'll show on hover
52+
position: absolute;
53+
visibility: hidden;
54+
opacity: 0;
55+
transform: translate(-65%);
56+
transition: opacity 0.2s ease-out, transform 0.2s ease-out;
5557

56-
// Links shouldn't have any effect when hovered
57-
a:hover {
58-
text-decoration: none;
58+
// Spacing and position
59+
width: 13em;
60+
z-index: 1000;
61+
border-radius: $box-border-radius;
62+
box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.25);
63+
padding: 0.5em;
64+
65+
// Style
66+
font-size: 0.9em;
67+
background-color: white;
68+
69+
.headerbtn {
70+
justify-content: left;
71+
72+
// Center the icon in the available white space
73+
i,
74+
img {
75+
margin: auto;
5976
}
6077

61-
// Wide topbar buttons have dark backgrounds since they hover over text
62-
.topbarbtn--wide {
63-
font-size: 1em;
64-
padding-top: 0.35rem;
65-
padding-bottom: 0.35rem;
66-
min-width: 125px !important;
67-
border: 1px white solid !important;
68-
background-color: $non-content-grey;
69-
color: white;
70-
border-radius: 0.5em;
78+
img {
79+
width: 1em;
7180
}
7281
}
7382

74-
&:hover div.dropdown-buttons {
75-
display: block;
83+
ul {
84+
list-style: none;
85+
padding-left: 0;
86+
margin-bottom: 0;
87+
}
88+
89+
a,
90+
button {
91+
padding: 0;
92+
}
93+
94+
span {
95+
display: flex;
96+
}
97+
98+
span.headerbtn__icon-container {
99+
width: 2em;
100+
}
101+
102+
span.headerbtn__text-container {
103+
flex-grow: 1;
76104
}
77105
}
78106

79-
a.dropdown-buttons i {
80-
margin-right: 0.5em;
107+
/**
108+
* In-page table of contents
109+
*/
110+
.headerbtn-page-toc {
111+
// Hide the button on wide screens since we display the TOC.
112+
display: block;
113+
@media (min-width: $breakpoint-md) {
114+
display: none;
115+
}
81116
}

0 commit comments

Comments
 (0)