Use prettier-plugin-svelte and prettier-plugin-tailwindcss

This commit is contained in:
dtonon 2026-05-27 15:30:11 +01:00
parent 2f6ea767d1
commit b3e6533748
23 changed files with 109 additions and 98 deletions

View file

@ -190,7 +190,7 @@
<aside
bind:this={asideEl}
class="flex-1 flex-col bg-white px-4 pt-4 pb-20 md:absolute md:top-6 md:right-0 md:z-10 md:h-[calc(100%-1.5rem)] md:flex-none md:rounded-tl-xl md:px-6 md:py-6 md:transition-all md:duration-200 min-[1540px]:rounded-tr-xl
class="flex-1 flex-col bg-white px-4 pt-4 pb-20 min-[1540px]:rounded-tr-xl md:absolute md:top-6 md:right-0 md:z-10 md:h-[calc(100%-1.5rem)] md:flex-none md:rounded-tl-xl md:px-6 md:py-6 md:transition-all md:duration-200
{mobileActive ? 'flex' : 'hidden'} md:flex
{expanded ? 'md:w-150 md:shadow-2xl' : 'md:w-80 md:shadow-lg'}"
>

View file

@ -70,7 +70,7 @@
disabled={deleteState.busy}
rows="2"
placeholder="Recorded with the deletion"
class="mb-4 w-full resize-none rounded border border-neutral-200 px-3 py-2 text-sm focus:ring-1 focus:ring-brand focus:outline-none disabled:opacity-50"
class="focus:ring-brand mb-4 w-full resize-none rounded border border-neutral-200 px-3 py-2 text-sm focus:ring-1 focus:outline-none disabled:opacity-50"
></textarea>
<div class="flex justify-end gap-2">

View file

@ -97,11 +97,11 @@
<div class="mx-auto max-w-6xl">
<div class="flex flex-wrap items-center justify-between gap-2 py-2">
<h1 class="text-[1.65rem] text-brand leading-7">{title}</h1>
<h1 class="text-brand text-[1.65rem] leading-7">{title}</h1>
<div class="flex items-center gap-2">
<button
onclick={onNewTopic}
class="rounded bg-brand px-4 py-1.5 md:text-sm font-medium text-white hover:bg-brand-hover md:px-6"
class="bg-brand hover:bg-brand-hover rounded px-4 py-1.5 font-medium text-white md:px-6 md:text-sm"
>
New discussion
</button>

View file

@ -47,7 +47,7 @@
onclick={onClose}
aria-label="Close"
disabled={joinState.busy}
class="absolute right-3 top-3 text-2xl leading-none text-neutral-400 hover:text-neutral-700 disabled:opacity-50"
class="absolute top-3 right-3 text-2xl leading-none text-neutral-400 hover:text-neutral-700 disabled:opacity-50"
>
×
</button>
@ -87,7 +87,7 @@
autocapitalize="off"
spellcheck="false"
onkeydown={(e) => e.key === "Enter" && onRetry()}
class="mb-3 w-full rounded border border-neutral-200 px-3 py-2 text-sm focus:outline-none focus:ring-1 focus:ring-brand disabled:opacity-50"
class="focus:ring-brand mb-3 w-full rounded border border-neutral-200 px-3 py-2 text-sm focus:ring-1 focus:outline-none disabled:opacity-50"
/>
{/if}
@ -104,7 +104,7 @@
type="button"
onclick={onRetry}
disabled={joinState.busy || (joinState.codeRequired && !code.trim())}
class="rounded bg-brand px-3 py-2 text-sm font-medium text-white hover:bg-brand-hover disabled:cursor-not-allowed disabled:opacity-50"
class="bg-brand hover:bg-brand-hover rounded px-3 py-2 text-sm font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
>
{joinState.busy ? "Trying…" : "Retry"}
</button>

View file

