Skip to content

Commit

Permalink
Add Storybook for SDK (thirdweb-dev#4230)
Browse files Browse the repository at this point in the history
## Problem solved

Short description of the bug fixed or feature added

<!-- start pr-codex -->

---

## PR-Codex overview
The focus of this PR is to add Storybook configuration, update dependencies, and improve story components.

### Detailed summary
- Added Storybook configuration for `storybook` and `build-storybook`
- Updated dependencies for Storybook addons and Vite
- Improved story components for `ConnectButton` and `PayEmbed`
- Defined absolute paths in Storybook config for addons
- Added global CSS styling for Storybook preview
- Created utility functions for story client and wallet adapter

> The following files were skipped due to too many changes: `pnpm-lock.yaml`

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
  • Loading branch information
MananTank committed Aug 22, 2024
1 parent 01dd80f commit 55bf1ad
Show file tree
Hide file tree
Showing 13 changed files with 1,565 additions and 67 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"preinstall": "npx only-allow pnpm",
"lint": "pnpm dlx sherif@latest -i @tanstack/react-query -i @coinbase/wallet-sdk -i remark-gfm && turbo run lint",
"lint:legacy": "pnpm lint",
"storybook:react": "turbo run storybook --filter=./packages/*",
"fix": "pnpm dlx sherif@latest -i @tanstack/react-query -i @coinbase/wallet-sdk -i remark-gfm --fix && turbo run fix",
"wallet-ui": "turbo run dev --filter=./apps/wallet-ui --filter=./packages/thirdweb",
"wallet-ui:build": "turbo run build --filter=./apps/wallet-ui --filter=./packages/thirdweb",
Expand Down
8 changes: 8 additions & 0 deletions packages/thirdweb/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# copy this file to .env in the same directory and fill in the values
# Note: Adding new env also requires defining it in vite.config.ts file

# required
STORYBOOK_CLIENT_ID=

# optional - for testing using a specific account
STORYBOOK_ACCOUNT_PRIVATE_KEY=
3 changes: 2 additions & 1 deletion packages/thirdweb/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist/
coverage/
.watchmanconfig
.watchmanconfig
*storybook.log
12 changes: 12 additions & 0 deletions packages/thirdweb/.storybook/global.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** I
IMPORTANT: Do not add tailwind or any global CSS here - so that we can test the components properly without any interference.
*/

@import url("https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap");

body {
font-family: "Inter", sans-serif;
font-optical-sizing: auto;
font-variation-settings: "slnt" 0;
}
27 changes: 27 additions & 0 deletions packages/thirdweb/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { dirname, join } from "node:path";
import type { StorybookConfig } from "@storybook/react-vite";

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/

// biome-ignore lint/suspicious/noExplicitAny: <explanation>
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, "package.json")));
}
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
getAbsolutePath("@storybook/addon-onboarding"),
getAbsolutePath("@storybook/addon-links"),
getAbsolutePath("@storybook/addon-essentials"),
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-interactions"),
],
framework: {
name: getAbsolutePath("@storybook/react-vite"),
options: {},
},
};
export default config;
26 changes: 26 additions & 0 deletions packages/thirdweb/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Preview } from "@storybook/react";
import React from "react";
import { ThirdwebProvider } from "../src/exports/react";
import "./global.css";

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [
(Story) => {
return (
<ThirdwebProvider>
<Story />
</ThirdwebProvider>
);
},
],
};

