feat: add Storybook configuration and mocks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
17ec53e08f
commit
74ee154669
48
apps/portal/.storybook/main.ts
Normal file
48
apps/portal/.storybook/main.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import type { StorybookConfig } from "@storybook/react-vite";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import path from "path";
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ["../src/**/*.stories.@(ts|tsx)"],
|
||||
addons: ["@storybook/addon-essentials"],
|
||||
framework: {
|
||||
name: "@storybook/react-vite",
|
||||
options: {},
|
||||
},
|
||||
staticDirs: ["../public"],
|
||||
viteFinal: async config => {
|
||||
config.plugins = config.plugins || [];
|
||||
config.plugins.push(tailwindcss());
|
||||
|
||||
// Ensure JSX runtime is available (auto-imports React)
|
||||
config.esbuild = {
|
||||
...config.esbuild,
|
||||
jsx: "automatic",
|
||||
};
|
||||
|
||||
config.resolve = config.resolve || {};
|
||||
config.resolve.alias = {
|
||||
...config.resolve.alias,
|
||||
"@": path.resolve(__dirname, "../src"),
|
||||
"next/link": path.resolve(__dirname, "mocks/next-link.tsx"),
|
||||
"next/image": path.resolve(__dirname, "mocks/next-image.tsx"),
|
||||
"next/navigation": path.resolve(__dirname, "mocks/next-navigation.tsx"),
|
||||
};
|
||||
|
||||
// Disable PostCSS — @tailwindcss/vite handles CSS directly
|
||||
config.css = config.css || {};
|
||||
config.css.postcss = { plugins: [] };
|
||||
|
||||
// Polyfill process.env for Next.js code that uses it
|
||||
config.define = {
|
||||
...config.define,
|
||||
"process.env": JSON.stringify({
|
||||
NODE_ENV: "development",
|
||||
}),
|
||||
};
|
||||
|
||||
return config;
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
24
apps/portal/.storybook/mocks/next-image.tsx
Normal file
24
apps/portal/.storybook/mocks/next-image.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
interface ImageProps extends React.ImgHTMLAttributes<HTMLImageElement> {
|
||||
src: string;
|
||||
alt: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
fill?: boolean;
|
||||
priority?: boolean;
|
||||
}
|
||||
|
||||
const Image = ({ src, alt, width, height, fill, priority: _priority, ...props }: ImageProps) => (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
src={src}
|
||||
alt={alt}
|
||||
width={width}
|
||||
height={height}
|
||||
style={fill ? { objectFit: "cover", width: "100%", height: "100%" } : undefined}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export default Image;
|
||||
13
apps/portal/.storybook/mocks/next-link.tsx
Normal file
13
apps/portal/.storybook/mocks/next-link.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
const Link = React.forwardRef<
|
||||
HTMLAnchorElement,
|
||||
React.AnchorHTMLAttributes<HTMLAnchorElement> & { href: string }
|
||||
>(({ href, children, ...props }, ref) => (
|
||||
<a ref={ref} href={href} {...props}>
|
||||
{children}
|
||||
</a>
|
||||
));
|
||||
Link.displayName = "Link";
|
||||
|
||||
export default Link;
|
||||
30
apps/portal/.storybook/mocks/next-navigation.tsx
Normal file
30
apps/portal/.storybook/mocks/next-navigation.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
export function useRouter() {
|
||||
return {
|
||||
push: (url: string) => {
|
||||
window.location.hash = url;
|
||||
},
|
||||
replace: (url: string) => {
|
||||
window.location.hash = url;
|
||||
},
|
||||
back: () => {
|
||||
window.history.back();
|
||||
},
|
||||
forward: () => {
|
||||
window.history.forward();
|
||||
},
|
||||
refresh: () => {},
|
||||
prefetch: () => Promise.resolve(),
|
||||
};
|
||||
}
|
||||
|
||||
export function usePathname() {
|
||||
return "/";
|
||||
}
|
||||
|
||||
export function useSearchParams() {
|
||||
return new URLSearchParams();
|
||||
}
|
||||
|
||||
export function useParams() {
|
||||
return {};
|
||||
}
|
||||
18
apps/portal/.storybook/preview.ts
Normal file
18
apps/portal/.storybook/preview.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import type { Preview } from "@storybook/react";
|
||||
import "../src/app/globals.css";
|
||||
|
||||
const preview: Preview = {
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
backgrounds: {
|
||||
default: "light",
|
||||
values: [
|
||||
{ name: "light", value: "#f9f9f9" },
|
||||
{ name: "white", value: "#ffffff" },
|
||||
{ name: "dark", value: "#1a1a2e" },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default preview;
|
||||
Loading…
x
Reference in New Issue
Block a user