Fix comments UX regressions and HTMX/Turnstile behavior
- standardize comment and reply UI layout - target replies with stable OOB container IDs - remove stale empty-state on approved HTMX comments - initialize Turnstile widgets after HTMX swaps - add regression tests for empty-state, OOB targets, and reply form rerender Refs #48
This commit is contained in:
@@ -1,46 +1,77 @@
|
||||
{% load static %}
|
||||
<div id="reply-form-container-{{ comment.id }}">
|
||||
<h4 class="font-display font-bold text-sm mb-4 uppercase tracking-wider">Reply to {{ comment.author_name }}</h4>
|
||||
|
||||
<h4 class="mb-3 font-display text-sm font-bold uppercase tracking-wider text-zinc-700 dark:text-zinc-200">Reply to {{ comment.author_name }}</h4>
|
||||
|
||||
{% if reply_success_message %}
|
||||
<div class="mb-6 p-4 bg-brand-cyan/10 border border-brand-cyan/20 font-mono text-sm text-brand-cyan animate-in fade-in">
|
||||
{{ reply_success_message }}
|
||||
</div>
|
||||
<div class="mb-4 rounded-md border border-brand-cyan/30 bg-brand-cyan/10 p-3 font-mono text-sm text-brand-cyan">
|
||||
{{ reply_success_message }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if reply_form_errors %}
|
||||
<div aria-label="Comment form errors" class="mb-6 p-4 bg-red-500/10 border border-red-500/20 font-mono text-sm text-red-400 animate-in shake-1">
|
||||
<div class="font-bold mb-2 uppercase tracking-widest text-xs">Errors:</div>
|
||||
<ul class="list-disc list-inside">
|
||||
{% for field, errors in reply_form_errors.items %}
|
||||
{% for error in errors %}<li>{{ error }}</li>{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<div aria-label="Comment form errors" class="mb-4 rounded-md border border-red-500/30 bg-red-500/10 p-3 font-mono text-sm text-red-500">
|
||||
<div class="mb-2 text-xs font-bold uppercase tracking-wider">Errors:</div>
|
||||
<ul class="list-disc list-inside space-y-1">
|
||||
{% for field, errors in reply_form_errors.items %}
|
||||
{% for error in errors %}<li>{{ error }}</li>{% endfor %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'comment_post' %}"
|
||||
hx-post="{% url 'comment_post' %}" hx-target="#reply-form-container-{{ comment.id }}" hx-swap="outerHTML"
|
||||
class="space-y-4">
|
||||
<form
|
||||
method="post"
|
||||
action="{% url 'comment_post' %}"
|
||||
hx-post="{% url 'comment_post' %}"
|
||||
hx-target="#reply-form-container-{{ comment.id }}"
|
||||
hx-swap="outerHTML"
|
||||
class="space-y-3"
|
||||
>
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="article_id" value="{{ page.id }}" />
|
||||
<input type="hidden" name="parent_id" value="{{ comment.id }}" />
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
<input type="text" name="author_name" required placeholder="Name *"
|
||||
class="bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all" />
|
||||
<input type="email" name="author_email" required placeholder="Email *"
|
||||
class="bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all" />
|
||||
|
||||
<div class="grid grid-cols-1 gap-3 sm:grid-cols-2">
|
||||
<input
|
||||
type="text"
|
||||
name="author_name"
|
||||
required
|
||||
placeholder="Name"
|
||||
value="{% if reply_form %}{{ reply_form.author_name.value|default:'' }}{% endif %}"
|
||||
class="w-full rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm text-zinc-900 focus:border-brand-cyan focus:outline-none focus:ring-2 focus:ring-brand-cyan/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
||||
/>
|
||||
<input
|
||||
type="email"
|
||||
name="author_email"
|
||||
required
|
||||
placeholder="Email"
|
||||
value="{% if reply_form %}{{ reply_form.author_email.value|default:'' }}{% endif %}"
|
||||
class="w-full rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm text-zinc-900 focus:border-brand-cyan focus:outline-none focus:ring-2 focus:ring-brand-cyan/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
||||
/>
|
||||
</div>
|
||||
<textarea name="body" required placeholder="Your reply..." rows="3"
|
||||
class="w-full bg-zinc-50 dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-800 px-4 py-2 font-mono text-sm focus:outline-none focus:border-brand-pink focus:ring-1 focus:ring-brand-pink transition-all resize-none"></textarea>
|
||||
|
||||
<textarea
|
||||
name="body"
|
||||
required
|
||||
placeholder="Write your reply"
|
||||
rows="3"
|
||||
class="w-full rounded-md border border-zinc-300 bg-white px-3 py-2 text-sm text-zinc-900 focus:border-brand-cyan focus:outline-none focus:ring-2 focus:ring-brand-cyan/30 dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-100"
|
||||
>{% if reply_form %}{{ reply_form.body.value|default:'' }}{% endif %}</textarea>
|
||||
|
||||
<input type="text" name="honeypot" hidden />
|
||||
|
||||
|
||||
{% if turnstile_site_key %}
|
||||
<div class="cf-turnstile mb-4" data-sitekey="{{ turnstile_site_key }}" data-theme="auto" data-size="flexible"></div>
|
||||
<div class="cf-turnstile" data-sitekey="{{ turnstile_site_key }}" data-theme="auto" data-size="flexible"></div>
|
||||
{% endif %}
|
||||
|
||||
<div class="flex justify-end gap-3">
|
||||
<button type="submit" data-testid="post-reply-btn" class="px-6 py-2 bg-brand-pink text-white font-display font-bold text-sm shadow-solid-dark hover:-translate-y-0.5 hover:shadow-solid-dark/80 transition-all active:translate-y-0">Post Reply</button>
|
||||
<div class="flex justify-end">
|
||||
<button
|
||||
type="submit"
|
||||
data-testid="post-reply-btn"
|
||||
class="inline-flex items-center rounded-md bg-brand-pink px-4 py-2 font-display text-sm font-bold uppercase tracking-wider text-white transition hover:bg-brand-pink/90 focus:outline-none focus:ring-2 focus:ring-brand-pink/40"
|
||||
>
|
||||
Post reply
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user