From b47c2e82b90b24842467109ad50dded1abd89498 Mon Sep 17 00:00:00 2001 From: behnam Date: Thu, 21 Nov 2024 19:52:49 +0300 Subject: [PATCH] Add storybook and base pallete mode --- .eslintrc.json | 39 +- .gitignore | 2 + .storybook/main.ts | 17 + .storybook/preview.tsx | 72 + docker-compose.yml | 1 - package.json | 15 +- .../client/theme-provider/theme-provider.tsx | 11 + src/app/[lang]/layout.tsx | 16 +- src/app/components/button/button.tsx | 1 + .../button/stories/Button.stories.tsx | 31 + .../view/storybook-base-template-type.ts | 5 + .../helpers/view/storybook-with-arg-vm.ts | 14 + yarn.lock | 3624 ++++++++++++++++- 13 files changed, 3770 insertions(+), 78 deletions(-) create mode 100644 .storybook/main.ts create mode 100644 .storybook/preview.tsx create mode 100644 src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx create mode 100644 src/app/components/button/stories/Button.stories.tsx create mode 100644 src/bootstrap/helpers/view/storybook-base-template-type.ts create mode 100644 src/bootstrap/helpers/view/storybook-with-arg-vm.ts diff --git a/.eslintrc.json b/.eslintrc.json index 6307415..4f0e6c5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,14 +5,19 @@ "src/**/*-vm.ts" ], "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": [ - "prettier" - ], - "settings": { + "settings": { "react": { "version": "detect" }, @@ -35,6 +40,16 @@ } } }, + "plugins": [ + "prettier" + ], + "extends": [ + "airbnb", + "next/core-web-vitals", + "next/typescript", + "prettier", + "plugin:storybook/recommended" + ], "rules": { "no-use-before-define": "off", "class-methods-use-this": "off", @@ -49,7 +64,7 @@ { "printWidth": 80, "tabWidth": 2, - "endOfLine":"auto", + "endOfLine": "auto", "useTabs": false, "semi": true, "singleQuote": false, @@ -85,11 +100,5 @@ "devDependencies": true } ] - }, - "extends": [ - "airbnb", - "next/core-web-vitals", - "next/typescript", - "prettier" - ] -} + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 39c19d2..a39f2a5 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +*storybook.log diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 0000000..3be7d13 --- /dev/null +++ b/.storybook/main.ts @@ -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; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx new file mode 100644 index 0000000..1daa757 --- /dev/null +++ b/.storybook/preview.tsx @@ -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, + leftKeys: string[], + value: unknown, +): Record => { + 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, + leftKeys, + value, + ); +}; + +const preview: Preview = { + decorators: [ + (Story, data) => { + const parsedProps = {} as Record; + 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 ( +
+ +
+ ); + }, + ], + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/docker-compose.yml b/docker-compose.yml index 9e2981f..189a656 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,7 +11,6 @@ services: POSTGRES_USER: admin POSTGRES_DB: nextbp - app: build: . ports: diff --git a/package.json b/package.json index ad7a6a0..20b92e2 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ "start": "next start --port 4000", "lint": "next lint --fix", "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": { "@heroicons/react": "^2.1.5", @@ -24,6 +26,7 @@ "lucide-react": "^0.454.0", "next": "15.0.2", "next-i18n-router": "^5.5.1", + "next-themes": "^0.4.3", "postgres": "^3.4.5", "react": "19.0.0-rc-69d4b800-20241021", "react-cookie": "^7.2.2", @@ -37,7 +40,15 @@ "zod": "^3.23.8" }, "devDependencies": { + "@chromatic-com/storybook": "^3.2.2", "@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/react": "^16.0.1", "@types/node": "^20", @@ -53,10 +64,12 @@ "eslint-import-resolver-alias": "^1.1.2", "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-storybook": "^0.11.1", "jsdom": "^25.0.1", "moq.ts": "^10.0.8", "postcss": "^8", "prettier": "^3.3.3", + "storybook": "^8.4.5", "tailwindcss": "^3.4.1", "typescript": "^5", "vitest": "^2.1.4" diff --git a/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx b/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx new file mode 100644 index 0000000..6a1ffe4 --- /dev/null +++ b/src/app/[lang]/dashboard/components/client/theme-provider/theme-provider.tsx @@ -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) { + return {children} +} diff --git a/src/app/[lang]/layout.tsx b/src/app/[lang]/layout.tsx index b142672..e192627 100644 --- a/src/app/[lang]/layout.tsx +++ b/src/app/[lang]/layout.tsx @@ -1,3 +1,4 @@ +import { ThemeProvider } from "@/app/[lang]/dashboard/components/client/theme-provider/theme-provider"; import { initI18next } from "@/bootstrap/i18n/i18n"; import TranslationsProvider from "@/bootstrap/i18n/i18n-provider"; import localFont from "next/font/local"; @@ -21,13 +22,20 @@ export default async function layout( const { lang } = await params; const { resources } = await initI18next({ lng: lang }); return ( - + - - {children} - + + + {children} + + ); diff --git a/src/app/components/button/button.tsx b/src/app/components/button/button.tsx index 5520728..d1f8224 100644 --- a/src/app/components/button/button.tsx +++ b/src/app/components/button/button.tsx @@ -59,6 +59,7 @@ export interface ButtonProps const ButtonUi = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { const Comp = asChild ? Slot : "button"; + console.log('is disabled', props); return ( { + const vm = getArgVM(globalData.parsedProps.vm)// You can use parsed props to access your vm properties. + return