From ef8f38297634bb9657f94f567d054cc1c888cc8e Mon Sep 17 00:00:00 2001 From: Russell Ballestrini Date: Fri, 19 Dec 2025 19:32:11 -0500 Subject: [PATCH] Replace jQuery toggle animations with CSS-based animations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use CSS keyframes (slideDown/slideUp) for 800ms door-like animations - JS only toggles classes and updates button text at correct timing - Preview toggle uses native
with animated open/close - Arrow indicators on right side (hide preview ▲ / show preview ▼) - No-JS fallback preserved (links navigate to dedicated pages) --- remarkbox/static/css/common.css | 194 +++++++++++------------ remarkbox/static/js/custom.js | 42 +++-- remarkbox/templates/base.j2 | 8 +- remarkbox/templates/list-nodes.j2 | 14 +- remarkbox/templates/show-node.j2 | 37 ++--- remarkbox/templates/snippets/forms.j2 | 8 +- remarkbox/templates/snippets/snippets.j2 | 10 +- 7 files changed, 157 insertions(+), 156 deletions(-) diff --git a/remarkbox/static/css/common.css b/remarkbox/static/css/common.css index 6772297..dc7b685 100644 --- a/remarkbox/static/css/common.css +++ b/remarkbox/static/css/common.css @@ -411,120 +411,112 @@ form.node-action { opacity: 0.8 !important; } -/* Pure CSS toggle using
element with animations */ -.toggle-summary { +.remark-box-div-main { + margin-bottom: 35px; +} + +.remark-box-div { + display: none; + overflow: hidden; + margin-top: 10px; +} + +.edit-box-div { + display: none; + overflow: hidden; + margin-top: 15px; +} + +/* CSS animation when toggled open via JS */ +.remark-box-div.toggle-open, +.edit-box-div.toggle-open { + display: block; + overflow: hidden; + max-height: 1000px; + animation: slideDown 0.8s ease-out forwards; +} + +.remark-box-div.toggle-closing, +.edit-box-div.toggle-closing { + display: block; + max-height: 1000px; + animation: slideUp 0.8s ease-out forwards; +} + +@keyframes slideDown { + from { + max-height: 0; + } + to { + max-height: 1000px; + } +} + +.my-namespaces-div { + display: none; + position: absolute; + background-color: #ffffff; + z-index: 1; + overflow: hidden; + padding-top: 10px; + padding-bottom: 10px; +} + +.my-namespaces-div.toggle-open { + display: block; + animation: slideDown 0.8s ease-out; +} + +/* Preview toggle with CSS animation */ +.preview-details { + overflow: hidden; +} + +.preview-details[open] > .preview { + overflow: hidden; + animation: slideDown 0.8s ease-out forwards; +} + +.preview-details.closing > .preview { + overflow: hidden; + max-height: 1000px; + animation: slideUp 0.8s ease-out forwards; +} + +@keyframes slideUp { + from { + max-height: 1000px; + } + to { + max-height: 0; + } +} + +.preview-toggle { cursor: pointer; list-style: none; } -.toggle-summary::-webkit-details-marker { +.preview-toggle::-webkit-details-marker { display: none; } -.toggle-summary::marker { - display: none; - content: ""; -} - -/* Toggle text switching: show/hide different text based on open state */ -.toggle-summary .when-open { - display: none; -} - -.toggle-summary .when-closed { +.preview-toggle .when-open { display: inline; } -details[open] > .toggle-summary .when-open { +.preview-toggle .when-closed { + display: none; +} + +.preview-details:not([open]) .when-open { + display: none; +} + +.preview-details:not([open]) .when-closed { display: inline; } -details[open] > .toggle-summary .when-closed { - display: none; -} - -/* Hidden summary for main remark box (always open) */ -.toggle-summary-hidden { - display: none; -} - -/* Fallback links hidden when JS not needed */ -.toggle-fallback { - 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; -} - -/* Remark box details styling */ -.remark-box-details { - margin-top: 10px; -} - -.remark-box-details-main { - margin-bottom: 35px; -} - -/* Namespace switcher dropdown */ -.my-namespaces-details { - display: inline; - position: relative; -} - -.my-namespaces-content { - position: absolute; - background-color: #ffffff; - z-index: 1; - 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 */ -.node-children-details { - margin-top: 5px; -} - -.node-children-details > .toggle-summary { - margin-bottom: 5px; -} - #remarkbox-footer { font-size: 0.8em; font-weight: bold; diff --git a/remarkbox/static/js/custom.js b/remarkbox/static/js/custom.js index 93bcf14..f2f7999 100644 --- a/remarkbox/static/js/custom.js +++ b/remarkbox/static/js/custom.js @@ -37,19 +37,39 @@ function sendPreview(textarea, div, mathjax=false){ } } +// CSS-based toggle for smoother animations. +function toggle(target, button, off_text, on_text="hide"){ + var el = document.getElementById(target); + var btn = document.getElementById(button); + if (el.classList.contains('toggle-open')) { + // Animate close, then update text + el.classList.add('toggle-closing'); + setTimeout(function() { + el.classList.remove('toggle-open'); + el.classList.remove('toggle-closing'); + btn.textContent = off_text; + }, 800); + } else { + // Update text immediately when opening + btn.textContent = on_text; + el.classList.add('toggle-open'); + } +} -// Auto-focus textarea when details element opens (progressive enhancement). -// Falls back gracefully if browser doesn't support the required APIs. +// Animate
close for preview-details elements. 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); + document.addEventListener('click', function(e) { + var summary = e.target.closest('.preview-toggle'); + if (!summary) return; + var details = summary.parentElement; + if (!details || !details.classList.contains('preview-details')) return; + if (details.open && !details.classList.contains('closing')) { + e.preventDefault(); + details.classList.add('closing'); + setTimeout(function() { + details.open = false; + details.classList.remove('closing'); + }, 800); } }, true); } diff --git a/remarkbox/templates/base.j2 b/remarkbox/templates/base.j2 index 6a8d35c..f0c7d78 100644 --- a/remarkbox/templates/base.j2 +++ b/remarkbox/templates/base.j2 @@ -35,9 +35,10 @@ {{ snippets.namespace_home_uri(request.namespace) }}   {%- if request.mode != 'embed' and request.user.authenticated and request.user.namespaces %} -
- (switch) -
+ (switch) + +
+ {% for namespace in request.user.namespaces %} {% if namespace != request.namespace %} {{ snippets.namespace_home_uri(namespace) }} @@ -50,7 +51,6 @@ setup
-
  {%- endif %} diff --git a/remarkbox/templates/list-nodes.j2 b/remarkbox/templates/list-nodes.j2 index a06a8a2..483a547 100644 --- a/remarkbox/templates/list-nodes.j2 +++ b/remarkbox/templates/list-nodes.j2 @@ -46,19 +46,13 @@ page: {{ request.page_number }} {{ snippets.actions(node) }} -
