Files
web/packages/design-system/lib/components/TextArea/TextArea.stories.tsx
Rasmus Langvad 4980cc830d Merged in feat/3685-new-textarea-component (pull request #3392)
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
2026-01-07 17:04:30 +00:00

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,
},
}