Skip to content

Commit a193606

Browse files
authored
feat(client): add Storybook with component stories (#256)
* feat(client): add Storybook with component stories - Set up Storybook with Vite and dark theme support - Add Chromatic CI workflow for visual regression testing - Create stories for 37+ UI components - Fix GameCard text color for cartridge preset compatibility - Exclude stories from production TypeScript build * feat(storybook): audit existing stories and add new component stories - Fix AssetPreview stories: add required 'order' prop (set to null) - Fix LeaderboardRow stories: migrate from react-router-dom MemoryRouter to @tanstack/react-router (matching the actual component) - Add Tooltip stories (Default, LongContent, WithIcon) - Add PositionCard stories (Default, NegativePnl, LargePosition, List) - Add PredictCard stories (Default, TiedScore, HighStakes, CardGrid) Skipped components with heavy provider dependencies: - achievement-card (useAnalytics/PostHog) - arcade-header (useDevice, useTheme, SidebarToggle) - tabs/sub-tabs (useDevice, useAnalytics) - price-footer (ListingWithUsd, erc20Metadata) - summary (useAnalytics via game-header) - CollectionHeader (useMarketplaceItemsViewModel, useShare) * fix: lint and format fixes for storybook stories * fix: format tooltip story
1 parent d2f420c commit a193606

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4819
-36
lines changed

.claude-modified-files

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
2+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/main.ts
3+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/preview.ts
4+
/Users/valentindosimont/www/c7e/arcade/client/package.json
5+
/Users/valentindosimont/www/c7e/arcade/turbo.json
6+
/Users/valentindosimont/www/c7e/arcade/.gitignore
7+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/button.stories.tsx
8+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/label.stories.tsx
9+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/floating-loading-spinner.stories.tsx
10+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/pagination.stories.tsx
11+
/Users/valentindosimont/www/c7e/arcade/.github/workflows/ci-chromatic.yml
12+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/main.ts
13+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/storybook.css
14+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/preview.ts
15+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/storybook.css
16+
/Users/valentindosimont/www/c7e/arcade/client/biome.json
17+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/carousel.stories.tsx
18+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/form.stories.tsx
19+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/tab.stories.tsx
20+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/sub-tab.stories.tsx
21+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/menu-button.stories.tsx
22+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/menu-item.stories.tsx
23+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/leaderboard-row.stories.tsx
24+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/leaderboard-username.stories.tsx
25+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/copy-address.stories.tsx
26+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/follow-tag.stories.tsx
27+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/player-label.stories.tsx
28+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/player-header.stories.tsx
29+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/search-input.stories.tsx
30+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-header.stories.tsx
31+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/link-item.stories.tsx
32+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-item.stories.tsx
33+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/index.stories.tsx
34+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/header.stories.tsx
35+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/footer.stories.tsx
36+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/preview.stories.tsx
37+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/filters/AttributeSearch.stories.tsx
38+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/filters/PropertyItem.stories.tsx
39+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/filters/OwnerFilterSection.stories.tsx
40+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/TokenProperties.stories.tsx
41+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/TokenTabs.stories.tsx
42+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/AssetPreview.stories.tsx
43+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
44+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/icons/index.stories.tsx
45+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-socials.stories.tsx
46+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/controller-action.stories.tsx
47+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-social.stories.tsx
48+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-actions.stories.tsx
49+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
50+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
51+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
52+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
53+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
54+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/preview.tsx
55+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/mocks/project.ts
56+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/main.ts
57+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
58+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/preview.tsx
59+
/Users/valentindosimont/.claude/plans/dreamy-drifting-hippo.md
60+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/preview.ts
61+
/Users/valentindosimont/www/c7e/arcade/client/.storybook/main.ts
62+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
63+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
64+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
65+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
66+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
67+
/Users/valentindosimont/.claude/plans/zazzy-percolating-wreath.md
68+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
69+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
70+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/index.stories.tsx
71+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/AssetPreview.stories.tsx
72+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/AssetPreview.stories.tsx
73+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/header.stories.tsx
74+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/preview.stories.tsx
75+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/preview.stories.tsx
76+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/footer.stories.tsx
77+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-header.stories.tsx
78+
/Users/valentindosimont/.claude/plans/zazzy-percolating-wreath.md
79+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
80+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
81+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-header.stories.tsx
82+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/index.stories.tsx
83+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/preview.stories.tsx
84+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/preview.stories.tsx
85+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/header.stories.tsx
86+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/collectible-card/footer.stories.tsx
87+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/AssetPreview.stories.tsx
88+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/marketplace/token-detail/AssetPreview.stories.tsx
89+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
90+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/game-select.stories.tsx
91+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
92+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
93+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
94+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
95+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.tsx
96+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
97+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
98+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
99+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
100+
/Users/valentindosimont/.claude/plans/zazzy-percolating-wreath.md
101+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-actions.stories.tsx
102+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-actions.stories.tsx
103+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-actions.stories.tsx
104+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/modules/edition-actions.stories.tsx
105+
/Users/valentindosimont/.claude/plans/zazzy-percolating-wreath.md
106+
/Users/valentindosimont/www/c7e/arcade/.github/workflows/ci-chromatic.yml
107+
/Users/valentindosimont/www/c7e/arcade/.github/workflows/ci-chromatic.yml
108+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
109+
/Users/valentindosimont/www/c7e/arcade/client/src/components/ui/dashboard/GameCard.stories.tsx
110+
/Users/valentindosimont/www/c7e/arcade/client/tsconfig.app.json

.github/workflows/ci-chromatic.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
name: chromatic
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- 'client/**'
9+
- '.github/workflows/ci-chromatic.yml'
10+
pull_request:
11+
branches:
12+
- main
13+
paths:
14+
- 'client/**'
15+
- '.github/workflows/ci-chromatic.yml'
16+
17+
concurrency:
18+
group: chromatic-${{ github.event.pull_request.number || github.ref }}
19+
cancel-in-progress: true
20+
21+
jobs:
22+
chromatic:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- name: Check for Chromatic token
26+
id: check-token
27+
run: |
28+
if [ -z "${{ secrets.CHROMATIC_PROJECT_TOKEN }}" ]; then
29+
echo "has_token=false" >> $GITHUB_OUTPUT
30+
echo "⚠️ CHROMATIC_PROJECT_TOKEN not configured. Skipping Chromatic."
31+
else
32+
echo "has_token=true" >> $GITHUB_OUTPUT
33+
fi
34+
35+
- uses: actions/checkout@v4
36+
if: steps.check-token.outputs.has_token == 'true'
37+
with:
38+
fetch-depth: 0
39+
40+
- uses: pnpm/action-setup@v4
41+
if: steps.check-token.outputs.has_token == 'true'
42+
with:
43+
version: 10.5.2
44+
45+
- uses: actions/setup-node@v4
46+
if: steps.check-token.outputs.has_token == 'true'
47+
with:
48+
node-version: 20
49+
cache: "pnpm"
50+
51+
- name: Cache turbo
52+
if: steps.check-token.outputs.has_token == 'true'
53+
uses: actions/cache@v4
54+
with:
55+
path: .turbo
56+
key: ${{ runner.os }}-turbo-chromatic-${{ github.sha }}
57+
restore-keys: |
58+
${{ runner.os }}-turbo-chromatic-
59+
${{ runner.os }}-turbo-
60+
61+
- name: Install dependencies
62+
if: steps.check-token.outputs.has_token == 'true'
63+
run: pnpm install --frozen-lockfile --ignore-scripts
64+
65+
- name: Build dependencies
66+
if: steps.check-token.outputs.has_token == 'true'
67+
run: pnpm turbo run build:deps --filter=@cartridge/client
68+
69+
- name: Publish to Chromatic
70+
if: steps.check-token.outputs.has_token == 'true'
71+
uses: chromaui/action@latest
72+
with:
73+
workingDir: client
74+
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
75+
onlyChanged: true
76+
autoAcceptChanges: ${{ github.ref == 'refs/heads/main' }}
77+
exitZeroOnChanges: ${{ github.event_name == 'pull_request' }}
78+
exitOnceUploaded: true
79+
skip: ${{ contains(github.event.head_commit.message, '[skip ci]') }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@ vite.config.ts.*
1515
.rules
1616
.DS_Store
1717
packages/*/tsup.config.bundled_*.mjs
18+
19+
# Storybook
20+
storybook-static/
21+
*storybook.log
1822
client/storybook-static/
1923
.claude-modified-files

client/.storybook/main.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// This file has been automatically migrated to valid ESM format by Storybook.
2+
import type { StorybookConfig } from "@storybook/react-vite";
3+
import { mergeConfig } from "vite";
4+
import { resolve, dirname } from "node:path";
5+
import { fileURLToPath } from "node:url";
6+
7+
const __filename = fileURLToPath(import.meta.url);
8+
9+
const __dirname = fileURLToPath(new URL(".", import.meta.url));
10+
11+
const config: StorybookConfig = {
12+
stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
13+
14+
addons: [
15+
getAbsolutePath("@storybook/addon-links"),
16+
getAbsolutePath("@storybook/addon-themes"),
17+
getAbsolutePath("@storybook/addon-docs")
18+
],
19+
20+
framework: {
21+
name: getAbsolutePath("@storybook/react-vite"),
22+
options: {},
23+
},
24+
25+
staticDirs: ["../public"],
26+
27+
viteFinal: async (config) => {
28+
const filteredPlugins = (config.plugins || []).filter((plugin) => {
29+
if (!plugin) return false;
30+
const pluginName = Array.isArray(plugin) ? undefined : (plugin as { name?: string }).name;
31+
return pluginName !== "vite-plugin-pwa:build" && pluginName !== "vite-plugin-pwa:dev";
32+
});
33+
34+
return mergeConfig(
35+
{ ...config, plugins: filteredPlugins },
36+
{
37+
resolve: {
38+
alias: {
39+
"@": resolve(__dirname, "../src"),
40+
},
41+
},
42+
optimizeDeps: {
43+
include: ["@cartridge/ui"],
44+
exclude: ["@dojoengine/torii-wasm"],
45+
},
46+
define: {
47+
__COMMIT_SHA__: JSON.stringify("storybook"),
48+
},
49+
}
50+
);
51+
},
52+
53+
typescript: {
54+
check: false,
55+
reactDocgen: "react-docgen-typescript",
56+
reactDocgenTypescriptOptions: {
57+
shouldExtractLiteralValuesFromEnum: true,
58+
propFilter: (prop) =>
59+
prop.parent ? !/node_modules/.test(prop.parent.fileName) : true,
60+
},
61+
}
62+
};
63+
64+
export default config;
65+
66+
function getAbsolutePath(value: string): any {
67+
return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`)));
68+
}

client/.storybook/preview.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import type { Preview } from "@storybook/react-vite";
2+
import { withThemeByClassName } from "@storybook/addon-themes";
3+
4+
import "./storybook.css";
5+
6+
const preview: Preview = {
7+
parameters: {
8+
controls: {
9+
matchers: {
10+
color: /(background|color)$/i,
11+
date: /Date$/i,
12+
},
13+
},
14+
backgrounds: {
15+
options: {
16+
dark: { name: "dark", value: "#161A17" },
17+
light: { name: "light", value: "#ffffff" }
18+
}
19+
},
20+
layout: "centered",
21+
},
22+
23+
decorators: [
24+
withThemeByClassName({
25+
themes: {
26+
light: "",
27+
dark: "dark",
28+
},
29+
defaultTheme: "dark",
30+
}),
31+
],
32+
33+
tags: ["autodocs"],
34+
35+
initialGlobals: {
36+
backgrounds: {
37+
value: "dark"
38+
}
39+
}
40+
};
41+
42+
export default preview;

client/.storybook/storybook.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@import "@cartridge/ui/themes/default.css";
2+
@import "@cartridge/ui/themes/dark.css";
3+
@import "@cartridge/ui/themes/fonts.css";
4+
5+
@tailwind base;
6+
@tailwind components;
7+
@tailwind utilities;
8+
9+
@layer base {
10+
:root {
11+
--chart-1: 12 76% 61%;
12+
--chart-2: 173 58% 39%;
13+
--chart-3: 197 37% 24%;
14+
--chart-4: 43 74% 66%;
15+
--chart-5: 27 87% 67%;
16+
}
17+
18+
.dark {
19+
--chart-1: 220 70% 50%;
20+
--chart-2: 160 60% 45%;
21+
--chart-3: 30 80% 55%;
22+
--chart-4: 280 65% 60%;
23+
--chart-5: 340 75% 55%;
24+
}
25+
}
26+
27+
#storybook-root {
28+
min-height: 100vh;
29+
}

client/biome.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
".vercel/**",
1414
"node_modules/**",
1515
"public/**",
16-
"src/*.gen.ts"
16+
"src/*.gen.ts",
17+
"storybook-static/**"
1718
]
1819
},
1920
"formatter": {

0 commit comments

Comments
 (0)