Give builder fields persistent labels, treat description as optional, and validate save-progress email with a real form.

Name stays required; description is a labelled optional textarea. Email uses native validity and form submit. Drop the dead workshop link and fix a few copy errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
adilallo
2026-09-10 11:37:41 -06:00
co-authored by Cursor
parent 130663f930
commit 42d83c8b62
33 changed files with 437 additions and 125 deletions
@@ -80,6 +80,8 @@ function CustomMethodCardWizardViewComponent({
<TextArea
appearance="default"
formHeader={false}
showHelpIcon={false}
label={copy.step2.title}
placeholder={copy.step2.fieldPlaceholder}
value={policyDescription}
maxLength={maxDescriptionChars}
@@ -1,6 +1,6 @@
"use client";
import { memo } from "react";
import { memo, useId } from "react";
import { ASSETS, getAssetPath } from "../../../../../lib/assetUtils";
import InputWithCounter from "../../../../components/controls/InputWithCounter";
import TextArea from "../../../../components/controls/TextArea";
@@ -39,6 +39,7 @@ function CustomMethodCardWizardFieldBodiesViewComponent({
onProportionBlockTitleChange,
onProportionDefaultChange,
}: CustomMethodCardWizardFieldBodiesViewProps) {
const placeholderFieldId = useId();
const uploadPreviewTrimmed = uploadAssetPreviewUrl?.trim() ?? "";
const hasUploadPreview = uploadPreviewTrimmed.length > 0;
@@ -53,10 +54,14 @@ function CustomMethodCardWizardFieldBodiesViewComponent({
maxLength={CUSTOM_METHOD_CARD_WIZARD_MAX_FIELD_CHARS}
/>
<div className="flex flex-col gap-2">
<label className="text-[14px] leading-[20px] font-medium text-[var(--color-content-default-primary)]">
<label
htmlFor={placeholderFieldId}
className="text-[14px] leading-[20px] font-medium text-[var(--color-content-default-primary)]"
>
{copy.text.placeholderLabel}
</label>
<TextArea
id={placeholderFieldId}
formHeader={false}
appearance="embedded"
value={textPlaceholderBody}
@@ -84,6 +89,7 @@ function CustomMethodCardWizardFieldBodiesViewComponent({
/>
<TextInput
formHeader={false}
label={copy.badges.blockTitleLabel}
placeholder={copy.badges.blockTitlePlaceholder}
value={badgeBlockTitle}
onChange={(e) => onBadgeBlockTitleChange(e.target.value)}
@@ -8,7 +8,7 @@
import { useEffect, useMemo, useRef, useState } from "react";
import { useBeforeUnloadGuard } from "../../../hooks/useBeforeUnloadGuard";
import Create from "../../../components/modals/Create";
import TextInput from "../../../components/controls/TextInput";
import TextArea from "../../../components/controls/TextArea";
import ContentLockup from "../../../components/type/ContentLockup";
import { useTranslation } from "../../../contexts/MessagesContext";
@@ -95,18 +95,20 @@ export function FinalReviewCommunityContextEditModal({
ariaLabel={tModal("title")}
>
<div className="pb-2">
<TextInput
<TextArea
className="!transition-none"
type="text"
label={tModal("title")}
placeholder={tField("placeholder")}
value={draft}
onChange={(e) => {
setDraft(e.target.value);
}}
inputSize="medium"
size="medium"
formHeader={false}
showHelpIcon={false}
textHint={characterHint}
maxLength={COMMUNITY_CONTEXT_FIELD_MAX_LENGTH}
rows={4}
/>
</div>
</Create>
@@ -93,6 +93,7 @@ export function FinalReviewTitleEditModal({
<TextInput
className="!transition-none"
type="text"
label={tModal("title")}
placeholder={tField("placeholder")}
value={draft}
onChange={(e) => {
@@ -100,8 +101,10 @@ export function FinalReviewTitleEditModal({
}}
inputSize="medium"
formHeader={false}
showHelpIcon={false}
textHint={characterHint}
maxLength={COMMUNITY_TITLE_FIELD_MAX_LENGTH}
required
/>
</div>
</Create>