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:
@@ -31,6 +31,11 @@ const TextInputContainer = forwardRef<HTMLInputElement, TextInputProps>(
|
||||
textHint = false,
|
||||
formHeader = true,
|
||||
maxLength,
|
||||
autoComplete,
|
||||
inputMode,
|
||||
required = false,
|
||||
form,
|
||||
onKeyDown,
|
||||
...props
|
||||
},
|
||||
ref,
|
||||
@@ -250,6 +255,11 @@ const TextInputContainer = forwardRef<HTMLInputElement, TextInputProps>(
|
||||
maxLength={maxLength}
|
||||
helpIconAlt={t("helpIconAlt")}
|
||||
hintDefault={t("hintDefault")}
|
||||
autoComplete={autoComplete}
|
||||
inputMode={inputMode}
|
||||
required={required}
|
||||
form={form}
|
||||
onKeyDown={onKeyDown}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -67,4 +67,9 @@ export interface TextInputViewProps {
|
||||
maxLength?: number;
|
||||
helpIconAlt: string;
|
||||
hintDefault: string;
|
||||
autoComplete?: string;
|
||||
inputMode?: React.HTMLAttributes<HTMLInputElement>["inputMode"];
|
||||
required?: boolean;
|
||||
form?: string;
|
||||
onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const TextInputView = forwardRef<HTMLInputElement, TextInputViewProps>(
|
||||
name,
|
||||
type,
|
||||
disabled,
|
||||
error: _error,
|
||||
error = false,
|
||||
className: _className,
|
||||
containerClasses,
|
||||
labelClasses,
|
||||
@@ -31,34 +31,49 @@ export const TextInputView = forwardRef<HTMLInputElement, TextInputViewProps>(
|
||||
maxLength,
|
||||
helpIconAlt,
|
||||
hintDefault,
|
||||
autoComplete,
|
||||
inputMode,
|
||||
required = false,
|
||||
form,
|
||||
onKeyDown,
|
||||
state: _state,
|
||||
isFilled: _isFilled,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const labelEl = label ? (
|
||||
formHeader ? (
|
||||
<div className="flex flex-wrap gap-[var(--measures-spacing-200,4px_8px)] items-baseline pr-[var(--measures-spacing-100,4px)] relative shrink-0 w-full">
|
||||
<div className="flex gap-[var(--measures-spacing-050,2px)] items-center relative shrink-0">
|
||||
<label
|
||||
id={labelId}
|
||||
htmlFor={inputId}
|
||||
className={`${labelClasses} font-medium text-[var(--color-content-default-primary)]`}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
{showHelpIcon && (
|
||||
<div className="relative shrink-0 size-[12px]">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element -- icon asset */}
|
||||
<img
|
||||
src={getAssetPath(ASSETS.ICON_HELP)}
|
||||
alt={helpIconAlt}
|
||||
className="block max-w-none size-full"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<label id={labelId} htmlFor={inputId} className="sr-only">
|
||||
{label}
|
||||
</label>
|
||||
)
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div className={containerClasses}>
|
||||
{formHeader && label && (
|
||||
<div className="flex flex-wrap gap-[var(--measures-spacing-200,4px_8px)] items-baseline pr-[var(--measures-spacing-100,4px)] relative shrink-0 w-full">
|
||||
<div className="flex gap-[var(--measures-spacing-050,2px)] items-center relative shrink-0">
|
||||
<label
|
||||
id={labelId}
|
||||
htmlFor={inputId}
|
||||
className={`${labelClasses} font-medium text-[var(--color-content-default-primary)]`}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
{showHelpIcon && (
|
||||
<div className="relative shrink-0 size-[12px]">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element -- icon asset */}
|
||||
<img
|
||||
src={getAssetPath(ASSETS.ICON_HELP)}
|
||||
alt={helpIconAlt}
|
||||
className="block max-w-none size-full"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{labelEl}
|
||||
<div className={inputWrapperClasses}>
|
||||
<div className={disabled ? "opacity-40" : ""}>
|
||||
<input
|
||||
@@ -71,9 +86,16 @@ export const TextInputView = forwardRef<HTMLInputElement, TextInputViewProps>(
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
onKeyDown={onKeyDown}
|
||||
onMouseDown={handleMouseDown}
|
||||
disabled={disabled}
|
||||
maxLength={maxLength}
|
||||
autoComplete={autoComplete}
|
||||
inputMode={inputMode}
|
||||
required={required}
|
||||
form={form}
|
||||
aria-invalid={error || undefined}
|
||||
aria-required={required || undefined}
|
||||
className={inputClasses}
|
||||
style={{ borderRadius }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user