chore: input character limit error message improvement (#4271)

This commit is contained in:
Anmol Singh Bhatia 2024-04-24 15:17:50 +05:30 committed by GitHub
parent fc1cffd524
commit 87737dbfbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 84 additions and 48 deletions

View File

@ -27,9 +27,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
: mode === "true-transparent"
? "rounded border-none bg-transparent ring-0"
: ""
} ${hasError ? "border-red-500" : ""} ${hasError && mode === "primary" ? "bg-red-500/20" : ""} ${
inputSize === "sm" ? "px-3 py-2" : inputSize === "md" ? "p-3" : ""
}`,
} ${hasError ? "border-red-500" : ""} ${inputSize === "sm" ? "px-3 py-2" : inputSize === "md" ? "p-3" : ""}`,
className
)}
{...rest}

View File

@ -77,7 +77,7 @@ export const CycleForm: React.FC<Props> = (props) => {
</div>
<div className="space-y-3">
<div className="mt-2 space-y-3">
<div>
<div className="flex flex-col gap-1">
<Controller
name="name"
control={control}
@ -85,7 +85,7 @@ export const CycleForm: React.FC<Props> = (props) => {
required: "Name is required",
maxLength: {
value: 255,
message: "Name should be less than 255 characters",
message: "Title should be less than 255 characters",
},
}}
render={({ field: { value, onChange } }) => (
@ -103,6 +103,7 @@ export const CycleForm: React.FC<Props> = (props) => {
/>
)}
/>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
</div>
<div>
<Controller

View File

@ -116,10 +116,16 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
setFormSubmitting(false);
};
const isTitleLengthMoreThan255Character = formData?.name ? formData.name.length > 255 : false;
if (!workspaceSlug || !projectId || !workspaceId) return <></>;
return (
<form className="relative space-y-4" onSubmit={handleFormSubmit}>
<InboxIssueTitle data={formData} handleData={handleFormData} />
<InboxIssueTitle
data={formData}
handleData={handleFormData}
isTitleLengthMoreThan255Character={isTitleLengthMoreThan255Character}
/>
<InboxIssueDescription
workspaceSlug={workspaceSlug}
projectId={projectId}
@ -138,7 +144,13 @@ export const InboxIssueCreateRoot: FC<TInboxIssueCreateRoot> = observer((props)
<Button variant="neutral-primary" size="sm" type="button" onClick={handleModalClose}>
Discard
</Button>
<Button variant="primary" size="sm" type="submit" loading={formSubmitting}>
<Button
variant="primary"
size="sm"
type="submit"
loading={formSubmitting}
disabled={isTitleLengthMoreThan255Character}
>
{formSubmitting ? "Adding Issue..." : "Add Issue"}
</Button>
</div>

View File

@ -121,10 +121,16 @@ export const InboxIssueEditRoot: FC<TInboxIssueEditRoot> = observer((props) => {
setFormSubmitting(false);
};
const isTitleLengthMoreThan255Character = formData?.name ? formData.name.length > 255 : false;
if (!workspaceSlug || !projectId || !workspaceId || !formData) return <></>;
return (
<div className="relative space-y-4">
<InboxIssueTitle data={formData} handleData={handleFormData} />
<InboxIssueTitle
data={formData}
handleData={handleFormData}
isTitleLengthMoreThan255Character={isTitleLengthMoreThan255Character}
/>
<InboxIssueDescription
workspaceSlug={workspaceSlug}
projectId={projectId}
@ -138,7 +144,14 @@ export const InboxIssueEditRoot: FC<TInboxIssueEditRoot> = observer((props) => {
<Button variant="neutral-primary" size="sm" type="button" onClick={handleModalClose}>
Cancel
</Button>
<Button variant="primary" size="sm" type="button" loading={formSubmitting} onClick={handleFormSubmit}>
<Button
variant="primary"
size="sm"
type="button"
loading={formSubmitting}
disabled={isTitleLengthMoreThan255Character}
onClick={handleFormSubmit}
>
{formSubmitting ? "Adding..." : "Add to project"}
</Button>
</div>

View File

@ -6,10 +6,11 @@ import { Input } from "@plane/ui";
type TInboxIssueTitle = {
data: Partial<TIssue>;
handleData: (issueKey: keyof Partial<TIssue>, issueValue: Partial<TIssue>[keyof Partial<TIssue>]) => void;
isTitleLengthMoreThan255Character?: boolean;
};
export const InboxIssueTitle: FC<TInboxIssueTitle> = observer((props) => {
const { data, handleData } = props;
const { data, handleData, isTitleLengthMoreThan255Character } = props;
return (
<div className="relative flex flex-wrap gap-2 items-center">
@ -21,9 +22,11 @@ export const InboxIssueTitle: FC<TInboxIssueTitle> = observer((props) => {
onChange={(e) => handleData("name", e.target.value)}
placeholder="Title"
className="w-full resize-none text-xl"
maxLength={255}
required
/>
{isTitleLengthMoreThan255Character && (
<span className="text-xs text-red-500">Title should be less than 255 characters</span>
)}
</div>
);
});

View File

@ -391,6 +391,8 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
/>
)}
/>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
<div className="relative">
{data?.description_html === undefined ? (
<Loader className="min-h-[7rem] space-y-2 overflow-hidden rounded-md border border-custom-border-200 p-2 py-2">

View File

@ -90,7 +90,7 @@ export const ModuleForm: React.FC<Props> = (props) => {
</div>
<div className="space-y-3">
<div>
<div className="flex flex-col gap-1">
<Controller
control={control}
name="name"
@ -109,13 +109,14 @@ export const ModuleForm: React.FC<Props> = (props) => {
value={value}
onChange={onChange}
ref={ref}
hasError={Boolean(errors.name)}
hasError={Boolean(errors?.name)}
placeholder="Module Title"
className="w-full resize-none placeholder:text-sm placeholder:font-medium focus:border-blue-400"
tabIndex={1}
/>
)}
/>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
</div>
<div>
<Controller

View File

@ -216,6 +216,10 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
name="name"
rules={{
required: "Name is required",
maxLength: {
value: 255,
message: "Project name should be less than 255 characters",
},
}}
render={({ field: { value, onChange, ref } }) => (
<Input
@ -232,9 +236,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
/>
)}
/>
<span className="text-xs text-red-500">
<>{errors?.name?.message}</>
</span>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
</div>
<div className="flex flex-col gap-1">
<h4 className="text-sm">Description</h4>

View File

@ -112,7 +112,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
<div className="space-y-5">
<h3 className="text-lg font-medium leading-6 text-custom-text-100">{data ? "Update" : "Create"} View</h3>
<div className="space-y-3">
<div>
<div className="flex flex-col gap-1">
<Controller
control={control}
name="name"
@ -137,6 +137,7 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
/>
)}
/>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
</div>
<div>
<Controller
@ -215,8 +216,8 @@ export const ProjectViewForm: React.FC<Props> = observer((props) => {
? "Updating View..."
: "Update View"
: isSubmitting
? "Creating View..."
: "Create View"}
? "Creating View..."
: "Create View"}
</Button>
</div>
</form>

View File

@ -125,35 +125,38 @@ export const CreateWorkspaceForm: FC<Props> = observer((props) => {
Workspace Name
<span className="ml-0.5 text-red-500">*</span>
</label>
<Controller
control={control}
name="name"
rules={{
required: "Workspace name is required",
validate: (value) =>
/^[\w\s-]*$/.test(value) || `Name can only contain (" "), ( - ), ( _ ) & alphanumeric characters.`,
maxLength: {
value: 80,
message: "Workspace name should not exceed 80 characters",
},
}}
render={({ field: { value, ref, onChange } }) => (
<Input
id="workspaceName"
type="text"
value={value}
onChange={(e) => {
onChange(e.target.value);
setValue("name", e.target.value);
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"));
}}
ref={ref}
hasError={Boolean(errors.name)}
placeholder="Enter workspace name..."
className="w-full"
/>
)}
/>
<div className="flex flex-col gap-1">
<Controller
control={control}
name="name"
rules={{
required: "Workspace name is required",
validate: (value) =>
/^[\w\s-]*$/.test(value) || `Name can only contain (" "), ( - ), ( _ ) & alphanumeric characters.`,
maxLength: {
value: 80,
message: "Workspace name should not exceed 80 characters",
},
}}
render={({ field: { value, ref, onChange } }) => (
<Input
id="workspaceName"
type="text"
value={value}
onChange={(e) => {
onChange(e.target.value);
setValue("name", e.target.value);
setValue("slug", e.target.value.toLocaleLowerCase().trim().replace(/ /g, "-"));
}}
ref={ref}
hasError={Boolean(errors.name)}
placeholder="Enter workspace name..."
className="w-full"
/>
)}
/>
<span className="text-xs text-red-500">{errors?.name?.message}</span>
</div>
</div>
<div className="space-y-1 text-sm">
<label htmlFor="workspaceUrl">