Skip to content

Commit 9cc44f8

Browse files
feat(module:anchor): horizontal anchors (#8342)
* feat(module:anchor): horizontal anchors * feat(module:anchor): horizontal anchors * feat(module:anchor): horizontal anchors * feat(module:anchor): horizontal anchors * feat(module:anchor): horizontal anchors * feat(module:anchor): horizontal anchors
1 parent e7b1fa0 commit 9cc44f8

8 files changed

Lines changed: 147 additions & 40 deletions

File tree

‎components/anchor/anchor-link.component.ts‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
ViewEncapsulation
2020
} from '@angular/core';
2121

22-
import { NzSafeAny } from 'ng-zorro-antd/core/types';
22+
import { NzDirectionVHType, NzSafeAny } from 'ng-zorro-antd/core/types';
2323

2424
import { NzAnchorComponent } from './anchor.component';
2525

@@ -44,7 +44,9 @@ import { NzAnchorComponent } from './anchor.component';
4444
<ng-template [ngTemplateOutlet]="titleTpl || nzTemplate" />
4545
}
4646
</a>
47-
<ng-content></ng-content>
47+
@if (nzDirection === 'vertical') {
48+
<ng-content></ng-content>
49+
}
4850
`,
4951
encapsulation: ViewEncapsulation.None,
5052
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -58,6 +60,7 @@ export class NzAnchorLinkComponent implements OnInit, OnDestroy {
5860

5961
titleStr: string | null = '';
6062
titleTpl?: TemplateRef<NzSafeAny>;
63+
nzDirection: NzDirectionVHType = 'vertical';
6164

6265
@Input()
6366
set nzTitle(value: string | TemplateRef<void>) {
@@ -81,6 +84,7 @@ export class NzAnchorLinkComponent implements OnInit, OnDestroy {
8184

8285
ngOnInit(): void {
8386
this.anchorComp.registerLink(this);
87+
this.nzDirection = this.anchorComp.nzDirection;
8488
}
8589

8690
getLinkTitleElement(): HTMLAnchorElement {

‎components/anchor/anchor.component.ts‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { takeUntil, throttleTime } from 'rxjs/operators';
2929
import { NzAffixModule } from 'ng-zorro-antd/affix';
3030
import { NzConfigKey, NzConfigService, WithConfig } from 'ng-zorro-antd/core/config';
3131
import { NzScrollService } from 'ng-zorro-antd/core/services';
32-
import { BooleanInput, NgStyleInterface, NumberInput, NzSafeAny } from 'ng-zorro-antd/core/types';
32+
import { BooleanInput, NgStyleInterface, NumberInput, NzDirectionVHType, NzSafeAny } from 'ng-zorro-antd/core/types';
3333
import { InputBoolean, InputNumber } from 'ng-zorro-antd/core/util';
3434

3535
import { NzAnchorLinkComponent } from './anchor-link.component';
@@ -61,7 +61,11 @@ const passiveEventListenerOptions = normalizePassiveListenerOptions({ passive: t
6161
}
6262
6363
<ng-template #content>
64-
<div class="ant-anchor-wrapper" [ngStyle]="wrapperStyle">
64+
<div
65+
class="ant-anchor-wrapper"
66+
[ngClass]="{ 'ant-anchor-wrapper-horizontal': nzDirection === 'horizontal' }"
67+
[ngStyle]="wrapperStyle"
68+
>
6569
<div class="ant-anchor" [ngClass]="{ 'ant-anchor-fixed': !nzAffix && !nzShowInkInFixed }">
6670
<div class="ant-anchor-ink">
6771
<div class="ant-anchor-ink-ball" #ink></div>
@@ -107,6 +111,7 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
107111

108112
@Input() nzContainer?: string | HTMLElement;
109113
@Input() nzCurrentAnchor?: string;
114+
@Input() nzDirection: NzDirectionVHType = 'vertical';
110115

111116
@Output() readonly nzClick = new EventEmitter<string>();
112117
@Output() readonly nzChange = new EventEmitter<string>();
@@ -219,7 +224,11 @@ export class NzAnchorComponent implements OnDestroy, AfterViewInit, OnChanges {
219224

220225
targetComp.setActive();
221226
const linkNode = targetComp.getLinkTitleElement();
222-
this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
227+
if (this.nzDirection === 'vertical') {
228+
this.ink.nativeElement.style.top = `${linkNode.offsetTop + linkNode.clientHeight / 2 - 4.5}px`;
229+
} else {
230+
this.ink.nativeElement.style.left = `${linkNode.offsetLeft + linkNode.clientWidth / 2}px`;
231+
}
223232
this.activeLink = (comp || targetComp).nzHref;
224233
if (originalActiveLink !== this.activeLink) {
225234
this.nzChange.emit(this.activeLink);

‎components/anchor/anchor.spec.ts‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { By } from '@angular/platform-browser';
66
import { NzScrollService } from 'ng-zorro-antd/core/services';
77
import { NzAnchorModule } from './anchor.module';
88
import { NzAnchorComponent } from './anchor.component';
9+
import { NzDirectionVHType } from 'ng-zorro-antd/core/types';
910

1011
const throttleTime = 51;
1112

@@ -61,6 +62,19 @@ describe('anchor', () => {
6162
}, throttleTime);
6263
});
6364

65+
it('should actived when scrolling to the anchor - horizontal', (done: () => void) => {
66+
context.nzDirection = 'horizontal';
67+
fixture.detectChanges();
68+
expect(context._scroll).not.toHaveBeenCalled();
69+
page.scrollTo();
70+
setTimeout(() => {
71+
const inkNode = page.getEl('.ant-anchor-ink-ball');
72+
expect(+inkNode.style.left!.replace('px', '')).not.toBeNull();
73+
expect(context._scroll).toHaveBeenCalled();
74+
done();
75+
}, throttleTime);
76+
});
77+
6478
it('should clean actived when leave all anchor', fakeAsync(() => {
6579
spyOn(context.comp, 'clearActive' as any);
6680
page.scrollTo();
@@ -226,6 +240,20 @@ describe('anchor', () => {
226240
});
227241
});
228242

243+
describe('direction', () => {
244+
it(`should have vertical direction by default`, () => {
245+
const wrapperEl = dl.query(By.css('.ant-anchor-wrapper'));
246+
expect(wrapperEl.nativeElement.classList).not.toContain('ant-anchor-wrapper-horizontal');
247+
});
248+
249+
it(`should have correct class name in horizontal mode`, () => {
250+
context.nzDirection = 'horizontal';
251+
fixture.detectChanges();
252+
const wrapperEl = dl.query(By.css('.ant-anchor-wrapper'));
253+
expect(wrapperEl.nativeElement.classList).toContain('ant-anchor-wrapper-horizontal');
254+
});
255+
});
256+
229257
describe('**boundary**', () => {
230258
it('#getOffsetTop', (done: () => void) => {
231259
const el1 = document.getElementById('何时使用')!;
@@ -273,6 +301,7 @@ describe('anchor', () => {
273301
[nzTargetOffset]="nzTargetOffset"
274302
[nzContainer]="nzContainer"
275303
[nzCurrentAnchor]="nzCurrentAnchor"
304+
[nzDirection]="nzDirection"
276305
(nzClick)="_click($event)"
277306
(nzScroll)="_scroll($event)"
278307
(nzChange)="_change($event)"
@@ -332,6 +361,7 @@ export class TestComponent {
332361
nzShowInkInFixed = false;
333362
nzContainer: any = null;
334363
nzCurrentAnchor?: string;
364+
nzDirection: NzDirectionVHType = 'vertical';
335365
_click() {}
336366
_change() {}
337367
_scroll() {}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
order: 7
3+
title:
4+
zh-CN: 横向 Anchor
5+
en-US: Horizontal Anchor
6+
---
7+
8+
## zh-CN
9+
10+
横向 Anchor。
11+
12+
## en-US
13+
14+
Horizontally aligned anchors
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'nz-demo-anchor-horizontal-anchor',
5+
template: `
6+
<nz-anchor [nzDirection]="'horizontal'">
7+
<nz-link nzHref="#components-anchor-demo-basic" nzTitle="Basic demo"></nz-link>
8+
<nz-link nzHref="#components-anchor-demo-static" nzTitle="Static demo"></nz-link>
9+
<nz-link nzHref="#api" nzTitle="API">
10+
<nz-link nzHref="#nz-anchor" nzTitle="nz-anchor"></nz-link>
11+
<nz-link nzHref="#nz-link" nzTitle="nz-link"></nz-link>
12+
</nz-link>
13+
</nz-anchor>
14+
`
15+
})
16+
export class NzDemoAnchorHorizontalAnchorComponent {}

‎components/anchor/doc/index.en-US.md‎

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,24 @@ import { NzAnchorModule } from 'ng-zorro-antd/anchor';
1919

2020
### nz-anchor:standalone
2121

22-
| Property | Description | Type | Default | Global Config |
23-
| -------- | ----------- | ---- | ------- | ------------- |
24-
| `[nzAffix]` | Fixed mode of Anchor | `boolean` | `true` |
25-
| `[nzBounds]` | Bounding distance of anchor area, unit: px | `number` | `5` | ✅ |
26-
| `[nzOffsetTop]` | Pixels to offset from top when calculating position of scroll | `number` | `0` | ✅ |
27-
| `[nzShowInkInFixed]` | Whether show ink-balls in Fixed mode | `boolean` | `false` | ✅ |
28-
| `[nzTargetOffset]` | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | |
29-
| `[nzContainer]` | Scrolling container | `string \| HTMLElement` | `window` |
30-
| `[nzCurrentAnchor]` | Customize the anchor highlight | string | - | |
31-
| `(nzClick)` | Click of Anchor item | `EventEmitter<string>` | - |
32-
| `(nzChange)` | Listening for anchor link change | `EventEmitter<string>` | - | |
33-
| `(nzScroll)` | The scroll function that is triggered when scrolling to an anchor. | `EventEmitter<NzAnchorLinkComponent>` | - |
22+
| Property | Description | Type | Default | Global Config |
23+
| -------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------- | ------------ | ------------- |
24+
| `[nzAffix]` | Fixed mode of Anchor | `boolean` | `true` |
25+
| `[nzBounds]` | Bounding distance of anchor area, unit: px | `number` | `5` | ✅ |
26+
| `[nzOffsetTop]` | Pixels to offset from top when calculating position of scroll | `number` | `0` | ✅ |
27+
| `[nzShowInkInFixed]` | Whether show ink-balls in Fixed mode | `boolean` | `false` | ✅ |
28+
| `[nzTargetOffset]` | Anchor scroll offset, default as `offsetTop`, [example](#components-anchor-demo-targetOffset) | number | - | |
29+
| `[nzContainer]` | Scrolling container | `string \| HTMLElement` | `window` |
30+
| `[nzCurrentAnchor]` | Customize the anchor highlight | string | - | |
31+
| `[nzDirection]` | Set Anchor direction | `'vertical' \| 'horizontal'` | `'vertical'` | |
32+
| `(nzClick)` | Click of Anchor item | `EventEmitter<string>` | - |
33+
| `(nzChange)` | Listening for anchor link change | `EventEmitter<string>` | - | |
34+
| `(nzScroll)` | The scroll function that is triggered when scrolling to an anchor. | `EventEmitter<NzAnchorLinkComponent>` | - |
3435

3536
### nz-link:standalone
3637

37-
| Property | Description | Type | Default |
38-
| -------- | ----------- | ---- | ------- |
39-
| `[nzHref]` | target of hyperlink | `string` | - |
40-
| `[nzTarget]` | Specifies where to display the linked URL | string | - | |
41-
| `[nzTitle]` | content of hyperlink | `string \| TemplateRef<void>` | - |
38+
| Property | Description | Type | Default |
39+
| ------------ | ----------------------------------------- | ----------------------------- | ------- | --- |
40+
| `[nzHref]` | target of hyperlink | `string` | - |
41+
| `[nzTarget]` | Specifies where to display the linked URL | string | - | |
42+
| `[nzTitle]` | content of hyperlink | `string \| TemplateRef<void>` | - |

‎components/anchor/doc/index.zh-CN.md‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,28 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_1-C1JwsC/Anchor.svg
1616
import { NzAnchorModule } from 'ng-zorro-antd/anchor';
1717
```
1818

