diff --git a/docs/_data/config-header.yml b/docs/_data/config-header.yml
index 0a3b9432..afae02e1 100644
--- a/docs/_data/config-header.yml
+++ b/docs/_data/config-header.yml
@@ -39,7 +39,9 @@ end:
icon: fab fa-github-square
title: GitHub
url: https://github.com/executablebooks
- - type: button
- icon: fas fa-comments
- title: Forum
- url: https://github.com/orgs/executablebooks/discussions
+ - type: button
+ icon: fas fa-comments
+ outline: true
+ content: Discussion
+ classes: text-primary
+ url: https://github.com/orgs/executablebooks/discussions
diff --git a/docs/_static/custom.css b/docs/_static/custom.css
index f0483400..ac67b7b1 100644
--- a/docs/_static/custom.css
+++ b/docs/_static/custom.css
@@ -1,3 +1,6 @@
:root {
- --sd-color-primary: #f37726;
+ /* WONT WORK UNTIL THE NEXT PYDATA THEME IS RELEASED
+ --sbt-color-primary: #f37726;
+ --sd-color-primary: var(--sbt-color-primary);
+ */
}
diff --git a/src/sphinx_book_theme/__init__.py b/src/sphinx_book_theme/__init__.py
index cc305967..ae17a4c4 100644
--- a/src/sphinx_book_theme/__init__.py
+++ b/src/sphinx_book_theme/__init__.py
@@ -76,9 +76,8 @@ def render_component(component):
output = COMPONENT_FUNCS[kind](app, context, **component_copy)
except Exception as exc:
msg = f"Component render failure for:\n{component}\n\n"
- msg += f"Exception: {exc}"
SPHINX_LOGGER.warn(msg)
- return
+ raise exc
return output
context["theme_render_component"] = render_component
diff --git a/src/sphinx_book_theme/_components.py b/src/sphinx_book_theme/_components.py
index b6726917..fb375eaf 100644
--- a/src/sphinx_book_theme/_components.py
+++ b/src/sphinx_book_theme/_components.py
@@ -16,22 +16,66 @@
def component_button(
app,
context,
- content="",
- title="",
- icon="",
- image="",
- url="",
- onclick="",
- button_id="",
- label_for="",
- id="",
- tooltip_placement="",
+ content=None,
+ title=None,
+ icon=None,
+ image=None,
+ outline=None,
+ id=None,
+ tooltip_placement=None,
+ url=None,
+ onclick=None,
+ button_id=None,
+ label_for=None,
attributes={},
classes=[],
):
+ """Render a clickable button.
+
+ There are three possible actions that will be triggered,
+ corresponding to different kwargs having values.
+
+ Meta Parameters
+ ---------------
+ app: An instance of sphinx.Application
+ context: A Sphinx build context dictionary
+
+ General parameters
+ ------------------
+ content: Content to populate inside the button.
+ title: A tooltip / accessibility-friendly title.
+ icon: A tiny square icon. A set of FontAwesome icon classes, or path to an image.
+ image: A larger image of any aspect ratio. A path to a local or remote image.
+ button_id: The ID to be added to this button.
+ outline: Whether to outline the button.
+ tooltip_placement: Whether the tooltip will be to the left, right, top, or bottom.
+ attributes: A dictionary of any key:val attributes to add to the button.
+ classes: A list of CSS classes to add to the button.
+
+ Action-specific parameters
+ --------------------------
+ url: The URL to which a button will direct when clicked.
+ onclick: JavaScript that will be called when a person clicks.
+ label_for: The input this label should trigger when clicked (button is a label).
+ """
+ # Set up attributes and classes that will be used to create HTML attributes at end
attributes = attributes.copy()
- attributes.update({"type": "button", "class": ["btn", "icon-button"]})
- attributes["class"].extend(classes.copy())
+ attributes.update({"type": "button"})
+
+ # Update classes with custom added ones
+ default_classes = ["btn", "icon-button"]
+ if classes:
+ if isinstance(classes, str):
+ classes = [classes]
+ else:
+ classes = []
+ classes.extend(default_classes)
+
+ # Give an outline if desired.
+ if outline:
+ classes.append("btn-outline")
+
+ # Checks for proper arguments
btn_content = ""
if url and onclick:
raise Exception("Button component cannot have both url and onclick specified.")
@@ -62,33 +106,23 @@ def component_button(
"""
if not content:
- attributes["class"].append("icon-button-no-content")
+ classes.append("icon-button-no-content")
else:
- btn_content += content
+ btn_content += f'{content}'
if button_id:
attributes["id"] = button_id
- attributes["aria-label"] = title
-
- # Handle tooltips
- title = context["translate"](title)
- tooltip_placement = "bottom" if not tooltip_placement else tooltip_placement
-
- # If we're already using data-toggle, wrap the button content in a span.
- # This lets us use another data-toggle.
- if "data-toggle" in attributes:
- btn_content = f"""
-
- {btn_content}
-
- """ # noqa
- else:
+ # Handle tooltips if a title is given
+ if title:
+ title = context["translate"](title)
+ tooltip_placement = "bottom" if not tooltip_placement else tooltip_placement
+ attributes["aria-label"] = title
attributes["data-placement"] = tooltip_placement
attributes["title"] = title
# Convert all the options for the button into a string of HTML attributes
- attributes["class"] = " ".join(attributes["class"])
+ attributes["class"] = " ".join(classes)
attributes_str = " ".join([f'{key}="{val}"' for key, val in attributes.items()])
# Generate the button HTML
@@ -163,13 +197,17 @@ def component_dropdown(
dropdown_id = "menu-dropdown-"
dropdown_id += hashlib.md5(dropdown_items.encode("utf-8")).hexdigest()[:5]
- # Generate the button HTML
+ # Generate the dropdown button HTML
dropdown_attributes = {
"data-toggle": "dropdown",
"aria-haspopup": "true",
"aria-expanded": "false",
"type": "button",
}
+ if "title" in kwargs:
+ SPHINX_LOGGER.warn("Cannot use title / tooltip with dropdown menu. Removing.")
+ kwargs.pop("title")
+
html_button = component_button(
app,
context,
diff --git a/src/sphinx_book_theme/assets/styles/components/_buttons.scss b/src/sphinx_book_theme/assets/styles/components/_buttons.scss
index 5f54e592..00bbe507 100644
--- a/src/sphinx_book_theme/assets/styles/components/_buttons.scss
+++ b/src/sphinx_book_theme/assets/styles/components/_buttons.scss
@@ -13,14 +13,6 @@
}
}
-// TODO NEW RULES THAT I NEED TO INCORPORATE ABOVE and in other places
-// Used when there's a solo icon with no text, so make the icon a bit bigger
-
-div.dropdown-menu button.btn {
- display: flex;
- align-items: center;
-}
-
.icon-button {
padding: 0.2em 0.2em;
margin-bottom: 0;
@@ -39,32 +31,73 @@ div.dropdown-menu button.btn {
font-size: 1.3rem;
}
-.dropdown-menu {
- // Copied from dropdown menu style above
- border-radius: $box-border-radius;
- box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.25);
+div.dropdown {
+ // Control the dropdown menu display
- button {
- padding-left: 0.5rem;
- width: 100%;
- border-radius: 0;
-
- &:hover {
- background-color: #eee;
- }
+ // First, overwrite the Bootstrap default so we can make nicer animations
+ // These make it "displayed" but hidden
+ .dropdown-menu {
+ display: block;
+ visibility: hidden;
+ opacity: 0;
+ transition: visibility 50ms ease-out, opacity 150ms ease-out 50ms;
}
- a:hover {
- text-decoration: none;
+
+ // On hover, we display the contents via visibility and opacity
+ &:hover div.dropdown-menu,
+ div.dropdown-menu:hover {
+ visibility: visible;
+ opacity: 1;
+ // Remove the delay when hovering, which makes it appear instantly, but delay in disappear
+ transition-delay: 0ms;
}
- span.btn__icon-container {
- display: flex;
- margin-right: 0.5rem;
+ // Other styling on the dropdown menu
+ .dropdown-menu {
+ // Copied from dropdown menu style above
+ border-radius: $box-border-radius;
+ box-shadow: 0px 3px 10px 0px rgba(0, 0, 0, 0.25);
+
+ button {
+ display: flex;
+ align-items: center;
+ padding-left: 0.5rem;
+ width: 100%;
+ border-radius: 0;
+
+ &:hover {
+ background-color: #eee;
+ }
+ }
- img,
- i {
- width: 1.2rem; // Slightly wider to make the font match the images
- font-size: 1rem;
+ a:hover {
+ text-decoration: none;
}
+
+ span.btn__icon-container {
+ display: flex;
+ margin-right: 0.5rem;
+
+ img,
+ i {
+ width: 1.2rem; // Slightly wider to make the font match the images
+ font-size: 1rem;
+ }
+ }
+ }
+}
+
+// Extra spacing when we have both icons and content
+span.btn__icon-container ~ .btn__content-container {
+ margin-left: 0.5em;
+}
+
+// Outline buttons need extra spacing
+button.btn-outline {
+ outline: 1px solid $non-content-grey;
+ padding: 0.3rem 0.5rem;
+
+ &:hover {
+ background-color: #ededed;
}
}
diff --git a/src/sphinx_book_theme/assets/styles/sections/_header-article.scss b/src/sphinx_book_theme/assets/styles/sections/_header-article.scss
index dc763366..055ea700 100644
--- a/src/sphinx_book_theme/assets/styles/sections/_header-article.scss
+++ b/src/sphinx_book_theme/assets/styles/sections/_header-article.scss
@@ -22,11 +22,16 @@
.header-article__right {
display: flex;
align-items: center;
- gap: 0.5rem;
}
.header-article__right {
margin-left: auto;
+
+ button,
+ label,
+ div {
+ padding-left: 0.25rem;
+ }
}
}
}
diff --git a/src/sphinx_book_theme/header_buttons/__init__.py b/src/sphinx_book_theme/header_buttons/__init__.py
index 1a61c005..47131aa7 100644
--- a/src/sphinx_book_theme/header_buttons/__init__.py
+++ b/src/sphinx_book_theme/header_buttons/__init__.py
@@ -118,7 +118,6 @@ def add_header_buttons(app, pagename, templatename, context, doctree):
header_buttons.append(
{
"type": "dropdown",
- "title": "Source repositories",
"icon": "fab fa-github",
"items": repo_buttons,
"side": "right",
@@ -171,7 +170,6 @@ def add_header_buttons(app, pagename, templatename, context, doctree):
header_buttons.append(
{
"type": "dropdown",
- "title": "Download this page",
"icon": "fas fa-download",
"items": download_buttons,
"side": "right",
diff --git a/src/sphinx_book_theme/header_buttons/launch.py b/src/sphinx_book_theme/header_buttons/launch.py
index 2a5dfada..678bf13c 100644
--- a/src/sphinx_book_theme/header_buttons/launch.py
+++ b/src/sphinx_book_theme/header_buttons/launch.py
@@ -180,7 +180,6 @@ def add_launch_buttons(
header_buttons.append(
{
"type": "dropdown",
- "title": "Launch interactive content",
"icon": "fas fa-rocket",
"items": launch_buttons_list,
"side": "right",