diff --git a/src/design-system/composites/LoginForm/LoginDialog.test.tsx b/src/design-system/composites/LoginForm/LoginDialog.test.tsx
new file mode 100644
index 0000000..6e486d0
--- /dev/null
+++ b/src/design-system/composites/LoginForm/LoginDialog.test.tsx
@@ -0,0 +1,54 @@
+import { describe, it, expect, vi } from 'vitest'
+import { render, screen } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import { LoginDialog } from './LoginDialog'
+
+const defaultProps = {
+ open: true,
+ onClose: vi.fn(),
+ onSubmit: vi.fn(),
+}
+
+describe('LoginDialog', () => {
+ it('renders Modal with LoginForm when open', () => {
+ render()
+ expect(screen.getByRole('dialog')).toBeInTheDocument()
+ expect(screen.getByRole('heading', { name: 'Sign in' })).toBeInTheDocument()
+ expect(screen.getByLabelText(/email/i)).toBeInTheDocument()
+ })
+
+ it('does not render when closed', () => {
+ render()
+ expect(screen.queryByRole('dialog')).not.toBeInTheDocument()
+ })
+
+ it('calls onClose on Esc', async () => {
+ const onClose = vi.fn()
+ const user = userEvent.setup()
+ render()
+ await user.keyboard('{Escape}')
+ expect(onClose).toHaveBeenCalled()
+ })
+
+ it('calls onClose on backdrop click', async () => {
+ const onClose = vi.fn()
+ const user = userEvent.setup()
+ render()
+ await user.click(screen.getByTestId('modal-backdrop'))
+ expect(onClose).toHaveBeenCalled()
+ })
+
+ it('passes LoginForm props through', () => {
+ render(
+ ,
+ )
+ expect(screen.getByText('Welcome')).toBeInTheDocument()
+ expect(screen.getByText('Continue with Google')).toBeInTheDocument()
+ expect(screen.getByText('Bad credentials')).toBeInTheDocument()
+ })
+})
diff --git a/src/design-system/composites/LoginForm/LoginDialog.tsx b/src/design-system/composites/LoginForm/LoginDialog.tsx
new file mode 100644
index 0000000..cffd740
--- /dev/null
+++ b/src/design-system/composites/LoginForm/LoginDialog.tsx
@@ -0,0 +1,15 @@
+import { Modal } from '../Modal/Modal'
+import { LoginForm, type LoginFormProps } from './LoginForm'
+
+export interface LoginDialogProps extends LoginFormProps {
+ open: boolean
+ onClose: () => void
+}
+
+export function LoginDialog({ open, onClose, className, ...formProps }: LoginDialogProps) {
+ return (
+
+
+
+ )
+}