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:
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useEffect, type HTMLInputTypeAttribute } from "react";
|
||||
import TextInput from "../../../../components/controls/TextInput";
|
||||
import TextArea from "../../../../components/controls/TextArea";
|
||||
import type { HeaderLockupJustificationValue } from "../../../../components/type/HeaderLockup/HeaderLockup.types";
|
||||
import { useTranslation } from "../../../../contexts/MessagesContext";
|
||||
import { useCreateFlow } from "../../context/CreateFlowContext";
|
||||
@@ -12,6 +13,7 @@ import {
|
||||
type CreateFlowContentTopBelowMd,
|
||||
} from "../../components/CreateFlowStepShell";
|
||||
import { CREATE_FLOW_MD_UP_COLUMN_MAX_CLASS } from "../../components/createFlowLayoutTokens";
|
||||
import { CREATE_FLOW_COMMUNITY_SAVE_FORM_ID } from "../../utils/createFlowPaths";
|
||||
import type { CreateFlowTextStateField } from "../../types";
|
||||
|
||||
type Props = {
|
||||
@@ -21,6 +23,10 @@ type Props = {
|
||||
/** Figma Flow — Text (`20094:41243`): main column `items-center` + horizontal padding token. */
|
||||
mainAlign?: "start" | "center";
|
||||
inputType?: HTMLInputTypeAttribute;
|
||||
/** Multi-line control (community description). */
|
||||
multiline?: boolean;
|
||||
/** Native `required` (community name and save-progress email). */
|
||||
required?: boolean;
|
||||
showCharacterCount?: boolean;
|
||||
headerJustification?: HeaderLockupJustificationValue;
|
||||
/** Top spacing under top chrome (`CreateFlowStepShell` / `CreateFlowContentTopBelowMd`). */
|
||||
@@ -28,7 +34,7 @@ type Props = {
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared narrow-column + TextInput pattern for Create Community text frames.
|
||||
* Shared narrow-column + labelled field pattern for Create Community text frames.
|
||||
*/
|
||||
export function CreateFlowTextFieldScreen({
|
||||
messageNamespace,
|
||||
@@ -36,6 +42,8 @@ export function CreateFlowTextFieldScreen({
|
||||
maxLength,
|
||||
mainAlign = "start",
|
||||
inputType = "text",
|
||||
multiline = false,
|
||||
required = false,
|
||||
showCharacterCount = true,
|
||||
headerJustification = "left",
|
||||
contentTopBelowMd = "space-1400",
|
||||
@@ -69,6 +77,15 @@ export function CreateFlowTextFieldScreen({
|
||||
const mainItems =
|
||||
mainAlign === "center" ? "items-center" : "items-start";
|
||||
|
||||
const isEmail = inputType === "email";
|
||||
const persistValue = (next: string) => {
|
||||
setValue(next);
|
||||
markCreateFlowInteraction();
|
||||
updateState({ [stateField]: next } as Record<string, string>);
|
||||
};
|
||||
|
||||
const fieldLabel = t("inputLabel");
|
||||
|
||||
return (
|
||||
<CreateFlowStepShell
|
||||
variant="centeredNarrow"
|
||||
@@ -85,22 +102,60 @@ export function CreateFlowTextFieldScreen({
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<TextInput
|
||||
className="!transition-none"
|
||||
type={inputType}
|
||||
placeholder={t("placeholder")}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
const v = e.target.value;
|
||||
setValue(v);
|
||||
markCreateFlowInteraction();
|
||||
updateState({ [stateField]: v } as Record<string, string>);
|
||||
}}
|
||||
inputSize={mdUp ? "medium" : "small"}
|
||||
formHeader={false}
|
||||
textHint={hint}
|
||||
maxLength={maxLength}
|
||||
/>
|
||||
{multiline ? (
|
||||
<TextArea
|
||||
className="!transition-none"
|
||||
label={fieldLabel}
|
||||
placeholder={t("placeholder")}
|
||||
value={value}
|
||||
onChange={(e) => persistValue(e.target.value)}
|
||||
onBlur={() => {
|
||||
const trimmed = value.trim();
|
||||
if (trimmed !== value) persistValue(trimmed);
|
||||
}}
|
||||
size={mdUp ? "medium" : "small"}
|
||||
formHeader={false}
|
||||
showHelpIcon={false}
|
||||
textHint={hint}
|
||||
maxLength={maxLength}
|
||||
required={required}
|
||||
rows={4}
|
||||
/>
|
||||
) : (
|
||||
<TextInput
|
||||
className="!transition-none"
|
||||
type={inputType}
|
||||
name={isEmail ? "email" : undefined}
|
||||
label={fieldLabel}
|
||||
placeholder={t("placeholder")}
|
||||
value={value}
|
||||
onChange={(e) => persistValue(e.target.value)}
|
||||
onBlur={() => {
|
||||
const trimmed = isEmail
|
||||
? value.trim().toLowerCase()
|
||||
: value.trim();
|
||||
if (trimmed !== value) persistValue(trimmed);
|
||||
}}
|
||||
onKeyDown={
|
||||
isEmail
|
||||
? (e) => {
|
||||
if (e.key !== "Enter") return;
|
||||
e.preventDefault();
|
||||
e.currentTarget.form?.requestSubmit();
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
inputSize={mdUp ? "medium" : "small"}
|
||||
formHeader={false}
|
||||
showHelpIcon={false}
|
||||
textHint={hint}
|
||||
maxLength={maxLength}
|
||||
required={required || isEmail}
|
||||
autoComplete={isEmail ? "email" : undefined}
|
||||
inputMode={isEmail ? "email" : undefined}
|
||||
form={isEmail ? CREATE_FLOW_COMMUNITY_SAVE_FORM_ID : undefined}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CreateFlowStepShell>
|
||||
|
||||
Reference in New Issue
Block a user