Pressify 支持两种写组件 demo 的方式,适用于不同的场景。
对于简单的组件 demo,我们可以直接在 Markdown 代码块中写 demo。
当在代码块的 ``` 后加上 demo
标记,这个代码块就会变成一个 demo。例如:
```ts demo
export default function Foo() {
return (
<button
className="px-3 py-1 rounded text-white bg-c-brand hover:bg-c-brand-light"
onClick={() => alert('Hi')}
>
Hello World
</button>
);
}
```
```ts demo
export default function Foo() {
return (
<button
className="px-3 py-1 rounded text-white bg-c-brand hover:bg-c-brand-light"
onClick={() => alert('Hi')}
>
Hello World
</button>
);
}
```
会渲染成 ↓↓↓:
对于比较复杂的 demo,如果还是“内联”在 Markdown 代码块中,就享受不到编辑器提供的类型提示、ESLint、Prettier 等功能的好处了,体验会有点糟糕。
建议把复杂的 demo 写在外部 JS/TS 文件中,然后在 Markdown 中通过 <Demo src="xxx" />
的形式引入这个 demo 组件。
例如我们在 <root>/.pressify/demo/Button.tsx
有这样的组件 demo:
export default function Button() {
return (
<button
className="px-3 py-1 rounded text-white bg-sky-500 hover:bg-sky-400"
onClick={() => alert('Hi')}
>
外部 demo
</button>
);
}
export default function Button() {
return (
<button
className="px-3 py-1 rounded text-white bg-sky-500 hover:bg-sky-400"
onClick={() => alert('Hi')}
>
外部 demo
</button>
);
}
然后在 Markdown 中把该组件路径传给 Demo
组件的 src
属性:
<Demo src="/.pressify/demo/Button.tsx" />
<Demo src="/.pressify/demo/Button.tsx" />
就能实现这样的 demo 效果啦:
其实代码块 demo 底层也是基于 <Demo />
组件来实现的。
如果要自定义 Demo 组件,可以考虑自定义主题或者扩展主题,
然后在主题的 mdxComponents
中传入自定义的 Demo 组件。
举个例子,可以通过下面的方法替换默认主题的 Demo 组件:
// .pressify/theme/index.js
import theme from 'pressify/theme';
function CustomDemo({ children, code }) {
return (
<>
<div>渲染结果:{children}</div>
<div>源代码:{code}</div>
</>
);
}
export default {
...theme,
mdxComponents: {
...theme.mdxComponents,
Demo: CustomDemo,
},
};
// .pressify/theme/index.js
import theme from 'pressify/theme';
function CustomDemo({ children, code }) {
return (
<>
<div>渲染结果:{children}</div>
<div>源代码:{code}</div>
</>
);
}
export default {
...theme,
mdxComponents: {
...theme.mdxComponents,
Demo: CustomDemo,
},
};
Demo 组件接收的 props 类型为:
interface DemoProps {
/* demo 源代码 */
code: string;
/* 经过 shiki 高亮的代码 html */
codeHtml: string;
/* demo meta 信息 */
meta?: Record<string, any>;
/* 组件的渲染结果 */
children: React.ReactNode;
}
interface DemoProps {
/* demo 源代码 */
code: string;
/* 经过 shiki 高亮的代码 html */
codeHtml: string;
/* demo meta 信息 */
meta?: Record<string, any>;
/* 组件的渲染结果 */
children: React.ReactNode;
}