- {/* Stripes are inside the bordered container so they don't escape visually */}
-
-
-
-
- {event.tags.some(([n, v]) => n === 'relay' && v === 'ALL_RELAYS') ? 'Global Request to Vanish' : 'Request to Vanish'}
-
-
- {nip19.npubEncode(event.pubkey)}
-
- {event.content && (
-
- “{event.content}”
-
- )}
-
-
-
+
{!compact && (
<>
{actionButtons}
@@ -700,7 +675,7 @@ export const NoteCard = memo(function NoteCard({
onClick={handleCardClick}
onAuxClick={handleAuxClick}
>
-
+
{!compact && (
<>
{actionButtons}
diff --git a/src/components/ReplyComposeModal.tsx b/src/components/ReplyComposeModal.tsx
index 219d27d5..77d39809 100644
--- a/src/components/ReplyComposeModal.tsx
+++ b/src/components/ReplyComposeModal.tsx
@@ -14,6 +14,7 @@ import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar';
import { getAvatarShape } from '@/lib/avatarShape';
import { NoteContent } from '@/components/NoteContent';
import { ComposeBox } from '@/components/ComposeBox';
+import { VanishCardCompact } from '@/components/VanishEventContent';
import { ProfilePreview } from '@/components/ExternalContentHeader';
import { useAuthor } from '@/hooks/useAuthor';
import { genUserName } from '@/lib/genUserName';
@@ -160,62 +161,13 @@ function EmbeddedPost({ event }: { event: NostrEvent }) {
// Kind 62 (Request to Vanish) — show a compact vanish preview
if (event.kind === 62) {
- return
;
+ return
;
}
return
;
}
-/** Compact embedded preview for NIP-62 vanish events in the reply composer. */
-function EmbeddedVanishPost({ event }: { event: NostrEvent }) {
- const npub = useMemo(() => nip19.npubEncode(event.pubkey), [event.pubkey]);
- const isGlobal = event.tags.some(([n, v]) => n === 'relay' && v === 'ALL_RELAYS');
- const reason = event.content || undefined;
- return (
-
- {/* Top caution stripe */}
-
-
-
- {/* Header row */}
-
-
-
-
-
- {isGlobal ? 'Global Request to Vanish' : 'Request to Vanish'}
-
-
- {npub}
-
-
-
-
- {timeAgo(event.created_at)}
-
-
-
- {/* Reason if available */}
- {reason && (
-
- “{reason}”
-
- )}
-
-
- {/* Bottom caution stripe */}
-
-
- );
-}
/** Compact embedded preview for regular note events. */
function EmbeddedNote({ event }: { event: NostrEvent }) {
diff --git a/src/components/VanishEventContent.tsx b/src/components/VanishEventContent.tsx
index 46b49d9b..bf602c4a 100644
--- a/src/components/VanishEventContent.tsx
+++ b/src/components/VanishEventContent.tsx
@@ -2,21 +2,97 @@ import type { NostrEvent } from '@nostrify/nostrify';
import { nip19 } from 'nostr-tools';
import { useMemo } from 'react';
+import { cn } from '@/lib/utils';
+
interface VanishEventContentProps {
event: NostrEvent;
/** Compact mode for feed cards — shorter layout */
compact?: boolean;
}
+interface VanishCardCompactProps {
+ event: { pubkey: string; content: string; tags: string[][] };
+ /** Optional className for the outer container */
+ className?: string;
+ /** Optional timestamp text shown to the right of the title */
+ timestamp?: string;
+}
+
+/**
+ * Compact card for NIP-62 Request to Vanish events.
+ *
+ * Used everywhere a vanish event needs a small inline preview: feed cards,
+ * embedded quotes, reply composer, threaded ancestors, etc. Stripes render
+ * inside the bordered container so they stay visually contained.
+ */
+export function VanishCardCompact({ event, className, timestamp }: VanishCardCompactProps) {
+ const npub = useMemo(() => nip19.npubEncode(event.pubkey), [event.pubkey]);
+ const isGlobal = event.tags.some(([n, v]) => n === 'relay' && v === 'ALL_RELAYS');
+ const reason = event.content || undefined;
+
+ return (
+
+ {/* Top caution stripe */}
+
+
+
+ {/* Header row */}
+
+
+
+
+
+ {isGlobal ? 'Global Request to Vanish' : 'Request to Vanish'}
+
+
+ {npub}
+
+
+
+ {timestamp && (
+
+ {timestamp}
+
+ )}
+
+
+ {/* Reason quote if available */}
+ {reason && (
+
+ “{reason}”
+
+ )}
+
+
+ {/* Bottom caution stripe */}
+
+
+ );
+}
+
/**
* Dramatic display for NIP-62 Request to Vanish (kind 62) events.
*
* These events represent a user permanently erasing their entire identity
* from the Nostr network. The display is intentionally theatrical — red
* caution stripes, glitch effects, and a "grand exit" aesthetic.
+ *
+ * This is the full detail-page view. For compact inline previews, use
+ * {@link VanishCardCompact} instead.
*/
export function VanishEventContent({ event, compact }: VanishEventContentProps) {
- const npub = useMemo(() => nip19.npubEncode(event.pubkey), [event.pubkey]);
+ if (compact) {
+ return
;
+ }
+
+ const npub = nip19.npubEncode(event.pubkey);
const relayTags = event.tags.filter(([n]) => n === 'relay');
const isGlobal = relayTags.some(([, v]) => v === 'ALL_RELAYS');
const relayList = relayTags.map(([, v]) => v).filter((v) => v !== 'ALL_RELAYS');
@@ -31,43 +107,6 @@ export function VanishEventContent({ event, compact }: VanishEventContentProps)
hour12: true,
});
- if (compact) {
- return (
-
- {/* Caution stripe header */}
-
-
-
- {/* Glitch icon */}
-
-
-
-
- {isGlobal ? 'Global Request to Vanish' : 'Request to Vanish'}
-
-
- {npub}
-
- {reason && (
-
- “{reason}”
-
- )}
-
-
-
-
-
- );
- }
-
return (
{/* Top caution stripe band */}