From 2f61922c509b026d2aeef0459aca6f72f6bfac9c Mon Sep 17 00:00:00 2001 From: Aaron Po Date: Thu, 8 Oct 2026 23:10:48 -0400 Subject: [PATCH] Cover the split-screen auth layout in Storybook --- .../components/AuthSplitLayout.stories.tsx | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 web/frontend/app/features/auth/components/AuthSplitLayout.stories.tsx diff --git a/web/frontend/app/features/auth/components/AuthSplitLayout.stories.tsx b/web/frontend/app/features/auth/components/AuthSplitLayout.stories.tsx new file mode 100644 index 00000000..9e3b7f69 --- /dev/null +++ b/web/frontend/app/features/auth/components/AuthSplitLayout.stories.tsx @@ -0,0 +1,107 @@ +import { zodResolver } from '@hookform/resolvers/zod'; +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { useForm } from 'react-hook-form'; +import { expect, within } from 'storybook/test'; +import AuthSplitLayout from './AuthSplitLayout'; +import AuthSwitchPrompt from './AuthSwitchPrompt'; +import LoginForm from './LoginForm'; +import RegisterForm from './RegisterForm'; +import { loginSchema, registerSchema, type LoginSchema, type RegisterSchema } from '../schemas'; + +const authSplitLayoutDescription = `The shared split-screen shell behind /login and /register: a brand panel carrying the headline and a form panel that centers the page's own heading, form, and switch prompt. Both stories compose the real forms, so they show the production layout at any viewport.`; + +const LoginPanel = () => { + const form = useForm({ resolver: zodResolver(loginSchema) }); + + return ( +
+
+

Sign in

+

Sign in to your Biergarten account

+
+ + {})} + formState={form.formState} + register={form.register} + submitting={false} + /> + + +
+ ); +}; + +const RegisterPanel = () => { + const form = useForm({ resolver: zodResolver(registerSchema) }); + + return ( +
+
+

Create your account

+

Create your Biergarten account

+
+ + {})} + formState={form.formState} + register={form.register} + submitting={false} + /> + + +
+ ); +}; + +const meta = { + title: 'Layout/AuthSplitLayout', + component: AuthSplitLayout, + tags: ['autodocs'], + parameters: { + layout: 'fullscreen', + docs: { + description: { + component: authSplitLayoutDescription, + }, + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Login: Story = { + args: { + headline: 'Good to see you again.', + blurb: 'Sign in to pick up where you left off with our partner breweries.', + children: , + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await expect(canvas.getByRole('heading', { name: 'Sign in' })).toBeInTheDocument(); + await expect(canvas.getByRole('button', { name: /show password/i })).toBeInTheDocument(); + }, +}; + +export const Register: Story = { + args: { + headline: 'Pull up a chair.', + blurb: 'Create an account to explore partner breweries and their beers.', + children: , + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await expect(canvas.getByLabelText(/date of birth/i)).toBeInTheDocument(); + await expect(canvas.getByRole('button', { name: /create account/i })).toBeInTheDocument(); + }, +}; + +export const RegisterMobile: Story = { + args: Register.args, + parameters: { + viewport: { + defaultViewport: 'mobile1', + }, + }, +};