Upgrade to React 19, MUI v7, Storybook 9
- React 18 → 19, MUI v5 → v7, Storybook 8 → 9 - Fix Grid v2 API in Footer (remove item prop, use size prop) - Inline provider fixtures (was importing from excluded demo dir) - Remove consolidated SB addons (essentials, storysource, blocks) - Update addon-designs to SB9-compatible version - Add autodocs via tags in preview config - Add Tailwind v3, PostCSS, autoprefixer dev deps (config next) - Zero TypeScript errors, Storybook starts clean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,28 +3,15 @@ import type { StorybookConfig } from '@storybook/react-vite';
|
|||||||
const config: StorybookConfig = {
|
const config: StorybookConfig = {
|
||||||
stories: ['../src/**/*.stories.@(ts|tsx)'],
|
stories: ['../src/**/*.stories.@(ts|tsx)'],
|
||||||
addons: [
|
addons: [
|
||||||
'@storybook/addon-essentials',
|
|
||||||
'@storybook/addon-a11y',
|
'@storybook/addon-a11y',
|
||||||
'@storybook/addon-designs',
|
'@storybook/addon-designs',
|
||||||
{
|
|
||||||
name: '@storybook/addon-storysource',
|
|
||||||
options: {
|
|
||||||
loaderOptions: {
|
|
||||||
injectStoryParameters: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
framework: {
|
framework: {
|
||||||
name: '@storybook/react-vite',
|
name: '@storybook/react-vite',
|
||||||
options: {},
|
options: {},
|
||||||
},
|
},
|
||||||
docs: {
|
|
||||||
autodocs: 'tag',
|
|
||||||
},
|
|
||||||
staticDirs: ['../brandassets'],
|
staticDirs: ['../brandassets'],
|
||||||
viteFinal: async (config) => {
|
viteFinal: async (config) => {
|
||||||
// Inherit aliases from vite.config.ts automatically via react-vite framework
|
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { theme } from '../src/theme';
|
|||||||
import '../src/theme/generated/tokens.css';
|
import '../src/theme/generated/tokens.css';
|
||||||
|
|
||||||
const preview: Preview = {
|
const preview: Preview = {
|
||||||
|
tags: ['autodocs'],
|
||||||
decorators: [
|
decorators: [
|
||||||
(Story) => (
|
(Story) => (
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
|
|||||||
12282
package-lock.json
generated
Normal file
12282
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "fa-design-system",
|
"name": "fa-design-system",
|
||||||
"version": "0.1.0",
|
"version": "1.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "Funeral Arranger Design System — React + MUI + Storybook",
|
"description": "Funeral Arranger Design System — React 19 + MUI v7 + Storybook 9 + Tailwind v3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
@@ -17,53 +17,45 @@
|
|||||||
"format": "prettier --write 'src/**/*.{ts,tsx}'",
|
"format": "prettier --write 'src/**/*.{ts,tsx}'",
|
||||||
"format:check": "prettier --check 'src/**/*.{ts,tsx}'",
|
"format:check": "prettier --check 'src/**/*.{ts,tsx}'",
|
||||||
"test": "vitest run --passWithNoTests",
|
"test": "vitest run --passWithNoTests",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest"
|
||||||
"chromatic": "chromatic --exit-zero-on-changes --build-script-name=build:storybook",
|
|
||||||
"demo:dev": "vite -c vite.demo.config.ts --mode arrangement",
|
|
||||||
"demo:build": "vite build -c vite.demo.config.ts",
|
|
||||||
"demo:publish": "npm run demo:build -- --mode arrangement && ./scripts/deploy-demo.sh arrangement",
|
|
||||||
"prepare": "husky"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.13.0",
|
"@emotion/react": "^11.13.0",
|
||||||
"@emotion/styled": "^11.13.0",
|
"@emotion/styled": "^11.13.0",
|
||||||
"@googlemaps/markerclusterer": "^2.6.2",
|
"@googlemaps/markerclusterer": "^2.6.2",
|
||||||
"@mui/icons-material": "^5.16.0",
|
"@mui/icons-material": "^7.0.0",
|
||||||
"@mui/material": "^5.16.0",
|
"@mui/material": "^7.0.0",
|
||||||
"@mui/system": "^5.16.0",
|
"@mui/system": "^7.0.0",
|
||||||
"@vis.gl/react-google-maps": "^1.8.3",
|
"@vis.gl/react-google-maps": "^1.8.3",
|
||||||
"react": "^18.3.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^18.3.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-router-dom": "^7.14.1",
|
"react-router-dom": "^7.14.1",
|
||||||
"zustand": "^5.0.12"
|
"zustand": "^5.0.12"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.39.4",
|
"@eslint/js": "^9.39.4",
|
||||||
"@playwright/mcp": "^0.0.68",
|
"@storybook/addon-a11y": "^9.0.0",
|
||||||
"@storybook/addon-a11y": "^8.6.14",
|
"@storybook/addon-designs": "^9.0.0-next.3",
|
||||||
"@storybook/addon-designs": "^8.0.0",
|
"@storybook/react": "^9.0.0",
|
||||||
"@storybook/addon-essentials": "^8.4.0",
|
"@storybook/react-vite": "^9.0.0",
|
||||||
"@storybook/addon-storysource": "^8.6.14",
|
|
||||||
"@storybook/blocks": "^8.4.0",
|
|
||||||
"@storybook/react": "^8.4.0",
|
|
||||||
"@storybook/react-vite": "^8.4.0",
|
|
||||||
"@testing-library/jest-dom": "^6.9.1",
|
"@testing-library/jest-dom": "^6.9.1",
|
||||||
"@testing-library/react": "^16.3.2",
|
"@testing-library/react": "^16.3.2",
|
||||||
"@types/react": "^18.3.0",
|
"@types/react": "^19.0.0",
|
||||||
"@types/react-dom": "^18.3.0",
|
"@types/react-dom": "^19.0.0",
|
||||||
"@vitejs/plugin-react": "^4.3.0",
|
"@vitejs/plugin-react": "^4.3.0",
|
||||||
"chromatic": "^11.29.0",
|
"autoprefixer": "^10.4.0",
|
||||||
"eslint": "^9.39.4",
|
"eslint": "^9.39.4",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||||
"eslint-plugin-react": "^7.37.5",
|
"eslint-plugin-react": "^7.37.5",
|
||||||
"eslint-plugin-react-hooks": "^7.0.1",
|
"eslint-plugin-react-hooks": "^7.0.1",
|
||||||
"husky": "^9.1.7",
|
|
||||||
"jsdom": "^29.0.1",
|
"jsdom": "^29.0.1",
|
||||||
"lint-staged": "^16.4.0",
|
"lint-staged": "^16.4.0",
|
||||||
|
"postcss": "^8.4.0",
|
||||||
"prettier": "^3.8.1",
|
"prettier": "^3.8.1",
|
||||||
"storybook": "^8.4.0",
|
"storybook": "^9.0.0",
|
||||||
"style-dictionary": "^4.2.0",
|
"style-dictionary": "^4.2.0",
|
||||||
|
"tailwindcss": "^3.4.0",
|
||||||
"typescript": "^5.5.0",
|
"typescript": "^5.5.0",
|
||||||
"typescript-eslint": "^8.57.2",
|
"typescript-eslint": "^8.57.2",
|
||||||
"vite": "^5.4.0",
|
"vite": "^5.4.0",
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
|
|||||||
{/* Main footer content */}
|
{/* Main footer content */}
|
||||||
<Grid container spacing={{ xs: 4, md: 6 }}>
|
<Grid container spacing={{ xs: 4, md: 6 }}>
|
||||||
{/* Logo + tagline column */}
|
{/* Logo + tagline column */}
|
||||||
<Grid item xs={12} md={4}>
|
<Grid size={{ xs: 12, md: 4 }}>
|
||||||
<Box sx={{ mb: 2 }}>{logo}</Box>
|
<Box sx={{ mb: 2 }}>{logo}</Box>
|
||||||
{tagline && (
|
{tagline && (
|
||||||
<Typography
|
<Typography
|
||||||
@@ -157,10 +157,7 @@ export const Footer = React.forwardRef<HTMLDivElement, FooterProps>(
|
|||||||
{/* Link group columns */}
|
{/* Link group columns */}
|
||||||
{linkGroups.map((group) => (
|
{linkGroups.map((group) => (
|
||||||
<Grid
|
<Grid
|
||||||
item
|
size={{ xs: 6, sm: 4, md: 'grow' }}
|
||||||
xs={6}
|
|
||||||
sm={4}
|
|
||||||
md
|
|
||||||
key={group.heading}
|
key={group.heading}
|
||||||
component="nav"
|
component="nav"
|
||||||
aria-label={group.heading}
|
aria-label={group.heading}
|
||||||
|
|||||||
@@ -2,8 +2,7 @@ import { useState } from 'react';
|
|||||||
import type { Meta, StoryObj } from '@storybook/react';
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { ProviderMap } from './ProviderMap';
|
import { ProviderMap } from './ProviderMap';
|
||||||
import { providers as demoProviders } from '../../../demo/shared/fixtures/providers';
|
import { providers } from '../../../fixtures/providers';
|
||||||
import type { ProviderData } from '../../pages/ProvidersStep';
|
|
||||||
|
|
||||||
const meta: Meta<typeof ProviderMap> = {
|
const meta: Meta<typeof ProviderMap> = {
|
||||||
title: 'Organisms/ProviderMap',
|
title: 'Organisms/ProviderMap',
|
||||||
@@ -29,9 +28,6 @@ const meta: Meta<typeof ProviderMap> = {
|
|||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof ProviderMap>;
|
type Story = StoryObj<typeof ProviderMap>;
|
||||||
|
|
||||||
// Cast: DemoProvider adds `tier` over ProviderData, structural subset for the map
|
|
||||||
const providers = demoProviders as ProviderData[];
|
|
||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/** All 7 demo providers with real NSW/QLD coordinates. Map fits bounds across them. */
|
/** All 7 demo providers with real NSW/QLD coordinates. Map fits bounds across them. */
|
||||||
|
|||||||
94
src/fixtures/providers.ts
Normal file
94
src/fixtures/providers.ts
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import type { ProviderData } from '../components/pages/ProvidersStep';
|
||||||
|
import { assetUrl } from '../utils/assetUrl';
|
||||||
|
|
||||||
|
export const providers: ProviderData[] = [
|
||||||
|
{
|
||||||
|
id: 'parsons',
|
||||||
|
name: 'H.Parsons Funeral Directors',
|
||||||
|
location: 'Wentworth, NSW',
|
||||||
|
verified: true,
|
||||||
|
imageUrl: assetUrl('/images/venues/hparsons-funeral-home-wollongong/01.jpg'),
|
||||||
|
logoUrl: assetUrl('/images/providers/hparsons-funeral-directors/logo.png'),
|
||||||
|
rating: 4.6,
|
||||||
|
reviewCount: 7,
|
||||||
|
startingPrice: 1800,
|
||||||
|
distanceKm: 2.3,
|
||||||
|
coords: { lat: -34.1074, lng: 141.9166 },
|
||||||
|
description:
|
||||||
|
'H.Parsons delivers premium funeral services with exceptional care and support, guiding families through every step with empathy and expertise.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'rankins',
|
||||||
|
name: 'Rankins Funeral Services',
|
||||||
|
location: 'Wollongong, NSW',
|
||||||
|
verified: true,
|
||||||
|
imageUrl: assetUrl('/images/venues/rankins-funeral-home-warrawong/01.jpg'),
|
||||||
|
logoUrl: assetUrl('/images/providers/rankins-funerals/logo.png'),
|
||||||
|
rating: 4.8,
|
||||||
|
reviewCount: 23,
|
||||||
|
startingPrice: 2450,
|
||||||
|
distanceKm: 5.1,
|
||||||
|
coords: { lat: -34.487, lng: 150.897 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'wollongong-city',
|
||||||
|
name: 'Wollongong City Funerals',
|
||||||
|
location: 'Wollongong, NSW',
|
||||||
|
verified: false,
|
||||||
|
rating: 4.2,
|
||||||
|
reviewCount: 15,
|
||||||
|
startingPrice: 3400,
|
||||||
|
distanceKm: 6.8,
|
||||||
|
coords: { lat: -34.4278, lng: 150.8931 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'killick',
|
||||||
|
name: 'Killick Family Funerals',
|
||||||
|
location: 'Kingaroy, QLD',
|
||||||
|
verified: true,
|
||||||
|
imageUrl: assetUrl('/images/venues/killick-family-funerals-chapel-kingaroy/01.jpg'),
|
||||||
|
logoUrl: assetUrl('/images/providers/killick-family-funerals/logo.png'),
|
||||||
|
rating: 4.9,
|
||||||
|
reviewCount: 15,
|
||||||
|
startingPrice: 3100,
|
||||||
|
distanceKm: 8.4,
|
||||||
|
coords: { lat: -26.5408, lng: 151.8388 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'mackay',
|
||||||
|
name: 'Mackay Family Funeral Directors',
|
||||||
|
location: 'Ourimbah, NSW',
|
||||||
|
verified: true,
|
||||||
|
imageUrl: assetUrl('/images/venues/mackay-family-garden-estate/01.jpg'),
|
||||||
|
logoUrl: assetUrl('/images/providers/mackay-family-funerals/logo.webp'),
|
||||||
|
rating: 4.6,
|
||||||
|
reviewCount: 87,
|
||||||
|
startingPrice: 2800,
|
||||||
|
distanceKm: 18.2,
|
||||||
|
coords: { lat: -33.3644, lng: 151.3728 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'mannings',
|
||||||
|
name: 'Mannings Funerals',
|
||||||
|
location: 'Bega, NSW',
|
||||||
|
verified: true,
|
||||||
|
imageUrl: assetUrl('/images/venues/mannings-chapel/01.jpg'),
|
||||||
|
logoUrl: assetUrl('/images/providers/mannings-funerals/logo.png'),
|
||||||
|
rating: 4.7,
|
||||||
|
reviewCount: 31,
|
||||||
|
startingPrice: 2600,
|
||||||
|
distanceKm: 22.0,
|
||||||
|
coords: { lat: -36.6742, lng: 149.8417 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'botanical',
|
||||||
|
name: 'Botanical Funerals',
|
||||||
|
location: 'Newtown, NSW',
|
||||||
|
verified: false,
|
||||||
|
rating: 4.9,
|
||||||
|
reviewCount: 8,
|
||||||
|
startingPrice: 5200,
|
||||||
|
distanceKm: 15.0,
|
||||||
|
coords: { lat: -33.8988, lng: 151.1794 },
|
||||||
|
},
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user