More visually interesting open animations, close details on outside click
This commit is contained in:
@ -7,9 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased](https://codeberg.org/daudix/duckquill/compare/v5.1.0...main)
|
## [Unreleased](https://codeberg.org/daudix/duckquill/compare/v5.1.0...main)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add `closable` class for making `details` closable when other `details` is open/outside area is clicked.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Get rid of dashed outline on article hover in article list.
|
- Get rid of dashed outline on article hover in article list.
|
||||||
|
- Make navabr menu/search open animation nicer (scale up instead of just fading from transparency).
|
||||||
- More visually interesting paginator.
|
- More visually interesting paginator.
|
||||||
- Move paginator from `articles.html` to `article-list.html`.
|
- Move paginator from `articles.html` to `article-list.html`.
|
||||||
- Tweak styling of `details`.
|
- Tweak styling of `details`.
|
||||||
|
@ -22,7 +22,7 @@ Some of the features Duckquill has to offer:
|
|||||||
|
|
||||||
- Cute and informative social media cards for Discourse, Facebook, LinkedIn, Mastodon and more.
|
- Cute and informative social media cards for Discourse, Facebook, LinkedIn, Mastodon and more.
|
||||||
- [Mastodon-powered comments](https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/); comment under a post by using your Mastodon account.
|
- [Mastodon-powered comments](https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/); comment under a post by using your Mastodon account.
|
||||||
- Lightweight by default, powerful when needed; no JavaScript is used by default.
|
- Lightweight by default, powerful when needed; no mandatory JavaScript is used by default.
|
||||||
- Privacy respecting analytics using [GoatCounter](https://www.goatcounter.com), with support for self-hosting.
|
- Privacy respecting analytics using [GoatCounter](https://www.goatcounter.com), with support for self-hosting.
|
||||||
- Estimated read time of the post; put away those with short attention spans.
|
- Estimated read time of the post; put away those with short attention spans.
|
||||||
- Light/dark/system theme switcher (for some reason everyone likes these).
|
- Light/dark/system theme switcher (for some reason everyone likes these).
|
||||||
|
@ -186,36 +186,23 @@
|
|||||||
|
|
||||||
@keyframes dropdown-open {
|
@keyframes dropdown-open {
|
||||||
from {
|
from {
|
||||||
transform: translate(-50%, 0);
|
transform: scale(0.5) translate(-50%, -1rem);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 480px) {
|
|
||||||
&[open]:has(summary:not(.circle)) ul {
|
|
||||||
animation: dropdown-open-2 var(--transition);
|
|
||||||
|
|
||||||
@keyframes dropdown-open-2 {
|
|
||||||
from {
|
|
||||||
transform: translate(-50%, -0.5rem);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
-webkit-backdrop-filter: var(--blur);
|
-webkit-backdrop-filter: var(--blur);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transform: translate(-50%, 1rem);
|
transform: translateX(-50%);
|
||||||
|
transform-origin: top left;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
backdrop-filter: var(--blur);
|
backdrop-filter: var(--blur);
|
||||||
box-shadow:
|
inset-block-start: 3.25rem;
|
||||||
var(--edge-highlight),
|
box-shadow: var(--edge-highlight),var(--shadow-glass);
|
||||||
var(--shadow-glass);
|
|
||||||
border-radius: calc(var(--rounded-corner) + 0.25rem);
|
border-radius: calc(var(--rounded-corner) + 0.25rem);
|
||||||
background-color: var(--nav-bg);
|
background-color: var(--nav-bg);
|
||||||
padding: 0.25rem;
|
padding: 0.25rem;
|
||||||
@ -233,7 +220,7 @@
|
|||||||
|
|
||||||
@media only screen and (max-width: 480px) {
|
@media only screen and (max-width: 480px) {
|
||||||
&:has(summary:not(.circle)) ul {
|
&:has(summary:not(.circle)) ul {
|
||||||
transform: translate(-50%, 0.5rem);
|
inset-block-start: 2.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -306,7 +293,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#search-container {
|
#search-container {
|
||||||
transform: translateY(-2.75rem);
|
transform: scale(0.5) translateY(-2.75rem);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: var(--transition);
|
transition: var(--transition);
|
||||||
padding: 0 0.5rem 0;
|
padding: 0 0.5rem 0;
|
||||||
@ -314,7 +301,7 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
transform: translateY(0);
|
transform: none;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
padding: 0 0.5rem 0.5rem;
|
padding: 0 0.5rem 0.5rem;
|
||||||
height: 2.75rem;
|
height: 2.75rem;
|
||||||
|
29
static/closable.js
Normal file
29
static/closable.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
|
const closable = document.querySelectorAll("details.closable");
|
||||||
|
|
||||||
|
closable.forEach((detail) => {
|
||||||
|
detail.addEventListener("toggle", () => {
|
||||||
|
if (detail.open) setTargetDetail(detail);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setTargetDetail(targetDetail) {
|
||||||
|
closable.forEach((detail) => {
|
||||||
|
if (detail !== targetDetail) {
|
||||||
|
detail.open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("click", function (event) {
|
||||||
|
const isClickInsideDetail = [...closable].some((detail) =>
|
||||||
|
detail.contains(event.target)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isClickInsideDetail) {
|
||||||
|
closable.forEach((detail) => {
|
||||||
|
detail.open = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -1,18 +0,0 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function () {
|
|
||||||
const nav = document.getElementById("site-nav");
|
|
||||||
const details = nav.querySelectorAll("details");
|
|
||||||
|
|
||||||
details.forEach((detail) => {
|
|
||||||
detail.addEventListener("toggle", () => {
|
|
||||||
if (detail.open) setTargetDetail(detail);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function setTargetDetail(targetDetail) {
|
|
||||||
details.forEach((detail) => {
|
|
||||||
if (detail !== targetDetail) {
|
|
||||||
detail.open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
<div id="buttons-container">
|
<div id="buttons-container">
|
||||||
{%- if page.extra.toc -%}
|
{%- if page.extra.toc -%}
|
||||||
<details id="toc">
|
<details id="toc" class="closable">
|
||||||
<summary title="{{ macros_translate::translate(key='table_of_contents', default='Table of Contents', language_strings=language_strings) }}"><i class="icon"></i></summary>
|
<summary title="{{ macros_translate::translate(key='table_of_contents', default='Table of Contents', language_strings=language_strings) }}"><i class="icon"></i></summary>
|
||||||
<div id="toc-dropdown">
|
<div id="toc-dropdown">
|
||||||
<strong id="toc-dropdown-title">{{ macros_translate::translate(key="table_of_contents", default="Table of Contents", language_strings=language_strings) }}</strong>
|
<strong id="toc-dropdown-title">{{ macros_translate::translate(key="table_of_contents", default="Table of Contents", language_strings=language_strings) }}</strong>
|
||||||
|
@ -63,7 +63,7 @@
|
|||||||
{%- include "partials/copy_button.html" %}
|
{%- include "partials/copy_button.html" %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- set scripts = [] %}
|
{%- set scripts = ["closable.js"] %}
|
||||||
|
|
||||||
{%- if config.extra.goatcounter %}
|
{%- if config.extra.goatcounter %}
|
||||||
{%- set scripts = scripts | concat(with=["count.js"]) %}
|
{%- set scripts = scripts | concat(with=["count.js"]) %}
|
||||||
@ -92,10 +92,6 @@
|
|||||||
{%- set scripts = scripts | concat(with=["theme-switcher.js"]) %}
|
{%- set scripts = scripts | concat(with=["theme-switcher.js"]) %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
{%- if config.extra.nav.links.menu or config.languages | length > 0 or config.extra.nav.show_theme_switcher or config.feed_filenames | length > 1 and config.extra.nav.show_feed %}
|
|
||||||
{%- set scripts = scripts | concat(with=["details.js"]) %}
|
|
||||||
{%- endif %}
|
|
||||||
|
|
||||||
{%- if config.extra.scripts %}
|
{%- if config.extra.scripts %}
|
||||||
{%- set scripts = scripts | concat(with=config.extra.scripts) %}
|
{%- set scripts = scripts | concat(with=config.extra.scripts) %}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{#- Based on https://github.com/welpo/tabi/blob/main/templates/partials/language_switcher.html -#}
|
{#- Based on https://github.com/welpo/tabi/blob/main/templates/partials/language_switcher.html -#}
|
||||||
|
|
||||||
<li id="language-switcher">
|
<li id="language-switcher">
|
||||||
<details>
|
<details class="closable">
|
||||||
<summary class="circle" title="{{ macros_translate::translate(key='language', default='Language', language_strings=language_strings) }}">
|
<summary class="circle" title="{{ macros_translate::translate(key='language', default='Language', language_strings=language_strings) }}">
|
||||||
<i class="icon"></i>
|
<i class="icon"></i>
|
||||||
</summary>
|
</summary>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
{%- for link in config.extra.nav.links %}
|
{%- for link in config.extra.nav.links %}
|
||||||
{%- if link.menu and link.menu | length > 0 -%}
|
{%- if link.menu and link.menu | length > 0 -%}
|
||||||
<li>
|
<li>
|
||||||
<details>
|
<details class="closable">
|
||||||
<summary>
|
<summary>
|
||||||
<i class="icon arrow"></i>
|
<i class="icon arrow"></i>
|
||||||
{{- macros_translate::translate(key=link.name, default=link.name, language_strings=language_strings) -}}
|
{{- macros_translate::translate(key=link.name, default=link.name, language_strings=language_strings) -}}
|
||||||
@ -81,7 +81,7 @@
|
|||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
{%- if config.extra.default_theme or config.extra.nav.show_theme_switcher %}
|
{%- if config.extra.default_theme or config.extra.nav.show_theme_switcher %}
|
||||||
<li id="theme-switcher">
|
<li id="theme-switcher">
|
||||||
<details>
|
<details class="closable">
|
||||||
<summary class="circle" title="{{ macros_translate::translate(key='theme', default='Theme', language_strings=language_strings) }}">
|
<summary class="circle" title="{{ macros_translate::translate(key='theme', default='Theme', language_strings=language_strings) }}">
|
||||||
<i class="icon"></i>
|
<i class="icon"></i>
|
||||||
</summary>
|
</summary>
|
||||||
@ -107,7 +107,7 @@
|
|||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if config.feed_filenames | length > 1 and config.extra.nav.show_feed -%}
|
{%- if config.feed_filenames | length > 1 and config.extra.nav.show_feed -%}
|
||||||
<li id="feed">
|
<li id="feed">
|
||||||
<details>
|
<details class="closable">
|
||||||
<summary class="circle" title="{{ macros_translate::translate(key='feed', default='Feed', language_strings=language_strings) }}">
|
<summary class="circle" title="{{ macros_translate::translate(key='feed', default='Feed', language_strings=language_strings) }}">
|
||||||
<i class="icon"></i>
|
<i class="icon"></i>
|
||||||
</summary>
|
</summary>
|
||||||
|
Reference in New Issue
Block a user