Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Harmonize and accessibilize the focus, hover and other styles across the theme #1402

Closed
wants to merge 1 commit into from
Closed
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
56 changes: 56 additions & 0 deletions src/pydata_sphinx_theme/assets/styles/abstracts/_links.scss
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,59 @@ $link-hover-decoration-thickness: unquote("max(3px, .1875rem, .12em)") !default;
outline: 2px solid var(--pst-color-accent);
}
}

/*
Mixin for links in the header (and the More dropdown toggle).

The mixin assumes it will be applied to some element X with a markup structure
like: X > .nav-link, or X > .dropdown-toggle.

It also assumes X.current is how the app annotates which item in the header nav
corresponds to the section in the docs that the user is currently reading.
*/
@mixin header-link {
> .nav-link,
> .dropdown-toggle {
border-radius: 2px;
color: var(--pst-color-text-muted);

&:hover {
background-color: var(--pst-color-header-link-hover-bg);
color: var(--pst-color-header-link-hover);
text-decoration: none; // override the link-style-hover mixin
}

&:focus {
box-shadow: none; // override Bootstrap
outline: 3px solid var(--pst-color-accent);
outline-offset: 2px;

&:not(:hover) {
background-color: var(--pst-color-accent-bg);
}
}
}

&.current {
> .nav-link,
> .dropdown-toggle {
color: var(--pst-color-primary);
&:hover {
color: var(--pst-color-header-link-hover);
}

// These styles underline the current navbar item
position: relative;
&::after {
content: "";
display: block;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border-bottom: 3px solid var(--pst-color-primary);
}
}
}
}
21 changes: 12 additions & 9 deletions src/pydata_sphinx_theme/assets/styles/sections/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -80,26 +80,29 @@

@include media-breakpoint-up($breakpoint-sidebar-primary) {
// Center align on wide screens so the dropdown button is centered properly
align-items: center;
align-items: baseline;
}

li a.nav-link {
@include link-style-text;
li.pst-header-nav-item {
margin-inline: 4px; // breathing room so hover, focus styles do not overlap
&:first-child {
margin-inline-start: 0;
}
&:last-child {
margin-inline-end: 0;
}
@include header-link;
}

// Current page is always underlined in the navbar
> .current > .nav-link {
@include link-navbar-current;
li a.nav-link.dropdown-item {
@include link-style-text;
}

// Dropdowns for the extra links
.dropdown {
button {
display: unset;
color: var(--pst-color-text-muted);
border: none;
@include link-style-hover;
@include focus-indicator;
}

.dropdown-menu {
Expand Down
6 changes: 6 additions & 0 deletions src/pydata_sphinx_theme/assets/styles/variables/_color.scss
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ $pst-semantic-colors: (
"light": #{map-deep-get($color-palette, "gray", "800")},
"dark": $foundation-light-gray,
),
"header-link-hover": (
"light": $foundation-white,
"bg-light": #{map-deep-get($color-palette, "violet", "500")},
"dark": #{map-deep-get($color-palette, "violet", "500")},
"bg-dark": #{map-deep-get($color-palette, "gray", "800")},
),
);

/*******************************************************************************
Expand Down
21 changes: 12 additions & 9 deletions src/pydata_sphinx_theme/toctree.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def generate_header_nav_before_dropdown(n_links_before_dropdown):
page = toc.attributes["parent"] if page == "self" else page

# If this is the active ancestor page, add a class so we highlight it
current = " current active" if page == active_header_page else ""
current = "current active" if page == active_header_page else ""

# sanitize page title for use in the html output if needed
if title is None:
Expand All @@ -108,14 +108,14 @@ def generate_header_nav_before_dropdown(n_links_before_dropdown):
# If it's an absolute one then we use the external class and
# the complete url.
is_absolute = bool(urlparse(page).netloc)
link_status = "external" if is_absolute else "internal"
link_status = "nav-external" if is_absolute else "nav-internal"
link_href = page if is_absolute else context["pathto"](page)

# create the html output
links_html.append(
f"""
<li class="nav-item{current}">
<a class="nav-link nav-{link_status}" href="{link_href}">
<li class="nav-item pst-header-nav-item {current}">
<a class="nav-link {link_status}" href="{link_href}">
{title}
</a>
</li>
Expand All @@ -126,7 +126,7 @@ def generate_header_nav_before_dropdown(n_links_before_dropdown):
for external_link in context["theme_external_links"]:
links_html.append(
f"""
<li class="nav-item">
<li class="nav-item pst-header-nav-item">
<a class="nav-link nav-external" href="{ external_link["url"] }">
{ external_link["name"] }
</a>
Expand All @@ -140,9 +140,12 @@ def generate_header_nav_before_dropdown(n_links_before_dropdown):

# Wrap the final few header items in a "more" dropdown
links_dropdown = [
# 🐲 brittle code, relies on the assumption that the code above
# gives each link in the nav a `nav-link` CSS class
html.replace("nav-link", "nav-link dropdown-item")
# 🐲 brittle code because it relies on the code above to build the HTML in a particular way
html.replace("nav-link", "nav-link dropdown-item").replace(
# Prevents the header-link mixin from applying to links within the dropdown
"pst-header-nav-item",
"",
)
for html in links_html[n_links_before_dropdown:]
]

Expand Down Expand Up @@ -177,7 +180,7 @@ def generate_header_nav_html(
dropdown_id = unique_html_id("pst-nav-more-links")
links_dropdown_html = "\n".join(links_dropdown)
out += f"""
<li class="nav-item dropdown">
<li class="nav-item dropdown pst-header-nav-item">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="{dropdown_id}">
{_(dropdown_text)}
</button>
Expand Down