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} />