19-
2019
## API
2120

2221
### nz-anchor:standalone
2322

24-
| 成员 | 说明 | 类型 | 默认值 | 全局配置 |
25-
| --- | --- | --- | --- | --- |
26-
| `[nzAffix]` | 固定模式 | `boolean` | `true` |
27-
| `[nzBounds]` | 锚点区域边界,单位:px | `number` | `5` | ✅ |
28-
| `[nzOffsetTop]` | 距离窗口顶部达到指定偏移量后触发 | `number` | - | ✅ |
29-
| `[nzShowInkInFixed]` | 固定模式是否显示小圆点 | `boolean` | `false` | ✅ |
30-
| `[nzTargetOffset]` | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | |
31-
| `[nzContainer]` | 指定滚动的容器 | `string \| HTMLElement` | `window` |
32-
| `[nzCurrentAnchor]` | 自定义高亮的锚点 | string | - | |
33-
| `(nzClick)` | 点击项触发 | `EventEmitter<string>` | - |
34-
| `(nzChange)` | 监听锚点链接改变 | `EventEmitter<string>` | - | |
35-
| `(nzScroll)` | 滚动至某锚点时触发 | `EventEmitter<NzAnchorLinkComponent>` | - |
23+
| 成员 | 说明 | 类型 | 默认值 | 全局配置 |
24+
| -------------------- | ----------------------------------------------------------------------------------- | ------------------------------------- | ------------ | -------- |
25+
| `[nzAffix]` | 固定模式 | `boolean` | `true` |
26+
| `[nzBounds]` | 锚点区域边界,单位:px | `number` | `5` | ✅ |
27+
| `[nzOffsetTop]` | 距离窗口顶部达到指定偏移量后触发 | `number` | - | ✅ |
28+
| `[nzShowInkInFixed]` | 固定模式是否显示小圆点 | `boolean` | `false` | ✅ |
29+
| `[nzTargetOffset]` | 锚点滚动偏移量,默认与 offsetTop 相同,[例子](#components-anchor-demo-targetOffset) | number | - | |
30+
| `[nzContainer]` | 指定滚动的容器 | `string \| HTMLElement` | `window` |
31+
| `[nzCurrentAnchor]` | 自定义高亮的锚点 | string | - | |
32+
| `[nzDirection]` | 设置导航方向 | `'vertical' \| 'horizontal'` | `'vertical'` | |
33+
| `(nzClick)` | 点击项触发 | `EventEmitter<string>` | - |
34+
| `(nzChange)` | 监听锚点链接改变 | `EventEmitter<string>` | - | |
35+
| `(nzScroll)` | 滚动至某锚点时触发 | `EventEmitter<NzAnchorLinkComponent>` | - |
3636

3737
### nz-link:standalone
3838

39-
| 成员 | 说明 | 类型 | 默认值 |
40-
| --- | --- | --- | --- |
41-
| `[nzHref]` | 锚点链接 | `string` | - |
42-
| `[nzTarget]` | 该属性指定在何处显示链接的资源。 | string | - | |
43-
| `[nzTitle]` | 文字内容 | `string \| TemplateRef<void>` | - |
39+
| 成员 | 说明 | 类型 | 默认值 |
40+
| ------------ | -------------------------------- | ----------------------------- | ------ | --- |
41+
| `[nzHref]` | 锚点链接 | `string` | - |
42+
| `[nzTarget]` | 该属性指定在何处显示链接的资源。 | string | - | |
43+
| `[nzTitle]` | 文字内容 | `string \| TemplateRef<void>` | - |

‎components/anchor/style/index.less‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,39 @@
1414
padding-left: 4px;
1515
overflow: auto;
1616
background-color: @anchor-bg;
17+
18+
&-horizontal {
19+
margin-left: unset;
20+
padding-left: unset;
21+
margin-bottom: -4px;
22+
padding-bottom: 4px;
23+
24+
.ant-anchor {
25+
display: flex;
26+
27+
&-ink {
28+
top: unset;
29+
bottom: 0;
30+
width: 100%;
31+
height: unset;
32+
33+
&:before {
34+
width: 100%;
35+
height: 2px;
36+
}
37+
38+
&-ball {
39+
transform: translate(-50%, -50%);
40+
}
41+
}
42+
43+
&-link {
44+
&:first-of-type {
45+
padding-inline: 0;
46+
}
47+
}
48+
}
49+
}
1750
}
1851

1952
&-ink {

0 commit comments

Comments
 (0)