Move i18n context wrapper to storybook template

This commit is contained in:
David Baker 2025-11-28 15:35:25 +00:00
parent 42d1da9afb
commit 6541d3f528
8 changed files with 32 additions and 83 deletions

View File

@ -6,6 +6,7 @@ import React, { useLayoutEffect } from "react";
import { setLanguage } from "../src/utils/i18n"; import { setLanguage } from "../src/utils/i18n";
import { TooltipProvider } from "@vector-im/compound-web"; import { TooltipProvider } from "@vector-im/compound-web";
import { StoryContext } from "storybook/internal/csf"; import { StoryContext } from "storybook/internal/csf";
import { I18nApi, I18nContext } from "../src";
export const globalTypes = { export const globalTypes = {
theme: { theme: {
@ -64,9 +65,11 @@ async function languageLoader(context: StoryContext<ReactRenderer, StrictArgs>):
const withTooltipProvider: Decorator = (Story) => { const withTooltipProvider: Decorator = (Story) => {
return ( return (
<TooltipProvider> <I18nContext.Provider value={new I18nApi()}>
<Story /> <TooltipProvider>
</TooltipProvider> <Story />
</TooltipProvider>
</I18nContext.Provider>
); );
}; };

View File

@ -11,8 +11,6 @@ import { fn } from "storybook/test";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryFn } from "@storybook/react-vite";
import { AudioPlayerView, type AudioPlayerViewActions, type AudioPlayerViewSnapshot } from "./AudioPlayerView"; import { AudioPlayerView, type AudioPlayerViewActions, type AudioPlayerViewSnapshot } from "./AudioPlayerView";
import { useMockedViewModel } from "../../useMockedViewModel"; import { useMockedViewModel } from "../../useMockedViewModel";
import { I18nContext } from "../../utils/i18nContext";
import { I18nApi } from "../../utils/I18nApi";
type AudioPlayerProps = AudioPlayerViewSnapshot & AudioPlayerViewActions; type AudioPlayerProps = AudioPlayerViewSnapshot & AudioPlayerViewActions;
const AudioPlayerViewWrapper = ({ togglePlay, onKeyDown, onSeekbarChange, ...rest }: AudioPlayerProps): JSX.Element => { const AudioPlayerViewWrapper = ({ togglePlay, onKeyDown, onSeekbarChange, ...rest }: AudioPlayerProps): JSX.Element => {
@ -21,11 +19,7 @@ const AudioPlayerViewWrapper = ({ togglePlay, onKeyDown, onSeekbarChange, ...res
onKeyDown, onKeyDown,
onSeekbarChange, onSeekbarChange,
}); });
return ( return <AudioPlayerView vm={vm} />;
<I18nContext.Provider value={new I18nApi()}>
<AudioPlayerView vm={vm} />
</I18nContext.Provider>
);
}; };
export default { export default {

View File

@ -9,8 +9,6 @@ import React from "react";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryFn } from "@storybook/react-vite";
import { Clock } from "./Clock"; import { Clock } from "./Clock";
import { I18nContext } from "../../utils/i18nContext";
import { I18nApi } from "../../utils/I18nApi";
export default { export default {
title: "Audio/Clock", title: "Audio/Clock",
@ -21,13 +19,7 @@ export default {
}, },
} as Meta<typeof Clock>; } as Meta<typeof Clock>;
const Template: StoryFn<typeof Clock> = (args) => { const Template: StoryFn<typeof Clock> = (args) => <Clock {...args} />;
return (
<I18nContext.Provider value={new I18nApi()}>
<Clock {...args} />
</I18nContext.Provider>
);
};
export const Default = Template.bind({}); export const Default = Template.bind({});

View File

@ -5,13 +5,10 @@
* Please see LICENSE files in the repository root for full details. * Please see LICENSE files in the repository root for full details.
*/ */
import React from "react";
import { fn } from "storybook/test"; import { fn } from "storybook/test";
import { PlayPauseButton } from "./PlayPauseButton"; import { PlayPauseButton } from "./PlayPauseButton";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryObj } from "@storybook/react-vite";
import { I18nContext } from "../../utils/i18nContext";
import { I18nApi } from "../..";
const meta = { const meta = {
title: "Audio/PlayPauseButton", title: "Audio/PlayPauseButton",
@ -23,17 +20,7 @@ const meta = {
} satisfies Meta<typeof PlayPauseButton>; } satisfies Meta<typeof PlayPauseButton>;
export default meta; export default meta;
type Story = StoryObj<typeof meta>;
const Template: StoryFn<typeof PlayPauseButton> = (args) => { export const Default: Story = {};
return ( export const Playing: Story = { args: { playing: true } };
<I18nContext.Provider value={new I18nApi()}>
<PlayPauseButton {...args} />
</I18nContext.Provider>
);
};
export const Default = Template.bind({});
export const Playing = Template.bind({});
Playing.args = {
playing: true,
};

View File

@ -10,7 +10,6 @@ import { useArgs } from "storybook/preview-api";
import { SeekBar } from "./SeekBar"; import { SeekBar } from "./SeekBar";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryFn } from "@storybook/react-vite";
import { I18nApi, I18nContext } from "../..";
export default { export default {
title: "Audio/SeekBar", title: "Audio/SeekBar",
@ -28,11 +27,7 @@ export default {
const Template: StoryFn<typeof SeekBar> = (args) => { const Template: StoryFn<typeof SeekBar> = (args) => {
const [, updateArgs] = useArgs(); const [, updateArgs] = useArgs();
return ( return <SeekBar onChange={(evt) => updateArgs({ value: parseInt(evt.target.value, 10) })} {...args} />;
<I18nContext.Provider value={new I18nApi()}>
<SeekBar onChange={(evt) => updateArgs({ value: parseInt(evt.target.value, 10) })} {...args} />
</I18nContext.Provider>
);
}; };
export const Default = Template.bind({}); export const Default = Template.bind({});

View File

@ -8,9 +8,8 @@
import React from "react"; import React from "react";
import { fn } from "storybook/test"; import { fn } from "storybook/test";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryObj } from "@storybook/react-vite";
import { Pill } from "./Pill"; import { Pill } from "./Pill";
import { I18nApi, I18nContext } from "../..";
const meta = { const meta = {
title: "PillInput/Pill", title: "PillInput/Pill",
@ -24,17 +23,7 @@ const meta = {
} satisfies Meta<typeof Pill>; } satisfies Meta<typeof Pill>;
export default meta; export default meta;
type Story = StoryObj<typeof meta>;
const Template: StoryFn<typeof Pill> = (args) => { export const Default: Story = {};
return ( export const WithoutCloseButton: Story = {};
<I18nContext.Provider value={new I18nApi()}>
<Pill {...args} />
</I18nContext.Provider>
);
};
export const Default = Template.bind({});
export const WithoutCloseButton = Template.bind({});
WithoutCloseButton.args = {
onClick: undefined,
};

View File

@ -37,11 +37,9 @@ export default {
} as Meta<typeof RichItem>; } as Meta<typeof RichItem>;
const Template: StoryFn<typeof RichItem> = (args) => ( const Template: StoryFn<typeof RichItem> = (args) => (
<I18nContext.Provider value={new I18nApi()}> <ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}> <RichItem {...args} />
<RichItem {...args} /> </ul>
</ul>
</I18nContext.Provider>
); );
export const Default = Template.bind({}); export const Default = Template.bind({});
@ -60,11 +58,9 @@ export const Hover = Template.bind({});
Hover.parameters = { pseudo: { hover: true } }; Hover.parameters = { pseudo: { hover: true } };
const TemplateSeparator: StoryFn<typeof RichItem> = (args) => ( const TemplateSeparator: StoryFn<typeof RichItem> = (args) => (
<I18nContext.Provider value={new I18nApi()}> <ul role="listbox" style={{ all: "unset", listStyle: "none" }}>
<ul role="listbox" style={{ all: "unset", listStyle: "none" }}> <RichItem {...args} />
<RichItem {...args} /> <RichItem {...args} />
<RichItem {...args} /> </ul>
</ul>
</I18nContext.Provider>
); );
export const Separator = TemplateSeparator.bind({}); export const Separator = TemplateSeparator.bind({});

View File

@ -8,9 +8,8 @@
import React from "react"; import React from "react";
import { RichList } from "./RichList"; import { RichList } from "./RichList";
import type { Meta, StoryFn } from "@storybook/react-vite"; import type { Meta, StoryObj } from "@storybook/react-vite";
import { RichItem } from "../RichItem"; import { RichItem } from "../RichItem";
import { I18nApi, I18nContext } from "../..";
const avatar = <div style={{ width: 32, height: 32, backgroundColor: "#ccc", borderRadius: "50%" }} />; const avatar = <div style={{ width: 32, height: 32, backgroundColor: "#ccc", borderRadius: "50%" }} />;
@ -40,18 +39,12 @@ const meta = {
} satisfies Meta<typeof RichList>; } satisfies Meta<typeof RichList>;
export default meta; export default meta;
type Story = StoryObj<typeof meta>;
const Template: StoryFn<typeof RichList> = (args) => { export const Default: Story = {};
return ( export const Empty: Story = {
<I18nContext.Provider value={new I18nApi()}> args: {
<RichList {...args} /> isEmpty: true,
</I18nContext.Provider> children: "No items available",
); },
};
export const Default = Template.bind({});
export const Empty = Template.bind({});
Empty.args = {
isEmpty: true,
children: "No items available",
}; };