Browse Source

make publication responsive to screen width

remove superfluous section indenting
correct menus
get rid of clunky button row
master
silberengel 3 months ago
parent
commit
4a57606889
  1. 244
      src/lib/components/publications/Publication.svelte
  2. 72
      src/lib/components/publications/PublicationSection.svelte
  3. 25
      src/lib/components/publications/TableOfContents.svelte
  4. 2
      src/lib/components/util/ArticleNav.svelte
  5. 13
      src/lib/components/util/CardActions.svelte
  6. 12
      src/lib/components/util/Details.svelte
  7. 2
      src/lib/snippets/PublicationSnippets.svelte

244
src/lib/components/publications/Publication.svelte

@ -8,18 +8,30 @@
SidebarWrapper, SidebarWrapper,
Heading, Heading,
CloseButton, CloseButton,
Textarea,
Popover,
P,
Modal,
} from "flowbite-svelte"; } from "flowbite-svelte";
import { getContext, onDestroy, onMount } from "svelte"; import { getContext, onDestroy, onMount } from "svelte";
import { import {
CloseOutline, CloseOutline,
ExclamationCircleOutline, ExclamationCircleOutline,
MessageDotsOutline,
FilePenOutline,
DotsVerticalOutline,
EyeOutline,
EyeSlashOutline,
ClipboardCleanOutline,
TrashBinOutline,
} from "flowbite-svelte-icons"; } from "flowbite-svelte-icons";
import type { NDKEvent } from "@nostr-dev-kit/ndk"; import type { NDKEvent } from "@nostr-dev-kit/ndk";
import PublicationSection from "./PublicationSection.svelte"; import PublicationSection from "./PublicationSection.svelte";
import Details from "$components/util/Details.svelte"; import Details from "$components/util/Details.svelte";
import CopyToClipboard from "$components/util/CopyToClipboard.svelte";
import { neventEncode, naddrEncode } from "$lib/utils";
import { publicationColumnVisibility } from "$lib/stores"; import { publicationColumnVisibility } from "$lib/stores";
import BlogHeader from "$components/cards/BlogHeader.svelte"; import BlogHeader from "$components/cards/BlogHeader.svelte";
import Interactions from "$components/util/Interactions.svelte";
import type { SveltePublicationTree } from "./svelte_publication_tree.svelte"; import type { SveltePublicationTree } from "./svelte_publication_tree.svelte";
import TableOfContents from "./TableOfContents.svelte"; import TableOfContents from "./TableOfContents.svelte";
import type { TableOfContents as TocType } from "./table_of_contents.svelte"; import type { TableOfContents as TocType } from "./table_of_contents.svelte";
@ -27,15 +39,13 @@
import { deleteEvent } from "$lib/services/deletion"; import { deleteEvent } from "$lib/services/deletion";
import { getNdkContext, activeOutboxRelays } from "$lib/ndk"; import { getNdkContext, activeOutboxRelays } from "$lib/ndk";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { getMatchingTags } from "$lib/utils/nostrUtils";
import HighlightLayer from "./HighlightLayer.svelte"; import HighlightLayer from "./HighlightLayer.svelte";
import { EyeOutline, EyeSlashOutline } from "flowbite-svelte-icons";
import HighlightButton from "./HighlightButton.svelte";
import HighlightSelectionHandler from "./HighlightSelectionHandler.svelte"; import HighlightSelectionHandler from "./HighlightSelectionHandler.svelte";
import CommentLayer from "./CommentLayer.svelte"; import CommentLayer from "./CommentLayer.svelte";
import CommentButton from "./CommentButton.svelte";
import SectionComments from "./SectionComments.svelte"; import SectionComments from "./SectionComments.svelte";
import { Textarea, P } from "flowbite-svelte";
import { userStore } from "$lib/stores/userStore"; import { userStore } from "$lib/stores/userStore";
import CardActions from "$components/util/CardActions.svelte";
let { rootAddress, publicationType, indexEvent, publicationTree, toc } = let { rootAddress, publicationType, indexEvent, publicationTree, toc } =
$props<{ $props<{
@ -62,6 +72,10 @@
let isSubmittingArticleComment = $state(false); let isSubmittingArticleComment = $state(false);
let articleCommentError = $state<string | null>(null); let articleCommentError = $state<string | null>(null);
let articleCommentSuccess = $state(false); let articleCommentSuccess = $state(false);
// Publication header actions menu state
let publicationActionsOpen = $state(false);
let detailsModalOpen = $state(false);
// Toggle between mock and real data for testing (DEBUG MODE) // Toggle between mock and real data for testing (DEBUG MODE)
// Can be controlled via VITE_USE_MOCK_COMMENTS and VITE_USE_MOCK_HIGHLIGHTS environment variables // Can be controlled via VITE_USE_MOCK_COMMENTS and VITE_USE_MOCK_HIGHLIGHTS environment variables
@ -240,6 +254,11 @@
publicationColumnVisibility.update((v) => ({ ...v, discussion: false })); publicationColumnVisibility.update((v) => ({ ...v, discussion: false }));
} }
function viewDetails() {
detailsModalOpen = true;
publicationActionsOpen = false;
}
function loadBlog(rootId: string) { function loadBlog(rootId: string) {
// depending on the size of the screen, also toggle discussion visibility // depending on the size of the screen, also toggle discussion visibility
publicationColumnVisibility.update((current) => { publicationColumnVisibility.update((current) => {
@ -445,6 +464,27 @@
if (isLeaf || isBlog) { if (isLeaf || isBlog) {
publicationColumnVisibility.update((v) => ({ ...v, toc: false })); publicationColumnVisibility.update((v) => ({ ...v, toc: false }));
} }
// Set up the intersection observer.
observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (
entry.isIntersecting &&
!isLoading &&
!isDone &&
publicationTree
) {
loadMore(1);
}
});
},
{ threshold: 0.5 },
);
// AI-NOTE: Removed duplicate loadMore call
// Initial content loading is handled by the $effect that watches publicationTree
// This prevents duplicate loading when both onMount and $effect trigger
// Set up the intersection observer. // Set up the intersection observer.
observer = new IntersectionObserver( observer = new IntersectionObserver(
@ -467,6 +507,7 @@
// Initial content loading is handled by the $effect that watches publicationTree // Initial content loading is handled by the $effect that watches publicationTree
// This prevents duplicate loading when both onMount and $effect trigger // This prevents duplicate loading when both onMount and $effect trigger
return () => { return () => {
observer.disconnect(); observer.disconnect();
}; };
@ -484,7 +525,7 @@
<!-- Add gap & items-start so sticky sidebars size correctly --> <!-- Add gap & items-start so sticky sidebars size correctly -->
<div <div
class="relative grid gap-4 items-start grid-cols-1 grid-rows-[auto_1fr]" class="relative grid gap-4 items-start grid-cols-1 grid-rows-[auto_1fr] overflow-x-hidden"
> >
<!-- Full-width ArticleNav row --> <!-- Full-width ArticleNav row -->
<ArticleNav {publicationType} rootId={indexEvent.id} {indexEvent} /> <ArticleNav {publicationType} rootId={indexEvent.id} {indexEvent} />
@ -505,14 +546,14 @@
}} }}
/> />
<!-- Content row --> <!-- Content row -->
<div class="contents flex justify-center"> <div class="contents">
<!-- Table of contents column removed - using overlay drawer instead --> <!-- Table of contents column removed - using overlay drawer instead -->
<div class="mt-[70px] w-full max-w-7xl"> <div class="mt-[70px] w-full max-w-full md:max-w-7xl mx-auto">
<!-- Default publications --> <!-- Default publications -->
{#if $publicationColumnVisibility.main} {#if $publicationColumnVisibility.main}
<!-- Remove overflow-auto so page scroll drives it --> <!-- Remove overflow-auto so page scroll drives it -->
<div <div
class="flex flex-col p-4 space-y-4 max-w-3xl flex-grow-2 mx-auto" class="flex flex-col p-4 space-y-4 max-w-3xl flex-grow-2 mx-auto text-left"
bind:this={publicationContentRef} bind:this={publicationContentRef}
> >
<!-- Publication header with comments (similar to section layout) --> <!-- Publication header with comments (similar to section layout) -->
@ -520,12 +561,150 @@
<!-- Main header content - centered --> <!-- Main header content - centered -->
<div class="max-w-4xl mx-auto px-4"> <div class="max-w-4xl mx-auto px-4">
<div <div
class="card-leather bg-highlight dark:bg-primary-900 p-4 mb-4 rounded-lg border" class="card-leather bg-highlight dark:bg-primary-900 p-4 mb-4 rounded-lg border relative"
id={rootAddress}
> >
<Details <Details
event={indexEvent} event={indexEvent}
onDelete={handleDeletePublication} onDelete={handleDeletePublication}
hideActions={true}
/> />
<!-- Publication actions menu button - positioned at top-right -->
<div
class="absolute top-2 right-2 card-actions z-20"
role="button"
tabindex={0}
onclick={(e) => e.stopPropagation()}
onkeydown={(e) => e.stopPropagation()}
>
<div
class="group bg-transparent rounded relative"
role="group"
onmouseenter={() => (publicationActionsOpen = true)}
>
<Button
type="button"
id="publication-actions"
class="!bg-transparent hover:!bg-primary-100 dark:hover:!bg-primary-800 text-primary-600 dark:text-gray-300 hover:text-primary-700 dark:hover:text-gray-200 p-1 dots !border-0 !shadow-none"
data-popover-target="popover-publication-actions"
>
<DotsVerticalOutline class="h-6 w-6" />
<span class="sr-only">Open publication actions menu</span>
</Button>
{#if publicationActionsOpen}
<Popover
id="popover-publication-actions"
placement="bottom"
trigger="click"
class="popover-leather w-fit z-10"
onmouseleave={() => (publicationActionsOpen = false)}
>
<div class="flex flex-row justify-between space-x-4">
<div class="flex flex-col text-nowrap">
<ul class="space-y-2">
<li>
<button
class="btn-leather w-full text-left"
onclick={() => {
showArticleCommentUI = !showArticleCommentUI;
publicationActionsOpen = false;
}}
>
<MessageDotsOutline class="inline mr-2" />
{showArticleCommentUI ? "Close Comment" : "Comment On Article"}
</button>
</li>
<li>
<button
class="btn-leather w-full text-left"
onclick={() => {
highlightModeActive = !highlightModeActive;
publicationActionsOpen = false;
}}
>
<FilePenOutline class="inline mr-2" />
{highlightModeActive ? "Exit Highlight Mode" : "Add Highlight"}
</button>
</li>
<li>
<button
class="btn-leather w-full text-left"
onclick={() => {
toggleComments();
publicationActionsOpen = false;
}}
>
{#if commentsVisible}
<EyeSlashOutline class="inline mr-2" />
Hide Comments
{:else}
<EyeOutline class="inline mr-2" />
Show Comments
{/if}
</button>
</li>
<li>
<button
class="btn-leather w-full text-left"
onclick={() => {
toggleHighlights();
publicationActionsOpen = false;
}}
>
{#if highlightsVisible}
<EyeSlashOutline class="inline mr-2" />
Hide Highlights
{:else}
<EyeOutline class="inline mr-2" />
Show Highlights
{/if}
</button>
</li>
<li>
<button
class="btn-leather w-full text-left"
onclick={viewDetails}
>
<EyeOutline class="inline mr-2" /> View details
</button>
</li>
<li>
<CopyToClipboard
displayText="Copy naddr address"
copyText={naddrEncode(indexEvent, $activeOutboxRelays)}
icon={ClipboardCleanOutline}
/>
</li>
<li>
<CopyToClipboard
displayText="Copy nevent address"
copyText={neventEncode(indexEvent, $activeOutboxRelays)}
icon={ClipboardCleanOutline}
/>
</li>
{#if $userStore.signedIn && $userStore.pubkey === indexEvent.pubkey}
<li>
<button
class="btn-leather w-full text-left text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20"
onclick={() => {
publicationActionsOpen = false;
handleDeletePublication();
}}
>
<TrashBinOutline class="inline mr-2" />
Delete publication
</button>
</li>
{/if}
</ul>
</div>
</div>
</Popover>
{/if}
</div>
</div>
</div> </div>
{#if publicationDeleted} {#if publicationDeleted}
@ -557,39 +736,6 @@
</div> </div>
</div> </div>
<!-- Action buttons row -->
<div class="flex justify-between gap-2 mb-4 bg-transparent">
<div class="flex gap-2 bg-transparent">
<Button
color="light"
size="sm"
onclick={() => (showArticleCommentUI = !showArticleCommentUI)}
>
{showArticleCommentUI ? "Close Comment" : "Comment On Article"}
</Button>
<HighlightButton bind:isActive={highlightModeActive} />
</div>
<div class="flex gap-2 bg-transparent">
<Button color="light" size="sm" onclick={toggleComments}>
{#if commentsVisible}
<EyeSlashOutline class="w-4 h-4 mr-2" />
Hide Comments
{:else}
<EyeOutline class="w-4 h-4 mr-2" />
Show Comments
{/if}
</Button>
<Button color="light" size="sm" onclick={toggleHighlights}>
{#if highlightsVisible}
<EyeSlashOutline class="w-4 h-4 mr-2" />
Hide Highlights
{:else}
<EyeOutline class="w-4 h-4 mr-2" />
Show Highlights
{/if}
</Button>
</div>
</div>
<!-- Article Comment UI --> <!-- Article Comment UI -->
{#if showArticleCommentUI} {#if showArticleCommentUI}
@ -647,6 +793,8 @@
</Alert> </Alert>
{:else} {:else}
{@const address = leaf.tagAddress()} {@const address = leaf.tagAddress()}
{@const publicationTitle = getMatchingTags(indexEvent, "title")[0]?.[1]}
{@const isFirstSection = i === 0}
<PublicationSection <PublicationSection
{rootAddress} {rootAddress}
{leaves} {leaves}
@ -655,6 +803,8 @@
{toc} {toc}
allComments={comments} allComments={comments}
{commentsVisible} {commentsVisible}
publicationTitle={publicationTitle}
{isFirstSection}
ref={(el) => onPublicationSectionMounted(el, address)} ref={(el) => onPublicationSectionMounted(el, address)}
/> />
{/if} {/if}
@ -861,3 +1011,11 @@
bind:comments bind:comments
{useMockComments} {useMockComments}
/> />
<!-- CardActions component to reuse its modal (button visually hidden but still functional) -->
<div style="position: fixed; left: -9999px; width: 1px; height: 1px; overflow: hidden;">
<CardActions
event={indexEvent}
bind:detailsModalOpen={detailsModalOpen}
/>
</div>

72
src/lib/components/publications/PublicationSection.svelte

@ -26,6 +26,8 @@
ref, ref,
allComments = [], allComments = [],
commentsVisible = true, commentsVisible = true,
publicationTitle,
isFirstSection = false,
}: { }: {
address: string; address: string;
rootAddress: string; rootAddress: string;
@ -35,6 +37,8 @@
ref: (ref: HTMLElement) => void; ref: (ref: HTMLElement) => void;
allComments?: NDKEvent[]; allComments?: NDKEvent[];
commentsVisible?: boolean; commentsVisible?: boolean;
publicationTitle?: string;
isFirstSection?: boolean;
} = $props(); } = $props();
const asciidoctor: Asciidoctor = getContext("asciidoctor"); const asciidoctor: Asciidoctor = getContext("asciidoctor");
@ -89,17 +93,32 @@
// AI-NOTE: Kind 30023 events contain Markdown content, not AsciiDoc // AI-NOTE: Kind 30023 events contain Markdown content, not AsciiDoc
// Use parseAdvancedmarkup for 30023 events, Asciidoctor for 30041/30818 events // Use parseAdvancedmarkup for 30023 events, Asciidoctor for 30041/30818 events
let processed: string;
if (event?.kind === 30023) { if (event?.kind === 30023) {
return await parseAdvancedmarkup(content); processed = await parseAdvancedmarkup(content);
} else { } else {
// For 30041 and 30818 events, use Asciidoctor (AsciiDoc) // For 30041 and 30818 events, use Asciidoctor (AsciiDoc)
const converted = asciidoctor.convert(content); const converted = asciidoctor.convert(content);
const processed = await postProcessAdvancedAsciidoctorHtml( processed = await postProcessAdvancedAsciidoctorHtml(
converted.toString(), converted.toString(),
ndk, ndk,
); );
return processed;
} }
// Remove redundant h1 title from first section if it matches publication title
if (isFirstSection && publicationTitle && typeof processed === 'string') {
const tempDiv = document.createElement('div');
tempDiv.innerHTML = processed;
const h1Elements = tempDiv.querySelectorAll('h1');
h1Elements.forEach((h1) => {
if (h1.textContent?.trim() === publicationTitle.trim()) {
h1.remove();
}
});
processed = tempDiv.innerHTML;
}
return processed;
}); });
let previousLeafEvent: NDKEvent | null = $derived.by(() => { let previousLeafEvent: NDKEvent | null = $derived.by(() => {
@ -224,7 +243,7 @@
</script> </script>
<!-- Wrapper for positioning context --> <!-- Wrapper for positioning context -->
<div class="relative w-full"> <div class="relative w-full overflow-x-hidden">
<section <section
id={address} id={address}
bind:this={sectionRef} bind:this={sectionRef}
@ -235,20 +254,8 @@
{#await Promise.all( [leafTitle, leafContent, leafHierarchy, publicationType, divergingBranches], )} {#await Promise.all( [leafTitle, leafContent, leafHierarchy, publicationType, divergingBranches], )}
<TextPlaceholder size="2xl" /> <TextPlaceholder size="2xl" />
{:then [leafTitle, leafContent, leafHierarchy, publicationType, divergingBranches]} {:then [leafTitle, leafContent, leafHierarchy, publicationType, divergingBranches]}
<!-- Main content area - centered --> <!-- Main content area - left-aligned -->
<div class="section-content relative max-w-4xl mx-auto px-4"> <div class="section-content relative w-full text-left">
<!-- Mobile menu - shown only on smaller screens -->
<div class="xl:hidden absolute top-2 right-2 z-10">
{#await leafEvent then event}
{#if event}
<CardActions
{event}
sectionAddress={address}
onDelete={handleDelete}
/>
{/if}
{/await}
</div>
{#each divergingBranches as [branch, depth]} {#each divergingBranches as [branch, depth]}
{@render sectionHeading( {@render sectionHeading(
getMatchingTags(branch, "title")[0]?.[1] ?? "", getMatchingTags(branch, "title")[0]?.[1] ?? "",
@ -257,7 +264,21 @@
{/each} {/each}
{#if leafTitle} {#if leafTitle}
{@const leafDepth = leafHierarchy.length - 1} {@const leafDepth = leafHierarchy.length - 1}
{@render sectionHeading(leafTitle, leafDepth)} <div class="relative">
<!-- Section actions button - positioned next to heading -->
<div class="absolute top-0 right-0 z-20">
{#await leafEvent then event}
{#if event}
<CardActions
{event}
sectionAddress={address}
onDelete={handleDelete}
/>
{/if}
{/await}
</div>
{@render sectionHeading(leafTitle, leafDepth)}
</div>
{/if} {/if}
{@render contentParagraph( {@render contentParagraph(
leafContent.toString(), leafContent.toString(),
@ -267,7 +288,7 @@
</div> </div>
<!-- Mobile comments - shown below content on smaller screens --> <!-- Mobile comments - shown below content on smaller screens -->
<div class="xl:hidden mt-8 max-w-4xl mx-auto px-4"> <div class="xl:hidden mt-8 w-full text-left">
<SectionComments <SectionComments
sectionAddress={address} sectionAddress={address}
comments={sectionComments} comments={sectionComments}
@ -277,17 +298,6 @@
{/await} {/await}
</section> </section>
<!-- Right sidebar elements - positioned very close to content, responsive width -->
{#await leafEvent then event}
{#if event}
<!-- Three-dot menu - positioned at top-center on XL+ screens -->
<div
class="hidden xl:block absolute left-[calc(50%+26rem)] top-[20%] z-10"
>
<CardActions {event} sectionAddress={address} onDelete={handleDelete} />
</div>
{/if}
{/await}
<!-- Comments area: positioned below menu, top-center of section --> <!-- Comments area: positioned below menu, top-center of section -->
<div <div

25
src/lib/components/publications/TableOfContents.svelte

@ -157,6 +157,31 @@
<!-- TODO: Figure out how to style indentations. --> <!-- TODO: Figure out how to style indentations. -->
<!-- TODO: Make group title fonts the same as entry title fonts. --> <!-- TODO: Make group title fonts the same as entry title fonts. -->
<SidebarGroup> <SidebarGroup>
<!-- Root entry (publication header) -->
{#if depth === 2}
{@const rootEntry = toc.getRootEntry()}
{#if rootEntry}
{@const isVisible = isEntryVisible(rootEntry.address)}
<SidebarItem
label={rootEntry.title}
href={`#${rootEntry.address}`}
spanClass="px-2 text-ellipsis"
class={`${isVisible ? "toc-highlight" : ""} `}
onclick={() => {
const element = document.getElementById(rootEntry.address);
if (element) {
element.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
}
onClose?.();
}}
>
<!-- Publication header entry -->
</SidebarItem>
{/if}
{/if}
{#each entries as entry, index} {#each entries as entry, index}
{@const address = entry.address} {@const address = entry.address}
{@const expanded = toc.expandedMap.get(address) ?? false} {@const expanded = toc.expandedMap.get(address) ?? false}

2
src/lib/components/util/ArticleNav.svelte

@ -40,8 +40,10 @@
// Function to toggle column visibility // Function to toggle column visibility
function toggleColumn(column: "toc" | "blog" | "inner" | "discussion") { function toggleColumn(column: "toc" | "blog" | "inner" | "discussion") {
console.log("[ArticleNav] toggleColumn called with:", column);
publicationColumnVisibility.update((current) => { publicationColumnVisibility.update((current) => {
const newValue = !current[column]; const newValue = !current[column];
console.log("[ArticleNav] Toggling", column, "from", current[column], "to", newValue);
const updated = { ...current, [column]: newValue }; const updated = { ...current, [column]: newValue };
if (window.innerWidth < 1400 && column === "blog" && newValue) { if (window.innerWidth < 1400 && column === "blog" && newValue) {

13
src/lib/components/util/CardActions.svelte

@ -26,10 +26,16 @@
import { WebSocketPool } from "$lib/data_structures/websocket_pool"; import { WebSocketPool } from "$lib/data_structures/websocket_pool";
// Component props // Component props
let { event, onDelete, sectionAddress } = $props<{ let {
event,
onDelete,
sectionAddress,
detailsModalOpen = $bindable(false)
} = $props<{
event: NDKEvent; event: NDKEvent;
onDelete?: () => void; onDelete?: () => void;
sectionAddress?: string; // If provided, shows "Comment on section" option sectionAddress?: string; // If provided, shows "Comment on section" option
detailsModalOpen?: boolean; // Bindable prop to control modal from outside
}>(); }>();
const ndk = getNdkContext(); const ndk = getNdkContext();
@ -72,8 +78,7 @@
event.tags.find((t: string[]) => t[0] === "identifier")?.[1] ?? null, event.tags.find((t: string[]) => t[0] === "identifier")?.[1] ?? null,
); );
// UI state // UI state - detailsModalOpen is now a bindable prop
let detailsModalOpen: boolean = $state(false);
let isOpen: boolean = $state(false); let isOpen: boolean = $state(false);
// Comment modal state // Comment modal state
@ -535,7 +540,7 @@
<div class="flex flex-row"> <div class="flex flex-row">
<h4 class="text-base font-normal mt-2"> <h4 class="text-base font-normal mt-2">
Index author: {@render userBadge(event.pubkey, author, ndk)} {event.kind === 30040 ? "Index author" : "Article author"}: {@render userBadge(event.pubkey, author, ndk)}
</h4> </h4>
</div> </div>

12
src/lib/components/util/Details.svelte

@ -14,10 +14,11 @@
// isModal // isModal
// - don't show interactions in modal view // - don't show interactions in modal view
// - don't show all the details when _not_ in modal view // - don't show all the details when _not_ in modal view
let { event, isModal = false, onDelete } = $props<{ let { event, isModal = false, onDelete, hideActions = false } = $props<{
event: any; event: any;
isModal?: boolean; isModal?: boolean;
onDelete?: () => void; onDelete?: () => void;
hideActions?: boolean;
}>(); }>();
let title: string = $derived(getMatchingTags(event, "title")[0]?.[1]); let title: string = $derived(getMatchingTags(event, "title")[0]?.[1]);
@ -66,7 +67,7 @@
</script> </script>
<div class="flex flex-col relative mb-2"> <div class="flex flex-col relative mb-2">
{#if !isModal} {#if !isModal && !hideActions}
<div class="flex flex-row justify-between items-center"> <div class="flex flex-row justify-between items-center">
<!-- Index author badge --> <!-- Index author badge -->
<P class="text-base font-normal" <P class="text-base font-normal"
@ -76,6 +77,13 @@
<CardActions {event} {onDelete}></CardActions> <CardActions {event} {onDelete}></CardActions>
</div> </div>
</div> </div>
{:else if !isModal && hideActions}
<div class="flex flex-row justify-between items-center">
<!-- Index author badge -->
<P class="text-base font-normal"
>{@render userBadge(event.pubkey, undefined, ndk)}</P
>
</div>
{/if} {/if}
<div <div
class="flex-grow grid grid-cols-1 md:grid-cols-[auto_1fr] gap-4 items-center" class="flex-grow grid grid-cols-1 md:grid-cols-[auto_1fr] gap-4 items-center"

2
src/lib/snippets/PublicationSnippets.svelte

@ -8,7 +8,7 @@
{@const headingLevel = Math.min(depth + 1, 6)} {@const headingLevel = Math.min(depth + 1, 6)}
<!-- TODO: Handle floating titles. --> <!-- TODO: Handle floating titles. -->
<svelte:element this={`h${headingLevel}`} class="h-leather"> <svelte:element this={`h${headingLevel}`} class="h-leather text-left">
{title} {title}
</svelte:element> </svelte:element>
{/snippet} {/snippet}

Loading…
Cancel
Save