- edithide -
+
{{ forms.edit(node) }} -
-
+ -
- remarkhide -
+
{{ forms.reply(node, node) }} -
-
+ {% endfor -%} diff --git a/remarkbox/templates/show-node.j2 b/remarkbox/templates/show-node.j2 index 4901a72..2e47d9b 100644 --- a/remarkbox/templates/show-node.j2 +++ b/remarkbox/templates/show-node.j2 @@ -75,19 +75,13 @@ {% endif %} -
- edithide -
+
{{ forms.edit(request.node) }} -
-
+ -
- -
+
{{ forms.reply(request.node, request.root_node) }} -
-
+ {%- if request.node.id and request.node_graph[request.node.id] -%} @@ -154,29 +148,20 @@ load more ({{children_ids | length}} remarks) {% endif %} -
- edithide -
+
{{ forms.edit(parent) }} -
-
+ -
- remarkhide -
+
{{ forms.reply(parent, request.root_node) }} -
-
- + + {#- nest children in this node's div for convo collapsing. -#} -
- expand [+]collapse [-] -
+
{%- if children_ids %} {{ loop(children_ids) }} {% endif -%} -
-
+ {# close the class="node" div #} diff --git a/remarkbox/templates/snippets/forms.j2 b/remarkbox/templates/snippets/forms.j2 index 03b7539..555f6ad 100644 --- a/remarkbox/templates/snippets/forms.j2 +++ b/remarkbox/templates/snippets/forms.j2 @@ -1,4 +1,5 @@ {% macro reply(node, root) %} + {% if root.locked %}

This thread was locked to prevent additional comments.

@@ -25,8 +26,8 @@ {% set submit_button_value = 'save message' %} {% include 'submit.j2' %} -
- hide preview +
+ hide preview ▲show preview ▼
@@ -38,9 +39,11 @@ {% endif %} + {% endmacro %} {% macro edit(node) %} +
{% if node.title %} @@ -67,6 +70,7 @@ {% set submit_button_value = 'save message' %} {% include 'submit.j2' %}
+ {% endmacro %} {% macro pay_what_you_can() %} diff --git a/remarkbox/templates/snippets/snippets.j2 b/remarkbox/templates/snippets/snippets.j2 index ed3f2f0..0750af6 100644 --- a/remarkbox/templates/snippets/snippets.j2 +++ b/remarkbox/templates/snippets/snippets.j2 @@ -84,7 +84,9 @@ {% macro button_remark(node, root_node) %} {% if root_node and not root_node.locked %} - remark + remark {% endif %} {% endmacro %} @@ -97,6 +99,9 @@ {% endmacro %} {% macro button_collapse(node) %} + {% endmacro %} {% macro permalinks(node, parent_node=None, root_node=None) %} @@ -206,7 +211,8 @@ {{ enable_node(node=node) }}   {% else %} edit + onclick="toggle('edit-box-{{ node.id }}', 'edit-link-{{ node.id }}', 'edit', 'hide'); document.getElementById('edit-textarea-{{ node.id }}').focus(); return false;" + id="edit-link-{{ node.id }}" class="action">edit {{ disable_node(node=node) }}