mirror of
https://github.com/aaronpo97/the-biergarten-app.git
synced 2026-10-14 17:54:42 +00:00
Add brewery discovery & detail pages with location-based search (#253)
This commit is contained in:
71
web/frontend/app/components/ui/forms/FormField.stories.tsx
Normal file
71
web/frontend/app/components/ui/forms/FormField.stories.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { expect, within } from 'storybook/test';
|
||||
import FormField from './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>
|
||||
),
|
||||
} 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();
|
||||
},
|
||||
};
|
||||
|
||||
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',
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const PasswordField: Story = {
|
||||
args: {
|
||||
id: 'password',
|
||||
name: 'password',
|
||||
type: 'password',
|
||||
label: 'Password',
|
||||
placeholder: 'Enter a strong password',
|
||||
hint: 'Use 12 or more characters.',
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { expect, within } from 'storybook/test';
|
||||
import SubmitButton from './SubmitButton';
|
||||
|
||||
const submitButtonDescription = `Shared submit action for Biergarten forms. These stories cover the idle, loading, and custom-width states so you can verify button copy, disabled behavior during submission, and theme styling without wiring up a full form flow.`;
|
||||
|
||||
const meta = {
|
||||
title: 'Forms/SubmitButton',
|
||||
component: SubmitButton,
|
||||
tags: ['autodocs'],
|
||||
args: {
|
||||
idleText: 'Save changes',
|
||||
submittingText: 'Saving changes',
|
||||
isSubmitting: false,
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
docs: {
|
||||
description: {
|
||||
component: submitButtonDescription,
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Meta<typeof SubmitButton>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Idle: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await expect(canvas.getByRole('button', { name: /save changes/i })).toBeEnabled();
|
||||
},
|
||||
};
|
||||
|
||||
export const Submitting: Story = {
|
||||
args: {
|
||||
isSubmitting: true,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await expect(canvas.getByRole('button', { name: /saving changes/i })).toBeDisabled();
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomWidth: Story = {
|
||||
args: {
|
||||
className: 'btn btn-secondary min-w-64',
|
||||
idleText: 'Register user',
|
||||
submittingText: 'Registering user',
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user