diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx
index 83dfb4b1..a334d262 100644
--- a/src/components/ProfileCard.tsx
+++ b/src/components/ProfileCard.tsx
@@ -86,6 +86,51 @@ interface ProfileField {
value: string;
}
+/**
+ * Shared dropdown of image actions used by both the avatar and the banner.
+ * Wraps the provided trigger element and surfaces "Upload file", an optional
+ * "Paste URL", and an optional "Remove" (only shown when the image exists and
+ * a remove handler is wired). Deduplicating this between avatar and banner
+ * keeps the two menus identical and the actions in one place.
+ */
+function ImageEditMenu({
+ trigger,
+ hasImage,
+ onUpload,
+ onPasteUrl,
+ onRemove,
+}: {
+ trigger: React.ReactNode;
+ hasImage: boolean;
+ onUpload: () => void;
+ onPasteUrl?: () => void;
+ onRemove?: () => void;
+}) {
+ return (
+
+ {trigger}
+
+
+
+ Upload file
+
+ {onPasteUrl && (
+
+
+ Paste URL
+
+ )}
+ {hasImage && onRemove && (
+
+
+ Remove
+
+ )}
+
+
+ );
+}
+
interface ProfileCardProps {
className?: string;
pubkey?: string;
@@ -101,6 +146,8 @@ interface ProfileCardProps {
onPasteUrl?: (field: 'picture' | 'banner') => void;
/** Called when user removes their avatar picture. */
onRemoveAvatar?: () => void;
+ /** Called when user removes their banner image. */
+ onRemoveBanner?: () => void;
/** Show NIP-05 row (default true) */
showNip05?: boolean;
/** Show NIP-58 badge showcase row (default true). */
@@ -124,6 +171,7 @@ export function ProfileCard({
onPickImage,
onPasteUrl,
onRemoveAvatar,
+ onRemoveBanner,
showNip05 = true,
showBadges = true,
bioField = 'about',
@@ -158,11 +206,15 @@ export function ProfileCard({
{/* Banner */}
- {editable && onPasteUrl ? (
- // With a paste handler, the banner opens a menu (Change / Paste URL)
- // instead of going straight to the file picker.
-
-
+ {editable && (onPasteUrl || onRemoveBanner) ? (
+ // When a paste or remove action exists, the banner opens the shared
+ // image menu instead of going straight to the file picker.
+ onPickImage?.('banner')}
+ onPasteUrl={onPasteUrl ? () => onPasteUrl('banner') : undefined}
+ onRemove={onRemoveBanner}
+ trigger={
-
-
- onPickImage?.('banner')}>
-
- {metadata.banner ? 'Change banner' : 'Add banner'}
-
- onPasteUrl?.('banner')}>
-
- Paste URL
-
-
-
+ }
+ />
) : (
{editable ? (
-
-
+ onPickImage?.('picture')}
+ onPasteUrl={onPasteUrl ? () => onPasteUrl('picture') : undefined}
+ onRemove={onRemoveAvatar}
+ trigger={
)}
-
-
- onPickImage?.('picture')}>
-
- Change avatar
-
- {onPasteUrl && (
- onPasteUrl?.('picture')}>
-
- Paste URL
-
- )}
- {metadata.picture && (
- onRemoveAvatar?.()} className="text-destructive focus:text-destructive">
-
- Remove avatar
-
- )}
-
-
+ }
+ />
) : (
diff --git a/src/components/onboarding/VerifierIdentityStep.tsx b/src/components/onboarding/VerifierIdentityStep.tsx
index 0ebebddb..0efd0e91 100644
--- a/src/components/onboarding/VerifierIdentityStep.tsx
+++ b/src/components/onboarding/VerifierIdentityStep.tsx
@@ -251,6 +251,8 @@ export function VerifierIdentityStep({
}}
onPickImage={handlePickImage}
onPasteUrl={handlePasteUrl}
+ onRemoveAvatar={() => onChange({ picture: '' })}
+ onRemoveBanner={() => onChange({ banner: '' })}
bioField="website"
showNip05={false}
showBadges={false}
diff --git a/src/pages/ProfileSettings.tsx b/src/pages/ProfileSettings.tsx
index d310c123..2c747804 100644
--- a/src/pages/ProfileSettings.tsx
+++ b/src/pages/ProfileSettings.tsx
@@ -316,6 +316,7 @@ export function ProfileSettings() {
onChange={handleCardChange}
onPickImage={handlePickImage}
onRemoveAvatar={() => form.setValue('picture', '', { shouldDirty: true })}
+ onRemoveBanner={() => form.setValue('banner', '', { shouldDirty: true })}
showBadges={false}
/>