feat:锚点导航支持水平样式 (#2930)

This commit is contained in:
hsm-lv 2021-11-12 17:51:32 +08:00 committed by GitHub
parent bf6f5e2681
commit bbfad03de4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 213 additions and 44 deletions

View File

@ -105,6 +105,100 @@ order: 68
默认想要显示多少锚点导航配置多少个 `links` 成员即可。
## 水平导航
```schema: scope="body"
{
"type": "anchor-nav",
"direction": "horizontal",
"links": [
{
"title": "基本信息",
"body": [
{
"type": "form",
"title": "基本信息",
"body": [
{
"type": "input-text",
"name": "name",
"label": "姓名:"
},
{
"name": "email",
"type": "input-email",
"label": "邮箱:"
}
]
}
]
},
{
"title": "工作信息",
"body": [
{
"type": "form",
"title": "工作信息",
"body": [
{
"type": "input-text",
"name": "cname",
"label": "公司名称:"
},
{
"name": "caddress",
"type": "input-text",
"label": "公司地址:"
}
]
}
]
},
{
"title": "兴趣爱好",
"body": [
{
"type": "form",
"title": "兴趣爱好",
"body": [
{
"type": "input-text",
"name": "interest1",
"label": "兴趣爱好1"
},
{
"name": "interest2",
"type": "input-text",
"label": "兴趣爱好2"
},
{
"name": "interest3",
"type": "input-text",
"label": "兴趣爱好3"
},
{
"name": "interest4",
"type": "input-text",
"label": "兴趣爱好4"
},
{
"name": "interest5",
"type": "input-text",
"label": "兴趣爱好5"
},
{
"name": "interest6",
"type": "input-text",
"label": "兴趣爱好6"
}
]
}
]
}
]
}
```
## 默认定位到某个区域
主要配置`active`属性来实现该效果,共有下面两种方法:
@ -304,15 +398,16 @@ order: 68
## 属性表
| 属性名 | 类型 | 默认值 | 说明 |
| ------------------ | --------------------------------- | ----------------------------------- | ----------------------- |
| type | `string` | `"anchor-nav"` | 指定为 AnchorNav 渲染器 |
| className | `string` | | 外层 Dom 的类名 |
| linkClassName | `string` | | 导航 Dom 的类名 |
| sectionClassName | `string` | | 锚点区域 Dom 的类名 |
| links | `Array` | | links 内容 |
| active | `string` | | 需要定位的区域 |
| links[x].title | `string` | | 区域 标题 |
| links[x].href | `string` | | 区域 标识 |
| links[x].body | [SchemaNode](../types/schemanode) | | 区域 内容区 |
| links[x].className | `string` | `"bg-white b-l b-r b-b wrapper-md"` | 区域成员 样式 |
| 属性名 | 类型 | 默认值 | 说明 |
| ------------------ | --------------------------------- | ----------------------------------- | -------------------------------------------------------------------------- |
| type | `string` | `"anchor-nav"` | 指定为 AnchorNav 渲染器 |
| className | `string` | | 外层 Dom 的类名 |
| linkClassName | `string` | | 导航 Dom 的类名 |
| sectionClassName | `string` | | 锚点区域 Dom 的类名 |
| links | `Array` | | links 内容 |
| direction | `string` | `"vertical"` | 可以配置导航水平展示还是垂直展示。对应的配置项分别是vertical、horizontal |
| active | `string` | | 需要定位的区域 |
| links[x].title | `string` | | 区域 标题 |
| links[x].href | `string` | | 区域 标识 |
| links[x].body | [SchemaNode](../types/schemanode) | | 区域 内容区 |
| links[x].className | `string` | `"bg-white b-l b-r b-b wrapper-md"` | 区域成员 样式 |

View File

@ -2,40 +2,99 @@
display: flex;
height: px2rem(400px);
&-link-wrap {
margin: 0;
padding: 0;
width: var(--Tabs--vertical-width);
border-right: var(--AnchorNav-links-container-borderRight);
padding-bottom: px2rem(60px);
&--vertical {
.#{$ns}AnchorNav-link-wrap {
margin: 0;
padding: 0;
width: var(--Tabs--vertical-width);
border-right: var(--AnchorNav-links-container-borderRight);
padding-bottom: px2rem(60px);
> .#{$ns}AnchorNav-link {
position: relative;
display: block;
> a {
> .#{$ns}AnchorNav-link {
position: relative;
display: block;
border: var(--Tabs-borderWidth) solid transparent;
border-width: var(--AnchorNav-onActive-borderWidth);
color: var(--Tabs-color);
padding: var(--Tabs-linkPadding);
font-size: var(--Tabs-linkFontSize);
outline: none;
text-align: right;
text-decoration: none;
cursor: pointer;
margin: 0;
&:hover {
color: var(--primary);
> a {
display: block;
border: var(--Tabs-borderWidth) solid transparent;
border-width: var(--AnchorNav-onActive-borderWidth);
color: var(--Tabs-color);
padding: var(--Tabs-linkPadding);
font-size: var(--Tabs-linkFontSize);
outline: none;
text-align: right;
text-decoration: none;
cursor: pointer;
margin: 0;
&:hover {
color: var(--primary);
}
}
&.is-active {
> a,
> a:hover {
color: var(--Tabs--vertical-onActive-color);
border-color: var(--Tabs--vertical-onActive-border);
}
}
}
}
}
&.is-active {
> a,
> a:hover {
color: var(--Tabs--vertical-onActive-color);
border-color: var(--Tabs--vertical-onActive-border);
&--horizontal {
flex-direction: column;
.#{$ns}AnchorNav-link-wrap {
user-select: none;
margin: 0px;
padding: 0px;
border-bottom: var(--Tabs-borderWidth) solid var(--Tabs-borderColor);
list-style: none;
> .#{$ns}AnchorNav-link {
margin-bottom: calc(var(--Tabs-borderWidth) * -1);
display: inline-block;
position: relative;
> a:first-child {
font-size: var(--Tabs-linkFontSize);
outline: 0;
border: var(--Tabs-borderWidth) solid transparent;
border-width: 0 0 var(--Tabs--line-borderWidth) 0;
border-top-left-radius: var(--Tabs-borderRadius);
border-top-right-radius: var(--Tabs-borderRadius);
color: var(--Tabs-color);
margin: var(--Tabs-linkMargin);
padding: var(--Tabs-linkPadding);
text-decoration: none;
cursor: pointer;
display: block;
&:hover,
&:focus {
color: var(--primary);
background: transparent;
border-color: transparent;
}
}
&:last-child {
> a {
margin: 0;
}
}
&.is-active {
> a:first-child,
> a:first-child:hover,
> a:first-child:focus {
font-size: var(--Tabs-linkFontSize);
border-width: 0 0 var(--Tabs--line-borderWidth) 0;
border-color: var(--Tabs--line-onHover-borderColor);
color: var(--Tabs--line-onHover-color);
background: transparent;
}
}
}
}

View File

@ -46,6 +46,7 @@ export interface AnchorNavProps extends ThemeProps {
props?: AnchorNavProps
) => JSX.Element; // 锚点区域渲染器
onSelect?: (key: string | number) => void; // 选中回调方法
direction?: 'vertical' | 'horizontal'; // 导航方向
}
export interface AnchorNavState {
@ -56,10 +57,11 @@ export interface AnchorNavState {
export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
static defaultProps: Pick<
AnchorNavProps,
'linkClassName' | 'sectionClassName'
'linkClassName' | 'sectionClassName' | 'direction'
> = {
linkClassName: '',
sectionClassName: ''
sectionClassName: '',
direction: 'vertical'
};
// 滚动区域DOM
@ -214,7 +216,8 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
className,
linkClassName,
sectionClassName,
children
children,
direction
} = this.props;
if (!Array.isArray(children)) {
@ -222,7 +225,15 @@ export class AnchorNav extends React.Component<AnchorNavProps, AnchorNavState> {
}
return (
<div className={cx(`AnchorNav`, className)}>
<div
className={cx(
'AnchorNav',
{
[`AnchorNav--${direction}`]: direction
},
className
)}
>
<ul
className={cx('AnchorNav-link-wrap', linkClassName)}
role="anchorlist"

View File

@ -65,6 +65,8 @@ export interface AnchorNavSchema extends BaseSchema {
*
*/
sectionClassName?: SchemaClassName;
direction?: 'vertical' | 'horizontal';
}
export interface AnchorNavProps
@ -148,6 +150,7 @@ export default class AnchorNav extends React.Component<
className,
linkClassName,
sectionClassName,
direction,
sectionRender,
render,
data
@ -187,6 +190,7 @@ export default class AnchorNav extends React.Component<
sectionClassName={sectionClassName}
onSelect={this.handleSelect}
active={this.state.active}
direction={direction}
>
{children}
</CAnchorNav>