Skip to content

Commit

Permalink
👌 Improve dropdown title bar (#192)
Browse files Browse the repository at this point in the history
This PR makes three visible changes:

1. The "default" behaviour of the right chevron is to go from right-facing (closed) to down-facing (open), instead of down-facing (closed) to up-facing (open). There is also a rotate transition on opening/closing.
    The old default behaviour can be retained by using the new `:chevron: down-up` directive option.
2. The prefix icon (optional), title text, and chevron state icon are now all better aligned
3. The top/bottom padding is now 0.5em instead of 1em

The PR also introduces three new CSS variables to control font sizes of the dropdown:

```css
--sd-fontsize-tabs-label: 1rem;
--sd-fontsize-dropdown-title: 1rem;
--sd-fontweight-dropdown-title: 700;
```

---

Internally, the HTML / CSS is changed, such that the title is now an `inline-flex` box, with three columns arranged with `justify-content: space-between`:

| icon (optional) | text (`flex-grow: 1`) | state chevron |
| -------------- | -------------------- | -------------- |

Also, the state chevron was previously two distinct SVGs (with one hidden), but now is one that get rotated on open/close.
  • Loading branch information
chrisjsewell committed May 20, 2024
1 parent 169c09d commit 89aaa26
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 109 deletions.
5 changes: 5 additions & 0 deletions docs/_static/furo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
body {
--sd-fontsize-dropdown: var(--admonition-font-size);
--sd-fontsize-dropdown-title: var(--admonition-title-font-size);
--sd-fontweight-dropdown-title: 500;
}
3 changes: 2 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
}
if html_theme == "furo":
html_css_files = [
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/fontawesome.min.css"
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/fontawesome.min.css",
"furo.css",
]
html_theme_options = {
"sidebar_hide_name": True,
Expand Down
4 changes: 3 additions & 1 deletion docs/css_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ The defaults are:
--sd-color-tabs-underline-inactive: transparent;
--sd-color-tabs-overline: rgb(222, 222, 222);
--sd-color-tabs-underline: rgb(222, 222, 222);
--sd-fontsize-tabs-label: 1rem
--sd-fontsize-tabs-label: 1rem;
--sd-fontsize-dropdown-title: 1rem;
--sd-fontweight-dropdown-title: 700;
}
```
37 changes: 36 additions & 1 deletion docs/dropdowns.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Dropdown content
````
`````

## Dropdown opening animations
## Opening animations

Use `:animate: fade-in` or `:animate: fade-in-slide-down` options to animate the reveal of the hidden content.

Expand All @@ -50,10 +50,41 @@ Use `:animate: fade-in` or `:animate: fade-in-slide-down` options to animate the
{{ loremipsum }}
:::

## More examples

:::{dropdown} Dropdown with icon
:icon: quote

Dropdown content
:::

:::{dropdown} Dropdown with icon and very long title, *lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec auctor, nunc nec fermentum ultricies, nunc sapien ultricies nunc, nec ultricies sapien sapien nec sapien*
:icon: quote

Dropdown content
:::

:::{dropdown} Using option `:chevron: down-up`
:chevron: down-up

Dropdown content
:::

## Dropdowns in other components

Dropdowns can be nested inside other components, such as inside parent dropdowns or within [grid items](./grids.md).

::::{admonition} Here is an admonition with a dropdown

Admonition content

:::{dropdown} Dropdown inside admonition
:icon: quote

{{ loremipsum }}
:::
::::

::::{dropdown} Parent dropdown title
:open:

Expand Down Expand Up @@ -94,6 +125,10 @@ color
icon
: Set an [octicon icon](icons) to prefix the dropdown header.

chevron
: The open-close direction of the chevron.
One of: `right-down`, `down-up`.

animate
: Animate the dropdown opening (`fade-in` or `fade-in-slide-down`).

Expand Down
2 changes: 1 addition & 1 deletion sphinx_design/compiled/style.min.css

Large diffs are not rendered by default.

56 changes: 30 additions & 26 deletions sphinx_design/dropdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ class DropdownDirective(SphinxDirective):
"open": directives.flag, # make open by default
"color": make_choice(SEMANTIC_COLORS),
"icon": make_choice(list_octicons()),
"chevron": make_choice(
["right-down", "down-up"]
), # chevron direction closed-open
"animate": make_choice(("fade-in", "fade-in-slide-down")),
"margin": margin_option,
"name": directives.unchanged,
Expand Down Expand Up @@ -114,6 +117,7 @@ def run(self):
type="dropdown",
has_title=len(self.arguments) > 0,
icon=self.options.get("icon"),
chevron=self.options.get("chevron"),
**classes,
)
self.set_source_info(container)
Expand Down Expand Up @@ -152,27 +156,18 @@ def run(self):
# TODO option to not have card css (but requires more formatting)
use_card = True

