diff --git a/app/assets/images/caret-down.svg b/app/assets/images/caret-down.svg new file mode 100644 index 000000000..a19d0f357 --- /dev/null +++ b/app/assets/images/caret-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/app/assets/stylesheets/base.css b/app/assets/stylesheets/base.css index 526b502bc..9301bbc61 100644 --- a/app/assets/stylesheets/base.css +++ b/app/assets/stylesheets/base.css @@ -21,6 +21,7 @@ background: var(--color-bg); color: var(--color-ink); font-family: var(--font-sans); + interpolate-size: allow-keywords; line-height: 1.375; overflow: unset; scroll-behavior: auto; diff --git a/app/assets/stylesheets/buttons.css b/app/assets/stylesheets/buttons.css index 3b6b3ebcc..0ca763506 100644 --- a/app/assets/stylesheets/buttons.css +++ b/app/assets/stylesheets/buttons.css @@ -193,3 +193,4 @@ } } } + diff --git a/app/assets/stylesheets/cards.css b/app/assets/stylesheets/cards.css index 366fdb6e3..d16a96e56 100644 --- a/app/assets/stylesheets/cards.css +++ b/app/assets/stylesheets/cards.css @@ -121,7 +121,7 @@ position: relative; z-index: 0; - &:has(dialog[open]) { + &:has([open]) { z-index: 1; } diff --git a/app/assets/stylesheets/expander.css b/app/assets/stylesheets/expander.css new file mode 100644 index 000000000..e7be6c769 --- /dev/null +++ b/app/assets/stylesheets/expander.css @@ -0,0 +1,112 @@ +/* https://nerdy.dev/open-and-close-transitions-for-the-details-element */ + +.expander { + --expander-height: calc(1em + 1lh); + --expander-width: 11ch; + --expander-radius: calc(var(--expander-height) / 2); + --expander-duration: 150ms; + + interpolate-size: allow-keywords; + position: relative; + z-index: 1; +} + +.expander__button { + --btn-border-radius: var(--expander-radius); + + align-items: center; + block-size: var(--expander-height); + cursor: pointer; + display: flex; + inline-size: var(--expander-width); + justify-content: flex-start; + padding-inline: 1.5ch; + position: relative; + white-space: nowrap; + z-index: 1; + + &::-webkit-details-marker { + display: none; + } + + [open] & { + box-shadow: none; + } + + .icon { + font-size: 1ch; + } +} + +.expander__content { + --btn-border-radius: var(--expander-radius); + + align-items: stretch; + border-radius: var(--expander-radius); + flex-direction: column; + gap: 0; + padding-block-start: var(--expander-height); + + &:hover { + box-shadow: none; + } +} + +/* For browsers that support animation */ +@supports selector(details::details-content) { + .expander::details-content { + --btn-border-radius: var(--expander-radius); + + block-size: var(--expander-height); + border-radius: var(--expander-radius); + inset: 0 auto auto 0; + inline-size: var(--expander-width); + overflow: clip; + position: absolute; + transition: content-visibility var(--expander-duration) allow-discrete, block-size var(--expander-duration), inline-size var(--expander-duration); + } + + .expander[open]::details-content { + block-size: auto; + inline-size: auto; + } + + .expander__content { + min-inline-size: var(--expander-width); + } +} + +/* Fallback for browsers that don't support animation */ +@supports not selector(details::details-content) { + .expander__content { + border-radius: var(--expander-radius); + inset: 0 auto auto 0; + min-inline-size: var(--expander-width); + position: absolute; + + [open] & { + block-size: auto; + inline-size: auto; + } + } +} + +.expander__item { + --btn-background: transparent; + --btn-border-radius: 0.3em; + --btn-border-size: 0; + --btn-font-weight: 500; + --btn-padding: var(--inline-space-half) var(--inline-space); + --hover-size: 0; + --outline-color: transparent; + + inline-size: calc(100% + var(--inline-space-double)); + margin-inline-start: calc(-1 * var(--inline-space)); + justify-content: flex-start; + white-space: nowrap; + + &:hover, + &:focus-visible { + background-color: oklch(var(--lch-white) / 15%); + } +} diff --git a/app/assets/stylesheets/icons.css b/app/assets/stylesheets/icons.css index 10e273bb5..2f0989518 100644 --- a/app/assets/stylesheets/icons.css +++ b/app/assets/stylesheets/icons.css @@ -35,6 +35,7 @@ .icon--calendar-add { --svg: url("calendar-add.svg "); } .icon--calendar { --svg: url("calendar.svg "); } .icon--camera { --svg: url("camera.svg "); } + .icon--caret-down { --svg: url("caret-down.svg "); } .icon--chart { --svg: url("chart.svg "); } .icon--check { --svg: url("check.svg "); } .icon--close { --svg: url("close.svg "); } diff --git a/app/javascript/controllers/details_controller.js b/app/javascript/controllers/details_controller.js new file mode 100644 index 000000000..7259fd665 --- /dev/null +++ b/app/javascript/controllers/details_controller.js @@ -0,0 +1,13 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + static targets = [ "details" ] + + close() { + this.detailsTarget.removeAttribute("open") + } + + closeOnClickOutside({ target }) { + if (!this.element.contains(target)) this.close() + } +} diff --git a/app/javascript/controllers/expandable_controller.js b/app/javascript/controllers/expandable_controller.js deleted file mode 100644 index 74b3bc050..000000000 --- a/app/javascript/controllers/expandable_controller.js +++ /dev/null @@ -1,9 +0,0 @@ -import { Controller } from "@hotwired/stimulus" - -export default class extends Controller { - closeOnFocusOutside(event) { - if (!this.element.contains(event.relatedTarget)) { - this.element.removeAttribute("open") - } - } -} diff --git a/app/views/cards/_closure_toggle.html.erb b/app/views/cards/_closure_toggle.html.erb index 46cf6e6ff..6ad45c388 100644 --- a/app/views/cards/_closure_toggle.html.erb +++ b/app/views/cards/_closure_toggle.html.erb @@ -5,23 +5,19 @@ Un-do <% end %> <% else %> -