feat: rework single post view for better content hierarchy
- Add post-type header (Reply/Like/Repost/Bookmark/Note) for titleless posts - Add left accent border to user content on interaction posts - Collapse AI Usage box into a compact <details> summary line - Collapse comments section when empty, auto-open when comments exist - Collapse webmention send form behind <details> toggle Confab-Link: http://localhost:8080/sessions/648a550c-4f65-46be-b9a9-6b7e0fd90751
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
{# Comments section — shown on post pages before webmentions #}
|
{# Comments section — shown on post pages before webmentions #}
|
||||||
|
{# Collapsed when empty, auto-opens when comments exist #}
|
||||||
{% set absoluteUrl = site.url + page.url %}
|
{% set absoluteUrl = site.url + page.url %}
|
||||||
|
|
||||||
<is-land on:visible>
|
<is-land on:visible>
|
||||||
@@ -6,8 +7,18 @@
|
|||||||
x-data="commentsSection('{{ absoluteUrl }}')"
|
x-data="commentsSection('{{ absoluteUrl }}')"
|
||||||
x-init="init()">
|
x-init="init()">
|
||||||
|
|
||||||
<h2 class="text-xl font-bold mb-4">Comments</h2>
|
<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 #}
|
{# Status messages #}
|
||||||
<div x-show="statusMessage" x-cloak
|
<div x-show="statusMessage" x-cloak
|
||||||
x-bind:class="statusType === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400' :
|
x-bind:class="statusType === 'error' ? 'bg-red-50 text-red-700 dark:bg-red-900/20 dark:text-red-400' :
|
||||||
@@ -92,5 +103,7 @@
|
|||||||
<p class="text-sm text-surface-500">No comments yet. Be the first to share your thoughts!</p>
|
<p class="text-sm text-surface-500">No comments yet. Be the first to share your thoughts!</p>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
</section>
|
</section>
|
||||||
</is-land>
|
</is-land>
|
||||||
|
|||||||
@@ -175,11 +175,15 @@
|
|||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Webmention send form #}
|
{# Webmention send form — collapsed by default #}
|
||||||
<section class="webmention-form mt-8 p-4 bg-surface-100 dark:bg-surface-800 rounded-lg">
|
<details class="mt-8">
|
||||||
<h3 class="text-sm font-semibold text-surface-700 dark:text-surface-300 mb-2">
|
<summary class="text-sm font-semibold text-surface-600 dark:text-surface-400 cursor-pointer hover:text-surface-700 dark:hover:text-surface-300 list-none [&::-webkit-details-marker]:hidden flex items-center gap-1.5">
|
||||||
|
<svg class="w-3.5 h-3.5 transition-transform [[open]>&]:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||||
|
</svg>
|
||||||
Send a Webmention
|
Send a Webmention
|
||||||
</h3>
|
</summary>
|
||||||
|
<div class="mt-3 p-4 bg-surface-100 dark:bg-surface-800 rounded-lg">
|
||||||
<p class="text-xs text-surface-600 dark:text-surface-400 mb-3">
|
<p class="text-xs text-surface-600 dark:text-surface-400 mb-3">
|
||||||
Have you written a response to this post? Send a webmention by entering your post URL below.
|
Have you written a response to this post? Send a webmention by entering your post URL below.
|
||||||
</p>
|
</p>
|
||||||
@@ -198,4 +202,5 @@
|
|||||||
Send
|
Send
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</div>
|
||||||
|
</details>
|
||||||
|
|||||||
+24
-31
@@ -3,8 +3,20 @@ layout: layouts/base.njk
|
|||||||
withBlogSidebar: true
|
withBlogSidebar: true
|
||||||
---
|
---
|
||||||
<article class="h-entry post" x-data="lightbox" @keydown.window="onKeydown($event)">
|
<article class="h-entry post" x-data="lightbox" @keydown.window="onKeydown($event)">
|
||||||
|
{# Support both camelCase (Indiekit Eleventy preset) and underscore (legacy) property names #}
|
||||||
|
{% set bookmarkedUrl = bookmarkOf or bookmark_of %}
|
||||||
|
{% set likedUrl = likeOf or like_of %}
|
||||||
|
{% set replyTo = inReplyTo or in_reply_to %}
|
||||||
|
{% set repostedUrl = repostOf or repost_of %}
|
||||||
|
|
||||||
{% if title %}
|
{% if title %}
|
||||||
<h1 class="p-name text-2xl sm:text-3xl font-bold text-surface-900 dark:text-surface-100 mb-3 sm:mb-4">{{ title }}</h1>
|
<h1 class="p-name text-2xl sm:text-3xl font-bold text-surface-900 dark:text-surface-100 mb-3 sm:mb-4">{{ title }}</h1>
|
||||||
|
{% else %}
|
||||||
|
<div class="flex items-center gap-2 mb-1">
|
||||||
|
<span class="text-sm font-medium text-surface-500 dark:text-surface-400">
|
||||||
|
{% if replyTo %}↩ Reply{% elif likedUrl %}♥ Like{% elif repostedUrl %}♻ Repost{% elif bookmarkedUrl %}🔖 Bookmark{% else %}✎ Note{% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="post-meta mb-4 sm:mb-6">
|
<div class="post-meta mb-4 sm:mb-6">
|
||||||
@@ -27,12 +39,6 @@ withBlogSidebar: true
|
|||||||
|
|
||||||
{# Bridgy syndication content - controls what gets posted to social networks #}
|
{# Bridgy syndication content - controls what gets posted to social networks #}
|
||||||
{# For interaction types (bookmarks, likes, replies, reposts), include the target URL #}
|
{# For interaction types (bookmarks, likes, replies, reposts), include the target URL #}
|
||||||
{# Support both camelCase (Indiekit Eleventy preset) and underscore (legacy) property names #}
|
|
||||||
{% set bookmarkedUrl = bookmarkOf or bookmark_of %}
|
|
||||||
{% set likedUrl = likeOf or like_of %}
|
|
||||||
{% set replyTo = inReplyTo or in_reply_to %}
|
|
||||||
{% set repostedUrl = repostOf or repost_of %}
|
|
||||||
|
|
||||||
{% set bridgySummary = description or summary or (content | ogDescription(280)) %}
|
{% set bridgySummary = description or summary or (content | ogDescription(280)) %}
|
||||||
{% set interactionUrl = bookmarkedUrl or likedUrl or replyTo or repostedUrl %}
|
{% set interactionUrl = bookmarkedUrl or likedUrl or replyTo or repostedUrl %}
|
||||||
|
|
||||||
@@ -53,44 +59,31 @@ withBlogSidebar: true
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="e-content prose prose-surface dark:prose-invert max-w-none">
|
{% set isInteraction = replyTo or likedUrl or repostedUrl or bookmarkedUrl %}
|
||||||
|
{% set hasContent = content and content | striptags | trim %}
|
||||||
|
<div class="e-content prose prose-surface dark:prose-invert max-w-none{% if isInteraction and hasContent %} border-l-[3px] border-l-accent-500 dark:border-l-accent-400 pl-4{% endif %}">
|
||||||
{{ content | safe }}
|
{{ content | safe }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# AI usage disclosure #}
|
{# AI usage disclosure — collapsed by default #}
|
||||||
{% set aiTextLevel = aiTextLevel or ai_text_level %}
|
{% set aiTextLevel = aiTextLevel or ai_text_level %}
|
||||||
{% set aiCodeLevel = aiCodeLevel or ai_code_level %}
|
{% set aiCodeLevel = aiCodeLevel or ai_code_level %}
|
||||||
{% set aiTools = aiTools or ai_tools %}
|
{% set aiTools = aiTools or ai_tools %}
|
||||||
{% set aiDescription = aiDescription or ai_description %}
|
{% set aiDescription = aiDescription or ai_description %}
|
||||||
{% if aiTextLevel or aiCodeLevel or aiTools %}
|
{% if aiTextLevel or aiCodeLevel or aiTools %}
|
||||||
<aside class="mt-6 p-4 rounded-lg bg-surface-50 dark:bg-surface-800/50 border border-surface-200 dark:border-surface-700">
|
<details class="mt-4 text-xs text-surface-500 dark:text-surface-400">
|
||||||
<div class="flex items-center gap-2 mb-2">
|
<summary class="cursor-pointer hover:text-surface-600 dark:hover:text-surface-300 list-none flex items-center gap-1.5 [&::-webkit-details-marker]:hidden">
|
||||||
<svg class="w-4 h-4 text-surface-500 dark:text-surface-400 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
<svg class="w-3.5 h-3.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714a2.25 2.25 0 00.659 1.591L19 14.5M14.25 3.104c.251.023.501.05.75.082M19 14.5l-2.47 2.47a2.25 2.25 0 01-1.59.659H9.06a2.25 2.25 0 01-1.591-.659L5 14.5m14 0V17a2 2 0 01-2 2H7a2 2 0 01-2-2v-2.5"/>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.75 3.104v5.714a2.25 2.25 0 01-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 014.5 0m0 0v5.714a2.25 2.25 0 00.659 1.591L19 14.5M14.25 3.104c.251.023.501.05.75.082M19 14.5l-2.47 2.47a2.25 2.25 0 01-1.59.659H9.06a2.25 2.25 0 01-1.591-.659L5 14.5m14 0V17a2 2 0 01-2 2H7a2 2 0 01-2-2v-2.5"/>
|
||||||
</svg>
|
</svg>
|
||||||
<strong class="text-sm font-semibold text-surface-700 dark:text-surface-300">AI Usage</strong>
|
<span>AI:
|
||||||
</div>
|
{% if aiTextLevel %}Text {% if aiTextLevel === "0" %}None{% elif aiTextLevel === "1" %}Editorial{% elif aiTextLevel === "2" %}Co-drafted{% elif aiTextLevel === "3" %}AI-generated{% endif %}{% endif %}{% if aiCodeLevel %}{% if aiTextLevel %} · {% endif %}Code {% if aiCodeLevel === "0" %}Human{% elif aiCodeLevel === "1" %}AI-assisted{% elif aiCodeLevel === "2" %}AI-generated{% endif %}{% endif %}{% if aiTools %}{% if aiTextLevel or aiCodeLevel %} · {% endif %}{{ aiTools }}{% endif %}
|
||||||
<div class="flex flex-wrap gap-3 text-xs text-surface-600 dark:text-surface-400">
|
|
||||||
{% if aiTextLevel %}
|
|
||||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-surface-100 dark:bg-surface-700">
|
|
||||||
Text: {% if aiTextLevel === "0" %}None{% elif aiTextLevel === "1" %}Editorial{% elif aiTextLevel === "2" %}Co-drafted{% elif aiTextLevel === "3" %}AI-generated{% endif %}
|
|
||||||
</span>
|
</span>
|
||||||
{% endif %}
|
</summary>
|
||||||
{% if aiCodeLevel %}
|
|
||||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-surface-100 dark:bg-surface-700">
|
|
||||||
Code: {% if aiCodeLevel === "0" %}Human{% elif aiCodeLevel === "1" %}AI-assisted{% elif aiCodeLevel === "2" %}AI-generated{% endif %}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
{% if aiTools %}
|
|
||||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded bg-surface-100 dark:bg-surface-700">
|
|
||||||
Tools: {{ aiTools }}
|
|
||||||
</span>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
{% if aiDescription %}
|
{% if aiDescription %}
|
||||||
<p class="mt-2 text-xs text-surface-500 dark:text-surface-400">{{ aiDescription }}</p>
|
<p class="mt-1 pl-5">{{ aiDescription }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</aside>
|
</details>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{# Rich reply context with h-cite microformat #}
|
{# Rich reply context with h-cite microformat #}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ document.addEventListener("alpine:init", () => {
|
|||||||
statusMessage: "",
|
statusMessage: "",
|
||||||
statusType: "info",
|
statusType: "info",
|
||||||
maxLength: 2000,
|
maxLength: 2000,
|
||||||
|
showForm: false,
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
await this.checkSession();
|
await this.checkSession();
|
||||||
|
|||||||
Reference in New Issue
Block a user