From a07e3c21d6d44ef1f72ec4e46b4899f47f9896b0 Mon Sep 17 00:00:00 2001 From: hafidnrzs Date: Sun, 16 Mar 2025 01:40:02 +0700 Subject: [PATCH] feat: add Textarea component --- libs/ui/src/atoms/index.ts | 1 + libs/ui/src/atoms/textarea/index.ts | 1 + .../src/atoms/textarea/textarea.stories.tsx | 49 +++++++++++++++ libs/ui/src/atoms/textarea/textarea.tsx | 59 +++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 libs/ui/src/atoms/textarea/index.ts create mode 100644 libs/ui/src/atoms/textarea/textarea.stories.tsx create mode 100644 libs/ui/src/atoms/textarea/textarea.tsx diff --git a/libs/ui/src/atoms/index.ts b/libs/ui/src/atoms/index.ts index 07e967b..c107e65 100644 --- a/libs/ui/src/atoms/index.ts +++ b/libs/ui/src/atoms/index.ts @@ -1,3 +1,4 @@ export * from './button'; export * from './input'; export * from './password-input'; +export * from './textarea'; diff --git a/libs/ui/src/atoms/textarea/index.ts b/libs/ui/src/atoms/textarea/index.ts new file mode 100644 index 0000000..23f3d74 --- /dev/null +++ b/libs/ui/src/atoms/textarea/index.ts @@ -0,0 +1 @@ +export * from "./textarea"; diff --git a/libs/ui/src/atoms/textarea/textarea.stories.tsx b/libs/ui/src/atoms/textarea/textarea.stories.tsx new file mode 100644 index 0000000..ffe3c44 --- /dev/null +++ b/libs/ui/src/atoms/textarea/textarea.stories.tsx @@ -0,0 +1,49 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { Textarea } from "./textarea"; + +const meta: Meta = { + title: "Components/Textarea", + component: Textarea, + argTypes: { + size: { + control: "select", + options: ["sm", "md", "lg"], + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Large: Story = { + args: { + size: "lg", + placeholder: "Placeholder", + }, +}; + +export const Medium: Story = { + args: { + size: "md", + }, +}; + +export const Small: Story = { + args: { + size: "sm", + }, +}; + +export const Disabled: Story = { + args: { + size: "md", + disabled: true, + }, +}; + +export const WithError: Story = { + args: { + size: "md", + error: "Error message", + }, +}; diff --git a/libs/ui/src/atoms/textarea/textarea.tsx b/libs/ui/src/atoms/textarea/textarea.tsx new file mode 100644 index 0000000..1c31100 --- /dev/null +++ b/libs/ui/src/atoms/textarea/textarea.tsx @@ -0,0 +1,59 @@ +import { cn } from '@imphnen-frontend-service/utils'; +import { + DetailedHTMLProps, + FC, + ReactElement, + TextareaHTMLAttributes, +} from 'react'; + +type TTextareaSize = 'sm' | 'md' | 'lg'; + +type TTextareaProps = Omit< + DetailedHTMLProps< + TextareaHTMLAttributes, + HTMLTextAreaElement + >, + 'size' +> & { + size?: TTextareaSize; + error?: string; +}; + +const sizeClasses: Record = { + sm: 'text-[10px]', + md: 'text-[12px]', + lg: 'text-[15px]', +}; + +const disabledClass = 'opacity-50 hover:border-neutral-200 cursor-not-allowed'; +const errorClass = + 'border-danger-500 hover:border-danger-500 focus:outline-danger-500'; + +export const Textarea: FC = ({ + size = 'md', + placeholder = 'Placeholder', + disabled, + error, + className, + ...rest +}): ReactElement => { + const mergedClassName = cn( + 'rounded-md border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 px-[12px] py-[8px] invalid:border-danger-500 invalid:text-danger-500', + sizeClasses[size], + disabled && disabledClass, + error && errorClass, + className + ); + return ( + <> + + {error &&

{error}

} + + ); +};