Skip to content

Commit 1a0a427

Browse files
committed
feat: tab.action&tab.extra
1 parent 2626409 commit 1a0a427

File tree

10 files changed

+125
-51
lines changed

10 files changed

+125
-51
lines changed

docs/guide/page-tab.md

+3
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ export default (api: IApi) => {
3232
key: 'test',
3333
component: require.resolve('./a.tsx'),
3434
test: /^\/components\//,
35+
extra: require.resolve('./extra.tsx'),
36+
action: require.resolve('./actions.tsx'),
3537
}));
3638
};
3739
```
3840

3941
`component` 放入我们自定义的 Tab 内容,`test` 可以写入正则来匹配路由,这样我们就实现了为 `/componets` 下的路由页面添加自定义 Tab。
42+
其中,`extra``action` 都是可选项,`extra` 可以自定义每个 Tab 的紧跟内容,`action` 可以自定义整个tab栏的右侧内容。

docs/theme/default.md

+7
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,11 @@ hero:
119119
link: /getting-started
120120
```
121121

122+
#### extra
123+
124+
- 类型:`String`
125+
- 默认值:`null`
126+
- 详细:
127+
128+
配置 Tab 页面紧跟的 Tab 区域
122129
<!-- md config end -->

examples/normal/actions.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import React from 'react';
2+
3+
export default () => <>🏀</>;

examples/normal/extra.tsx

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import React from 'react';
2+
3+
export default () => <>😄</>;

examples/normal/plugin.ts

+7
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,12 @@ export default (api: IApi) => {
44
api.addContentTab(() => ({
55
key: 'test',
66
component: require.resolve('./a.tsx'),
7+
extra: require.resolve('./extra.tsx'),
8+
action: require.resolve('./actions.tsx'),
9+
}));
10+
11+
api.addContentTab(() => ({
12+
key: 'test2',
13+
component: require.resolve('./a.tsx'),
714
}));
815
};

examples/normal/src/Foo/index.$tab-api.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: API
3+
extra: 😭
34
---
45

56
约定式 Tab 测试 + 自动 API 测试

src/client/theme-api/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export interface IRouteMeta {
8080
};
8181
atomId?: string;
8282
filename?: string;
83+
extra: string;
8384
[key: string]: any;
8485
};
8586
// route toc

src/client/theme-default/slots/ContentTabs/index.less

+41-31
Original file line numberDiff line numberDiff line change
@@ -24,48 +24,58 @@
2424
}
2525
}
2626

