diff --git a/docs/guide/page-tab.md b/docs/guide/page-tab.md index 49da1dc2f3..9757f94796 100644 --- a/docs/guide/page-tab.md +++ b/docs/guide/page-tab.md @@ -32,8 +32,11 @@ export default (api: IApi) => { key: 'test', component: require.resolve('./a.tsx'), test: /^\/components\//, + extra: require.resolve('./extra.tsx'), + action: require.resolve('./actions.tsx'), })); }; ``` `component` 放入我们自定义的 Tab 内容,`test` 可以写入正则来匹配路由,这样我们就实现了为 `/componets` 下的路由页面添加自定义 Tab。 +其中,`extra` 和 `action` 都是可选项,`extra` 可以自定义每个 Tab 的紧跟内容,`action` 可以自定义整个tab栏的右侧内容。 diff --git a/docs/theme/default.md b/docs/theme/default.md index c54c6fe80d..a54b9cad05 100644 --- a/docs/theme/default.md +++ b/docs/theme/default.md @@ -119,4 +119,11 @@ hero: link: /getting-started ``` +#### extra + +- 类型:`String` +- 默认值:`null` +- 详细: + +配置 Tab 页面紧跟的 Tab 区域 diff --git a/examples/normal/actions.tsx b/examples/normal/actions.tsx new file mode 100644 index 0000000000..a88c1b76df --- /dev/null +++ b/examples/normal/actions.tsx @@ -0,0 +1,3 @@ +import React from 'react'; + +export default () => <>🏀; diff --git a/examples/normal/extra.tsx b/examples/normal/extra.tsx new file mode 100644 index 0000000000..258ac64a79 --- /dev/null +++ b/examples/normal/extra.tsx @@ -0,0 +1,3 @@ +import React from 'react'; + +export default () => <>😄; diff --git a/examples/normal/plugin.ts b/examples/normal/plugin.ts index 9c3b897e84..856a2a866a 100644 --- a/examples/normal/plugin.ts +++ b/examples/normal/plugin.ts @@ -4,5 +4,12 @@ export default (api: IApi) => { api.addContentTab(() => ({ key: 'test', component: require.resolve('./a.tsx'), + extra: require.resolve('./extra.tsx'), + action: require.resolve('./actions.tsx'), + })); + + api.addContentTab(() => ({ + key: 'test2', + component: require.resolve('./a.tsx'), })); }; diff --git a/examples/normal/src/Foo/index.$tab-api.md b/examples/normal/src/Foo/index.$tab-api.md index fb7874a450..fa18db32ed 100644 --- a/examples/normal/src/Foo/index.$tab-api.md +++ b/examples/normal/src/Foo/index.$tab-api.md @@ -1,5 +1,6 @@ --- title: API +extra: 😭 --- 约定式 Tab 测试 + 自动 API 测试 diff --git a/src/client/theme-api/types.ts b/src/client/theme-api/types.ts index 8ae62a5d38..11685fcf5f 100644 --- a/src/client/theme-api/types.ts +++ b/src/client/theme-api/types.ts @@ -80,6 +80,7 @@ export interface IRouteMeta { }; atomId?: string; filename?: string; + extra: string; [key: string]: any; }; // route toc diff --git a/src/client/theme-default/slots/ContentTabs/index.less b/src/client/theme-default/slots/ContentTabs/index.less index 25cc0dbcac..5a3effa410 100644 --- a/src/client/theme-default/slots/ContentTabs/index.less +++ b/src/client/theme-default/slots/ContentTabs/index.less @@ -24,48 +24,58 @@ } } - > li { - height: inherit; + &-nav { + flex: auto; + display: flex; + height: 60px; - > button { - padding: 0; + >li { height: inherit; - color: @c-text-secondary; - font-size: 17px; - border: 0; - background: transparent; - cursor: pointer; - transition: all 0.2s; - &:hover { - color: @c-primary; + >button { + padding: 0; + height: inherit; + color: @c-text-secondary; + font-size: 17px; + border: 0; + background: transparent; + cursor: pointer; + transition: all 0.2s; + + &:hover { + color: @c-primary; + } } - } - &:not(last-child) { - margin-inline-end: 42px; + &:not(last-child) { + margin-inline-end: 42px; - @media @mobile { - margin-inline-end: 20px; + @media @mobile { + margin-inline-end: 20px; + } } - } - &[data-active] { - position: relative; + &[data-active] { + position: relative; - > button { - color: @c-text; - } + >button { + color: @c-text; + } - &::after { - content: ''; - position: absolute; - left: 0; - right: 0; - bottom: -1px; - height: 1px; - background-color: @c-primary; + &::after { + content: ''; + position: absolute; + left: 0; + right: 0; + bottom: -1px; + height: 1px; + background-color: @c-primary; + } } } } + + &-action { + flex: none; + } } diff --git a/src/client/theme-default/slots/ContentTabs/index.tsx b/src/client/theme-default/slots/ContentTabs/index.tsx index a5d6bb2fe9..1ca885bce7 100644 --- a/src/client/theme-default/slots/ContentTabs/index.tsx +++ b/src/client/theme-default/slots/ContentTabs/index.tsx @@ -4,6 +4,18 @@ import './index.less'; type IContentTabs = ReturnType['tabs']; +const TabsAction: FC<{ tabs: IContentTabs }> = ({ tabs }) => { + const tabActions = tabs + ?.map((tab) => tab.components.Action) + .filter((tab) => tab); + + return Boolean(tabActions?.length) ? ( +
+ {React.createElement(tabActions![0])} +
+ ) : null; +}; + export interface IContentTabsProps { tabs: IContentTabs; tabKey: string | null; @@ -17,24 +29,27 @@ const ContentTabs: FC = ({ }) => { const intl = useIntl(); - // TODO: tab.Extra & tab.Action render - return Boolean(tabs?.length) ? ( ) : null; }; diff --git a/src/features/tabs.ts b/src/features/tabs.ts index ee61269829..cb5d06726c 100644 --- a/src/features/tabs.ts +++ b/src/features/tabs.ts @@ -9,6 +9,8 @@ export interface IContentTab { id?: string; test?: RegExp; component: string; + extra?: string; + action?: string; } export function isTabRouteFile(file: string) { @@ -30,8 +32,9 @@ export default (api: IApi) => { key: string; id: string; file: string; + extra?: string; + action?: string; }[] = []; - api.describe({ key: undefined }); // collect extra content tabs before routes generate @@ -96,9 +99,10 @@ export default (api: IApi) => { key: tab.key, id: tab.id!, file: tab.component, + extra: tab.extra, + action: tab.action, })), ); - return routes; }); @@ -121,24 +125,44 @@ export default (api: IApi) => { index: metaFiles.length, }); }); - return metaFiles; }, }); // generate tabs tmp file api.onGenerateFiles(() => { + console.log(tabs, 'tabs'); api.writeTmpFile({ noPluginDir: true, path: TABS_META_PATH, content: Mustache.render( `{{#tabs}} -import * as tab{{{index}}} from '{{{file}}}'; +import tab{{{index}}} from '{{{file}}}'; + +{{#extra}} +import tabExtra{{{index}}} from '{{{extra}}}'; +{{/extra}} + +{{#action}} +import tabAction{{{index}}} from '{{{action}}}'; +{{/action}} + {{/tabs}} export const tabs = { {{#tabs}} - '{{{id}}}': { key: '{{{key}}}', components: tab{{{index}}} }, + '{{{id}}}': { + key: '{{{key}}}', + components: { + default: tab{{{index}}}, + {{#extra}} + Extra: tabExtra{{{index}}}, + {{/extra}} + {{#action}} + Action: tabAction{{{index}}} + {{/action}} + } + }, {{/tabs}} } `,