feat(anchor): add direction action (#6447)
* refactor(anchor): direction show * refactor(anchor): update anchor css * feat(anchor): update demo * test(anchor): update demo test snap * feat(anchor): update docs * Update index.zh-CN.md * Update index.en-US.md --------- Co-authored-by: tangjinzhou <415800467@qq.com>pull/6514/head
parent
de00607dc7
commit
8932aff13f
|
@ -1,5 +1,6 @@
|
|||
import type { CSSProperties, ExtractPropTypes, PropType } from 'vue';
|
||||
import {
|
||||
watch,
|
||||
defineComponent,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
|
@ -9,6 +10,7 @@ import {
|
|||
ref,
|
||||
computed,
|
||||
} from 'vue';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import classNames from '../_util/classNames';
|
||||
import addEventListener from '../vc-util/Dom/addEventListener';
|
||||
import Affix from '../affix';
|
||||
|
@ -20,6 +22,8 @@ import useStyle from './style';
|
|||
import type { AnchorLinkProps } from './AnchorLink';
|
||||
import AnchorLink from './AnchorLink';
|
||||
import type { Key } from '../_util/type';
|
||||
import PropTypes from '../_util/vue-types';
|
||||
import devWarning from '../vc-util/devWarning';
|
||||
|
||||
export interface AnchorLinkItemProps extends AnchorLinkProps {
|
||||
key: Key;
|
||||
|
@ -27,6 +31,9 @@ export interface AnchorLinkItemProps extends AnchorLinkProps {
|
|||
style?: CSSProperties;
|
||||
children?: AnchorLinkItemProps[];
|
||||
}
|
||||
|
||||
export type AnchorDirection = 'vertical' | 'horizontal';
|
||||
|
||||
function getDefaultContainer() {
|
||||
return window;
|
||||
}
|
||||
|
@ -73,6 +80,7 @@ export const anchorProps = () => ({
|
|||
type: Array as PropType<AnchorLinkItemProps[]>,
|
||||
default: undefined as AnchorLinkItemProps[],
|
||||
},
|
||||
direction: PropTypes.oneOf(['vertical', 'horizontal'] as AnchorDirection[]).def('vertical'),
|
||||
onChange: Function as PropType<(currentActiveLink: string) => void>,
|
||||
onClick: Function as PropType<(e: MouseEvent, link: { title: any; href: string }) => void>,
|
||||
});
|
||||
|
@ -93,6 +101,24 @@ export default defineComponent({
|
|||
props: anchorProps(),
|
||||
setup(props, { emit, attrs, slots, expose }) {
|
||||
const { prefixCls, getTargetContainer, direction } = useConfigInject('anchor', props);
|
||||
const anchorDirection = computed(() => props.direction ?? 'vertical');
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
devWarning(
|
||||
typeof slots.default !== 'function',
|
||||
'Anchor',
|
||||
'`Anchor children` is deprecated. Please use `items` instead.',
|
||||
);
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
devWarning(
|
||||
!(anchorDirection.value === 'horizontal' && props.items?.some(n => 'children' in n)),
|
||||
'Anchor',
|
||||
'`Anchor items#children` is not supported when `Anchor` direction is horizontal.',
|
||||
);
|
||||
}
|
||||
|
||||
const spanLinkNode = ref<HTMLSpanElement>(null);
|
||||
const anchorRef = ref();
|
||||
const state = reactive<AnchorState>({
|
||||
|
@ -184,12 +210,21 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
const updateInk = () => {
|
||||
const linkNode = anchorRef.value.getElementsByClassName(
|
||||
`${prefixCls.value}-link-title-active`,
|
||||
)[0];
|
||||
const linkNode = anchorRef.value.querySelector(`.${prefixCls.value}-link-title-active`);
|
||||
if (linkNode && spanLinkNode.value) {
|
||||
spanLinkNode.value.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2}px`;
|
||||
spanLinkNode.value.style.height = `${linkNode.clientHeight}px`;
|
||||
const horizontalAnchor = anchorDirection.value === 'horizontal';
|
||||
spanLinkNode.value.style.top = horizontalAnchor
|
||||
? ''
|
||||
: `${linkNode.offsetTop + linkNode.clientHeight / 2}px`;
|
||||
spanLinkNode.value.style.height = horizontalAnchor ? '' : `${linkNode.clientHeight}px`;
|
||||
spanLinkNode.value.style.left = horizontalAnchor ? `${linkNode.offsetLeft}px` : '';
|
||||
spanLinkNode.value.style.width = horizontalAnchor ? `${linkNode.clientWidth}px` : '';
|
||||
if (horizontalAnchor) {
|
||||
scrollIntoView(linkNode, {
|
||||
scrollMode: 'if-needed',
|
||||
block: 'nearest',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -210,6 +245,7 @@ export default defineComponent({
|
|||
handleClick: (e, info) => {
|
||||
emit('click', e, info);
|
||||
},
|
||||
direction: anchorDirection,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -237,23 +273,31 @@ export default defineComponent({
|
|||
}
|
||||
updateInk();
|
||||
});
|
||||
|
||||
watch([anchorDirection, getCurrentAnchor, state.links, activeLink], () => {
|
||||
updateInk();
|
||||
});
|
||||
|
||||
const createNestedLink = (options?: AnchorLinkItemProps[]) =>
|
||||
Array.isArray(options)
|
||||
? options.map(item => (
|
||||
<AnchorLink {...item} key={item.key}>
|
||||
{createNestedLink(item.children)}
|
||||
{anchorDirection.value === 'vertical' ? createNestedLink(item.children) : null}
|
||||
</AnchorLink>
|
||||
))
|
||||
: null;
|
||||
|
||||
const [wrapSSR, hashId] = useStyle(prefixCls);
|
||||
|
||||
return () => {
|
||||
const { offsetTop, affix, showInkInFixed } = props;
|
||||
const pre = prefixCls.value;
|
||||
const inkClass = classNames(`${pre}-ink-ball`, {
|
||||
[`${pre}-ink-ball-visible`]: activeLink.value,
|
||||
const inkClass = classNames(`${pre}-ink`, {
|
||||
[`${pre}-ink-visible`]: activeLink.value,
|
||||
});
|
||||
|
||||
const wrapperClass = classNames(hashId.value, props.wrapperClass, `${pre}-wrapper`, {
|
||||
[`${pre}-wrapper-horizontal`]: anchorDirection.value === 'horizontal',
|
||||
[`${pre}-rtl`]: direction.value === 'rtl',
|
||||
});
|
||||
|
||||
|
@ -268,9 +312,7 @@ export default defineComponent({
|
|||
const anchorContent = (
|
||||
<div class={wrapperClass} style={wrapperStyle} ref={anchorRef}>
|
||||
<div class={anchorClass}>
|
||||
<div class={`${pre}-ink`}>
|
||||
<span class={inkClass} ref={spanLinkNode} />
|
||||
</div>
|
||||
<span class={inkClass} ref={spanLinkNode} />
|
||||
{Array.isArray(props.items) ? createNestedLink(props.items) : slots.default?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,27 +2,19 @@
|
|||
|
||||
exports[`renders ./components/anchor/demo/basic.vue correctly 1`] = `
|
||||
<div>
|
||||
<div class="">
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
<div class="css-dev-only-do-not-override-1tii49m">
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#part-1" title="Part 1">Part 1</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-static" title="Static demo">Static demo</a>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#part-2" title="Part 2">Part 2</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo with Target" target="_blank">Basic demo with Target</a>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#part-3" title="Part 3">Part 3</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#API" title="API">API</a>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#Anchor-Props" title="Anchor Props">Anchor Props</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#Link-Props" title="Link Props">Link Props</a>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -30,9 +22,8 @@ exports[`renders ./components/anchor/demo/basic.vue correctly 1`] = `
|
|||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/customizeHighlight.vue correctly 1`] = `
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -51,10 +42,41 @@ exports[`renders ./components/anchor/demo/customizeHighlight.vue correctly 1`] =
|
|||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/horizontal.vue correctly 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<!---->
|
||||
<div class="css-dev-only-do-not-override-1tii49m">
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper ant-anchor-wrapper-horizontal" style="max-height: 100vh;">
|
||||
<div class="ant-anchor"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-1" title="Part 1">Part 1</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-2" title="Part 2">Part 2</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-3" title="Part 3">Part 3</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-4" title="Part 4">Part 4</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-5" title="Part 5">Part 5</a>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#horizontally-part-6" title="Part 6">Part 6</a>
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/onChange.vue correctly 1`] = `
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -74,9 +96,8 @@ exports[`renders ./components/anchor/demo/onChange.vue correctly 1`] = `
|
|||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/onClick.vue correctly 1`] = `
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -96,9 +117,8 @@ exports[`renders ./components/anchor/demo/onClick.vue correctly 1`] = `
|
|||
`;
|
||||
|
||||
exports[`renders ./components/anchor/demo/static.vue correctly 1`] = `
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor ant-anchor-fixed"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
</div>
|
||||
|
@ -119,10 +139,10 @@ exports[`renders ./components/anchor/demo/static.vue correctly 1`] = `
|
|||
|
||||
exports[`renders ./components/anchor/demo/targetOffset.vue correctly 1`] = `
|
||||
<div>
|
||||
<div class="">
|
||||
<div class="ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor">
|
||||
<div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div>
|
||||
<!---->
|
||||
<div class="css-dev-only-do-not-override-1tii49m">
|
||||
<div class="css-dev-only-do-not-override-1tii49m ant-anchor-wrapper" style="max-height: 100vh;">
|
||||
<div class="ant-anchor"><span class="ant-anchor-ink"></span>
|
||||
<div class="ant-anchor-link"><a class="ant-anchor-link-title" href="#components-anchor-demo-basic" title="Basic demo">Basic demo</a>
|
||||
<!---->
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import type { Ref, InjectionKey } from 'vue';
|
||||
import type { Ref, InjectionKey, ComputedRef } from 'vue';
|
||||
import type { AnchorDirection } from './Anchor';
|
||||
import { computed, inject, provide } from 'vue';
|
||||
|
||||
export interface AnchorContext {
|
||||
|
@ -7,6 +8,7 @@ export interface AnchorContext {
|
|||
activeLink: Ref<string>;
|
||||
scrollTo: (link: string) => void;
|
||||
handleClick: (e: Event, info: { title: any; href: string }) => void;
|
||||
direction: ComputedRef<AnchorDirection>;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
@ -25,6 +27,7 @@ const useInjectAnchor = () => {
|
|||
scrollTo: noop,
|
||||
activeLink: computed(() => ''),
|
||||
handleClick: noop,
|
||||
direction: computed(() => 'vertical'),
|
||||
} as AnchorContext);
|
||||
};
|
||||
|
||||
|
|
|
@ -16,17 +16,23 @@ The simplest usage.
|
|||
</docs>
|
||||
|
||||
<template>
|
||||
<a-anchor>
|
||||
<a-anchor-link href="#components-anchor-demo-basic" title="Basic demo" />
|
||||
<a-anchor-link href="#components-anchor-demo-static" title="Static demo" />
|
||||
<a-anchor-link
|
||||
href="#components-anchor-demo-basic"
|
||||
title="Basic demo with Target"
|
||||
target="_blank"
|
||||
/>
|
||||
<a-anchor-link href="#API" title="API">
|
||||
<a-anchor-link href="#Anchor-Props" title="Anchor Props" />
|
||||
<a-anchor-link href="#Link-Props" title="Link Props" />
|
||||
</a-anchor-link>
|
||||
</a-anchor>
|
||||
<a-anchor
|
||||
:items="[
|
||||
{
|
||||
key: 'part-1',
|
||||
href: '#part-1',
|
||||
title: 'Part 1',
|
||||
},
|
||||
{
|
||||
key: 'part-2',
|
||||
href: '#part-2',
|
||||
title: 'Part 2',
|
||||
},
|
||||
{
|
||||
key: 'part-3',
|
||||
href: '#part-3',
|
||||
title: 'Part 3',
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<docs>
|
||||
---
|
||||
order: 1
|
||||
title:
|
||||
zh-CN: 横向 Anchor。
|
||||
en-US: Horizontally aligned anchors
|
||||
---
|
||||
|
||||
|
||||
## zh-CN
|
||||
|
||||
横向 Anchor。
|
||||
|
||||
## en-US
|
||||
|
||||
Horizontally aligned anchors
|
||||
|
||||
</docs>
|
||||
|
||||
<template>
|
||||
<div
|
||||
style="
|
||||
{
|
||||
padding: '20px';
|
||||
}
|
||||
"
|
||||
>
|
||||
<a-anchor
|
||||
direction="horizontal"
|
||||
:items="[
|
||||
{
|
||||
key: 'horizontally-part-1',
|
||||
href: '#horizontally-part-1',
|
||||
title: 'Part 1',
|
||||
},
|
||||
{
|
||||
key: 'horizontally-part-2',
|
||||
href: '#horizontally-part-2',
|
||||
title: 'Part 2',
|
||||
},
|
||||
{
|
||||
key: 'horizontally-part-3',
|
||||
href: '#horizontally-part-3',
|
||||
title: 'Part 3',
|
||||
},
|
||||
{
|
||||
key: 'horizontally-part-4',
|
||||
href: '#horizontally-part-4',
|
||||
title: 'Part 4',
|
||||
},
|
||||
{
|
||||
key: 'horizontally-part-5',
|
||||
href: '#horizontally-part-5',
|
||||
title: 'Part 5',
|
||||
},
|
||||
{
|
||||
key: 'horizontally-part-6',
|
||||
href: '#horizontally-part-6',
|
||||
title: 'Part 6',
|
||||
},
|
||||
]"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<demo-sort>
|
||||
<basic />
|
||||
<horizontal />
|
||||
<static />
|
||||
<on-click />
|
||||
<customize-highlight />
|
||||
|
@ -16,6 +17,7 @@ import OnClick from './onClick.vue';
|
|||
import CustomizeHighlight from './customizeHighlight.vue';
|
||||
import TargetOffset from './targetOffset.vue';
|
||||
import OnChange from './onChange.vue';
|
||||
import Horizontal from './horizontal.vue';
|
||||
import CN from '../index.zh-CN.md';
|
||||
import US from '../index.en-US.md';
|
||||
import { defineComponent } from 'vue';
|
||||
|
@ -29,6 +31,7 @@ export default defineComponent({
|
|||
OnClick,
|
||||
CustomizeHighlight,
|
||||
TargetOffset,
|
||||
Horizontal,
|
||||
OnChange,
|
||||
},
|
||||
setup() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
category: Components
|
||||
type: Other
|
||||
type: Navigation
|
||||
cols: 2
|
||||
title: Anchor
|
||||
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*TBTSR4PyVmkAAAAAAAAAAAAADrJ8AQ/original
|
||||
|
@ -29,7 +29,18 @@ For displaying anchor hyperlinks on page and jumping between them.
|
|||
| targetOffset | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
|
||||
| wrapperClass | The class name of the container | string | - | |
|
||||
| wrapperStyle | The style of the container | object | - | |
|
||||
| items | Data configuration option content, support nesting through children | { href, title, target, children, key }\[] | - | 4.0 |
|
||||
| items | Data configuration option content, support nesting through children | { key, href, title, target, children }\[] [see](#anchoritem) | - | 4.0 |
|
||||
| direction | Set Anchor direction | `vertical` \| `horizontal` | `vertical` | 4.0 |
|
||||
|
||||
### AnchorItem
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| key | The unique identifier of the Anchor Link | string \| number | - | |
|
||||
| href | The target of hyperlink | string | | |
|
||||
| target | Specifies where to display the linked URL | string | | |
|
||||
| title | The content of hyperlink | VueNode \| (item: AnchorItem) => VueNode | | |
|
||||
| children | Nested Anchor Link, `Attention: This attribute does not support horizontal orientation` | [AnchorItem](#anchoritem)\[] | - | |
|
||||
|
||||
### Events
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
category: Components
|
||||
subtitle: 锚点
|
||||
cols: 2
|
||||
type: 其他
|
||||
type: 导航
|
||||
title: Anchor
|
||||
cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*TBTSR4PyVmkAAAAAAAAAAAAADrJ8AQ/original
|
||||
coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JGb3RIzyOCkAAAAAAAAAAAAADrJ8AQ/original
|
||||
|
@ -30,7 +30,18 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*JGb3RIzyOCkAAA
|
|||
| targetOffset | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | `offsetTop` | 1.5.0 |
|
||||
| wrapperClass | 容器的类名 | string | - | |
|
||||
| wrapperStyle | 容器样式 | object | - | |
|
||||
| items | 数据化配置选项内容,支持通过 children 嵌套 | { href, title, target, children, key }\[] | - | 4.0 |
|
||||
| items | 数据化配置选项内容,支持通过 children 嵌套 | { key, href, title, target, children }\[] [具体见](#anchoritem) | - | 4.0 |
|
||||
| direction | 设置导航方向 | `vertical` \| `horizontal` | `vertical` | 4.0 |
|
||||
|
||||
### AnchorItem
|
||||
|
||||
| 成员 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| key | 唯一标志 | string \| number | - | |
|
||||
| href | 锚点链接 | string | - | |
|
||||
| target | 该属性指定在何处显示链接的资源 | string | - | |
|
||||
| title | 文字内容 | VueNode \| (item: AnchorItem) => VueNode | - | |
|
||||
| children | 嵌套的 Anchor Link,`注意:水平方向该属性不支持` | [AnchorItem](#anchoritem)\[] | - | |
|
||||
|
||||
### 事件
|
||||
|
||||
|
|
|
@ -16,8 +16,15 @@ interface AnchorToken extends FullToken<'Anchor'> {
|
|||
|
||||
// ============================== Shared ==============================
|
||||
const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
const { componentCls, holderOffsetBlock, motionDurationSlow, lineWidthBold, colorPrimary } =
|
||||
token;
|
||||
const {
|
||||
componentCls,
|
||||
holderOffsetBlock,
|
||||
motionDurationSlow,
|
||||
lineWidthBold,
|
||||
colorPrimary,
|
||||
lineType,
|
||||
colorSplit,
|
||||
} = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-wrapper`]: {
|
||||
|
@ -34,40 +41,6 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||
position: 'relative',
|
||||
paddingInlineStart: lineWidthBold,
|
||||
|
||||
[`${componentCls}-ink`]: {
|
||||
position: 'absolute',
|
||||
insetBlockStart: 0,
|
||||
insetInlineStart: 0,
|
||||
height: '100%',
|
||||
|
||||
'&::before': {
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
width: lineWidthBold,
|
||||
height: '100%',
|
||||
margin: '0 auto',
|
||||
backgroundColor: token.colorSplit,
|
||||
content: '" "',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-ink-ball`]: {
|
||||
position: 'absolute',
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
display: 'none',
|
||||
transform: 'translateY(-50%)',
|
||||
transition: `top ${motionDurationSlow} ease-in-out`,
|
||||
width: lineWidthBold,
|
||||
backgroundColor: colorPrimary,
|
||||
|
||||
[`&${componentCls}-ink-ball-visible`]: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-link`]: {
|
||||
paddingBlock: token.anchorPaddingBlock,
|
||||
paddingInline: `${token.anchorPaddingInline}px 0`,
|
||||
|
@ -96,13 +69,94 @@ const genSharedAnchorStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
|||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-fixed ${componentCls}-ink ${componentCls}-ink-ball`]: {
|
||||
[`&:not(${componentCls}-wrapper-horizontal)`]: {
|
||||
[componentCls]: {
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
top: 0,
|
||||
height: '100%',
|
||||
borderInlineStart: `${lineWidthBold}px ${lineType} ${colorSplit}`,
|
||||
content: '" "',
|
||||
},
|
||||
|
||||
[`${componentCls}-ink`]: {
|
||||
position: 'absolute',
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
display: 'none',
|
||||
transform: 'translateY(-50%)',
|
||||
transition: `top ${motionDurationSlow} ease-in-out`,
|
||||
width: lineWidthBold,
|
||||
backgroundColor: colorPrimary,
|
||||
|
||||
[`&${componentCls}-ink-visible`]: {
|
||||
display: 'inline-block',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
[`${componentCls}-fixed ${componentCls}-ink ${componentCls}-ink`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const genSharedAnchorHorizontalStyle: GenerateStyle<AnchorToken> = (token): CSSObject => {
|
||||
const { componentCls, motionDurationSlow, lineWidthBold, colorPrimary } = token;
|
||||
|
||||
return {
|
||||
[`${componentCls}-wrapper-horizontal`]: {
|
||||
position: 'relative',
|
||||
|
||||
'&::before': {
|
||||
position: 'absolute',
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
right: {
|
||||
_skip_check_: true,
|
||||
value: 0,
|
||||
},
|
||||
bottom: 0,
|
||||
borderBottom: `1px ${token.lineType} ${token.colorSplit}`,
|
||||
content: '" "',
|
||||
},
|
||||
|
||||
[componentCls]: {
|
||||
overflowX: 'scroll',
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
scrollbarWidth: 'none' /* Firefox */,
|
||||
|
||||
'&::-webkit-scrollbar': {
|
||||
display: 'none' /* Safari and Chrome */,
|
||||
},
|
||||
|
||||
[`${componentCls}-link:first-of-type`]: {
|
||||
paddingInline: 0,
|
||||
},
|
||||
|
||||
[`${componentCls}-ink`]: {
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
transition: `left ${motionDurationSlow} ease-in-out, width ${motionDurationSlow} ease-in-out`,
|
||||
height: lineWidthBold,
|
||||
backgroundColor: colorPrimary,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// ============================== Export ==============================
|
||||
export default genComponentStyleHook('Anchor', token => {
|
||||
const { fontSize, fontSizeLG, padding, paddingXXS } = token;
|
||||
|
@ -115,5 +169,5 @@ export default genComponentStyleHook('Anchor', token => {
|
|||
anchorTitleBlock: (fontSize / 14) * 3,
|
||||
anchorBallSize: fontSizeLG / 2,
|
||||
});
|
||||
return [genSharedAnchorStyle(anchorToken)];
|
||||
return [genSharedAnchorStyle(anchorToken), genSharedAnchorHorizontalStyle(anchorToken)];
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue