feat(SW-3685): Add new TextArea and FormTextArea components * Add new TextArea and FormTextArea components * Update example form with description * Merge branch 'master' into feat/3685-new-textarea-component * Formatting new files with new prettier config * Added custom controls for the text area story Approved-by: Linus Flood
197 lines
5.0 KiB
TypeScript
197 lines
5.0 KiB
TypeScript
import { zodResolver } from "@hookform/resolvers/zod"
|
|
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
|
import { useEffect } from "react"
|
|
import { FormProvider, useForm } from "react-hook-form"
|
|
import { z } from "zod"
|
|
|
|
import { FormTextArea } from "../Form/FormTextArea"
|
|
import type { MaterialIconProps } from "../Icons/MaterialIcon"
|
|
|
|
interface FormTextAreaStoryProps {
|
|
label?: string
|
|
placeholder?: string
|
|
description?: string
|
|
descriptionIcon?: MaterialIconProps["icon"]
|
|
disabled?: boolean
|
|
readOnly?: boolean
|
|
required?: boolean
|
|
showLabel?: boolean
|
|
showDescription?: boolean
|
|
showDescriptionIcon?: boolean
|
|
filled?: boolean
|
|
defaultValue?: string
|
|
errorMessage?: string
|
|
name?: string
|
|
}
|
|
|
|
function FormTextAreaComponent({
|
|
label,
|
|
placeholder,
|
|
description,
|
|
descriptionIcon = "info",
|
|
disabled = false,
|
|
readOnly = false,
|
|
required = false,
|
|
showLabel = true,
|
|
showDescription = true,
|
|
showDescriptionIcon = true,
|
|
filled = false,
|
|
defaultValue = "",
|
|
errorMessage,
|
|
name = "textarea",
|
|
}: FormTextAreaStoryProps) {
|
|
const schema = z.object({
|
|
[name]: errorMessage
|
|
? z.string().min(1, errorMessage)
|
|
: required
|
|
? z.string().min(1, "This field is required")
|
|
: z.string().optional(),
|
|
})
|
|
|
|
const methods = useForm<{ [key: string]: string }>({
|
|
resolver: zodResolver(schema),
|
|
defaultValues: {
|
|
[name]: filled ? defaultValue : "",
|
|
},
|
|
mode: "onChange",
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (errorMessage) {
|
|
// Set error manually if errorMessage is provided
|
|
methods.setError(name, {
|
|
type: "manual",
|
|
message: errorMessage,
|
|
})
|
|
// Trigger validation to show the error immediately
|
|
methods.trigger(name)
|
|
} else {
|
|
// Clear errors if errorMessage is removed
|
|
methods.clearErrors(name)
|
|
}
|
|
}, [errorMessage, methods, name])
|
|
|
|
return (
|
|
<FormProvider {...methods}>
|
|
<div style={{ maxWidth: "500px", padding: "1rem" }}>
|
|
<FormTextArea
|
|
name={name}
|
|
label={showLabel ? label : undefined}
|
|
placeholder={placeholder}
|
|
description={showDescription ? description : undefined}
|
|
descriptionIcon={showDescriptionIcon ? descriptionIcon : undefined}
|
|
disabled={disabled}
|
|
readOnly={readOnly}
|
|
registerOptions={required ? { required: true } : undefined}
|
|
/>
|
|
</div>
|
|
</FormProvider>
|
|
)
|
|
}
|
|
|
|
const meta: Meta<typeof FormTextAreaComponent> = {
|
|
title: "Core Components/TextArea",
|
|
component: FormTextAreaComponent,
|
|
argTypes: {
|
|
label: {
|
|
control: "text",
|
|
description: "The label text displayed above the textarea field",
|
|
table: {
|
|
type: { summary: "string" },
|
|
},
|
|
},
|
|
placeholder: {
|
|
control: "text",
|
|
description: "Placeholder text shown when textarea is empty",
|
|
table: {
|
|
type: { summary: "string" },
|
|
defaultValue: { summary: "undefined" },
|
|
},
|
|
},
|
|
description: {
|
|
control: "text",
|
|
description: "Supporting text displayed below the textarea",
|
|
table: {
|
|
type: { summary: "string" },
|
|
defaultValue: { summary: "undefined" },
|
|
},
|
|
},
|
|
|
|
disabled: {
|
|
control: "boolean",
|
|
description: "Whether the textarea is disabled",
|
|
table: {
|
|
type: { summary: "boolean" },
|
|
defaultValue: { summary: "false" },
|
|
},
|
|
},
|
|
readOnly: {
|
|
control: "boolean",
|
|
description: "Whether the textarea is read-only",
|
|
table: {
|
|
type: { summary: "boolean" },
|
|
defaultValue: { summary: "false" },
|
|
},
|
|
},
|
|
required: {
|
|
control: "boolean",
|
|
description: "Whether the textarea is required",
|
|
table: {
|
|
type: { summary: "boolean" },
|
|
defaultValue: { summary: "false" },
|
|
},
|
|
},
|
|
showLabel: {
|
|
control: "boolean",
|
|
description: "Whether to show the label",
|
|
table: {
|
|
type: { summary: "boolean" },
|
|
defaultValue: { summary: "true" },
|
|
},
|
|
},
|
|
showDescription: {
|
|
control: "boolean",
|
|
description: "Whether to show the description/supporting text",
|
|
table: {
|
|
type: { summary: "boolean" },
|
|
defaultValue: { summary: "true" },
|
|
},
|
|
},
|
|
defaultValue: {
|
|
control: "text",
|
|
description: "Default value when filled is true",
|
|
table: {
|
|
type: { summary: "string" },
|
|
defaultValue: { summary: "" },
|
|
},
|
|
},
|
|
errorMessage: {
|
|
control: "text",
|
|
description: "Error message to display (triggers error state)",
|
|
table: {
|
|
type: { summary: "string" },
|
|
defaultValue: { summary: "undefined" },
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
export default meta
|
|
|
|
type Story = StoryObj<typeof FormTextAreaComponent>
|
|
|
|
export const Default: Story = {
|
|
args: {
|
|
label: "Label",
|
|
placeholder: "Placeholder",
|
|
description: "Supporting text",
|
|
disabled: false,
|
|
readOnly: false,
|
|
required: false,
|
|
showLabel: true,
|
|
showDescription: true,
|
|
defaultValue: "",
|
|
errorMessage: undefined,
|
|
},
|
|
}
|