27-
> li {
28-
height: inherit;
27+
&-nav {
28+
flex: auto;
29+
display: flex;
30+
height: 60px;
2931

30-
> button {
31-
padding: 0;
32+
>li {
3233
height: inherit;
33-
color: @c-text-secondary;
34-
font-size: 17px;
35-
border: 0;
36-
background: transparent;
37-
cursor: pointer;
38-
transition: all 0.2s;
3934

40-
&:hover {
41-
color: @c-primary;
35+
>button {
36+
padding: 0;
37+
height: inherit;
38+
color: @c-text-secondary;
39+
font-size: 17px;
40+
border: 0;
41+
background: transparent;
42+
cursor: pointer;
43+
transition: all 0.2s;
44+
45+
&:hover {
46+
color: @c-primary;
47+
}
4248
}
43-
}
4449

45-
&:not(last-child) {
46-
margin-inline-end: 42px;
50+
&:not(last-child) {
51+
margin-inline-end: 42px;
4752

48-
@media @mobile {
49-
margin-inline-end: 20px;
53+
@media @mobile {
54+
margin-inline-end: 20px;
55+
}
5056
}
51-
}
5257

53-
&[data-active] {
54-
position: relative;
58+
&[data-active] {
59+
position: relative;
5560

56-
> button {
57-
color: @c-text;
58-
}
61+
>button {
62+
color: @c-text;
63+
}
5964

60-
&::after {
61-
content: '';
62-
position: absolute;
63-
left: 0;
64-
right: 0;
65-
bottom: -1px;
66-
height: 1px;
67-
background-color: @c-primary;
65+
&::after {
66+
content: '';
67+
position: absolute;
68+
left: 0;
69+
right: 0;
70+
bottom: -1px;
71+
height: 1px;
72+
background-color: @c-primary;
73+
}
6874
}
6975
}
7076
}
77+
78+
&-action {
79+
flex: none;
80+
}
7181
}

src/client/theme-default/slots/ContentTabs/index.tsx

+30-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@ import './index.less';
44

55
type IContentTabs = ReturnType<typeof useRouteMeta>['tabs'];
66

7+
const TabsAction: FC<{ tabs: IContentTabs }> = ({ tabs }) => {
8+
const tabActions = tabs
9+
?.map((tab) => tab.components.Action)
10+
.filter((tab) => tab);
11+
12+
return Boolean(tabActions?.length) ? (
13+
<div className="dumi-default-content-tabs-actions">
14+
{React.createElement(tabActions![0])}
15+
</div>
16+
) : null;
17+
};
18+
719
export interface IContentTabsProps {
820
tabs: IContentTabs;
921
tabKey: string | null;
@@ -17,24 +29,27 @@ const ContentTabs: FC<IContentTabsProps> = ({
1729
}) => {
1830
const intl = useIntl();
1931

20-
// TODO: tab.Extra & tab.Action render
21-
2232
return Boolean(tabs?.length) ? (
2333
<ul className="dumi-default-content-tabs">
24-
<li onClick={() => onChange()} data-active={!key || undefined}>
25-
<button type="button">
26-
{intl.formatMessage({ id: 'content.tabs.default' })}
27-
</button>
28-
</li>
29-
{tabs!.map((tab) => (
30-
<li
31-
key={tab.key}
32-
onClick={() => onChange(tab)}
33-
data-active={key === tab.key || undefined}
34-
>
35-
<button type="button">{tab.meta.frontmatter.title}</button>
34+
<div className="dumi-default-content-tabs-nav">
35+
<li onClick={() => onChange()} data-active={!key || undefined}>
36+
<button type="button">
37+
{intl.formatMessage({ id: 'content.tabs.default' })}
38+
</button>
3639
</li>
37-
))}
40+
{tabs!.map((tab) => (
41+
<li
42+
key={tab.key}
43+
onClick={() => onChange(tab)}
44+
data-active={key === tab.key || undefined}
45+
>
46+
<button type="button">{tab.meta.frontmatter.title}</button>
47+
{tab.meta.frontmatter.extra}
48+
{tab.components.Extra && React.createElement(tab.components.Extra)}
49+
</li>
50+
))}
51+
</div>
52+
<TabsAction tabs={tabs} />
3853
</ul>
3954
) : null;
4055
};

src/features/tabs.ts

+29-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export interface IContentTab {
99
id?: string;
1010
test?: RegExp;
1111
component: string;
12+
extra?: string;
13+
action?: string;
1214
}
1315

1416
export function isTabRouteFile(file: string) {
@@ -30,8 +32,9 @@ export default (api: IApi) => {
3032
key: string;
3133
id: string;
3234
file: string;
35+
extra?: string;
36+
action?: string;
3337
}[] = [];
34-
3538
api.describe({ key: undefined });
3639

3740
// collect extra content tabs before routes generate
@@ -96,9 +99,10 @@ export default (api: IApi) => {
9699
key: tab.key,
97100
id: tab.id!,
98101
file: tab.component,
102+
extra: tab.extra,
103+
action: tab.action,
99104
})),
100105
);
101-
102106
return routes;
103107
});
104108

@@ -121,24 +125,44 @@ export default (api: IApi) => {
121125
index: metaFiles.length,
122126
});
123127
});
124-
125128
return metaFiles;
126129
},
127130
});
128131

129132
// generate tabs tmp file
130133
api.onGenerateFiles(() => {
134+
console.log(tabs, 'tabs');
131135
api.writeTmpFile({
132136
noPluginDir: true,
133137
path: TABS_META_PATH,
134138
content: Mustache.render(
135139
`{{#tabs}}
136-
import * as tab{{{index}}} from '{{{file}}}';
140+
import tab{{{index}}} from '{{{file}}}';
141+
142+
{{#extra}}
143+
import tabExtra{{{index}}} from '{{{extra}}}';
144+
{{/extra}}
145+
146+
{{#action}}
147+
import tabAction{{{index}}} from '{{{action}}}';
148+
{{/action}}
149+
137150
{{/tabs}}
138151
139152
export const tabs = {
140153
{{#tabs}}
141-
'{{{id}}}': { key: '{{{key}}}', components: tab{{{index}}} },
154+
'{{{id}}}': {
155+
key: '{{{key}}}',
156+
components: {
157+
default: tab{{{index}}},
158+
{{#extra}}
159+
Extra: tabExtra{{{index}}},
160+
{{/extra}}
161+
{{#action}}
162+
Action: tabAction{{{index}}}
163+
{{/action}}
164+
}
165+
},
142166
{{/tabs}}
143167
}
144168
`,

0 commit comments

Comments
 (0)