Enable dark mode
This commit is contained in:
parent
b3e6533748
commit
dcd3857c80
26 changed files with 410 additions and 220 deletions
|
|
@ -120,7 +120,7 @@
|
|||
it first and it reappears once the top is reached. Desktop only. -->
|
||||
<div class="hidden md:block md:h-6" aria-hidden="true"></div>
|
||||
<div
|
||||
class="min-h-[calc(100dvh_-_4rem)] bg-white px-6 pt-4 pb-20 shadow-lg md:min-h-full md:rounded-t-xl md:px-10 md:pt-6 md:pt-8"
|
||||
class="min-h-[calc(100dvh_-_4rem)] bg-white dark:bg-neutral-900 px-6 pt-4 pb-20 shadow-lg md:min-h-full md:rounded-t-xl md:px-10 md:pt-6 md:pt-8"
|
||||
>
|
||||
{@render children()}
|
||||
</div>
|
||||
|
|
@ -140,7 +140,7 @@
|
|||
>
|
||||
<div class="hidden md:block md:h-6" aria-hidden="true"></div>
|
||||
<div
|
||||
class="bg-white px-6 pt-8 pb-20 shadow-lg md:min-h-full md:rounded-t-xl md:px-8 md:pt-6"
|
||||
class="bg-white dark:bg-neutral-900 px-6 pt-8 pb-20 shadow-lg md:min-h-full md:rounded-t-xl md:px-8 md:pt-6"
|
||||
>
|
||||
<LatestDiscussions />
|
||||
</div>
|
||||
|
|
@ -149,7 +149,7 @@
|
|||
</div>
|
||||
{#if showChat}
|
||||
<nav
|
||||
class="fixed inset-x-0 bottom-0 z-30 flex border-t border-neutral-200 bg-neutral-100 md:hidden"
|
||||
class="fixed inset-x-0 bottom-0 z-30 flex border-t border-neutral-200 dark:border-neutral-700 bg-neutral-100 dark:bg-neutral-800 md:hidden"
|
||||
aria-label="Switch view"
|
||||
>
|
||||
<button
|
||||
|
|
@ -157,7 +157,7 @@
|
|||
onclick={() => (mobileView = "forum")}
|
||||
aria-pressed={mobileView === "forum"}
|
||||
class="flex flex-1 flex-col items-center gap-0.5 py-2 text-xs font-medium
|
||||
{mobileView === 'forum' ? 'text-brand' : 'text-neutral-500'}"
|
||||
{mobileView === 'forum' ? 'text-brand' : 'text-neutral-500 dark:text-neutral-400'}"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -181,7 +181,7 @@
|
|||
onclick={() => (mobileView = "chat")}
|
||||
aria-pressed={mobileView === "chat"}
|
||||
class="flex flex-1 flex-col items-center gap-0.5 py-2 text-xs font-medium
|
||||
{mobileView === 'chat' ? 'text-brand' : 'text-neutral-500'}"
|
||||
{mobileView === 'chat' ? 'text-brand' : 'text-neutral-500 dark:text-neutral-400'}"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
<img src={a.picture} alt="" class="h-5 w-5 rounded-full object-cover" />
|
||||
{:else}
|
||||
<span
|
||||
class="flex h-5 w-5 items-center justify-center rounded-full bg-neutral-200 text-[10px] font-semibold text-neutral-500"
|
||||
class="flex h-5 w-5 items-center justify-center rounded-full bg-neutral-200 dark:bg-neutral-700 text-[10px] font-semibold text-neutral-500 dark:text-neutral-400"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{a.name[0].toUpperCase()}
|
||||
|
|
@ -60,18 +60,18 @@
|
|||
<DiscussionsFeed groupId={GROUP_ID} title="Discussions" />
|
||||
{:else}
|
||||
{#if partial}
|
||||
<hr class="text-neutral-300" />
|
||||
<hr class="text-neutral-300 dark:text-neutral-600" />
|
||||
{:else}
|
||||
<h1 class="text-brand py-2 text-[1.65rem]">Forum rooms</h1>
|
||||
{/if}
|
||||
|
||||
{#if groupsStore.list.length === 0}
|
||||
<p class="py-6 text-sm text-neutral-400">
|
||||
<p class="py-6 text-sm text-neutral-400 dark:text-neutral-500">
|
||||
{groupsStore.loaded ? "No rooms available yet." : "Loading rooms…"}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<div class="divide-y divide-neutral-100">
|
||||
<div class="divide-y divide-neutral-100 dark:divide-neutral-800">
|
||||
{#each groupsStore.list as room}
|
||||
{@const act = overviewStore.activity[room.id]}
|
||||
{@const adminPk = overviewStore.admins[room.id]}
|
||||
|
|
@ -82,14 +82,14 @@
|
|||
class="group flex items-start justify-between gap-4 py-5"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<h2 class="group-hover:text-brand text-2xl text-neutral-800">
|
||||
<h2 class="group-hover:text-brand text-2xl text-neutral-800 dark:text-neutral-200">
|
||||
{room.name}
|
||||
</h2>
|
||||
{#if room.about}
|
||||
<p class="mt-1 leading-5 text-neutral-600">{room.about}</p>
|
||||
<p class="mt-1 leading-5 text-neutral-600 dark:text-neutral-400">{room.about}</p>
|
||||
{/if}
|
||||
{#if admin}
|
||||
<div class="mt-2 flex items-center gap-2 text-sm text-neutral-500">
|
||||
<div class="mt-2 flex items-center gap-2 text-sm text-neutral-500 dark:text-neutral-400">
|
||||
<span>Admin</span>
|
||||
{@render pic(admin)}
|
||||
</div>
|
||||
|
|
@ -99,9 +99,9 @@
|
|||
<div class="flex shrink-0 flex-col items-center gap-0.5">
|
||||
<div class="flex items-center gap-1">
|
||||
{@render pic(last)}
|
||||
<span class="text-neutral-800">{relativeTime(act.latestAt)}</span>
|
||||
<span class="text-neutral-800 dark:text-neutral-200">{relativeTime(act.latestAt)}</span>
|
||||
</div>
|
||||
<span class="text-sm text-neutral-400">activity</span>
|
||||
<span class="text-sm text-neutral-400 dark:text-neutral-500">activity</span>
|
||||
</div>
|
||||
{/if}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -81,14 +81,14 @@
|
|||
{/if}
|
||||
|
||||
{#if loading}
|
||||
<p class="py-6 text-center text-neutral-400">Loading…</p>
|
||||
<p class="py-6 text-center text-neutral-400 dark:text-neutral-500">Loading…</p>
|
||||
{:else if contacts.length === 0}
|
||||
<p class="py-6 text-center text-neutral-400">No admins listed.</p>
|
||||
<p class="py-6 text-center text-neutral-400 dark:text-neutral-500">No admins listed.</p>
|
||||
{:else}
|
||||
<ul class="mt-2 space-y-3">
|
||||
{#each contacts as c (c.pubkey)}
|
||||
<li
|
||||
class="flex gap-4 rounded-lg border border-neutral-100 p-4 shadow-sm"
|
||||
class="flex gap-4 rounded-lg border border-neutral-100 dark:border-neutral-800 p-4 shadow-sm"
|
||||
>
|
||||
{#if c.entry?.picture}
|
||||
<img
|
||||
|
|
@ -98,7 +98,7 @@
|
|||
/>
|
||||
{:else}
|
||||
<span
|
||||
class="flex h-14 w-14 shrink-0 items-center justify-center rounded-full bg-neutral-200 text-lg font-semibold text-neutral-500"
|
||||
class="flex h-14 w-14 shrink-0 items-center justify-center rounded-full bg-neutral-200 dark:bg-neutral-700 text-lg font-semibold text-neutral-500 dark:text-neutral-400"
|
||||
>
|
||||
{displayName(c)[0].toUpperCase()}
|
||||
</span>
|
||||
|
|
@ -107,11 +107,11 @@
|
|||
<div class="min-w-0 flex-1">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div class="min-w-0">
|
||||
<p class="truncate text-2xl font-medium text-neutral-900">
|
||||
<p class="truncate text-2xl font-medium text-neutral-900 dark:text-neutral-100">
|
||||
{displayName(c)}
|
||||
</p>
|
||||
{#if c.entry?.nip05}
|
||||
<p class="truncate text-neutral-400">
|
||||
<p class="truncate text-neutral-400 dark:text-neutral-500">
|
||||
{c.entry.nip05}
|
||||
</p>
|
||||
{/if}
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
</div>
|
||||
|
||||
{#if c.entry?.about}
|
||||
<p class="mt-2 whitespace-pre-line text-neutral-600">
|
||||
<p class="mt-2 whitespace-pre-line text-neutral-600 dark:text-neutral-400">
|
||||
{c.entry.about}
|
||||
</p>
|
||||
{/if}
|
||||
|
|
@ -145,7 +145,7 @@
|
|||
</a>
|
||||
{/if}
|
||||
{#if c.entry?.lud16}
|
||||
<span class="text-neutral-500" title="Lightning address">
|
||||
<span class="text-neutral-500 dark:text-neutral-400" title="Lightning address">
|
||||
⚡ {c.entry.lud16}
|
||||
</span>
|
||||
{/if}
|
||||
|
|
@ -155,8 +155,8 @@
|
|||
{#if MODE === "full"}
|
||||
{@const rooms = roomsOf(c.pubkey)}
|
||||
{#if rooms.length > 0}
|
||||
<p class="mt-2 text-neutral-500">
|
||||
<span class="text-neutral-400">Manages:</span>
|
||||
<p class="mt-2 text-neutral-500 dark:text-neutral-400">
|
||||
<span class="text-neutral-400 dark:text-neutral-500">Manages:</span>
|
||||
{#each rooms as r, i}<a
|
||||
href="/room/{r.id}"
|
||||
class="text-brand hover:underline">{r.name}</a
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
@plugin "@tailwindcss/forms";
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
/* Class-based dark mode: the FOUC script in app.html and the theme store add
|
||||
`dark` to <html> so `dark:` utilities apply without relying on prefers-color-scheme. */
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
|
@ -9,6 +13,9 @@ html {
|
|||
body {
|
||||
background-color: var(--color-neutral-100);
|
||||
}
|
||||
:where(.dark) body {
|
||||
background-color: var(--color-neutral-800);
|
||||
}
|
||||
|
||||
.no-scrollbar {
|
||||
scrollbar-width: none;
|
||||
|
|
@ -17,6 +24,20 @@ body {
|
|||
display: none;
|
||||
}
|
||||
|
||||
/* Form inputs in dark mode — the forms plugin defaults to a white background,
|
||||
which would punch holes through panels. Override at the element level so we
|
||||
don't have to add `dark:bg-neutral-800` to every <input>/<textarea>. */
|
||||
:where(.dark) input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"]):not([type="color"]):not([type="submit"]):not([type="reset"]):not([type="button"]),
|
||||
:where(.dark) textarea,
|
||||
:where(.dark) select {
|
||||
background-color: var(--color-neutral-800);
|
||||
color: var(--color-neutral-100);
|
||||
}
|
||||
:where(.dark) input::placeholder,
|
||||
:where(.dark) textarea::placeholder {
|
||||
color: var(--color-neutral-500);
|
||||
}
|
||||
|
||||
/* Tighter heading rhythm for all rendered (prose) content. Overrides the
|
||||
typography plugin's em-based heading margins; the first block stays flush. */
|
||||
.prose :is(h1, h2, h3, h4, h5, h6) {
|
||||
|
|
@ -35,6 +56,21 @@ body {
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Prose headings/strong/links default to dark text colors; flip them in dark mode. */
|
||||
:where(.dark) .prose :is(h1, h2, h3, h4, h5, h6, strong, th) {
|
||||
color: var(--color-neutral-100);
|
||||
}
|
||||
:where(.dark) .prose :is(h1) {
|
||||
color: var(--color-brand);
|
||||
}
|
||||
:where(.dark) .prose :is(blockquote) {
|
||||
color: var(--color-neutral-400);
|
||||
border-left-color: var(--color-neutral-700);
|
||||
}
|
||||
:where(.dark) .prose :is(hr, thead, tbody tr) {
|
||||
border-color: var(--color-neutral-700);
|
||||
}
|
||||
|
||||
@theme {
|
||||
--color-brand: #e32a6d;
|
||||
--color-brand-hover: #c4205a;
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="mx-auto max-w-6xl">
|
||||
<a
|
||||
href="/"
|
||||
class="hover:text-brand mb-1 inline-flex items-center gap-1 text-sm text-neutral-400"
|
||||
class="hover:text-brand mb-1 inline-flex items-center gap-1 text-sm text-neutral-400 dark:text-neutral-500"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -56,8 +56,8 @@
|
|||
<PostContent content={resource.content} headingOffset={0} />
|
||||
</div>
|
||||
{:else if notFound}
|
||||
<p class="py-12 text-center text-neutral-400">Resource not found.</p>
|
||||
<p class="py-12 text-center text-neutral-400 dark:text-neutral-500">Resource not found.</p>
|
||||
{:else}
|
||||
<p class="py-12 text-center text-neutral-400">Loading…</p>
|
||||
<p class="py-12 text-center text-neutral-400 dark:text-neutral-500">Loading…</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@
|
|||
/>
|
||||
{:else}
|
||||
<span
|
||||
class="flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200 text-lg font-semibold text-neutral-500"
|
||||
class="flex h-12 w-12 items-center justify-center rounded-full bg-neutral-200 dark:bg-neutral-700 text-lg font-semibold text-neutral-500 dark:text-neutral-400"
|
||||
>
|
||||
{author.name[0].toUpperCase()}
|
||||
</span>
|
||||
|
|
@ -293,7 +293,7 @@
|
|||
<div class="flex-shrink-0 md:hidden">
|
||||
{@render avatar(author)}
|
||||
</div>
|
||||
<span class="truncate font-medium text-neutral-500"
|
||||
<span class="truncate font-medium text-neutral-500 dark:text-neutral-400"
|
||||
>{author.name}</span
|
||||
>
|
||||
</div>
|
||||
|
|
@ -302,7 +302,7 @@
|
|||
<div class="relative">
|
||||
<button
|
||||
onclick={(e) => toggleMenu(p.id, e)}
|
||||
class="flex items-center justify-center rounded p-1 text-neutral-300 transition-colors hover:bg-neutral-100 hover:text-neutral-500"
|
||||
class="flex items-center justify-center rounded p-1 text-neutral-300 dark:text-neutral-600 transition-colors hover:bg-neutral-100 dark:hover:bg-neutral-800 hover:text-neutral-500 dark:hover:text-neutral-400"
|
||||
aria-label="Post actions"
|
||||
aria-haspopup="menu"
|
||||
aria-expanded={openMenuId === p.id}
|
||||
|
|
@ -321,7 +321,7 @@
|
|||
{#if openMenuId === p.id}
|
||||
<div
|
||||
role="menu"
|
||||
class="absolute top-7 right-0 z-20 w-36 rounded-lg border border-neutral-100 bg-white py-1 text-sm shadow-lg"
|
||||
class="absolute top-7 right-0 z-20 w-36 rounded-lg border border-neutral-100 dark:border-neutral-800 bg-white dark:bg-neutral-900 py-1 text-sm shadow-lg"
|
||||
>
|
||||
<button
|
||||
role="menuitem"
|
||||
|
|
@ -336,7 +336,7 @@
|
|||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
<span class="text-sm text-neutral-400">{formatDate(p.createdAt)}</span
|
||||
<span class="text-sm text-neutral-400 dark:text-neutral-500">{formatDate(p.createdAt)}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -348,7 +348,7 @@
|
|||
<button
|
||||
onclick={() => quotePost(p)}
|
||||
disabled={!auth.user}
|
||||
class="hover:text-brand flex cursor-pointer items-center gap-1.5 text-neutral-300 transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
||||
class="hover:text-brand flex cursor-pointer items-center gap-1.5 text-neutral-300 dark:text-neutral-600 transition-colors disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
<span>Quote post</span>
|
||||
<svg
|
||||
|
|
@ -375,11 +375,11 @@
|
|||
<div class="flex items-start gap-6">
|
||||
<div class="min-w-0 flex-1 {!scrubberVisible ? 'md:pr-18' : ''}">
|
||||
<div
|
||||
class="relative z-10 bg-white pb-1 md:sticky md:-top-6 md:-mx-10 md:-mt-6 md:px-10 md:pt-6"
|
||||
class="relative z-10 bg-white dark:bg-neutral-900 pb-1 md:sticky md:-top-6 md:-mx-10 md:-mt-6 md:px-10 md:pt-6"
|
||||
>
|
||||
<a
|
||||
href={MODE === "full" ? `/room/${detail.groupId}` : "/"}
|
||||
class="hover:text-brand mb-1 inline-flex items-center gap-1 text-sm text-neutral-400"
|
||||
class="hover:text-brand mb-1 inline-flex items-center gap-1 text-sm text-neutral-400 dark:text-neutral-500"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
|
@ -401,8 +401,8 @@
|
|||
<h1 class="text-brand text-[1.65rem] leading-7">{detail.title}</h1>
|
||||
{#if isScrolled}
|
||||
<div
|
||||
class="pointer-events-none absolute right-0 left-0 h-8 transition-opacity duration-200"
|
||||
style="top: 100%; background: linear-gradient(to bottom, white, transparent);"
|
||||
class="pointer-events-none absolute right-0 left-0 h-8 bg-gradient-to-b from-white to-transparent transition-opacity duration-200 dark:from-neutral-900"
|
||||
style="top: 100%;"
|
||||
></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -420,7 +420,7 @@
|
|||
</div>
|
||||
|
||||
{#if detail.replies.length > 0}
|
||||
<div class="divide-y divide-neutral-100 border-t border-neutral-100">
|
||||
<div class="divide-y divide-neutral-100 dark:divide-neutral-800 border-t border-neutral-100 dark:border-neutral-800">
|
||||
{#each detail.replies as reply, i}
|
||||
<div class="py-6" bind:this={replyEls[i]}>
|
||||
{@render post(reply, i + 1, () => {})}
|
||||
|
|
@ -429,7 +429,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="mt-8 border-t border-neutral-200 pt-6 md:pl-18">
|
||||
<div class="mt-8 border-t border-neutral-200 dark:border-neutral-700 pt-6 md:pl-18">
|
||||
{#if auth.user}
|
||||
{#if replyError}
|
||||
<div
|
||||
|
|
@ -458,7 +458,7 @@
|
|||
</button>
|
||||
</div>
|
||||
{:else}
|
||||
<p class=" text-center text-neutral-500">
|
||||
<p class=" text-center text-neutral-500 dark:text-neutral-400">
|
||||
To participate and reply, please
|
||||
<button onclick={openLogin} class="text-brand hover:underline"
|
||||
>login now</button
|
||||
|
|
@ -476,7 +476,7 @@
|
|||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="py-12 text-center text-neutral-400">Loading…</div>
|
||||
<div class="py-12 text-center text-neutral-400 dark:text-neutral-500">Loading…</div>
|
||||
{/if}
|
||||
|
||||
{#if selectionTarget && auth.user}
|
||||
|
|
@ -485,7 +485,7 @@
|
|||
onmousedown={(e) => e.preventDefault()}
|
||||
onclick={quoteFromSelection}
|
||||
style="top: {selectionTarget.top}px; left: {selectionTarget.left}px;"
|
||||
class="fixed z-50 -translate-x-1/2 -translate-y-full rounded bg-neutral-900 px-3 py-1 text-xs font-medium text-white shadow-md hover:bg-neutral-700"
|
||||
class="bg-brand hover:bg-brand-hover fixed z-50 -translate-x-1/2 -translate-y-full rounded px-3 py-1 text-xs font-medium text-white shadow-md"
|
||||
>
|
||||
Quote
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue