Refactor authentication and account management with modular UI components (#242)

This commit is contained in:
2026-08-23 01:30:58 -04:00
committed by GitHub
parent c514eb9814
commit 1621313daa
109 changed files with 14743 additions and 10792 deletions

View File

@@ -1,68 +1,71 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import { expect, within } from 'storybook/test';
import FormField from '../app/components/forms/FormField';
import FormField from '../app/components/ui/forms/FormField';
const formFieldDescription = `Reusable labeled input for Biergarten forms. This page shows guided, error, and password states so you can review label spacing, helper text, validation messaging, and ARIA behavior in the same card layout used across the app.`;
const meta = {
title: 'Forms/FormField',
component: FormField,
tags: ['autodocs'],
args: {
id: 'email',
name: 'email',
type: 'email',
label: 'Email address',
placeholder: 'you@example.com',
hint: 'We only use this to manage your account.',
},
parameters: {
layout: 'centered',
docs: {
description: {
component: formFieldDescription,
},
},
},
render: (args) => (
<div className="w-full max-w-md rounded-box bg-base-100 p-6 shadow-lg">
<FormField {...args} />
</div>
),
title: 'Forms/FormField',
component: FormField,
tags: ['autodocs'],
args: {
id: 'email',
name: 'email',
type: 'email',
label: 'Email address',
placeholder: 'you@example.com',
hint: 'We only use this to manage your account.',
},
parameters: {
layout: 'centered',
docs: {
description: {
component: formFieldDescription,
},
},
},
render: (args) => (
<div className="w-full max-w-md rounded-box bg-base-100 p-6 shadow-lg">
<FormField {...args} />
</div>
),
} satisfies Meta<typeof FormField>;
export default meta;
type Story = StoryObj<typeof meta>;
export const WithHint: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByLabelText(/email address/i)).toBeInTheDocument();
await expect(canvas.getByText(/manage your account/i)).toBeInTheDocument();
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByLabelText(/email address/i)).toBeInTheDocument();
await expect(canvas.getByText(/manage your account/i)).toBeInTheDocument();
},
};
export const WithError: Story = {
args: {
error: 'Please enter a valid email address.',
hint: undefined,
'aria-invalid': true,
defaultValue: 'not-an-email',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByText(/valid email address/i)).toBeInTheDocument();
await expect(canvas.getByLabelText(/email address/i)).toHaveAttribute('aria-invalid', 'true');
},
args: {
error: 'Please enter a valid email address.',
hint: undefined,
'aria-invalid': true,
defaultValue: 'not-an-email',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByText(/valid email address/i)).toBeInTheDocument();
await expect(canvas.getByLabelText(/email address/i)).toHaveAttribute(
'aria-invalid',
'true',
);
},
};
export const PasswordField: Story = {
args: {
id: 'password',
name: 'password',
type: 'password',
label: 'Password',
placeholder: 'Enter a strong password',
hint: 'Use 12 or more characters.',
},
args: {
id: 'password',
name: 'password',
type: 'password',
label: 'Password',
placeholder: 'Enter a strong password',
hint: 'Use 12 or more characters.',
},
};