文中有部分名词可能不准确,见谅
本文主要介绍storybook+shadcn/ui+tailwindcss的storybook代码编写。
相关lib版本
“storybook”: “^8.2.4”,
“tailwindcss”: “^3.4.1”,
一、简介
首先,使用storybook开发一个组件需要两个文件,一个是组件*.tsx一个是story*.stories.ts/*.stories.tsx,css使用了tailwind,所以不单独进行css文件的编写。
在这里关于story文件*.stories.ts/*.stories.tsx,如果有引入组件的需求,请务必使用tsx或者jsx,否则无法识别。
二、开始
以开发一个列表为例,此列表的列表项左侧是icon+title,并且支持点击选中和点击事件。
分成两个组件开发。一个是<ListItem>,一个是<List>。
先看ListItem的开发
1.ListItem
1)组件
下方是ListItem的组件代码,icon可以是导入的icon组件或者本地图片放在img标签内,这点随意。
注意,因为是tsx,所以该组件需要声明类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| //ListItem.tsx import React from 'react';
interface List{ title: string; icon: string; }
interface ListItemProps { list: List; onClick: () => void; selected?: boolean; }
const ListItem: React.FC<ListItemProps> = ({ list, onClick, selected = false, }) => { return( <div className={`flex items-center justify-between p-4 text-sm ${selected?'border-l-4 border-l-black bg-gray-500':''}`} onClick={onClick} > <div className="flex items-center"> <div className="relative mr-4 size-10"> <img src={list.icon} alt=""/> </div> <div className="font-semibold">{list.title}</div> </div> </div> ) }
|
这个组件接收三个参数,分别是list对象、onClick函数和select状态。根据这三个,在story文件中定义不同的story。
2)story
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| //ListItem.stories.tsx import { Meta, StoryObj } from '@storybook/react'; import ListItem from './ListItem';
const meta: Meta<typeof ListItem> = { title: 'List/ListItem', component: ListItem, argTypes: { onClick: { action: 'onClick' }, selected: { control: 'boolean' }, }, tags: ['autodocs'], };
export default meta;
type Story = StoryObj<typeof ListItem>;
|
编写story文件,导入Meta生成meta,定义组件的属性。对于onClick和selected,放在argTypes中,因为需要在文档中实现这两个属性的交互。StoryObj用于生成推断类型,在生成story实例时进行类型声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| //ListItem.stories.tsx const List = { title: "tmp1"; icon: "img1"; }
export const Default: Story = { args: { network: List, selected: false, }, };
export const Selected: Story = { args: { network: List, selected: true, }, };
|
上方的代码生成了两个story实例。在args中定义属性。args也可以在meta定义时声明,这样就可以得到所有story实例通用的属性。类似继承和重写。
2.List
1)组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| //List.tsx import React from 'react'; import ListItem from './ListItem';
interface List{ title: string; icon: string; } interface ListProps { lists: List[]; onSelect: () => void; selected:string }
const List: React.FC<ListProps> = ({ lists, onSelect, selected }) => { return ( <div className="divide-y"> {lists.map((list) => ( <ListItem key={list.title} list={list} onClick={onSelect} selected={list.title === selected} /> ))} </div> ); };
export default List;
|
2)story
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| //List.stories.tsx import { Meta, StoryObj } from '@storybook/react'; import List from './List';
const meta: Meta<typeof List> = { title: 'List/List', component: List, argTypes: { onSelect: { action: 'onSelect' }, selected: { control: 'text' }, }, };
export default meta;
type Story = StoryObj<typeof List>;
const lists: List[] = [ { title: 'tmp1', icon: 'img1', }, { title: 'tmp2', icon: 'img2', }, ];
export const Default: Story = { args: { list2, selected: 'tmp2', }, };
|