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 Aaron Po
parent 6a44afd6b6
commit bfd45842fe
109 changed files with 14743 additions and 10792 deletions

View File

@@ -1,50 +1,55 @@
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: [
'../stories/Configure.mdx',
'../stories/SubmitButton.stories.tsx',
'../stories/FormField.stories.tsx',
'../stories/Navbar.stories.tsx',
'../stories/Toast.stories.tsx',
'../stories/Themes.stories.tsx',
],
addons: [
'@chromatic-com/storybook',
'@storybook/addon-vitest',
'@storybook/addon-a11y',
'@storybook/addon-docs',
'@storybook/addon-onboarding',
],
framework: '@storybook/react-vite',
async viteFinal(config) {
config.plugins = (config.plugins ?? []).filter((plugin) => {
if (!plugin) {
return true;
}
stories: [
'../stories/Configure.mdx',
'../stories/SubmitButton.stories.tsx',
'../stories/FormField.stories.tsx',
'../stories/SectionCard.stories.tsx',
'../stories/UsernameSection.stories.tsx',
'../stories/PasswordSection.stories.tsx',
'../stories/LoginForm.stories.tsx',
'../stories/RegisterForm.stories.tsx',
'../stories/Navbar.stories.tsx',
'../stories/Toast.stories.tsx',
'../stories/Themes.stories.tsx',
],
addons: [
'@chromatic-com/storybook',
'@storybook/addon-vitest',
'@storybook/addon-a11y',
'@storybook/addon-docs',
'@storybook/addon-onboarding',
],
framework: '@storybook/react-vite',
async viteFinal(config) {
config.plugins = (config.plugins ?? []).filter((plugin) => {
if (!plugin) {
return true;
}
const pluginName = typeof plugin === 'object' && 'name' in plugin ? plugin.name : '';
return !pluginName.startsWith('react-router');
});
const pluginName = typeof plugin === 'object' && 'name' in plugin ? plugin.name : '';
return !pluginName.startsWith('react-router');
});
config.build ??= {};
config.build.rollupOptions ??= {};
config.build ??= {};
config.build.rollupOptions ??= {};
const previousOnWarn = config.build.rollupOptions.onwarn;
config.build.rollupOptions.onwarn = (warning, warn) => {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
return;
}
const previousOnWarn = config.build.rollupOptions.onwarn;
config.build.rollupOptions.onwarn = (warning, warn) => {
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
return;
}
if (typeof previousOnWarn === 'function') {
previousOnWarn(warning, warn);
return;
}
if (typeof previousOnWarn === 'function') {
previousOnWarn(warning, warn);
return;
}
warn(warning);
};
warn(warning);
};
return config;
},
return config;
},
};
export default config;

View File

@@ -1,6 +1,6 @@
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="anonymous" />
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..900;1,9..40,100..900&family=Volkhov:ital,wght@0,400;0,700;1,400;1,700&display=swap"
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,100..900;1,9..40,100..900&family=Volkhov:ital,wght@0,400;0,700;1,400;1,700&display=swap"
/>

View File

@@ -2,62 +2,71 @@ import type { Preview } from '@storybook/react-vite';
import { createElement } from 'react';
import { MemoryRouter } from 'react-router';
import '../app/app.css';
import { biergartenThemes, defaultThemeName, isBiergartenTheme } from '../app/lib/themes';
import {
biergartenThemes,
defaultThemeName,
isBiergartenTheme,
} from '../app/features/theme/themes';
const preview: Preview = {
globalTypes: {
theme: {
description: 'Active Biergarten theme',
toolbar: {
title: 'Theme',
icon: 'paintbrush',
dynamicTitle: true,
items: biergartenThemes.map((theme) => ({
value: theme.value,
title: theme.label,
})),
},
},
},
initialGlobals: {
theme: defaultThemeName,
},
decorators: [
(Story, context) => {
const theme = isBiergartenTheme(String(context.globals.theme))
? context.globals.theme
: defaultThemeName;
globalTypes: {
theme: {
description: 'Active Biergarten theme',
toolbar: {
title: 'Theme',
icon: 'paintbrush',
dynamicTitle: true,
items: biergartenThemes.map((theme) => ({
value: theme.value,
title: theme.label,
})),
},
},
},
initialGlobals: {
theme: defaultThemeName,
},
decorators: [
(Story, context) => {
const theme = isBiergartenTheme(String(context.globals.theme))
? context.globals.theme
: defaultThemeName;
return createElement(
MemoryRouter,
undefined,
createElement(
'div',
{
'data-theme': theme,
className: 'bg-base-200 p-6 text-base-content',
},
createElement('div', { className: 'mx-auto max-w-7xl' }, createElement(Story)),
),
);
},
],
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
layout: 'padded',
const content = createElement(
'div',
{
'data-theme': theme,
className: 'bg-base-200 p-6 text-base-content',
},
createElement('div', { className: 'mx-auto max-w-7xl' }, createElement(Story)),
);
a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
// Stories driving `useSubmit`/`useNavigation` bring their own data
// router (createMemoryRouter + RouterProvider), which can't nest
// inside another <Router>.
if (context.parameters.usesDataRouter) {
return content;
}
return createElement(MemoryRouter, undefined, content);
},
],
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
layout: 'padded',
a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
};
export default preview;