Add CSS animations and minimal auto-focus JS with graceful fallback

- CSS grid animation for smooth expand/collapse transitions
- Fade-in animation for namespace dropdown
- Auto-focus textarea on details open (progressive enhancement)
- Falls back gracefully if browser lacks support
This commit is contained in:
Russell Ballestrini 2025-12-19 17:53:29 -05:00
parent 18a65fb506
commit 9c74e6256a
4 changed files with 65 additions and 1 deletions

View file

@ -411,7 +411,7 @@ form.node-action {
opacity: 0.8 !important;
}
/* Pure CSS toggle using <details> element */
/* Pure CSS toggle using <details> element with animations */
.toggle-summary {
cursor: pointer;
list-style: none;
@ -453,6 +453,33 @@ details[open] > .toggle-summary .when-closed {
display: none;
}
/* Animated details content using CSS grid technique */
.edit-box-details,
.remark-box-details,
.node-children-details {
--details-transition-duration: 0.3s;
}
.edit-box-details > .details-content,
.remark-box-details > .details-content,
.node-children-details > .details-content {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows var(--details-transition-duration) ease-out;
}
.edit-box-details[open] > .details-content,
.remark-box-details[open] > .details-content,
.node-children-details[open] > .details-content {
grid-template-rows: 1fr;
}
.edit-box-details > .details-content > .details-content-inner,
.remark-box-details > .details-content > .details-content-inner,
.node-children-details > .details-content > .details-content-inner {
overflow: hidden;
}
/* Edit box details styling */
.edit-box-details {
margin-top: 15px;
@ -480,6 +507,13 @@ details[open] > .toggle-summary .when-closed {
padding: 10px;
border: 1px solid #ddd;
min-width: 120px;
/* Fade in animation for dropdown */
animation: fadeIn 0.2s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-5px); }
to { opacity: 1; transform: translateY(0); }
}
/* Node children collapse/expand */

View file

@ -38,6 +38,22 @@ function sendPreview(textarea, div, mathjax=false){
}
// Auto-focus textarea when details element opens (progressive enhancement).
// Falls back gracefully if browser doesn't support the required APIs.
if (typeof document.addEventListener === 'function') {
document.addEventListener('toggle', function(e) {
var details = e.target;
if (details.tagName !== 'DETAILS' || !details.open) return;
// Find textarea inside the details element and focus it.
var textarea = details.querySelector('textarea');
if (textarea && typeof textarea.focus === 'function') {
// Small delay to let the CSS transition start.
setTimeout(function() { textarea.focus(); }, 50);
}
}, true);
}
$(document).ready( function() {
$('button.vote-up').click(

View file

@ -48,12 +48,16 @@ page: {{ request.page_number }}
<details id="edit-box-{{ node.id }}" class="edit-box-details">
<summary class="action toggle-summary"><span class="when-closed">edit</span><span class="when-open">hide</span></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.edit(node) }}
</div></div>
</details>
<details id="remark-box-{{ node.id }}" class="remark-box-details">
<summary class="remark toggle-summary"><span class="when-closed">remark</span><span class="when-open">hide</span></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.reply(node, node) }}
</div></div>
</details>
{% endfor -%}

View file

@ -77,12 +77,16 @@
<details id="edit-box-{{ request.node.id }}" class="edit-box-details">
<summary class="action toggle-summary"><span class="when-closed">edit</span><span class="when-open">hide</span></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.edit(request.node) }}
</div></div>
</details>
<details id="remark-box-{{ request.node.id }}" class="remark-box-details remark-box-details-main" open>
<summary class="toggle-summary toggle-summary-hidden"></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.reply(request.node, request.root_node) }}
</div></div>
</details>
@ -152,20 +156,26 @@
<details id="edit-box-{{ parent.id }}" class="edit-box-details">
<summary class="action toggle-summary"><span class="when-closed">edit</span><span class="when-open">hide</span></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.edit(parent) }}
</div></div>
</details>
<details id="remark-box-{{ parent.id }}" class="remark-box-details">
<summary class="remark toggle-summary"><span class="when-closed">remark</span><span class="when-open">hide</span></summary>
<div class="details-content"><div class="details-content-inner">
{{ forms.reply(parent, request.root_node) }}
</div></div>
</details>
{#- nest children in this node's div for convo collapsing. -#}
<details id="node-children-{{ parent.id }}" class="node-children-details" open>
<summary class="action link toggle-summary"><span class="when-closed">expand [+]</span><span class="when-open">collapse [-]</span></summary>
<div class="details-content"><div class="details-content-inner">
{%- if children_ids %}
{{ loop(children_ids) }}
{% endif -%}
</div></div>
</details>
{# close the class="node" div #}