export default preview;
79 changes: 30 additions & 49 deletions packages/thirdweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,54 +117,22 @@
},
"typesVersions": {
"*": {
"adapters/*": [
"./dist/types/exports/adapters/*.d.ts"
],
"auth": [
"./dist/types/exports/auth.d.ts"
],
"chains": [
"./dist/types/exports/chains.d.ts"
],
"contract": [
"./dist/types/exports/contract.d.ts"
],
"deploys": [
"./dist/types/exports/deploys.d.ts"
],
"event": [
"./dist/types/exports/event.d.ts"
],
"extensions/*": [
"./dist/types/exports/extensions/*.d.ts"
],
"pay": [
"./dist/types/exports/pay.d.ts"
],
"react": [
"./dist/types/exports/react.d.ts"
],
"react-native": [
"./dist/types/exports/react-native.d.ts"
],
"rpc": [
"./dist/types/exports/rpc.d.ts"
],
"storage": [
"./dist/types/exports/storage.d.ts"
],
"transaction": [
"./dist/types/exports/transaction.d.ts"
],
"utils": [
"./dist/types/exports/utils.d.ts"
],
"wallets": [
"./dist/types/exports/wallets.d.ts"
],
"wallets/*": [
"./dist/types/exports/wallets/*.d.ts"
]
"adapters/*": ["./dist/types/exports/adapters/*.d.ts"],
"auth": ["./dist/types/exports/auth.d.ts"],
"chains": ["./dist/types/exports/chains.d.ts"],
"contract": ["./dist/types/exports/contract.d.ts"],
"deploys": ["./dist/types/exports/deploys.d.ts"],
"event": ["./dist/types/exports/event.d.ts"],
"extensions/*": ["./dist/types/exports/extensions/*.d.ts"],
"pay": ["./dist/types/exports/pay.d.ts"],
"react": ["./dist/types/exports/react.d.ts"],
"react-native": ["./dist/types/exports/react-native.d.ts"],
"rpc": ["./dist/types/exports/rpc.d.ts"],
"storage": ["./dist/types/exports/storage.d.ts"],
"transaction": ["./dist/types/exports/transaction.d.ts"],
"utils": ["./dist/types/exports/utils.d.ts"],
"wallets": ["./dist/types/exports/wallets.d.ts"],
"wallets/*": ["./dist/types/exports/wallets/*.d.ts"]
}
},
"browser": {
Expand Down Expand Up @@ -302,17 +270,28 @@
"test:dev": "vitest run -c ./test/vitest.config.ts",
"test:react": "vitest run -c ./test/vitest.config.ts dev --ui src/react",
"typedoc": "bun run scripts/typedoc.mjs",
"update-version": "node scripts/version.mjs"
"update-version": "node scripts/version.mjs",
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"engines": {
"node": ">=18"
},
"devDependencies": {
"@aws-sdk/client-lambda": "3.577.0",
"@aws-sdk/credential-providers": "3.577.0",
"@chromatic-com/storybook": "^1.5.0",
"@coinbase/wallet-mobile-sdk": "1.0.13",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-clipboard/clipboard": "1.14.1",
"@storybook/addon-essentials": "^8.2.9",
"@storybook/addon-interactions": "^8.2.9",
"@storybook/addon-links": "^8.2.9",
"@storybook/addon-onboarding": "^8.2.9",
"@storybook/blocks": "^8.2.9",
"@storybook/react": "^8.2.9",
"@storybook/react-vite": "^8.2.9",
"@storybook/test": "^8.2.9",
"@testing-library/jest-dom": "^6.4.7",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2",
Expand All @@ -333,6 +312,8 @@
"react-native-quick-crypto": "0.7.0-rc.6",
"react-native-svg": "15.3.0",
"typescript": "5.5.4",
"storybook": "^8.2.9",
"vite": "^5.3.1",
"vitest": "1.6.0"
}
}
31 changes: 31 additions & 0 deletions packages/thirdweb/src/stories/ConnectButton.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Meta, StoryObj } from "@storybook/react";
import { ConnectButton } from "../react/web/ui/ConnectWallet/ConnectButton.js";
import { storyClient } from "./utils.js";

const meta = {
title: "Connect/ConnectButton",
component: ConnectButton,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
args: {
client: storyClient,
},
} satisfies Meta<typeof ConnectButton>;

type Story = StoryObj<typeof meta>;

export const Dark: Story = {
args: {
theme: "dark",
},
};

export const Light: Story = {
args: {
theme: "light",
},
};

export default meta;
42 changes: 42 additions & 0 deletions packages/thirdweb/src/stories/PayEmbed.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { Meta, StoryObj } from "@storybook/react";
import { PayEmbed } from "../react/web/ui/PayEmbed.js";
import { storyClient } from "./utils.js";

const meta = {
title: "Connect/PayEmbed",
component: PayEmbed,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
args: {
client: storyClient,
},
} satisfies Meta<typeof PayEmbed>;

type Story = StoryObj<typeof meta>;

export const Dark: Story = {
args: {
theme: "dark",
},
};

export const FiatTestMode: Story = {
args: {
theme: "dark",
payOptions: {
buyWithFiat: {
testMode: true,
},
},
},
};

export const Light: Story = {
args: {
theme: "light",
},
};

export default meta;
29 changes: 29 additions & 0 deletions packages/thirdweb/src/stories/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { generatePrivateKey } from "viem/accounts";
import { createWalletAdapter } from "../adapters/wallet-adapter.js";
import { ethereum } from "../chains/chain-definitions/ethereum.js";
import { createThirdwebClient } from "../client/client.js";
import type { Account } from "../wallets/interfaces/wallet.js";
import { privateKeyToAccount } from "../wallets/private-key.js";

const clientId = process.env.STORYBOOK_CLIENT_ID;

if (!clientId) {
throw new Error("STORYBOOK_CLIENT_ID env is not configured");
}

export const storyClient = createThirdwebClient({
clientId: clientId,
});

export const storyAccount: Account = privateKeyToAccount({
client: storyClient,
privateKey: process.env.STORYBOOK_ACCOUNT_PRIVATE_KEY || generatePrivateKey(),
});

export const storyWallet = createWalletAdapter({
adaptedAccount: storyAccount,
client: storyClient,
chain: ethereum,
onDisconnect: () => {},
switchChain: () => {},
});
23 changes: 23 additions & 0 deletions packages/thirdweb/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";

// This config is required for storybook HMR

const quotesIfString = (value: string | undefined) => {
if (value === undefined) {
return undefined;
}
return `"${value}"`;
};

export default defineConfig({
plugins: [react()],
define: {
"process.env.STORYBOOK_CLIENT_ID": quotesIfString(
process.env.STORYBOOK_CLIENT_ID,
),
"process.env.STORYBOOK_ACCOUNT_PRIVATE_KEY": quotesIfString(
process.env.STORYBOOK_ACCOUNT_PRIVATE_KEY,
),
},
});
Loading

0 comments on commit 55bf1ad

Please sign in to comment.