mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 02:59:04 +08:00
Merge pull request #27477 from ant-design/feature-merge-master
chore: Feature merge master
This commit is contained in:
commit
f6f3166108
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -1,6 +1,6 @@
|
||||
name: test
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
|
28
.github/workflows/ui.yml
vendored
Normal file
28
.github/workflows/ui.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
name: UI
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: install
|
||||
run: npm install
|
||||
|
||||
- name: test
|
||||
run: npm run test-image
|
||||
|
||||
- name: argos-ci
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: npm run argos -- --token ${{ secrets.ARGOS_TOKEN }} --branch pull/${{ github.event.pull_request.number }}/merge --commit ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: argos-ci
|
||||
if: github.event_name == 'push'
|
||||
run: npm run argos -- --token ${{ secrets.ARGOS_TOKEN }} --branch ${GITHUB_REF##*/} --commit ${{ github.sha }}
|
@ -1,11 +1,7 @@
|
||||
name: Ant Design
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
exclude:
|
||||
- gh-pages
|
||||
trigger: none
|
||||
|
||||
# https://developercommunity.visualstudio.com/comments/949241/view.html
|
||||
pr:
|
||||
autoCancel: true
|
||||
branches:
|
||||
@ -64,32 +60,3 @@ stages:
|
||||
- script: |
|
||||
node ./scripts/azure-github-comment.js "[<img width="534" src="https://user-images.githubusercontent.com/5378891/75333447-1e63a280-58c1-11ea-975d-235367fd1522.png">](https://dev.azure.com/ant-design/ant-design/_build/results?buildId=$(Build.BuildId))"
|
||||
displayName: 'Comment on github'
|
||||
|
||||
- stage: ui
|
||||
variables:
|
||||
${{ if startsWith(variables['Build.SourceBranch'], 'refs/heads/') }}:
|
||||
branchName: $[ replace(variables['Build.SourceBranch'], 'refs/heads/', '') ]
|
||||
commitId: $(Build.SourceVersion)
|
||||
${{ if startsWith(variables['Build.SourceBranch'], 'refs/pull/') }}:
|
||||
branchName: $[ replace(variables['Build.SourceBranch'], 'refs/', '') ]
|
||||
commitId: $(System.PullRequest.SourceCommitId)
|
||||
dependsOn: []
|
||||
jobs:
|
||||
- job: UI_Test
|
||||
steps:
|
||||
- script: |
|
||||
echo $(commitId)
|
||||
- checkout: self
|
||||
displayName: 'Checkout'
|
||||
clean: true
|
||||
fetchDepth: 1
|
||||
- task: NodeTool@0
|
||||
displayName: 'Install Node.js'
|
||||
inputs:
|
||||
versionSpec: '14.7.0'
|
||||
- script: npm install
|
||||
displayName: 'Install modules'
|
||||
- script: npm run test-image
|
||||
displayName: 'UI Test'
|
||||
- script: npm run argos -- --token $ARGOS_TOKEN --branch $(branchName) --commit $(commitId)
|
||||
displayName: 'Upload to argos-ci'
|
||||
|
@ -239,6 +239,8 @@
|
||||
&-in-view&-range-hover-start:not(&-in-range):not(&-range-start):not(&-range-end),
|
||||
&-in-view&-range-hover-end:not(&-in-range):not(&-range-start):not(&-range-end),
|
||||
&-in-view&-range-hover-start&-range-start-single,
|
||||
&-in-view&-range-hover-start&-range-start&-range-end&-range-end-near-hover,
|
||||
&-in-view&-range-hover-end&-range-start&-range-end&-range-start-near-hover,
|
||||
&-in-view&-range-hover-end&-range-end-single,
|
||||
&-in-view&-range-hover:not(&-in-range) {
|
||||
&::after {
|
||||
|
@ -7623,7 +7623,7 @@ exports[`renders ./components/form/demo/validate-static.md correctly 1`] = `
|
||||
class="ant-form-item-control-input-content"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper"
|
||||
class="ant-input-affix-wrapper ant-input-password"
|
||||
>
|
||||
<input
|
||||
action="click"
|
||||
|
@ -12,6 +12,10 @@ export function hasPrefixSuffix(props: InputProps | ClearableInputProps) {
|
||||
return !!(props.prefix || props.suffix || props.allowClear);
|
||||
}
|
||||
|
||||
function hasAddon(props: InputProps | ClearableInputProps) {
|
||||
return !!(props.addonBefore || props.addonAfter);
|
||||
}
|
||||
|
||||
/**
|
||||
* This basic props required for input and textarea.
|
||||
*/
|
||||
@ -121,8 +125,8 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-affix-wrapper-readonly`]: readOnly,
|
||||
[`${prefixCls}-affix-wrapper-borderless`]: !bordered,
|
||||
// https://github.com/ant-design/ant-design/issues/27258
|
||||
[`${className}`]: !allowClear && className,
|
||||
// className will go to addon wrapper
|
||||
[`${className}`]: !hasAddon(this.props) && className,
|
||||
});
|
||||
return (
|
||||
<span
|
||||
@ -145,7 +149,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
renderInputWithLabel(prefixCls: string, labeledElement: React.ReactElement) {
|
||||
const { addonBefore, addonAfter, style, size, className, direction } = this.props;
|
||||
// Not wrap when there is not addons
|
||||
if (!addonBefore && !addonAfter) {
|
||||
if (!hasAddon(this.props)) {
|
||||
return labeledElement;
|
||||
}
|
||||
|
||||
@ -156,8 +160,7 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
) : null;
|
||||
const addonAfterNode = addonAfter ? <span className={addonClassName}>{addonAfter}</span> : null;
|
||||
|
||||
const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, {
|
||||
[wrapperClassName]: addonBefore || addonAfter,
|
||||
const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, wrapperClassName, {
|
||||
[`${wrapperClassName}-rtl`]: direction === 'rtl',
|
||||
});
|
||||
|
||||
@ -197,8 +200,9 @@ class ClearableLabeledInput extends React.Component<ClearableInputProps> {
|
||||
{
|
||||
[`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl',
|
||||
[`${prefixCls}-affix-wrapper-borderless`]: !bordered,
|
||||
// className will go to addon wrapper
|
||||
[`${className}`]: !hasAddon(this.props) && className,
|
||||
},
|
||||
className,
|
||||
);
|
||||
return (
|
||||
<span className={affixWrapperCls} style={style}>
|
||||
|
@ -22,10 +22,8 @@ describe('Input.Search', () => {
|
||||
});
|
||||
|
||||
it('should support ReactNode suffix without error', () => {
|
||||
const fn = () => {
|
||||
mount(<Search suffix={<div>ok</div>} />);
|
||||
};
|
||||
expect(fn).not.toThrow();
|
||||
const wrapper = mount(<Search suffix={<div>ok</div>} />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should disable enter button when disabled prop is true', () => {
|
||||
|
@ -45,6 +45,62 @@ exports[`Input.Search rtl render component should be rendered correctly in RTL d
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support ReactNode suffix without error 1`] = `
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
<div>
|
||||
ok
|
||||
</div>
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-icon-only ant-input-search-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
class="anticon anticon-search"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="search"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support addonAfter 1`] = `
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search"
|
||||
@ -149,7 +205,7 @@ exports[`Input.Search should support addonAfter and suffix for loading 1`] = `
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-search"
|
||||
class="ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
@ -208,7 +264,7 @@ exports[`Input.Search should support addonAfter and suffix for loading 2`] = `
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-search ant-input-search-with-button"
|
||||
class="ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
@ -365,7 +421,7 @@ exports[`Input.Search should support invalid suffix 1`] = `
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-search"
|
||||
class="ant-input-affix-wrapper"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
|
@ -2737,7 +2737,7 @@ Array [
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-affix-wrapper-lg ant-input-search ant-input-search-large ant-input-search-with-button"
|
||||
class="ant-input-affix-wrapper ant-input-affix-wrapper-lg"
|
||||
>
|
||||
<input
|
||||
class="ant-input ant-input-lg"
|
||||
|
@ -354,57 +354,3 @@ exports[`Input should support size in form 1`] = `
|
||||
</div>
|
||||
</form>
|
||||
`;
|
||||
|
||||
exports[`Input.Search should support suffix 1`] = `
|
||||
<span
|
||||
class="ant-input-group-wrapper ant-input-search"
|
||||
>
|
||||
<span
|
||||
class="ant-input-wrapper ant-input-group"
|
||||
>
|
||||
<span
|
||||
class="ant-input-affix-wrapper ant-input-search"
|
||||
>
|
||||
<input
|
||||
class="ant-input"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<span
|
||||
class="ant-input-suffix"
|
||||
>
|
||||
suffix
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
class="ant-input-group-addon"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-icon-only ant-input-search-button"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-label="search"
|
||||
class="anticon anticon-search"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="search"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M909.6 854.5L649.9 594.8C690.2 542.7 712 479 712 412c0-80.2-31.3-155.4-87.9-212.1-56.6-56.7-132-87.9-212.1-87.9s-155.5 31.3-212.1 87.9C143.2 256.5 112 331.8 112 412c0 80.1 31.3 155.5 87.9 212.1C256.5 680.8 331.8 712 412 712c67 0 130.6-21.8 182.7-62l259.7 259.6a8.2 8.2 0 0011.6 0l43.6-43.5a8.2 8.2 0 000-11.6zM570.4 570.4C528 612.7 471.8 636 412 636s-116-23.3-158.4-65.6C211.3 528 188 471.8 188 412s23.3-116.1 65.6-158.4C296 211.3 352.2 188 412 188s116.1 23.2 158.4 65.6S636 352.2 636 412s-23.3 116.1-65.6 158.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
`;
|
||||
|
@ -76,6 +76,20 @@ describe('Input', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('prefix and suffix', () => {
|
||||
it('should support className when has suffix', () => {
|
||||
const wrapper = mount(<Input suffix="suffix" className="my-class-name" />);
|
||||
expect(wrapper.getDOMNode().className.includes('my-class-name')).toBe(true);
|
||||
expect(wrapper.find('input').getDOMNode().className.includes('my-class-name')).toBe(false);
|
||||
});
|
||||
|
||||
it('should support className when has prefix', () => {
|
||||
const wrapper = mount(<Input prefix="prefix" className="my-class-name" />);
|
||||
expect(wrapper.getDOMNode().className.includes('my-class-name')).toBe(true);
|
||||
expect(wrapper.find('input').getDOMNode().className.includes('my-class-name')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('As Form Control', () => {
|
||||
it('should be reset when wrapped in form.getFieldDecorator without initialValue', () => {
|
||||
const Demo = () => {
|
||||
@ -110,13 +124,6 @@ describe('As Form Control', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Input.Search', () => {
|
||||
it('should support suffix', () => {
|
||||
const wrapper = mount(<Input.Search suffix="suffix" />);
|
||||
expect(wrapper.render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Input allowClear', () => {
|
||||
it('should change type when click', () => {
|
||||
const wrapper = mount(<Input allowClear />);
|
||||
@ -189,4 +196,11 @@ describe('Input allowClear', () => {
|
||||
expect(wrapper.find('.ant-input-clear-icon-hidden').exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/27444
|
||||
it('should support className', () => {
|
||||
const wrapper = mount(<Input allowClear className="my-class-name" />);
|
||||
expect(wrapper.getDOMNode().className.includes('my-class-name')).toBe(true);
|
||||
expect(wrapper.find('input').getDOMNode().className.includes('my-class-name')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -33,6 +33,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
prefixCls,
|
||||
rootPrefixCls,
|
||||
bodyStyle,
|
||||
modalRender,
|
||||
} = props;
|
||||
|
||||
devWarning(
|
||||
@ -95,6 +96,7 @@ const ConfirmDialog = (props: ConfirmDialogProps) => {
|
||||
keyboard={keyboard}
|
||||
centered={centered}
|
||||
getContainer={getContainer}
|
||||
modalRender={modalRender}
|
||||
>
|
||||
<div className={`${contentPrefixCls}-body-wrapper`}>
|
||||
<ConfigProvider prefixCls={rootPrefixCls}>
|
||||
|
@ -80,6 +80,7 @@ export interface ModalProps {
|
||||
wrapProps?: any;
|
||||
prefixCls?: string;
|
||||
closeIcon?: React.ReactNode;
|
||||
modalRender?: (node: React.ReactNode) => React.ReactNode;
|
||||
}
|
||||
|
||||
type getContainerFunc = () => HTMLElement;
|
||||
@ -115,6 +116,7 @@ export interface ModalFuncProps {
|
||||
maskTransitionName?: string;
|
||||
direction?: string;
|
||||
bodyStyle?: React.CSSProperties;
|
||||
modalRender?: (node: React.ReactNode) => React.ReactNode;
|
||||
}
|
||||
|
||||
export interface ModalLocale {
|
||||
|
@ -4,4 +4,4 @@ title: 组件总览
|
||||
type: 组件总览
|
||||
---
|
||||
|
||||
`antd` 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践。除了官方组件,我们也提供了[社区精选组件](/docs/react/recommendation)作为必要的补充。
|
||||
`antd` 为 Web 应用提供了丰富的基础 UI 组件,我们还将持续探索企业级应用的最佳 UI 实践。除了官方组件,我们也提供了[社区精选组件](/docs/react/recommendation)作为必要的补充,另外如果您是内网用户,欢迎尝试使用 [TechUI](https://techui.alipay.com)。
|
||||
|
@ -49,7 +49,7 @@ Select component to select value from options.
|
||||
| mode | Set mode of Select | `multiple` \| `tags` | - | |
|
||||
| notFoundContent | Specify content to show when no result matches | ReactNode | `Not Found` | |
|
||||
| open | Controlled open state of dropdown | boolean | - | |
|
||||
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | `value` | |
|
||||
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true. If `options` is set, it should be set to `label` | string | `value` | |
|
||||
| optionLabelProp | Which prop value of option will render as content of select. [Example](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
||||
| options | Select options. Will get better perf than jsx definition | { label, value }\[] | - | |
|
||||
| placeholder | Placeholder of select | ReactNode | - | |
|
||||
|
@ -50,8 +50,8 @@ cover: https://gw.alipayobjects.com/zos/alicdn/_0XzgOis7/Select.svg
|
||||
| mode | 设置 Select 的模式为多选或标签 | `multiple` \| `tags` | - | |
|
||||
| notFoundContent | 当下拉列表为空时显示的内容 | ReactNode | `Not Found` | |
|
||||
| open | 是否展开下拉菜单 | boolean | - | |
|
||||
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索。[示例](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `value` | |
|
||||
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value` | string | `children` | |
|
||||
| optionFilterProp | 搜索时过滤对应的 `option` 属性,如设置为 `children` 表示对内嵌内容进行搜索。若通过 `options` 属性配置选项内容,建议设置 `optionFilterProp="label"` 来对内容进行搜索。 | string | `value` | |
|
||||
| optionLabelProp | 回填到选择框的 Option 的属性值,默认是 Option 的子元素。比如在子元素需要高亮效果时,此值可以设为 `value`。[示例](https://codesandbox.io/s/antd-reproduction-template-tk678) | string | `children` | |
|
||||
| options | 数据化配置选项内容,相比 jsx 定义会获得更好的渲染性能 | { label, value }\[] | - | |
|
||||
| placeholder | 选择框默认文字 | string | - | |
|
||||
| removeIcon | 自定义的多选框清除图标 | ReactNode | - | |
|
||||
|
@ -132,7 +132,7 @@ toc: false
|
||||
|
||||
### UI/UE 设计师
|
||||
|
||||
简历和作品集请投递:lindong.lld#alipay.com
|
||||
简历和作品集请投递:lindong.lld#antgroup.com
|
||||
|
||||
> 注明简历来自 ant.design 官网
|
||||
|
||||
@ -146,13 +146,13 @@ toc: false
|
||||
- 有数据驱动的增长设计实践,加分;
|
||||
- 深度理解 SAP、Salesforce、Google 等设计体系,能提出自己独到见解并落实到实践中,加加加分。
|
||||
- 岗位职责:
|
||||
- 参与[蚂蚁金融科技](https://tech.antfin.com/)、[区块链](https://tech.antfin.com/blockchain)、人工智能等企业级产品的设计工作;
|
||||
- 参与[蚂蚁链](https://blockchain.antgroup.com/)、人工智能、数据平台等企业级产品的设计工作;
|
||||
- 参与[语雀](https://www.yuque.com/)、[云凤蝶](https://www.yunfengdie.com/)等创新产品的设计工作;
|
||||
- 参与 Ant Design 的打磨,将其建设成全球卓越的设计体系。
|
||||
- 参与 AntV 的打磨,将其建设成全球一流的数据可视化体系。
|
||||
- One More Thing ❤️ :
|
||||
|
||||
- 你们总是为世界带去美好,但总是忘却你们也需要美好。我们正在努力打造 [🍳 Kitchen:一款为设计师提效的 Sketch 工具集](https://kitchen.alipay.com/)、[语雀画板](https://yuque.com/) 等专属设计师的产品,让设计真正变成财富。期待志同道合的你,一道给设计行业带来「微小而美好的改变」。
|
||||
- 你们总是为世界带去美好,但总是忘却你们也需要美好。我们正在努力打造 [🍳 Kitchen:一款为设计师提效的 Sketch 工具集](https://kitchen.alipay.com/)等专属设计师的产品,让设计真正变成财富。期待志同道合的你,一道给设计行业带来「微小而美好的改变」。
|
||||
|
||||
### 前端工程师
|
||||
|
||||
|
@ -218,7 +218,7 @@
|
||||
"http-server": "^0.12.0",
|
||||
"husky": "^4.0.3",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"ignore-emit-webpack-plugin": "^2.0.2",
|
||||
"ignore-emit-webpack-plugin": "2.0.3",
|
||||
"immutability-helper": "^3.0.0",
|
||||
"inquirer": "^7.1.0",
|
||||
"intersection-observer": "^0.11.0",
|
||||
|
@ -16,42 +16,40 @@ interface Recommend {
|
||||
|
||||
const LIST_CN: Recommend[] = [
|
||||
{
|
||||
title: '这几个 Ant Design 色彩的小知识,我猜你不知道!',
|
||||
description: '今天不说大道理,就给大家科普几个 Ant Design 色彩的小知识——',
|
||||
img: 'https://pic4.zhimg.com/v2-254eebfe6b092b0b9c1f8d17f3c64d3d_1440w.jpg?source=172ae18b',
|
||||
href: 'https://zhuanlan.zhihu.com/p/268168773',
|
||||
title: '新一代 Ant Design,未来已来,邀你共建!',
|
||||
description: '欢迎加入,Ant Designers!',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*yGcPRroihLQAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/269789439',
|
||||
popularize: true,
|
||||
},
|
||||
{
|
||||
title: '在Ant Design 4.0里,我们如何追求快乐的工作?',
|
||||
description: '蚂蚁集团高级体验设计专家林外在上海外滩大会上分享 Ant Design4.0 背后的设计理念',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_b56775/afts/img/A*psuyRqopCIEAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://mp.weixin.qq.com/s/QUqy1-g0FElqOs9cQFFWHA',
|
||||
},
|
||||
{
|
||||
title: '第十五届 D2 前端技术论坛 - 无界',
|
||||
description: '前端热爱,技术无界,第十五届 D2 前端技术论坛,我们云端相聚!',
|
||||
img: 'https://img.alicdn.com/tfs/TB1R39KnSR26e4jSZFEXXbwuXXa-1960-768.png',
|
||||
href: 'http://d2forum.alibaba-inc.com/',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design 4.0 的一些杂事儿 - VirtualList 篇',
|
||||
description:
|
||||
'在 React 中,我们常说不太需要关注性能问题。然而作为组件库,这些事你就不得不考虑一下。',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*ULOBQroFRMQAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/237996796',
|
||||
},
|
||||
];
|
||||
|
||||
const LIST_EN: Recommend[] = [
|
||||
{
|
||||
title: 'These a few color knowledge of Ant Design, I guess you do not know!',
|
||||
description:
|
||||
'🎨 This time, we do not talk about theoretical knowledge, just a few color design skills of Ant Design',
|
||||
img: 'https://pic4.zhimg.com/v2-254eebfe6b092b0b9c1f8d17f3c64d3d_1440w.jpg?source=172ae18b',
|
||||
href: 'https://zhuanlan.zhihu.com/p/268168773',
|
||||
title: 'New generation of Ant Design, the future is coming, let us create it together!',
|
||||
description: 'Welcome to join us,Ant Designers!',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*yGcPRroihLQAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/269789439',
|
||||
popularize: true,
|
||||
},
|
||||
{
|
||||
title: 'Next Generation of Component Library?',
|
||||
title: 'How do we pursue happy work in Ant Design 4.0?',
|
||||
description:
|
||||
'😎 With the launch of React hooks and Vue composition API, perhaps we have met a new breakthrough point of component libraries.',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_08e378/afts/img/A*SU6hQ5jHVEsAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://zhuanlan.zhihu.com/p/252824872',
|
||||
'Ant group senior experience design expert Lin Wai shares the design concept behind Ant Design 4.0',
|
||||
img: 'https://gw.alipayobjects.com/mdn/rms_b56775/afts/img/A*psuyRqopCIEAAAAAAAAAAAAAARQnAQ',
|
||||
href: 'https://mp.weixin.qq.com/s/QUqy1-g0FElqOs9cQFFWHA',
|
||||
},
|
||||
{
|
||||
title: 'Stories about Ant Design 4.0: VirtualList',
|
||||
|
@ -77,7 +77,7 @@ const Home = (props: { location: any }) => {
|
||||
<BlockContent
|
||||
title={<FormattedMessage id="app.home.more" />}
|
||||
extra={
|
||||
<Link to={getLink()}>
|
||||
<Link to={getLink()} target="_blank">
|
||||
<FormattedMessage id="app.home.view-more" />
|
||||
</Link>
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ export interface NavigationProps extends SharedProps {
|
||||
responsive: null | 'narrow' | 'crowded';
|
||||
location: { pathname: string; query: any };
|
||||
directionText: string;
|
||||
showTechUIButton: boolean;
|
||||
onLangChange: () => void;
|
||||
onDirectionChange: () => void;
|
||||
}
|
||||
@ -29,6 +30,7 @@ export default ({
|
||||
responsive,
|
||||
location,
|
||||
directionText,
|
||||
showTechUIButton,
|
||||
onLangChange,
|
||||
onDirectionChange,
|
||||
}: NavigationProps) => {
|
||||
@ -100,6 +102,13 @@ export default ({
|
||||
<FormattedMessage id="app.header.menu.resource" />
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
{showTechUIButton && (
|
||||
<Menu.Item key="tech-ui">
|
||||
<a href="https://techui.alipay.com" target="__blank" rel="noopener noreferrer">
|
||||
TechUI
|
||||
</a>
|
||||
</Menu.Item>
|
||||
)}
|
||||
{isZhCN && !isGitee && (
|
||||
<Menu.Item key="mirror">
|
||||
<a href="https://ant-design.gitee.io">国内镜像</a>
|
||||
|
@ -12,6 +12,7 @@ import More from './More';
|
||||
import Navigation from './Navigation';
|
||||
import Github from './Github';
|
||||
import SiteContext from '../SiteContext';
|
||||
import { ping } from '../../utils';
|
||||
|
||||
import './index.less';
|
||||
|
||||
@ -61,15 +62,19 @@ interface HeaderState {
|
||||
menuVisible: boolean;
|
||||
windowWidth: number;
|
||||
searching: boolean;
|
||||
showTechUIButton: boolean;
|
||||
}
|
||||
|
||||
class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
static contextType = SiteContext;
|
||||
|
||||
pingTimer: NodeJS.Timeout;
|
||||
|
||||
state = {
|
||||
menuVisible: false,
|
||||
windowWidth: 1400,
|
||||
searching: false,
|
||||
showTechUIButton: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
@ -79,10 +84,19 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
|
||||
window.addEventListener('resize', this.onWindowResize);
|
||||
this.onWindowResize();
|
||||
|
||||
this.pingTimer = ping(status => {
|
||||
if (status !== 'timeout' && status !== 'error') {
|
||||
this.setState({
|
||||
showTechUIButton: true,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('resize', this.onWindowResize);
|
||||
clearTimeout(this.pingTimer);
|
||||
}
|
||||
|
||||
onWindowResize = () => {
|
||||
@ -179,7 +193,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
return (
|
||||
<SiteContext.Consumer>
|
||||
{({ isMobile }) => {
|
||||
const { menuVisible, windowWidth, searching } = this.state;
|
||||
const { menuVisible, windowWidth, searching, showTechUIButton } = this.state;
|
||||
const { direction } = this.context;
|
||||
const {
|
||||
location,
|
||||
@ -232,6 +246,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
location={location}
|
||||
responsive={responsive}
|
||||
isMobile={isMobile}
|
||||
showTechUIButton={showTechUIButton}
|
||||
pathname={pathname}
|
||||
directionText={this.getNextDirectionText()}
|
||||
onLangChange={this.onLangChange}
|
||||
|
Loading…
Reference in New Issue
Block a user