diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 32d4bc1867..abbd193c68 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -55,12 +55,31 @@ const preview: Preview = { locale: 'en', }, decorators: [ - (Story, { parameters, globals, args }) => { + (Story, { parameters, globals, args, argTypes }) => { // Get the locale from the global toolbar // and merge it with any parameters or args state. const { locale } = globals as { locale: string }; const { state = {} } = parameters; - const { state: argsState = {} } = args; + + const argsState: Record = {}; + for (const [key, value] of Object.entries(args)) { + const argType = argTypes[key]; + if (argType?.reduxPath) { + const reduxPath = Array.isArray(argType.reduxPath) + ? argType.reduxPath.map((p) => p.toString()) + : argType.reduxPath.split('.'); + + reduxPath.reduce((acc, key, i) => { + if (acc[key] === undefined) { + acc[key] = {}; + } + if (i === reduxPath.length - 1) { + acc[key] = value; + } + return acc[key] as Record; + }, argsState); + } + } const reducer = reducerWithInitialState( { @@ -69,7 +88,7 @@ const preview: Preview = { }, }, state as Record, - argsState as Record, + argsState, ); const store = configureStore({ diff --git a/.storybook/storybook-addon-vitest.d.ts b/.storybook/storybook.d.ts similarity index 54% rename from .storybook/storybook-addon-vitest.d.ts rename to .storybook/storybook.d.ts index 86852faca9..47624d1e9c 100644 --- a/.storybook/storybook-addon-vitest.d.ts +++ b/.storybook/storybook.d.ts @@ -1,7 +1,20 @@ // The addon package.json incorrectly exports types, so we need to override them here. + +import type { RootState } from '@/mastodon/store'; + // See: https://github.com/storybookjs/storybook/blob/v9.0.4/code/addons/vitest/package.json#L70-L76 declare module '@storybook/addon-vitest/vitest-plugin' { export * from '@storybook/addon-vitest/dist/vitest-plugin/index'; } +type RootPathKeys = keyof RootState; + +declare module 'storybook/internal/csf' { + export interface InputType { + reduxPath?: + | `${RootPathKeys}.${string}` + | [RootPathKeys, ...(string | number)[]]; + } +} + export {}; diff --git a/app/javascript/mastodon/components/account/account.stories.tsx b/app/javascript/mastodon/components/account/account.stories.tsx index 3a3a255b7f..050ed6e900 100644 --- a/app/javascript/mastodon/components/account/account.stories.tsx +++ b/app/javascript/mastodon/components/account/account.stories.tsx @@ -1,16 +1,28 @@ +import type { ComponentProps } from 'react'; + import type { Meta, StoryObj } from '@storybook/react-vite'; import { accountFactoryState, relationshipsFactory } from '@/testing/factories'; import { Account } from './index'; +type Props = Omit, 'id'> & { + name: string; + username: string; +}; + const meta = { title: 'Components/Account', - component: Account, argTypes: { - id: { + name: { + type: 'string', + description: 'The display name of the account', + reduxPath: 'accounts.1.display_name_html', + }, + username: { type: 'string', - description: 'ID of the account to display', + description: 'The username of the account', + reduxPath: 'accounts.1.acct', }, size: { type: 'number', @@ -40,7 +52,8 @@ const meta = { }, }, args: { - id: '1', + name: 'Test User', + username: 'testuser', size: 46, hidden: false, minimal: false, @@ -55,17 +68,16 @@ const meta = { }, }, }, -} satisfies Meta; + render(args) { + return ; + }, +} satisfies Meta; export default meta; type Story = StoryObj; -export const Primary: Story = { - args: { - id: '1', - }, -}; +export const Primary: Story = {}; export const Hidden: Story = { args: { diff --git a/app/javascript/mastodon/components/emoji/emoji.stories.tsx b/app/javascript/mastodon/components/emoji/emoji.stories.tsx index d390387a03..fcc81db6c3 100644 --- a/app/javascript/mastodon/components/emoji/emoji.stories.tsx +++ b/app/javascript/mastodon/components/emoji/emoji.stories.tsx @@ -4,20 +4,22 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { Emoji } from './index'; -type EmojiProps = ComponentProps & { state: string }; +type EmojiProps = ComponentProps & { + style: 'auto' | 'native' | 'twemoji'; +}; const meta = { title: 'Components/Emoji', component: Emoji, args: { code: '🖤', - state: 'auto', + style: 'auto', }, argTypes: { code: { name: 'Emoji', }, - state: { + style: { control: { type: 'select', labels: { @@ -28,11 +30,7 @@ const meta = { }, options: ['auto', 'native', 'twemoji'], name: 'Emoji Style', - mapping: { - auto: { meta: { emoji_style: 'auto' } }, - native: { meta: { emoji_style: 'native' } }, - twemoji: { meta: { emoji_style: 'twemoji' } }, - }, + reduxPath: 'meta.emoji_style', }, }, render(args) {