Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ dist
# TypeDoc generated docs (auto-generated during build)
site/typedoc

# Storybook build output
storybook-static
site/public/storybook

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
"check": "biome check --write",
"check:types": "pnpm build && pnpm run --r --parallel check:types && tsc --noEmit",
"clean": "pnpm run --r --parallel clean",
"storybook": "pnpm --filter @mbga/kit storybook",
"storybook:build": "pnpm --filter @mbga/kit storybook:build",
"docs:typedoc": "typedoc",
"docs:dev": "pnpm --filter site dev",
"docs:build": "pnpm --filter site build",
"docs:dev": "pnpm storybook:build && rm -rf site/public/storybook && cp -r packages/kit/storybook-static site/public/storybook && pnpm --filter site dev",
"docs:build": "pnpm storybook:build && rm -rf site/public/storybook && cp -r packages/kit/storybook-static site/public/storybook && pnpm --filter site build",
"docs:preview": "pnpm --filter site preview",
"format": "biome format --write",
"test": "vitest",
Expand Down
8 changes: 8 additions & 0 deletions packages/kit/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { StorybookConfig } from 'storybook'

const config: StorybookConfig = {
stories: ['../src/**/*.stories.tsx'],
framework: '@storybook/react-vite',
}

export default config
28 changes: 28 additions & 0 deletions packages/kit/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Preview } from 'storybook'
import { withProviders } from '../src/__stories__/decorators'

const preview: Preview = {
decorators: [withProviders],
parameters: {
layout: 'centered',
},
globalTypes: {
theme: {
description: 'Kit theme',
toolbar: {
title: 'Theme',
icon: 'paintbrush',
items: [
{ value: 'light', title: 'Light', icon: 'sun' },
{ value: 'dark', title: 'Dark', icon: 'moon' },
],
dynamicTitle: true,
},
},
},
initialGlobals: {
theme: 'light',
},
}

export default preview
11 changes: 9 additions & 2 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
},
"scripts": {
"build": "tsup",
"storybook": "storybook dev -p 6006",
"storybook:build": "storybook build -o storybook-static",
"check:types": "tsc --noEmit",
"check:publint": "publint",
"check:attw": "attw --pack .",
Expand All @@ -21,7 +23,10 @@
"src/**/*.tsx",
"!src/**/*.test.ts",
"!src/**/*.test.tsx",
"!src/**/*.test-d.ts"
"!src/**/*.test-d.ts",
"!src/**/*.stories.ts",
"!src/**/*.stories.tsx",
"!src/__stories__"
],
"sideEffects": false,
"type": "module",
Expand Down Expand Up @@ -75,13 +80,15 @@
},
"devDependencies": {
"@mbga/test": "workspace:*",
"@storybook/react-vite": "^10.3.4",
"@tanstack/react-query": "^5.49.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/react": "^16.3.2",
"@types/react": "^19.2.0",
"@types/react-dom": "^19.2.0",
"react": "^19.2.0",
"react-dom": "^19.2.0"
"react-dom": "^19.2.0",
"storybook": "^10.3.4"
},
"keywords": [
"mbga",
Expand Down
31 changes: 31 additions & 0 deletions packages/kit/src/__stories__/decorators.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { createConfig, sparkMainnet } from '@mbga/core'
import { mock } from '@mbga/test'
import { MbgaProvider } from 'mbga'
import type { Decorator } from 'storybook'
import { KitProvider } from '../components/KitProvider'

function createMockConfig() {
return createConfig({
network: sparkMainnet,
connectors: [
mock({
accounts: ['sp1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx'],
balance: 2_100_000n,
}),
],
storage: null,
})
}

export const withProviders: Decorator = (Story, context) => {
const theme = (context.globals.theme as 'light' | 'dark') ?? 'light'
const config = createMockConfig()

return (
<MbgaProvider config={config}>
<KitProvider theme={theme}>
<Story />
</KitProvider>
</MbgaProvider>
)
}
37 changes: 37 additions & 0 deletions packages/kit/src/components/AccountModal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { connect } from '@mbga/core'
import { useConfig } from 'mbga'
import { useEffect, useState } from 'react'
import type { Meta, StoryObj } from 'storybook'
import { useKitContext } from '../context'
import { AccountModal } from './AccountModal'

function AccountModalOpener() {
const config = useConfig()
const { openModal } = useKitContext()
const [ready, setReady] = useState(false)

useEffect(() => {
connect(config, { connector: config.connectors[0]! }).then(() => {
setReady(true)
openModal('account')
})
}, [config, openModal])

if (!ready) return <div>Connecting...</div>
return <AccountModal />
}

const meta = {
title: 'Components/AccountModal',
component: AccountModal,
parameters: {
layout: 'fullscreen',
},
} satisfies Meta<typeof AccountModal>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
render: () => <AccountModalOpener />,
}
66 changes: 66 additions & 0 deletions packages/kit/src/components/ConnectButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { connect } from '@mbga/core'
import { useConfig } from 'mbga'
import { useEffect, useState } from 'react'
import type { Meta, StoryObj } from 'storybook'
import { ConnectButton } from './ConnectButton'

const meta = {
title: 'Components/ConnectButton',
component: ConnectButton,
} satisfies Meta<typeof ConnectButton>

export default meta
type Story = StoryObj<typeof meta>

export const Disconnected: Story = {}

export const CustomLabel: Story = {
args: {
label: 'Link Wallet',
},
}

function ConnectedWrapper() {
const config = useConfig()
const [ready, setReady] = useState(false)

useEffect(() => {
connect(config, { connector: config.connectors[0]! }).then(() =>
setReady(true),
)
}, [config])

if (!ready) return <div>Connecting...</div>
return <ConnectButton />
}

export const Connected: Story = {
render: () => <ConnectedWrapper />,
}

function CustomRenderPropWrapper() {
return (
<ConnectButton.Custom>
{({ isConnected, show, truncatedAddress }) => (
<button
type="button"
onClick={show}
style={{
padding: '10px 20px',
background: '#f7931a',
color: '#fff',
border: 'none',
borderRadius: '8px',
cursor: 'pointer',
}}
>
{isConnected ? truncatedAddress : 'Custom Connect'}
</button>
)}
</ConnectButton.Custom>
)
}

export const CustomRenderProp: Story = {
render: () => <CustomRenderPropWrapper />,
}
27 changes: 27 additions & 0 deletions packages/kit/src/components/ConnectModal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useEffect } from 'react'
import type { Meta, StoryObj } from 'storybook'
import { useKitContext } from '../context'
import { ConnectModal } from './ConnectModal'

function ConnectModalOpener() {
const { openModal } = useKitContext()
useEffect(() => {
openModal('connect')
}, [openModal])
return <ConnectModal />
}

const meta = {
title: 'Components/ConnectModal',
component: ConnectModal,
parameters: {
layout: 'fullscreen',
},
} satisfies Meta<typeof ConnectModal>

export default meta
type Story = StoryObj<typeof meta>

export const Default: Story = {
render: () => <ConnectModalOpener />,
}
1 change: 1 addition & 0 deletions packages/kit/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.json",
"include": ["src/**/*.ts", "src/**/*.tsx"],
"exclude": ["src/**/*.stories.ts", "src/**/*.stories.tsx", "src/__stories__"],
"compilerOptions": {
"composite": true,
"rootDir": "src",
Expand Down
Loading
Loading