- Add skip-to-main-content link and main content ID target - Add prefers-reduced-motion media queries for all animations - Enhance visible focus indicators (2px offset, high-contrast ring) - Replace ~160 text-surface-500 instances with text-surface-600/dark:text-surface-400 for 4.5:1+ contrast ratio compliance - Add aria-hidden="true" to ~30+ decorative SVG icons across sidebars/widgets - Convert facepile containers from div to semantic ul/li with role="list" - Add aria-label to icon-only buttons (share, sort controls) - Add sr-only labels to form inputs (webmention, search) - Add aria-live="polite" to dynamically loaded webmentions - Add aria-label with relative+absolute date to time-difference component - Add keyboard handlers (Enter/Space) to custom interactive elements - Add aria-label to nav landmarks (table of contents) - Fix modal focus trap and dialog accessibility - Fix lightbox keyboard navigation and screen reader announcements Confab-Link: http://localhost:8080/sessions/edb1b7b0-da66-4486-bd9c-d1cfa7553b88
112 lines
6.0 KiB
Plaintext
112 lines
6.0 KiB
Plaintext
{# Comments section — shown on post pages before webmentions #}
|
|
{# Collapsed when empty, auto-opens when comments exist #}
|
|
{% set absoluteUrl = site.url + page.url %}
|
|
|
|
<is-land on:visible>
|
|
<section class="comments mt-8 pt-8 border-t border-surface-200 dark:border-surface-700" id="comments"
|
|
x-data="commentsSection('{{ absoluteUrl }}')"
|
|
x-init="init()">
|
|
|
|
<details class="group" x-bind:open="comments.length > 0 || showForm">
|
|
<summary class="flex items-center justify-between cursor-pointer list-none [&::-webkit-details-marker]:hidden" @click="showForm = true">
|
|
<h2 class="text-lg font-semibold text-surface-700 dark:text-surface-300">
|
|
Comments
|
|
<span x-show="comments.length > 0" x-text="'(' + comments.length + ')'" class="text-sm font-normal" x-cloak></span>
|
|
</h2>
|
|
<svg class="w-4 h-4 text-surface-400 transition-transform group-open:rotate-180" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"/>
|
|
</svg>
|
|
</summary>
|
|
|
|
<div class="mt-4">
|
|
{# Status messages #}
|
|
<div x-show="statusMessage" x-cloak
|
|
role="alert"
|
|
x-bind:class="statusType === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400' :
|
|
statusType === 'success' ? 'bg-green-50 text-green-700 dark:bg-green-900/20 dark:text-green-400' :
|
|
'bg-blue-50 text-blue-700 dark:bg-blue-900/20 dark:text-blue-400'"
|
|
class="p-3 rounded-lg mb-4 text-sm">
|
|
<span x-text="statusMessage"></span>
|
|
</div>
|
|
|
|
{# Sign-in form (shown when not authenticated) #}
|
|
<div x-show="!user" x-cloak>
|
|
<p class="text-sm text-surface-600 dark:text-surface-400 mb-3">Sign in with your website to comment:</p>
|
|
<form x-on:submit.prevent="startAuth()" class="flex gap-2 items-end flex-wrap">
|
|
<div class="flex-1 min-w-[200px]">
|
|
<label for="comment-me" class="block text-sm font-medium mb-1">Your website</label>
|
|
<input id="comment-me" type="url" x-model="meUrl"
|
|
placeholder="https://yourdomain.com" required
|
|
class="w-full px-3 py-2 border rounded-lg dark:bg-surface-800 dark:border-surface-700 dark:text-surface-100">
|
|
</div>
|
|
<button type="submit" class="button" x-bind:disabled="authLoading">
|
|
<span x-show="!authLoading">Sign In</span>
|
|
<span x-show="authLoading" x-cloak>Signing in...</span>
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
{# Comment form (shown when authenticated) #}
|
|
<div x-show="user" x-cloak>
|
|
<div class="flex items-center gap-2 mb-3 text-sm text-surface-600 dark:text-surface-400">
|
|
<span>Signed in as</span>
|
|
<a x-bind:href="user?.url" class="font-medium hover:underline" x-text="user?.name || user?.url" target="_blank" rel="noopener"></a>
|
|
<button x-on:click="signOut()" class="text-xs underline hover:no-underline">Sign out</button>
|
|
</div>
|
|
|
|
<form x-on:submit.prevent="submitComment()">
|
|
<label for="comment-text" class="sr-only">Your comment</label>
|
|
<textarea id="comment-text" x-model="commentText" rows="4" required
|
|
placeholder="Share your thoughts... (supports **bold**, *italic*, and [links](url))"
|
|
class="w-full px-3 py-2 border rounded-lg mb-2 dark:bg-surface-800 dark:border-surface-700 dark:text-surface-100"
|
|
x-bind:maxlength="maxLength"></textarea>
|
|
<div class="flex items-center justify-between">
|
|
<span class="text-xs text-surface-600 dark:text-surface-400" x-text="commentText.length + '/' + maxLength"></span>
|
|
<button type="submit" class="button" x-bind:disabled="submitting">
|
|
<span x-show="!submitting">Post Comment</span>
|
|
<span x-show="submitting" x-cloak>Posting...</span>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
{# Comment list #}
|
|
<div class="mt-6 space-y-4">
|
|
<template x-if="loading">
|
|
<p class="text-sm text-surface-600 dark:text-surface-400">Loading comments...</p>
|
|
</template>
|
|
|
|
<template x-for="comment in comments" x-bind:key="comment.published">
|
|
<div class="p-4 bg-surface-50 dark:bg-surface-800 rounded-lg border border-surface-200 dark:border-surface-700 shadow-sm">
|
|
<div class="flex items-start gap-3">
|
|
<template x-if="comment.author?.photo">
|
|
<img x-bind:src="comment.author.photo" x-bind:alt="comment.author.name"
|
|
class="w-8 h-8 rounded-full flex-shrink-0" loading="lazy">
|
|
</template>
|
|
<template x-if="!comment.author?.photo">
|
|
<div class="w-8 h-8 rounded-full bg-surface-200 dark:bg-surface-700 flex-shrink-0 flex items-center justify-center text-xs font-bold"
|
|
x-text="(comment.author?.name || '?')[0].toUpperCase()">
|
|
</div>
|
|
</template>
|
|
<div class="flex-1">
|
|
<div class="flex items-center gap-2">
|
|
<a x-bind:href="comment.author?.url" class="font-medium text-sm hover:underline" target="_blank" rel="noopener"
|
|
x-text="comment.author?.name || comment.author?.url"></a>
|
|
<time class="text-xs text-surface-600 dark:text-surface-400 font-mono" x-bind:datetime="comment.published"
|
|
x-text="new Date(comment.published).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })"></time>
|
|
</div>
|
|
<div class="mt-1 text-sm prose dark:prose-invert" x-html="comment.content?.html || comment.content?.text"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<template x-if="!loading && comments.length === 0">
|
|
<p class="text-sm text-surface-600 dark:text-surface-400">No comments yet. Be the first to share your thoughts!</p>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</section>
|
|
</is-land>
|