@ -28,7 +28,7 @@
</script>
<aside aria-label="Latest discussions">
<h2 class="pb-2 text-[1.5rem] leading-7 text-brand">Latest discussions</h2>
<h2 class="text-brand pb-2 text-[1.5rem] leading-7">Latest discussions</h2>
{#if overviewStore.recent.length === 0}
<p class="text-sm text-neutral-400">
{overviewStore.loading ? "Loading…" : "Nothing yet."}
@ -40,7 +40,7 @@
<li>
<a href="/thread/{t.id}" class="group block py-3">
<p
class="line-clamp-2 text-lg text-neutral-700 leading-5 group-hover:text-brand"
class="group-hover:text-brand line-clamp-2 text-lg leading-5 text-neutral-700"
>
{t.title}
</p>

View file

@ -30,12 +30,12 @@
</script>
<aside
class="hidden max-w-52 min-w-48 shrink-0 flex-col justify-between pl-8 pr-1 pb-8 md:flex md:pt-6"
class="hidden max-w-52 min-w-48 shrink-0 flex-col justify-between pr-1 pb-8 pl-8 md:flex md:pt-6"
>
<div>
<a
href="/"
class="mb-6 mt-3 flex flex-col min-w-0 hover:opacity-90"
class="mt-3 mb-6 flex min-w-0 flex-col hover:opacity-90"
aria-label="{name} — home"
>
{#if groupStore.data?.picture}
@ -45,26 +45,26 @@
class="max-w-[90%] shrink-0 object-cover"
/>
{/if}
<span class="text-[1.3rem] font-medium text-neutral-900 mt-2 leading-6"
<span class="mt-2 text-[1.3rem] leading-6 font-medium text-neutral-900"
>{name}</span
>
</a>
<a
href="/"
class="flex items-center gap-2 py-1 hover:bg-neutral-100 text-neutral-700"
class="flex items-center gap-2 py-1 text-neutral-700 hover:bg-neutral-100"
>
{mode === "simple" ? "Discussions" : "Home"}
</a>
{#if mode === "simple"}
<div class="flex mt-6">
<div class="mt-6 flex">
<p class="text-sm text-neutral-500">{groupStore.data?.about ?? ""}</p>
</div>
{:else}
<nav class="flex-auto mt-6" aria-label="Rooms">
<nav class="mt-6 flex-auto" aria-label="Rooms">
<p
class="pb-1 text-xs font-semibold uppercase tracking-wider text-neutral-400"
class="pb-1 text-xs font-semibold tracking-wider text-neutral-400 uppercase"
>
Rooms
</p>
@ -84,7 +84,7 @@
{#if activeAbout}
<div class="mt-6">
<p
class="pb-1 text-xs font-semibold uppercase tracking-wider text-neutral-400"
class="pb-1 text-xs font-semibold tracking-wider text-neutral-400 uppercase"
>
About
</p>
@ -93,9 +93,9 @@
{/if}
{/if}
<nav class="flex-auto mt-6" aria-label="Resources">
<nav class="mt-6 flex-auto" aria-label="Resources">
<p
class="pb-1 text-xs font-semibold uppercase tracking-wider text-neutral-400"
class="pb-1 text-xs font-semibold tracking-wider text-neutral-400 uppercase"
>
Resources
</p>
@ -122,7 +122,7 @@
<button
type="button"
onclick={resumeDraft}
class="w-full rounded bg-brand px-3 py-1.5 text-sm font-medium text-white hover:bg-brand-hover"
class="bg-brand hover:bg-brand-hover w-full rounded px-3 py-1.5 text-sm font-medium text-white"
>
Resume draft
</button>
@ -154,7 +154,7 @@
{:else}
<button
onclick={openLogin}
class="mt-3 w-full rounded bg-brand px-3 py-1.5 font-medium text-sm text-white hover:bg-brand-hover"
class="bg-brand hover:bg-brand-hover mt-3 w-full rounded px-3 py-1.5 text-sm font-medium text-white"
>
Login
</button>

View file

@ -97,7 +97,7 @@
type="button"
onclick={onClose}
aria-label="Close"
class="absolute right-3 top-3 text-2xl leading-none text-neutral-400 hover:text-neutral-700"
class="absolute top-3 right-3 text-2xl leading-none text-neutral-400 hover:text-neutral-700"
>
×
</button>
@ -119,7 +119,7 @@
<button
onclick={handleExtension}
disabled={busy || !hasExtension}
class="w-full rounded bg-brand px-3 py-2 text-sm font-medium text-white hover:bg-brand-hover disabled:cursor-not-allowed disabled:opacity-50"
class="bg-brand hover:bg-brand-hover w-full rounded px-3 py-2 text-sm font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
>
{busy ? "Connecting…" : "Log in with extension"}
</button>
@ -131,7 +131,7 @@
<button
type="button"
onclick={showNsecView}
class="mt-4 block w-full text-center text-sm text-brand hover:underline"
class="text-brand mt-4 block w-full text-center text-sm hover:underline"
>
Or log in using your nsec
</button>
@ -149,12 +149,12 @@
autocorrect="off"
spellcheck="false"
onkeydown={(e) => e.key === "Enter" && handleNsec()}
class="w-full rounded border border-neutral-200 px-3 py-2 font-mono text-sm focus:outline-none focus:ring-1 focus:ring-brand disabled:opacity-50"
class="focus:ring-brand w-full rounded border border-neutral-200 px-3 py-2 font-mono text-sm focus:ring-1 focus:outline-none disabled:opacity-50"
/>
<button
onclick={handleNsec}
disabled={busy || !nsec.trim()}
class="mt-3 w-full rounded bg-brand px-3 py-2 text-sm font-medium text-white hover:bg-brand-hover disabled:cursor-not-allowed disabled:opacity-50"
class="bg-brand hover:bg-brand-hover mt-3 w-full rounded px-3 py-2 text-sm font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
>
{busy ? "Logging in…" : "Log in"}
</button>
@ -164,7 +164,7 @@
<button
type="button"
onclick={showExtensionView}
class="mt-4 block w-full text-center text-sm text-brand hover:underline"
class="text-brand mt-4 block w-full text-center text-sm hover:underline"
>
Log in with extension
</button>

View file

@ -119,14 +119,14 @@
<a
href="/"
onclick={onClose}
class="py-2 text-xl text-neutral-700 hover:text-brand"
class="hover:text-brand py-2 text-xl text-neutral-700"
>{mode === "simple" ? "Discussions" : "Home"}</a
>
{#if mode === "full"}
<nav class="mt-4" aria-label="Rooms">
<p
class="pb-1 font-semibold uppercase tracking-wider text-neutral-400"
class="pb-1 font-semibold tracking-wider text-neutral-400 uppercase"
>
Rooms
</p>
@ -138,7 +138,7 @@
href="/room/{room.id}"
onclick={onClose}
class="block py-1.5 text-xl
{activeRoom === room.id ? 'text-brand' : 'text-neutral-700 hover:text-brand'}"
{activeRoom === room.id ? 'text-brand' : 'hover:text-brand text-neutral-700'}"
>
{room.name}
</a>
@ -148,7 +148,7 @@
<nav class="mt-4" aria-label="Resources">
<p
class="pb-1 font-semibold uppercase tracking-wider text-neutral-400"
class="pb-1 font-semibold tracking-wider text-neutral-400 uppercase"
>
Resources
</p>
@ -157,7 +157,7 @@
href="/resource/{r.slug}"
onclick={onClose}
aria-current={activeResource === r.slug ? "page" : undefined}
class="block py-1.5 text-xl hover:text-brand
class="hover:text-brand block py-1.5 text-xl
{activeResource === r.slug ? 'text-brand' : 'text-neutral-700'}"
>{r.title}</a
>
@ -166,9 +166,8 @@
href="/contacts"
onclick={onClose}
aria-current={contactsActive ? "page" : undefined}
class="block py-1.5 text-lg hover:text-brand
{contactsActive ? 'text-brand' : 'text-neutral-700'}"
>Contacts</a
class="hover:text-brand block py-1.5 text-lg
{contactsActive ? 'text-brand' : 'text-neutral-700'}">Contacts</a
>
</nav>
@ -177,7 +176,7 @@
<button
type="button"
onclick={onResume}
class="w-full rounded bg-brand px-3 py-2 font-medium text-white hover:bg-brand-hover"
class="bg-brand hover:bg-brand-hover w-full rounded px-3 py-2 font-medium text-white"
>
Resume draft
</button>
@ -214,7 +213,7 @@
<button
type="button"
onclick={onLogin}
class="w-full rounded bg-brand px-3 py-2 text-lg font-medium text-white hover:bg-brand-hover"
class="bg-brand hover:bg-brand-hover w-full rounded px-3 py-2 text-lg font-medium text-white"
>
Login
</button>

View file

@ -8,7 +8,8 @@
// PUBLIC_TITLE always wins when set. Without it, simple mode shows the room's
// own name; full mode has no single room, so it falls back to GROUP_ID.
const name = $derived(
TITLE || (MODE === "simple" ? (groupStore.data?.name ?? GROUP_ID) : GROUP_ID),
TITLE ||
(MODE === "simple" ? (groupStore.data?.name ?? GROUP_ID) : GROUP_ID),
);
</script>
@ -34,7 +35,8 @@
{name[0].toUpperCase()}
</div>
{/if}
<span class="truncate text-2xl font-medium text-neutral-900 md:text-[1.7rem]"
<span
class="truncate text-2xl font-medium text-neutral-900 md:text-[1.7rem]"
>{name}</span
>
</a>

View file

@ -24,7 +24,7 @@
const targetName = $derived(
MODE === "full"
? (groupsStore.list.find((g) => g.id === activeGroup.id)?.name ??
groupStore.data?.name)
groupStore.data?.name)
: groupStore.data?.name,
);
@ -151,7 +151,7 @@
{#if targetName}
<p class="text-sm text-neutral-700">{targetName}</p>
{/if}
<h2 id="newdisc-title" class="text-2xl text-brand">New discussion</h2>
<h2 id="newdisc-title" class="text-brand text-2xl">New discussion</h2>
</div>
<button
type="button"
@ -179,7 +179,7 @@
<div>
<label
for="newdisc-title-input"
class="block text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-1"
class="mb-1 block text-xs font-semibold tracking-wider text-neutral-400 uppercase"
>
Title
</label>
@ -190,7 +190,7 @@
bind:value={draftState.title}
disabled={draftState.publishing}
maxlength="72"
class="w-full rounded border border-neutral-200 px-3 py-2 focus:outline-none focus:ring-1 focus:ring-brand disabled:opacity-50"
class="focus:ring-brand w-full rounded border border-neutral-200 px-3 py-2 focus:ring-1 focus:outline-none disabled:opacity-50"
/>
</div>
@ -199,16 +199,16 @@
<div class="relative">
<label
for="newdisc-labels-input"
class="block text-xs font-semibold uppercase tracking-wider text-neutral-400 mb-1"
class="mb-1 block text-xs font-semibold tracking-wider text-neutral-400 uppercase"
>
Labels
</label>
<div
class="flex flex-wrap gap-1.5 items-center rounded border border-neutral-200 px-3 py-1.5 min-h-[2.5rem] focus-within:ring-1 focus-within:ring-brand"
class="focus-within:ring-brand flex min-h-[2.5rem] flex-wrap items-center gap-1.5 rounded border border-neutral-200 px-3 py-1.5 focus-within:ring-1"
>
{#each draftState.labels as l}
<span
class="inline-flex items-center gap-1 rounded-lg bg-accent px-2 py-0.5 text-sm text-white"
class="bg-accent inline-flex items-center gap-1 rounded-lg px-2 py-0.5 text-sm text-white"
>
{l}
<button
@ -219,7 +219,7 @@
>
</span>
{/each}
<div class="relative flex-1 min-w-[6rem]">
<div class="relative min-w-[6rem] flex-1">
<input
id="newdisc-labels-input"
type="text"
@ -234,7 +234,7 @@
placeholder={draftState.labels.length === 0
? "Click to choose…"
: ""}
class="relative z-10 w-full border-0 bg-transparent p-0 outline-none focus:ring-0 text-sm py-0.5 disabled:opacity-50"
class="relative z-10 w-full border-0 bg-transparent p-0 py-0.5 text-sm outline-none focus:ring-0 disabled:opacity-50"
/>
{#if suggestion}
<span
@ -250,14 +250,14 @@
</div>
{#if suggestOpen && filtered.length > 0}
<div
class="absolute left-0 right-0 z-20 mt-1 rounded border border-neutral-200 bg-white shadow-lg p-3 flex flex-wrap gap-1.5"
class="absolute right-0 left-0 z-20 mt-1 flex flex-wrap gap-1.5 rounded border border-neutral-200 bg-white p-3 shadow-lg"
>
{#each filtered as l}
<button
type="button"
onmousedown={(e) => e.preventDefault()}
onclick={() => onSuggestionClick(l)}
class="rounded-lg bg-accent hover:bg-accent-hover px-2.5 py-0.5 text-sm text-white"
class="bg-accent hover:bg-accent-hover rounded-lg px-2.5 py-0.5 text-sm text-white"
>
{l}
</button>
@ -304,7 +304,7 @@
disabled={draftState.publishing ||
!draftState.title.trim() ||
!draftState.content.trim()}
class="rounded bg-brand px-5 py-1.5 font-medium text-white hover:bg-brand-hover disabled:cursor-not-allowed disabled:opacity-50"
class="bg-brand hover:bg-brand-hover rounded px-5 py-1.5 font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
>
{draftState.publishing ? "Publishing…" : "Publish discussion"}
</button>

View file

@ -593,7 +593,7 @@
href={inline.href}
target={internal ? undefined : "_blank"}
rel={internal ? undefined : "noopener noreferrer"}
class="text-brand hover:underline break-all">{inline.label}</a
class="text-brand break-all hover:underline">{inline.label}</a
>
{:else if inline.type === "mention"}
{@const u = profiles[inline.pubkey] ?? resolvedUsers[inline.pubkey]}
@ -607,10 +607,10 @@
{@const u = profiles[inline.pubkey] ?? resolvedUsers[inline.pubkey]}
<a
href="#post-{inline.eventId}"
class="no-underline font-normal leading-4 bg-neutral-100 block -ml-3 pl-3 py-1 hover:bg-neutral-200"
class="-ml-3 block bg-neutral-100 py-1 pl-3 leading-4 font-normal no-underline hover:bg-neutral-200"
>{u?.shortName ?? inline.pubkey.slice(0, 8)} said
<svg
class="inline w-3 mb-0.5"
class="mb-0.5 inline w-3"
viewBox="0 0 800 800"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
@ -628,7 +628,7 @@
href="https://njump.me/{inline.entity}"
target="_blank"
rel="noopener noreferrer"
class="text-brand hover:underline break-all">{inline.label}</a
class="text-brand break-all hover:underline">{inline.label}</a
>
{:else if inline.type === "strong"}
<strong>{@render renderInlines(inline.children)}</strong>
@ -679,11 +679,11 @@
src={block.src}
alt={block.alt}
loading="lazy"
class="block -mx-6 w-[calc(100%_+_3rem)] max-w-none max-h-[80vh] object-contain rounded-none md:mx-auto md:w-full md:max-w-full md:rounded"
class="-mx-6 block max-h-[80vh] w-[calc(100%_+_3rem)] max-w-none rounded-none object-contain md:mx-auto md:w-full md:max-w-full md:rounded"
/>
{:else if block.type === "blockquote"}
<blockquote
class="my-3 pb-1 mb-3 border-l-3 border-neutral-200 pl-3 text-neutral-500"
class="my-3 mb-3 border-l-3 border-neutral-200 pb-1 pl-3 text-neutral-500"
>
{@render renderBlocks(block.blocks)}
</blockquote>
@ -713,7 +713,7 @@
{:else if block.type === "table"}
{@const headRows = block.rows.filter((r) => r.head)}
{@const bodyRows = block.rows.filter((r) => !r.head)}
<div class="overflow-x-auto my-4">
<div class="my-4 overflow-x-auto">
<table>
{#if headRows.length}
<thead>
@ -752,7 +752,7 @@
{/snippet}
<div
class="prose leading-5 max-w-none text-neutral-700 [&_p]:my-3 [&_img]:my-5 [&_blockquote_img]:mx-0 [&_blockquote_img]:w-full [&_blockquote_img]:max-w-full [&_blockquote_img]:rounded [&_table]:my-0 [&_pre]:bg-neutral-100 [&_pre]:text-neutral-800 [&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-neutral-100 [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_blockquote_p]:before:content-none [&_blockquote_p]:after:content-none [&_code]:before:content-none [&_code]:after:content-none"
class="prose max-w-none leading-5 text-neutral-700 [&_:not(pre)>code]:rounded [&_:not(pre)>code]:bg-neutral-100 [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_blockquote_img]:mx-0 [&_blockquote_img]:w-full [&_blockquote_img]:max-w-full [&_blockquote_img]:rounded [&_blockquote_p]:before:content-none [&_blockquote_p]:after:content-none [&_code]:before:content-none [&_code]:after:content-none [&_img]:my-5 [&_p]:my-3 [&_pre]:bg-neutral-100 [&_pre]:text-neutral-800 [&_table]:my-0"
>
{@render renderBlocks(blocks)}
</div>

View file

@ -61,7 +61,7 @@
aria-haspopup="menu"
aria-expanded={open}
aria-label="Sort discussions, current: {currentLabel}"
class="flex items-center gap-2 rounded bg-neutral-800 px-4 py-1.5 md:text-sm font-medium text-white hover:bg-neutral-700"
class="flex items-center gap-2 rounded bg-neutral-800 px-4 py-1.5 font-medium text-white hover:bg-neutral-700 md:text-sm"
>
<svg
class="h-4 w-4"

View file

@ -3,6 +3,6 @@
let { label }: Props = $props();
</script>
<span class="rounded-lg bg-accent px-2.5 py-0 text-sm text-white">
<span class="bg-accent rounded-lg px-2.5 py-0 text-sm text-white">
{label}
</span>

View file

@ -39,8 +39,8 @@
class="flex items-center gap-3 border-b border-neutral-100 py-4 hover:bg-neutral-50 sm:gap-6"
>
<!-- Col 1: title + byline -->
<div class="flex-1 min-w-0">
<div class="text-lg mb-1.5 text-neutral-900 leading-5">{thread.title}</div>
<div class="min-w-0 flex-1">
<div class="mb-1.5 text-lg leading-5 text-neutral-900">{thread.title}</div>
<div class="flex items-center gap-1.5 text-sm text-neutral-500">
<span>by</span>
{@render avatar(thread.author, "h-5 w-5 rounded-full object-cover")}

View file

@ -141,7 +141,7 @@
</script>
<div
class="sticky self-start flex-shrink-0 flex-col items-end select-none pt-1 max-md:hidden {isOverflowing
class="sticky flex-shrink-0 flex-col items-end self-start pt-1 select-none max-md:hidden {isOverflowing
? 'flex'
: 'hidden'}"
style="top: calc({topOffset}px - 1.5rem); height: 50vh; width: 72px;"
@ -149,7 +149,7 @@
>
<!-- First post date -->
<div
class="text-xs text-neutral-300 mb-1 text-right leading-tight whitespace-pre"
class="mb-1 text-right text-xs leading-tight whitespace-pre text-neutral-300"
>
{firstPost ? formatDate(firstPost.createdAt) : ""}
</div>
@ -157,7 +157,7 @@
<!-- Track area -->
<div
bind:this={trackEl}
class="relative flex-1 w-full cursor-pointer"
class="relative w-full flex-1 cursor-pointer"
onclick={onTrackClick}
role="presentation"
>
@ -169,7 +169,7 @@
<!-- Thumb -->
<div
class="absolute rounded-full bg-brand hover:bg-neutral-600 transition-colors cursor-grab active:cursor-grabbing touch-none"
class="bg-brand absolute cursor-grab touch-none rounded-full transition-colors hover:bg-neutral-600 active:cursor-grabbing"
style="width: 4px; right: 3px; top: {thumbTop}px; height: {thumbHeight}px;"
onpointerdown={onThumbPointerDown}
onpointermove={onThumbPointerMove}
@ -180,7 +180,7 @@
<!-- Current date label -->
<div
class="absolute text-xs text-neutral-400 whitespace-nowrap pointer-events-none leading-tight"
class="pointer-events-none absolute text-xs leading-tight whitespace-nowrap text-neutral-400"
style="right: 18px; top: {thumbTop +
thumbHeight / 2}px; transform: translateY(-50%);"
>
@ -190,7 +190,7 @@
<!-- Last post date -->
<div
class="text-xs text-neutral-300 mt-1 text-right leading-tight whitespace-pre"
class="mt-1 text-right text-xs leading-tight whitespace-pre text-neutral-300"
>
{lastPost ? formatDate(lastPost.createdAt) : ""}
</div>