diff --git a/package.json b/package.json index d53576ab..46571a4c 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@eslint/js": "^9.13.0", "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.0.1", + "@testing-library/user-event": "^14.5.2", "@types/node": "^22.9.0", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f38b54dd..ef9f79da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: '@testing-library/react': specifier: ^16.0.1 version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.5.2(@testing-library/dom@10.4.0) '@types/node': specifier: ^22.9.0 version: 22.9.0 @@ -612,6 +615,12 @@ packages: '@types/react-dom': optional: true + '@testing-library/user-event@14.5.2': + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -2374,6 +2383,10 @@ snapshots: '@types/react': 18.3.12 '@types/react-dom': 18.3.1 + '@testing-library/user-event@14.5.2(@testing-library/dom@10.4.0)': + dependencies: + '@testing-library/dom': 10.4.0 + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': diff --git a/src/components/Dummy.test.tsx b/src/components/Dummy.test.tsx deleted file mode 100644 index 330a24a3..00000000 --- a/src/components/Dummy.test.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { describe, it, expect } from 'vitest'; -import { render, screen } from '@testing-library/react'; -import Dummy from './Dummy'; - -describe('Component: Dummy', () => { - it('should render with dummy text', () => { - render(); - expect(screen.getByText('dummy')).toBeInTheDocument(); - }); -}); diff --git a/src/components/Dummy.tsx b/src/components/Dummy.tsx deleted file mode 100644 index 6d7a6416..00000000 --- a/src/components/Dummy.tsx +++ /dev/null @@ -1,6 +0,0 @@ -// This is a dummy component for the test setup -const Dummy = () => { - return
dummy
; -}; - -export default Dummy; diff --git a/src/components/FormContainer.tsx b/src/components/FormContainer.tsx new file mode 100644 index 00000000..bd620675 --- /dev/null +++ b/src/components/FormContainer.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from 'react'; + +const FormContainer = ({ children }: { children: ReactNode }) => { + return ( +
+
+ {children} +
+
+ ); +}; + +export { FormContainer }; \ No newline at end of file diff --git a/src/components/TextArea.tsx b/src/components/TextArea.tsx new file mode 100644 index 00000000..605ee96d --- /dev/null +++ b/src/components/TextArea.tsx @@ -0,0 +1,73 @@ +import { forwardRef } from 'react'; +import { Field, Label, Textarea } from '@headlessui/react'; + +interface TextAreaProps extends React.TextareaHTMLAttributes { + label?: string; + error?: string; + description?: string; + value?: string; + required?: boolean; + onChange?: (e: React.ChangeEvent) => void; +} + +const TextArea = forwardRef( + ({ label, error, description, className = '', value, required, onChange, ...props }, ref) => { + const inputProps = onChange + ? { value, onChange } + : { defaultValue: value }; + + const sharedClassNames = ` + w-full px-4 py-2 + bg-white + border border-gray-300 + rounded-md + focus:outline-none focus:ring-2 focus:ring-blue-500 + data-[invalid]:border-red-500 + min-h-[100px] resize-y + ${className} + `; + + return ( +
+ + {label && ( +
+ + {required && ( + + Required + + )} +
+ )} + +