diff --git a/assets/theme-css/sphinx-design/_dropdown.scss b/assets/theme-css/sphinx-design/_dropdown.scss index 9b850649..9be9a358 100644 --- a/assets/theme-css/sphinx-design/_dropdown.scss +++ b/assets/theme-css/sphinx-design/_dropdown.scss @@ -5,10 +5,35 @@ details.sd-dropdown { 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; + display: inline-flex; + justify-content: space-between; + align-items: center; + width: 100%; + + .sd-summary-text { + flex-grow: 1; + line-height: 1.5; + padding-right: 0.5rem; + } + + .sd-summary-state-marker { + position: absolute; + right: 1em; + top: 50%; + transform: translateY(-50%); + pointer-events: none; + display: inline-flex; + align-items: center; + justify-content: center; + width: 0.75em; + } + + // The hover effect should only change opacity, not transform. + // We are transforming the chevron elements instead, see below. + &:hover .sd-summary-state-marker svg { + opacity: 1; + } } &:hover { @@ -54,7 +79,6 @@ details.sd-dropdown { summary:hover .sd-summary-up svg, summary:hover .sd-summary-down svg { opacity: 1; - transform: scale(1.1); } .sd-summary-up svg, @@ -79,6 +103,61 @@ details.sd-dropdown { visibility: hidden; } + // Chevron transitions + .sd-summary-chevron-right i, + .sd-summary-chevron-down i { + display: inline-block; + transform-origin: center; + opacity: 0.6; + } + + // The chevron rotation animations are applied to + // the icon inside the dropdown title div + &[open] > .sd-summary-title .sd-summary-chevron-right i { + transform: rotate(90deg); + animation: rotate-to-90 0.25s ease-in-out; + } + + &[open] > .sd-summary-title .sd-summary-chevron-down i { + transform: rotate(-180deg); + animation: rotate-to-negative-180 0.25s ease-in-out; + } + + &:not([open]) > .sd-summary-title .sd-summary-chevron-right i { + transform: rotate(0deg); + animation: rotate-to-0-from-90 0.25s ease-in-out; + } + + &:not([open]) > .sd-summary-title .sd-summary-chevron-down i { + transform: rotate(0deg); + animation: rotate-to-0-from-negative-180 0.25s ease-in-out; + } + + > .sd-summary-title:hover .sd-summary-chevron-right i, + > .sd-summary-title:hover .sd-summary-chevron-down i { + opacity: 1; + } + + // Combined transforms for each state with hover. These cover + // the cases where the chevron is rotated, say, when the dropdown + // is open or if the chevron starts rotated (e.g. in the down-up + // state). + &:not([open]) > .sd-summary-title:hover .sd-summary-chevron-right i { + transform: scale(1.1); + } + + &:not([open]) > .sd-summary-title:hover .sd-summary-chevron-down i { + transform: scale(1.1); + } + + &[open] > .sd-summary-title:hover .sd-summary-chevron-right i { + transform: rotate(90deg) scale(1.1); + } + + &[open] > .sd-summary-title:hover .sd-summary-chevron-down i { + transform: rotate(-180deg) scale(1.1); + } + // Hide the card body border when not open &:not([open]).sd-card { border: none; @@ -90,18 +169,10 @@ details.sd-dropdown { // Transition animation &.sd-fade-in[open] summary ~ * { - -moz-animation: sd-fade-in 0.5s ease-in-out; - -webkit-animation: sd-fade-in 0.5s ease-in-out; animation: sd-fade-in 0.5s ease-in-out; } &.sd-fade-in-slide-down[open] summary ~ * { - -moz-animation: - sd-fade-in 0.5s ease-in-out, - sd-slide-down 0.5s ease-in-out; - -webkit-animation: - sd-fade-in 0.5s ease-in-out, - sd-slide-down 0.5s ease-in-out; animation: sd-fade-in 0.5s ease-in-out, sd-slide-down 0.5s ease-in-out; @@ -135,3 +206,39 @@ details.sd-dropdown { transform: translate(0, 0); } } + +@keyframes rotate-to-90 { + from { + transform: rotate(0deg) scale(1.1); + } + to { + transform: rotate(90deg) scale(1.1); + } +} + +@keyframes rotate-to-negative-180 { + from { + transform: rotate(0deg) scale(1.1); + } + to { + transform: rotate(-180deg) scale(1.1); + } +} + +@keyframes rotate-to-0-from-90 { + from { + transform: rotate(90deg) scale(1.1); + } + to { + transform: rotate(0deg) scale(1.1); + } +} + +@keyframes rotate-to-0-from-negative-180 { + from { + transform: rotate(-180deg) scale(1.1); + } + to { + transform: rotate(0deg) scale(1.1); + } +} diff --git a/layouts/shortcodes/dropdown.html b/layouts/shortcodes/dropdown.html index 645aab89..74b37816 100644 --- a/layouts/shortcodes/dropdown.html +++ b/layouts/shortcodes/dropdown.html @@ -31,23 +31,152 @@ body = 'And some content and an icon!' {{< /dropdown >}} +{{< dropdown >}} +title = 'A success color dropdown' +icon = 'fa-solid fa-check' +color = 'success' +body = 'And some content and an icon!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'A warning color dropdown' +icon = 'fa-solid fa-exclamation' +color = 'warning' +body = 'And some content and an icon!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'A danger color dropdown' +icon = 'fa-solid fa-exclamation-triangle' +color = 'danger' +body = 'And some content and an icon!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Open dropdown by default' +icon = 'fa-solid fa-eye' +color = 'info' +open = true +body = 'This dropdown is open by default!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Fade in animation' +icon = 'fa-solid fa-magic' +animate = 'fade-in' +body = 'This dropdown fades in when opened!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Fade in and slide down animation' +icon = 'fa-solid fa-chart-line' +animate = 'fade-in-slide-down' +body = 'This dropdown fades in and slides down when opened!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Using chevron: down-up' +icon = 'fa-solid fa-cog' +chevron = 'down-up' +body = 'Notice the different chevron direction!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Custom chevron with animation' +icon = 'fa-solid fa-star' +chevron = 'down-up' +animate = 'fade-in' +color = 'warning' +body = 'Combining different features!' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Multi-line content' +icon = 'fa-solid fa-align-left' +body = ''' +This is multi-line content. + +It can include **markdown** and multiple paragraphs. +And even lists: + +- Item 1 +- Item 2 +- Item 3 +''' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Dropdown with code' +icon = 'fa-solid fa-code' +color = 'success' +body = ''' +Here's some code inside a dropdown: + +```python +def hello_world(): + print("Hello from a dropdown!") + return 42 +``` + +And more content after the code. +''' +{{< /dropdown >}} + +{{< dropdown >}} +title = 'Nested dropdowns' +icon = 'fa-solid fa-folder' +body = ''' +This is a dropdown with a dropdown inside it. + +{{< dropdown >}} +title = 'Inner dropdown' +icon = 'fa-solid fa-code' +body = ''' +I'm inside a dropdown in a dropdown! +''' +{{< /dropdown >}} + +And here is some more content after the inner dropdown. +''' +{{< /dropdown >}} + */}} {{- $data := .Inner | transform.Unmarshal -}} -
- {{- with $data.color }} - - {{- else }} - - {{- end }} - {{- with $data.icon }} - - {{- end }} - {{- with $data.title }} - {{- . }} - {{- else }} -   - {{- end }} + +{{- $chevronClass := "sd-summary-chevron-right" -}} +{{- $chevronIcon := "fa-chevron-right" -}} +{{- if eq $data.chevron "down-up" -}} + {{- $chevronClass = "sd-summary-chevron-down" -}} + {{- $chevronIcon = "fa-chevron-down" -}} +{{- end -}} + +{{- $detailsClasses := slice "sd-sphinx-override" "sd-dropdown" "sd-card" "sd-mb-3" -}} +{{- with $data.animate -}} + {{- $detailsClasses = $detailsClasses | append (printf "sd-%s" .) -}} +{{- end -}} + +
+ {{- $summaryClasses := slice "sd-summary-title" "sd-card-header" -}} + {{- with $data.color -}} + {{- $summaryClasses = $summaryClasses | append (printf "sd-bg-%s" .) -}} + {{- $summaryClasses = $summaryClasses | append (printf "sd-bg-text-%s" .) -}} + {{- end -}} + + + {{- with $data.icon }} + + {{- end }} + + {{- with $data.title }} + {{- . }} + {{- else }} + + {{- end }} + + + +
{{- with (trim $data.body "\n") }}