feature/storybook #2

Merged
behnam merged 7 commits from feature/storybook into develop 2024-11-26 15:42:17 +00:00
13 changed files with 3770 additions and 78 deletions
Showing only changes of commit b47c2e82b9 - Show all commits

View File

@ -5,14 +5,19 @@
"src/**/*-vm.ts" "src/**/*-vm.ts"
], ],
"rules": { "rules": {
"react-hooks/rules-of-hooks": "off" "react-hooks/rules-of-hooks": "off"
} }
} },
{
"files": [
"src/app/**/*.stories.tsx"
],
"rules": {
"react/jsx-props-no-spreading": "off"
}
},
], ],
"plugins": [ "settings": {
"prettier"
],
"settings": {
"react": { "react": {
"version": "detect" "version": "detect"
}, },
@ -35,6 +40,16 @@
} }
} }
}, },
"plugins": [
"prettier"
],
"extends": [
"airbnb",
"next/core-web-vitals",
"next/typescript",
"prettier",
"plugin:storybook/recommended"
],
"rules": { "rules": {
"no-use-before-define": "off", "no-use-before-define": "off",
"class-methods-use-this": "off", "class-methods-use-this": "off",
@ -49,7 +64,7 @@
{ {
"printWidth": 80, "printWidth": 80,
"tabWidth": 2, "tabWidth": 2,
"endOfLine":"auto", "endOfLine": "auto",
"useTabs": false, "useTabs": false,
"semi": true, "semi": true,
"singleQuote": false, "singleQuote": false,
@ -85,11 +100,5 @@
"devDependencies": true "devDependencies": true
} }
] ]
}, }
"extends": [
"airbnb",
"next/core-web-vitals",
"next/typescript",
"prettier"
]
} }

2
.gitignore vendored
View File

@ -38,3 +38,5 @@ yarn-error.log*
# typescript # typescript
*.tsbuildinfo *.tsbuildinfo
next-env.d.ts next-env.d.ts
*storybook.log

17
.storybook/main.ts Normal file
View File

@ -0,0 +1,17 @@
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
"@storybook/addon-onboarding",
"@storybook/addon-essentials",
"@chromatic-com/storybook",
"@storybook/addon-interactions",
],
framework: {
name: "@storybook/nextjs",
options: {},
},
staticDirs: ["../public"],
};
export default config;

72
.storybook/preview.tsx Normal file
View File

