Loading...
Loading...
Compare original and translation side by side
@storybook/react-native@storybook/react-nativeimport type { Meta, StoryObj } from '@storybook/react-native';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Basic: Story = {
args: {
label: 'Hello',
},
};import type { Meta, StoryObj } from '@storybook/react-native';
import { MyComponent } from './MyComponent';
const meta = {
component: MyComponent,
} satisfies Meta<typeof MyComponent>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Basic: Story = {
args: {
label: 'Hello',
},
};ComponentName.stories.tsxMetaStoryObj@storybook/react-nativemetasatisfies Meta<typeof Component>StoryObj<typeof meta>argsargTypesparametersrenderdecoratorsComponentName.stories.tsx@storybook/react-nativeMetaStoryObjmetaMeta<typeof Component>StoryObj<typeof meta>argsargTypesparametersrenderdecoratorsexport const Primary: Story = {
args: { variant: 'primary', title: 'Click me' },
};
export const Secondary: Story = {
args: { ...Primary.args, variant: 'secondary' },
};export const Primary: Story = {
args: { variant: 'primary', title: 'Click me' },
};
export const Secondary: Story = {
args: { ...Primary.args, variant: 'secondary' },
};export const WithScrollView: Story = {
render: (args) => (
<ScrollView>
<MyComponent {...args} />
</ScrollView>
),
};export const WithScrollView: Story = {
render: (args) => (
<ScrollView>
<MyComponent {...args} />
</ScrollView>
),
};export const Interactive: Story = {
render: function InteractiveRender() {
const [count, setCount] = useReducer((s) => s + 1, 0);
return <Counter count={count} onPress={setCount} />;
},
};export const Interactive: Story = {
render: function InteractiveRender() {
const [count, setCount] = useReducer((s) => s + 1, 0);
return <Counter count={count} onPress={setCount} />;
},
};import { fn } from 'storybook/test';
const meta = {
component: Button,
args: { onPress: fn() },
} satisfies Meta<typeof Button>;argTypes: { onPress: { action: 'pressed' } },import { fn } from 'storybook/test';
const meta = {
component: Button,
args: { onPress: fn() },
} satisfies Meta<typeof Button>;argTypes: { onPress: { action: 'pressed' } },export const MyStory: Story = {
storyName: 'Custom Display Name',
args: { label: 'Hello' },
};export const MyStory: Story = {
storyName: 'Custom Display Name',
args: { label: 'Hello' },
};const meta = {
title: 'NestingExample/Message/Bubble',
component: MyComponent,
} satisfies Meta<typeof MyComponent>;const meta = {
title: 'NestingExample/Message/Bubble',
component: MyComponent,
} satisfies Meta<typeof MyComponent>;const meta = {
component: MyComponent,
argTypes: {
// Select dropdown
size: {
options: ['small', 'medium', 'large'],
control: { type: 'select' },
},
// Range slider
opacity: {
control: { type: 'range', min: 0, max: 1, step: 0.1 },
},
// Color picker
color: { control: { type: 'color' } },
// Conditional control (shows only when `advanced` arg is true)
padding: { control: 'number', if: { arg: 'advanced' } },
},
} satisfies Meta<typeof MyComponent>;stringbooleannumberconst meta = {
component: MyComponent,
argTypes: {
// 下拉选择器
size: {
options: ['small', 'medium', 'large'],
control: { type: 'select' },
},
// 范围滑块
opacity: {
control: { type: 'range', min: 0, max: 1, step: 0.1 },
},
// 颜色选择器
color: { control: { type: 'color' } },
// 条件控件(仅当`advanced`参数为true时显示)
padding: { control: 'number', if: { arg: 'advanced' } },
},
} satisfies Meta<typeof MyComponent>;stringbooleannumberparameters: {
// Markdown docs in the Notes addon tab
notes: `# MyComponent\nUsage: \`<MyComponent label="hi" />\``,
// Background options for Backgrounds addon
backgrounds: {
default: 'dark',
values: [
{ name: 'light', value: 'white' },
{ name: 'dark', value: '#333' },
],
},
},parameters: {
// 在Notes插件标签页中显示Markdown文档
notes: `# MyComponent\nUsage: \`<MyComponent label="hi" />\``,
// Backgrounds插件的背景选项
backgrounds: {
default: 'dark',
values: [
{ name: 'light', value: 'white' },
{ name: 'dark', value: '#333' },
],
},
},| Parameter | Type | Description |
|---|---|---|
| | Remove top safe area padding. When using this, the component itself must handle safe areas since Storybook will no longer provide safe area padding. Prefer |
| | Initial UI visibility |
| | Hide fullscreen toggle |
| | Story container layout |
| 参数名称 | 类型 | 说明 |
|---|---|---|
| | 移除顶部安全区域内边距。使用此参数时,组件本身必须处理安全区域,因为Storybook将不再提供安全区域内边距。优先使用 |
| | 初始UI可见性 |
| | 隐藏全屏切换按钮 |
| | 故事容器布局 |
const meta = {
component: MyComponent,
decorators: [
(Story) => (
<View style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}>
<Story />
</View>
),
],
} satisfies Meta<typeof MyComponent>;.rnstorybook/preview.tsximport { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';
import type { Preview } from '@storybook/react-native';
const preview: Preview = {
decorators: [withBackgrounds],
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
backgrounds: {
default: 'plain',
values: [
{ name: 'plain', value: 'white' },
{ name: 'dark', value: '#333' },
],
},
},
};
export default preview;const meta = {
component: MyComponent,
decorators: [
(Story) => (
<View style={{ alignItems: 'center', justifyContent: 'center', flex: 1 }}>
<Story />
</View>
),
],
} satisfies Meta<typeof MyComponent>;.rnstorybook/preview.tsximport { withBackgrounds } from '@storybook/addon-ondevice-backgrounds';
import type { Preview } from '@storybook/react-native';
const preview: Preview = {
decorators: [withBackgrounds],
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
backgrounds: {
default: 'plain',
values: [
{ name: 'plain', value: 'white' },
{ name: 'dark', value: '#333' },
],
},
},
};
export default preview;import type { StorybookConfig } from '@storybook/react-native';
const main: StorybookConfig = {
stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
addons: [
'@storybook/addon-ondevice-controls',
'@storybook/addon-ondevice-backgrounds',
'@storybook/addon-ondevice-actions',
'@storybook/addon-ondevice-notes',
],
framework: '@storybook/react-native',
};
export default main;stories: [
'../components/**/*.stories.?(ts|tsx|js|jsx)',
{ directory: '../other_components', files: '**/*.stories.?(ts|tsx|js|jsx)' },
],import type { StorybookConfig } from '@storybook/react-native';
const main: StorybookConfig = {
stories: ['../components/**/*.stories.?(ts|tsx|js|jsx)'],
addons: [
'@storybook/addon-ondevice-controls',
'@storybook/addon-ondevice-backgrounds',
'@storybook/addon-ondevice-actions',
'@storybook/addon-ondevice-notes',
],
framework: '@storybook/react-native',
};
export default main;stories: [
'../components/**/*.stories.?(ts|tsx|js|jsx)',
{ directory: '../other_components', files: '**/*.stories.?(ts|tsx|js|jsx)' },
],import { render, screen } from '@testing-library/react-native';
import { composeStories } from '@storybook/react';
import * as stories from './Button.stories';
const { Primary, Secondary } = composeStories(stories);
test('renders primary button', () => {
render(<Primary />);
expect(screen.getByText('Click me')).toBeTruthy();
});
// Override args in tests
test('renders with custom props', () => {
render(<Primary title="Custom" />);
expect(screen.getByText('Custom')).toBeTruthy();
});composeStoryimport { composeStory } from '@storybook/react';
import meta, { Primary } from './Button.stories';
const PrimaryStory = composeStory(Primary, meta);// setup-portable-stories.ts
import { setProjectAnnotations } from '@storybook/react';
import * as previewAnnotations from '../.rnstorybook/preview';
setProjectAnnotations(previewAnnotations);import { render, screen } from '@testing-library/react-native';
import { composeStories } from '@storybook/react';
import * as stories from './Button.stories';
const { Primary, Secondary } = composeStories(stories);
test('renders primary button', () => {
render(<Primary />);
expect(screen.getByText('Click me')).toBeTruthy();
});
// 在测试中覆盖参数
test('renders with custom props', () => {
render(<Primary title="Custom" />);
expect(screen.getByText('Custom')).toBeTruthy();
});composeStoryimport { composeStory } from '@storybook/react';
import meta, { Primary } from './Button.stories';
const PrimaryStory = composeStory(Primary, meta);// setup-portable-stories.ts
import { setProjectAnnotations } from '@storybook/react';
import * as previewAnnotations from '../.rnstorybook/preview';
setProjectAnnotations(previewAnnotations);| Addon | Package | Purpose |
|---|---|---|
| Controls | | Edit props interactively |
| Actions | | Log component interactions |
| Backgrounds | | Change story backgrounds |
| Notes | | Add markdown documentation |
| 插件名称 | 包名 | 用途 |
|---|---|---|
| Controls | | 交互式编辑组件属性 |
| Actions | | 记录组件交互行为 |
| Backgrounds | | 切换故事背景 |
| Notes | | 添加Markdown文档说明 |