open_marker = create_component(
"dropdown-open-marker",
classes=["sd-summary-up"],
children=[
nodes.raw(
"",
nodes.Text(get_octicon("chevron-up", height="1.5em")),
format="html",
)
],
marker_type = (
"chevron-down" if node["chevron"] == "down-up" else "chevron-right"
)
closed_marker = create_component(
"dropdown-closed-marker",
classes=["sd-summary-down"],
children=[
nodes.raw(
"",
nodes.Text(get_octicon("chevron-down", height="1.5em")),
format="html",
)
],
state_marker = nodes.inline(
"",
"",
nodes.raw(
"",
nodes.Text(get_octicon(marker_type, height="1.5em")),
format="html",
),
classes=["sd-summary-state-marker", f"sd-summary-{marker_type}"],
)

newnode = dropdown_main(
Expand All @@ -183,25 +178,36 @@ def run(self):
)

if node["has_title"]:
title_children = node[0].children
title_text_children = node[0].children
if node[0].get("ids"):
newnode["ids"] += node[0]["ids"]
body_children = node[1:]
else:
title_children = [
title_text_children = [
nodes.raw(
"...",
nodes.Text(get_octicon("kebab-horizontal", height="1.5em")),
nodes.Text(
get_octicon(
"kebab-horizontal", height="1.5em", classes=["no-title"]
)
),
format="html",
)
]
body_children = node.children
title_text_node = nodes.inline(
"",
"",
*title_text_children,
classes=["sd-summary-text"],
)
title_children = [title_text_node, state_marker]
if node["icon"]:
title_children.insert(
0,
nodes.raw(
"",
nodes.Text(get_octicon(node["icon"], height="1em")),
get_octicon(node["icon"], height="1em"),
classes=["sd-summary-icon"],
format="html",
),
Expand All @@ -211,8 +217,6 @@ def run(self):
"",
"",
*title_children,
closed_marker,
open_marker,
classes=["sd-summary-title"]
+ (["sd-card-header"] if use_card else [])
+ node["title_classes"],
Expand Down
117 changes: 66 additions & 51 deletions style/_dropdown.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
details.sd-dropdown {

position: relative;

.sd-summary-title {
font-weight: 700;
// don't overlap the chevron
padding-right: 3em !important;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
user-select: none;
}
font-size: var(--sd-fontsize-dropdown);

&:hover {
cursor: pointer;
Expand All @@ -20,64 +11,88 @@ details.sd-dropdown {
cursor: default;
}

summary {
summary.sd-summary-title {
padding: 0.5em 1em;
font-size: var(--sd-fontsize-dropdown-title);
font-weight: var(--sd-fontweight-dropdown-title);

// make the text un-selectable
user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;

// hide the default triangle marker
list-style: none;
padding: 1em;
// chrome doesn't yet support list-style
&::-webkit-details-marker {
display: none;
}

// Ellipsis added when no title
.sd-octicon.no-title {
vertical-align: middle;
&:focus {
outline: none;
}
}

&[open] summary .sd-octicon.no-title {
visibility: hidden;
}
// The title is split into three parts:
// 1. The icon (optional), which should be on the left
// 2. The text, which should be in the middle, and take all available space
// 3. The state marker, which should be on the right

// chrome doesn't yet support list-style
summary::-webkit-details-marker {
display: none;
}
display: inline-flex;
justify-content: space-between;

summary:focus {
outline: none;
}
.sd-summary-icon {
margin-right: 0.6em;
// align the icon vertically within its container
display: inline-flex;
align-items: center;
}

.sd-summary-icon {
margin-right: 0.5em;
}
.sd-summary-icon svg {
opacity: 0.8;
}

.sd-summary-icon svg {
opacity: 0.8;
}
.sd-summary-text {
flex-grow: 1;
line-height: 1.5;
// note, we add right padding to the text, rather than a left margin to the state marker,
// because when you rotate the state marker, left is no longer left
padding-right: 0.5rem;
}

summary:hover .sd-summary-up svg,
summary:hover .sd-summary-down svg {
opacity: 1;
transform: scale(1.1);
}
.sd-summary-state-marker {
pointer-events: none;
// align the icon vertically within its container
display: inline-flex;
align-items: center;
}

.sd-summary-up svg,
.sd-summary-down svg {
display: block;
opacity: 0.6;
}
// make the state marker a bit more prominent when hovered
.sd-summary-state-marker svg {
opacity: 0.6;
}
&:hover .sd-summary-state-marker svg {
opacity: 1;
transform: scale(1.1);
}

.sd-summary-up,
.sd-summary-down {
pointer-events: none;
position: absolute;
right: 1em;
top: 1em;
}

&[open] > .sd-summary-title .sd-summary-down {
// Hide the octicon added as a placeholder for when no title is provided,
// but only when the summary is open
&[open] summary .sd-octicon.no-title {
visibility: hidden;
}

&:not([open]) > .sd-summary-title .sd-summary-up {
visibility: hidden;
// setup how state marker changes on open/close of the dropdown
.sd-summary-chevron-right {
transition: 0.25s;
}
&[open] > .sd-summary-title .sd-summary-chevron-right {
transform: rotate(90deg);
}
&[open] > .sd-summary-title .sd-summary-chevron-down {
transform: rotate(180deg);
}

// Hide the card body border when not open
Expand Down
8 changes: 8 additions & 0 deletions style/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
@each $color, $value in $semantic-colors {
--sd-color-#{$color}-highlight: #{mix(black, $value, 15%)};
}
// semantic colors for backgrounds
@each $color, $value in $semantic-colors {
--sd-color-#{$color}-bg: #{rgba($value, 0.2)};
}
// colors for text on top of a semantic color background
@each $color, $value in $semantic-colors {
--sd-color-#{$color}-text: #{text-color($value)};
Expand All @@ -30,4 +34,8 @@
--sd-color-tabs-overline: rgb(222, 222, 222);
--sd-color-tabs-underline: rgb(222, 222, 222);
--sd-fontsize-tabs-label: 1rem;
// dropdown
--sd-fontsize-dropdown: inherit;
--sd-fontsize-dropdown-title: 1rem;
--sd-fontweight-dropdown-title: 700;
}

0 comments on commit 89aaa26

Please sign in to comment.