From 90e06e328fb5a9b1da1a9af7f95e8987c17f734e Mon Sep 17 00:00:00 2001 From: lemon Date: Fri, 12 Jun 2026 18:12:19 -0700 Subject: [PATCH] Make website replace the bio slot; relax identity requirements Add a bioField prop to ProfileCard so the editable slot below the name can edit the website instead of the bio. The verifier identity step now edits the website inline (no separate input) and only requires avatar + name; banner and website are optional, with website still https-validated when entered. --- src/components/ProfileCard.tsx | 25 ++++++++- .../onboarding/VerifierIdentityStep.tsx | 54 +++++++------------ src/locales/en.json | 3 +- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/src/components/ProfileCard.tsx b/src/components/ProfileCard.tsx index fb10138d..b4f7b32a 100644 --- a/src/components/ProfileCard.tsx +++ b/src/components/ProfileCard.tsx @@ -97,6 +97,12 @@ interface ProfileCardProps { showNip05?: boolean; /** Show NIP-58 badge showcase row (default true). */ showBadges?: boolean; + /** + * Which kind-0 field the editable text slot below the name edits. + * - `'about'` (default): the bio textarea. + * - `'website'`: a single-line website input, replacing the bio entirely. + */ + bioField?: 'about' | 'website'; /** When provided, render an editable profile fields section below bio */ extraFields?: ProfileField[]; onExtraFieldsChange?: (fields: ProfileField[]) => void; @@ -110,6 +116,7 @@ export function ProfileCard({ onRemoveAvatar, showNip05 = true, showBadges = true, + bioField = 'about', extraFields, onExtraFieldsChange, }: ProfileCardProps) { @@ -268,9 +275,23 @@ export function ProfileCard({ )} - {/* Bio */} + {/* Bio — or, when `bioField` is `'website'`, a website input that + takes the bio's place entirely. */}
- {editable ? ( + {bioField === 'website' ? ( + editable ? ( + + ) : metadata.website ? ( +

+ {metadata.website} +

+ ) : null + ) : editable ? ( 0; - const websiteValid = !!sanitizeUrl(draft.website.trim()); - const websiteTouched = draft.website.trim().length > 0; const avatarProvided = draft.picture.trim().length > 0; - const bannerProvided = draft.banner.trim().length > 0; - const canContinue = - nameProvided && websiteValid && avatarProvided && bannerProvided && !isUploading; + const websiteTouched = draft.website.trim().length > 0; + const websiteValid = !websiteTouched || !!sanitizeUrl(draft.website.trim()); + const canContinue = nameProvided && avatarProvided && websiteValid && !isUploading; return (
@@ -172,41 +170,29 @@ export function VerifierIdentityStep({ { if (patch.name !== undefined) onChange({ name: patch.name }); + if (patch.website !== undefined) { + onChange({ website: patch.website as string }); + } }} onPickImage={handlePickImage} + bioField="website" showNip05={false} showBadges={false} />
- {/* Website — a first-class required field for organizations, so it - gets its own labeled input rather than living in ProfileCard's - collapsible extra-fields section. */} -
- - onChange({ website: e.target.value })} - placeholder="https://your-org.org" - aria-required - aria-invalid={websiteTouched && !websiteValid} - /> - {websiteTouched && !websiteValid && ( -

- {t('onboarding.verifier.identity.websiteInvalid')} -

- )} -
+ {/* Website is optional, but if entered it must be a valid https URL. */} + {websiteTouched && !websiteValid && ( +

+ {t('onboarding.verifier.identity.websiteInvalid')} +

+ )} {isUploading && (
diff --git a/src/locales/en.json b/src/locales/en.json index 4384f348..ac388fb9 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -153,8 +153,7 @@ "verifier": { "identity": { "title": "Set up your organization", - "subtitle": "Add your organization's name, website, logo, and a banner. Donors will see these on every campaign you verify.", - "websiteLabel": "Website", + "subtitle": "Add your organization's name and logo. A website and banner are optional. Donors will see these on every campaign you verify.", "websiteInvalid": "Enter a valid website starting with https://", "cropAvatar": "Crop logo", "cropBanner": "Crop banner",