diff --git a/packages/ui/.gitignore b/packages/ui/.gitignore new file mode 100644 index 0000000..2068747 --- /dev/null +++ b/packages/ui/.gitignore @@ -0,0 +1 @@ +storybook-static diff --git a/packages/ui/.storybook/main.ts b/packages/ui/.storybook/main.ts new file mode 100644 index 0000000..5de8877 --- /dev/null +++ b/packages/ui/.storybook/main.ts @@ -0,0 +1,75 @@ +import type { StorybookConfig } from "@storybook/react-webpack5"; + +import { dirname, join, resolve } from "node:path"; + +// ? for monorepo support +function getAbsolutePath(value: string): string { + return dirname(require.resolve(join(value, "package.json"))); +} + +// ? https://github.com/storybookjs/addon-react-native-web/issues/45 +export default { + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(ts|tsx)"], + addons: [ + getAbsolutePath("@storybook/addon-webpack5-compiler-babel"), + getAbsolutePath("@storybook/addon-onboarding"), + getAbsolutePath("@storybook/addon-essentials"), + getAbsolutePath("@chromatic-com/storybook"), + getAbsolutePath("@storybook/addon-interactions"), + { + name: getAbsolutePath("@storybook/addon-react-native-web"), + options: { + modulesToTranspile: [ + "react-native-reanimated", + "nativewind", + "react-native-css-interop", + ], + babelPresets: ["nativewind/babel"], + babelPresetReactOptions: { jsxImportSource: "nativewind" }, + babelPlugins: [ + "react-native-reanimated/plugin", + [ + "@babel/plugin-transform-react-jsx", + { + runtime: "automatic", + importSource: "nativewind", + }, + ], + ], + }, + }, + ], + framework: { + name: getAbsolutePath("@storybook/react-webpack5"), + options: { fastRefresh: true }, + }, + typescript: { + check: false, + checkOptions: {}, + }, + docs: { + autodocs: "tag", + }, + webpackFinal: (config) => { + if (config.module?.rules) { + config.module.rules.push({ + test: /\.css$/, + use: [ + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [require("tailwindcss"), require("autoprefixer")], + }, + }, + }, + ], + include: resolve(__dirname, "../"), + }); + } + + return { + ...config, + }; + }, +} satisfies StorybookConfig; diff --git a/packages/ui/.storybook/preview.ts b/packages/ui/.storybook/preview.ts new file mode 100644 index 0000000..e5f99ad --- /dev/null +++ b/packages/ui/.storybook/preview.ts @@ -0,0 +1,16 @@ +import type { Preview } from "@storybook/react"; + +import "../global.css"; + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + }, +}; + +export default preview; diff --git a/packages/ui/global.css b/packages/ui/global.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/packages/ui/global.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/packages/ui/nativewind-env.d.ts b/packages/ui/nativewind-env.d.ts new file mode 100644 index 0000000..a13e313 --- /dev/null +++ b/packages/ui/nativewind-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/packages/ui/package.json b/packages/ui/package.json index 2cd9636..974e1a6 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -9,14 +9,19 @@ }, "./*": { "types": "./dist/src/*.d.ts", - "default": ["./src/*.ts", "./src/*.tsx"] + "default": [ + "./src/*.ts", + "./src/*.tsx" + ] } }, "scripts": { "build": "tsc", + "build-storybook": "storybook build", "clean": "git clean -xdf .cache .turbo dist node_modules", "dev": "tsc", "lint": "biome lint --fix --unsafe --no-errors-on-unmatched", + "storybook": "storybook dev -p 6006", "type-check": "tsc --noEmit" }, "dependencies": { @@ -25,8 +30,24 @@ "tailwindcss": "catalog:" }, "devDependencies": { + "@babel/plugin-transform-react-jsx": "^7.25.9", "@biomejs/biome": "catalog:", + "@chromatic-com/storybook": "^3.2.2", "@infinite-loop-factory/config-typescript": "workspace:^", + "@storybook/addon-essentials": "^8.4.1", + "@storybook/addon-interactions": "^8.4.1", + "@storybook/addon-onboarding": "^8.4.1", + "@storybook/addon-react-native-web": "^0.0.26", + "@storybook/addon-webpack5-compiler-babel": "^3.0.3", + "@storybook/blocks": "^8.4.1", + "@storybook/react": "^8.4.1", + "@storybook/react-webpack5": "^8.4.1", + "@storybook/test": "^8.4.1", + "autoprefixer": "^10.4.20", + "postcss-loader": "^8.1.1", + "react-native-css-interop": "^0.1.20", + "react-native-reanimated": "^3.16.1", + "storybook": "^8.4.1", "type-fest": "catalog:", "typescript": "catalog:" } diff --git a/packages/ui/src/button/button.stories.tsx b/packages/ui/src/button/button.stories.tsx new file mode 100644 index 0000000..d382133 --- /dev/null +++ b/packages/ui/src/button/button.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { View } from "react-native"; +import MyButton from "./button"; + +const meta = { + title: "MyButton", + component: MyButton, + argTypes: { + onPress: { action: "pressed the button" }, + }, + args: { + title: "Hello world", + }, + decorators: [ + (Story) => ( + + + + ), + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Basic: Story = {}; + +export const AnotherExample: Story = { + args: { + title: "Another example", + }, +}; diff --git a/packages/ui/src/button/button.tsx b/packages/ui/src/button/button.tsx new file mode 100644 index 0000000..dd7d6b6 --- /dev/null +++ b/packages/ui/src/button/button.tsx @@ -0,0 +1,15 @@ +import { Text, TouchableOpacity } from "react-native"; + +export default function Button({ + title, + onPress, +}: { title: string; onPress?: () => void }) { + return ( + + {title} + + ); +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts deleted file mode 100644 index 3b39966..0000000 --- a/packages/ui/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function add(a: number, b: number) { - return a + b; -} diff --git a/packages/ui/tailwind.config.ts b/packages/ui/tailwind.config.ts new file mode 100644 index 0000000..43ac3ee --- /dev/null +++ b/packages/ui/tailwind.config.ts @@ -0,0 +1,10 @@ +import type { Config } from "tailwindcss"; + +// @ts-expect-error - no types +import nativewind from "nativewind/preset"; + +export default { + content: ["src/**/*.{js,jsx,ts,tsx}"], + presets: [nativewind], + plugins: [], +} satisfies Config; diff --git a/packages/ui/tsconfig.build.json b/packages/ui/tsconfig.build.json new file mode 100644 index 0000000..0f59732 --- /dev/null +++ b/packages/ui/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["**/*.stories.tsx", "node_modules"] +} diff --git a/packages/ui/tsconfig.json b/packages/ui/tsconfig.json index e37cda1..7215978 100644 --- a/packages/ui/tsconfig.json +++ b/packages/ui/tsconfig.json @@ -4,6 +4,6 @@ "jsx": "preserve", "lib": ["ES2022", "dom", "dom.iterable"] }, - "include": ["src"], + "include": ["src", "nativewind-env.d.ts"], "exclude": ["node_modules"] }