@ -0,0 +1,72 @@
import type { Preview } from "@storybook/react";
import React from "react";
import "../src/app/globals.css"
/**
*
* This function will expand the object with nested properties
* @param obj refrence Object to that
* @param leftKeys keys to be nested object keys
* @param value value to be nested
*
*/
export const recursiveNestedProps = (
obj: Record<string, unknown>,
leftKeys: string[],
value: unknown,
): Record<string, unknown> => {
if (leftKeys.length <= 0) return obj;
if (leftKeys.length === 1) {
// eslint-disable-next-line no-param-reassign
obj[leftKeys[0]] = value;
return obj;
}
const key = leftKeys.shift();
if (!key) return obj;
if (!obj[key]) {
// eslint-disable-next-line no-param-reassign
obj[key] = {};
}
return recursiveNestedProps(
obj[key] as Record<string, unknown>,
leftKeys,
value,
);
};
const preview: Preview = {
decorators: [
(Story, data) => {
const parsedProps = {} as Record<string, unknown>;
const props = data.allArgs;
Object.entries(props).forEach((prop) => {
const [key, value] = prop;
if (!key.includes("vm")) {
parsedProps[key] = value;
return;
}
const splitedKey = key.split(".");
recursiveNestedProps(parsedProps, splitedKey, value);
});
return (
<div>
<Story parsedProps={parsedProps} />
</div>
);
},
],
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;

View File

@ -11,7 +11,6 @@ services:
POSTGRES_USER: admin POSTGRES_USER: admin
POSTGRES_DB: nextbp POSTGRES_DB: nextbp
app: app:
build: . build: .
ports: ports:

View File

@ -8,7 +8,9 @@
"start": "next start --port 4000", "start": "next start --port 4000",
"lint": "next lint --fix", "lint": "next lint --fix",
"test": "vitest", "test": "vitest",
"seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js" "seed": "node -r dotenv/config ./src/bootstrap/boundaries/db/seed.js",
"storybook": "storybook dev -p 6006 --no-open",
"build-storybook": "storybook build"
}, },
"dependencies": { "dependencies": {
"@heroicons/react": "^2.1.5", "@heroicons/react": "^2.1.5",
@ -24,6 +26,7 @@
"lucide-react": "^0.454.0", "lucide-react": "^0.454.0",
"next": "15.0.2", "next": "15.0.2",
"next-i18n-router": "^5.5.1", "next-i18n-router": "^5.5.1",
"next-themes": "^0.4.3",
"postgres": "^3.4.5", "postgres": "^3.4.5",
"react": "19.0.0-rc-69d4b800-20241021", "react": "19.0.0-rc-69d4b800-20241021",
"react-cookie": "^7.2.2", "react-cookie": "^7.2.2",
@ -37,7 +40,15 @@
"zod": "^3.23.8" "zod": "^3.23.8"
}, },
"devDependencies": { "devDependencies": {
"@chromatic-com/storybook": "^3.2.2",
"@faker-js/faker": "^9.1.0", "@faker-js/faker": "^9.1.0",
"@storybook/addon-essentials": "^8.4.5",
"@storybook/addon-interactions": "^8.4.5",
"@storybook/addon-onboarding": "^8.4.5",
"@storybook/blocks": "^8.4.5",
"@storybook/nextjs": "^8.4.5",
"@storybook/react": "^8.4.5",
"@storybook/test": "^8.4.5",
"@testing-library/dom": "^10.4.0", "@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.0.1", "@testing-library/react": "^16.0.1",
"@types/node": "^20", "@types/node": "^20",
@ -53,10 +64,12 @@
"eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-alias": "^1.1.2",
"eslint-import-resolver-typescript": "^3.6.3", "eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-prettier": "^5.2.1", "eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-storybook": "^0.11.1",
"jsdom": "^25.0.1", "jsdom": "^25.0.1",
"moq.ts": "^10.0.8", "moq.ts": "^10.0.8",
"postcss": "^8", "postcss": "^8",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"storybook": "^8.4.5",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5", "typescript": "^5",
"vitest": "^2.1.4" "vitest": "^2.1.4"

View File

@ -0,0 +1,11 @@
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
export function ThemeProvider({
children,
...props
}: React.ComponentProps<typeof NextThemesProvider>) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}

View File

@ -1,3 +1,4 @@
import { ThemeProvider } from "@/app/[lang]/dashboard/components/client/theme-provider/theme-provider";
import { initI18next } from "@/bootstrap/i18n/i18n"; import { initI18next } from "@/bootstrap/i18n/i18n";
import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider";
import localFont from "next/font/local"; import localFont from "next/font/local";
@ -21,13 +22,20 @@ export default async function layout(
const { lang } = await params; const { lang } = await params;
const { resources } = await initI18next({ lng: lang }); const { resources } = await initI18next({ lng: lang });
return ( return (
<html lang={lang}> <html lang={lang} suppressHydrationWarning>
<body <body
className={`${geistSans.variable} ${geistMono.variable} antialiased`} className={`${geistSans.variable} ${geistMono.variable} antialiased`}
> >
<TranslationsProvider lng={lang} resources={resources}> <ThemeProvider
{children} attribute="class"
</TranslationsProvider> defaultTheme="light"
enableSystem
disableTransitionOnChange
>
<TranslationsProvider lng={lang} resources={resources}>
{children}
</TranslationsProvider>
</ThemeProvider>
</body> </body>
</html> </html>
); );

View File

@ -59,6 +59,7 @@ export interface ButtonProps
const ButtonUi = React.forwardRef<HTMLButtonElement, ButtonProps>( const ButtonUi = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => { ({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"; const Comp = asChild ? Slot : "button";
console.log('is disabled', props);
return ( return (
<Comp <Comp
className={cn(buttonVariants({ variant, size, className }))} className={cn(buttonVariants({ variant, size, className }))}

View File

@ -0,0 +1,31 @@
import Button from "@/app/components/button/button";
import Story from "@/bootstrap/helpers/view/storybook-base-template-type";
import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm";
import type { Meta } from "@storybook/react";
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
const meta: Meta = {
title: "general/Button",
};
export default meta;
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
argTypes: {
"vm.props.isDisable": {
control: "boolean",
},
"vm.props.title": {
control: "text",
},
},
args: {
"vm.props.title": "Button",
"vm.props.isDisable": false,
},
render: (_props, globalData) => {
const vm = getArgVM(globalData.parsedProps.vm)// You can use parsed props to access your vm properties.
return <Button vm={vm} memoizedByVM={false} />
}
};

View File

@ -0,0 +1,5 @@
import { Meta, StoryObj } from "@storybook/react";
type Story = StoryObj<Meta>;
export default Story;

View File

@ -0,0 +1,14 @@
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
const getArgVM = <IVM>(vmObj: IVM) => {
class VM implements IBaseVM<IVM> {
useVM(): IVM {
return {
...vmObj,
};
}
}
return new VM();
};
export default getArgVM;

3624
yarn.lock

File diff suppressed because it is too large Load Diff