diff --git a/libs/ui/src/atoms/index.ts b/libs/ui/src/atoms/index.ts
index eaf5eea..55d2082 100644
--- a/libs/ui/src/atoms/index.ts
+++ b/libs/ui/src/atoms/index.ts
@@ -1 +1,2 @@
export * from './button';
+export * from './input';
diff --git a/libs/ui/src/atoms/input/index.ts b/libs/ui/src/atoms/input/index.ts
new file mode 100644
index 0000000..4ce4a88
--- /dev/null
+++ b/libs/ui/src/atoms/input/index.ts
@@ -0,0 +1 @@
+export * from "./input";
diff --git a/libs/ui/src/atoms/input/input.spec.tsx b/libs/ui/src/atoms/input/input.spec.tsx
new file mode 100644
index 0000000..4fdf16b
--- /dev/null
+++ b/libs/ui/src/atoms/input/input.spec.tsx
@@ -0,0 +1,36 @@
+import { describe, it, expect } from "vitest";
+import { render, screen } from "@testing-library/react";
+import { Input } from "./input";
+
+describe("Test Input Component", () => {
+ it("renders the input with placeholder text", () => {
+ render();
+ expect(screen.getByPlaceholderText("Placeholder")).toBeInTheDocument();
+ });
+
+ // it("renders the input with different sizes", () => {
+ // const sizeClasses = {
+ // sm: "text-[10px] max-h-[28px]",
+ // md: "text-[12px] max-h-[30px]",
+ // lg: "text-[15px] max-h-[34px]",
+ // };
+ // Object.entries(sizeClasses).forEach(([size, className]) => {
+ // render();
+ // expect(screen.getByRole("textbox")).toHaveClass(className);
+ // });
+ // });
+
+ // it("renders the input with different types", () => {
+ // const types = ["text", "password", "email", "number"];
+ // types.forEach((type) => {
+ // render();
+ // const input = screen.getByRole("textbox");
+ // expect(input).toHaveAttribute("type", type);
+ // });
+ // });
+
+ it("disables the input field when 'disabled' prop is set", () => {
+ render();
+ expect(screen.getByRole("textbox")).toBeDisabled();
+ });
+});
diff --git a/libs/ui/src/atoms/input/input.stories.tsx b/libs/ui/src/atoms/input/input.stories.tsx
new file mode 100644
index 0000000..7bea8f5
--- /dev/null
+++ b/libs/ui/src/atoms/input/input.stories.tsx
@@ -0,0 +1,71 @@
+import { Meta, StoryObj } from '@storybook/react';
+import { Input } from './input';
+
+const meta: Meta = {
+ title: 'Components/Input',
+ component: Input,
+ argTypes: {
+ type: {
+ control: 'select',
+ options: ['text', 'email'],
+ },
+ 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',
+ placeholder: 'Placeholder',
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: 'sm',
+ placeholder: 'Placeholder',
+ },
+};
+
+export const TextInput: Story = {
+ args: {
+ size: 'md',
+ type: 'text',
+ },
+};
+
+export const EmailInput: Story = {
+ args: {
+ size: 'md',
+ type: 'email',
+ },
+};
+
+export const Disabled: Story = {
+ args: {
+ size: 'md',
+ type: 'text',
+ disabled: true,
+ },
+};
+
+export const WithError: Story = {
+ args: {
+ size: 'md',
+ type: 'text',
+ error: 'This field is required',
+ },
+};
diff --git a/libs/ui/src/atoms/input/input.tsx b/libs/ui/src/atoms/input/input.tsx
new file mode 100644
index 0000000..3a80d49
--- /dev/null
+++ b/libs/ui/src/atoms/input/input.tsx
@@ -0,0 +1,60 @@
+import {
+ DetailedHTMLProps,
+ FC,
+ InputHTMLAttributes,
+ ReactElement,
+} from 'react';
+import { cn } from '@imphnen-frontend-service/utils';
+
+type TInputType = 'text' | 'email';
+type TInputSize = 'sm' | 'md' | 'lg';
+
+type TInputProps = Omit<
+ DetailedHTMLProps, HTMLInputElement>,
+ 'size' | 'type'
+> & {
+ type?: TInputType;
+ size?: TInputSize;
+ error?: string;
+};
+
+const sizeClasses: Record = {
+ sm: 'text-[10px] max-h-[28px]',
+ md: 'text-[12px] max-h-[30px]',
+ lg: 'text-[15px] max-h-[34px]',
+};
+
+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 Input: FC = ({
+ size = 'md',
+ type,
+ placeholder = 'Placeholder',
+ disabled,
+ error,
+ className,
+ ...rest
+}): ReactElement => {
+ const mergedClassName = cn(
+ 'px-[12px] py-[8px] text-neutral-800 placeholder:text-neutral-300 border border-neutral-200 hover:border-blue-300 focus:outline-1 focus:outline-blue-500 rounded-md font-bai-jamjuree',
+ sizeClasses[size],
+ disabled && disabledClass,
+ error && errorClass,
+ className
+ );
+
+ return (
+ <>
+
+ {error && {error}
}
+ >
+ );
+};