mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-12-02 20:19:44 +08:00
Merge pull request #16187 from ant-design/page-header-button
Back icon should is a button
This commit is contained in:
commit
4e5497328a
@ -5,8 +5,8 @@
|
||||
import * as React from 'react';
|
||||
import KeyCode from 'rc-util/lib/KeyCode';
|
||||
|
||||
interface TransButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
|
||||
onClick?: () => void;
|
||||
interface TransButtonProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
onClick?: (e?: React.MouseEvent<HTMLDivElement>) => void;
|
||||
}
|
||||
|
||||
const inlineStyle: React.CSSProperties = {
|
||||
@ -14,20 +14,21 @@ const inlineStyle: React.CSSProperties = {
|
||||
background: 'transparent',
|
||||
padding: 0,
|
||||
lineHeight: 'inherit',
|
||||
display: 'inline-block',
|
||||
};
|
||||
|
||||
class TransButton extends React.Component<TransButtonProps> {
|
||||
button?: HTMLButtonElement;
|
||||
div?: HTMLDivElement;
|
||||
lastKeyCode?: number;
|
||||
|
||||
onKeyDown: React.KeyboardEventHandler<HTMLButtonElement> = event => {
|
||||
onKeyDown: React.KeyboardEventHandler<HTMLDivElement> = event => {
|
||||
const { keyCode } = event;
|
||||
if (keyCode === KeyCode.ENTER) {
|
||||
event.preventDefault();
|
||||
}
|
||||
};
|
||||
|
||||
onKeyUp: React.KeyboardEventHandler<HTMLButtonElement> = event => {
|
||||
onKeyUp: React.KeyboardEventHandler<HTMLDivElement> = event => {
|
||||
const { keyCode } = event;
|
||||
const { onClick } = this.props;
|
||||
if (keyCode === KeyCode.ENTER && onClick) {
|
||||
@ -35,26 +36,28 @@ class TransButton extends React.Component<TransButtonProps> {
|
||||
}
|
||||
};
|
||||
|
||||
setRef = (btn: HTMLButtonElement) => {
|
||||
this.button = btn;
|
||||
setRef = (btn: HTMLDivElement) => {
|
||||
this.div = btn;
|
||||
};
|
||||
|
||||
focus() {
|
||||
if (this.button) {
|
||||
this.button.focus();
|
||||
if (this.div) {
|
||||
this.div.focus();
|
||||
}
|
||||
}
|
||||
|
||||
blur() {
|
||||
if (this.button) {
|
||||
this.button.blur();
|
||||
if (this.div) {
|
||||
this.div.blur();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { style } = this.props;
|
||||
return (
|
||||
<button
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
ref={this.setRef}
|
||||
{...this.props}
|
||||
onKeyDown={this.onKeyDown}
|
||||
|
@ -53,4 +53,7 @@ export default {
|
||||
copied: 'copy success',
|
||||
expand: 'expand',
|
||||
},
|
||||
PageHeader: {
|
||||
back: 'back',
|
||||
},
|
||||
};
|
||||
|
@ -53,4 +53,7 @@ export default {
|
||||
copied: '复制成功',
|
||||
expand: '展开',
|
||||
},
|
||||
PageHeader: {
|
||||
back: '返回',
|
||||
},
|
||||
};
|
||||
|
@ -39,4 +39,7 @@ export default {
|
||||
Empty: {
|
||||
description: '無此資料',
|
||||
},
|
||||
PageHeader: {
|
||||
back: '返回',
|
||||
},
|
||||
};
|
||||
|
@ -5,27 +5,35 @@ exports[`renders ./components/page-header/demo/actions.md correctly 1`] = `
|
||||
class="ant-page-header ant-page-header-has-footer"
|
||||
>
|
||||
<div
|
||||
class="ant-page-header-back-icon"
|
||||
class="ant-page-header-back"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: arrow-left"
|
||||
class="anticon anticon-arrow-left"
|
||||
<div
|
||||
aria-label="back"
|
||||
class="ant-page-header-back-button"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="arrow-left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
<i
|
||||
aria-label="icon: arrow-left"
|
||||
class="anticon anticon-arrow-left"
|
||||
>
|
||||
<path
|
||||
d="M872 474H286.9l350.2-304c5.6-4.9 2.2-14-5.2-14h-88.5c-3.9 0-7.6 1.4-10.5 3.9L155 487.8a31.96 31.96 0 0 0 0 48.3L535.1 866c1.5 1.3 3.3 2 5.2 2h91.5c7.4 0 10.8-9.2 5.2-14L286.9 550H872c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="arrow-left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M872 474H286.9l350.2-304c5.6-4.9 2.2-14-5.2-14h-88.5c-3.9 0-7.6 1.4-10.5 3.9L155 487.8a31.96 31.96 0 0 0 0 48.3L535.1 866c1.5 1.3 3.3 2 5.2 2h91.5c7.4 0 10.8-9.2 5.2-14L286.9 550H872c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
/>
|
||||
@ -406,27 +414,35 @@ exports[`renders ./components/page-header/demo/basic.md correctly 1`] = `
|
||||
class="ant-page-header"
|
||||
>
|
||||
<div
|
||||
class="ant-page-header-back-icon"
|
||||
class="ant-page-header-back"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: arrow-left"
|
||||
class="anticon anticon-arrow-left"
|
||||
<div
|
||||
aria-label="back"
|
||||
class="ant-page-header-back-button"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="arrow-left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
<i
|
||||
aria-label="icon: arrow-left"
|
||||
class="anticon anticon-arrow-left"
|
||||
>
|
||||
<path
|
||||
d="M872 474H286.9l350.2-304c5.6-4.9 2.2-14-5.2-14h-88.5c-3.9 0-7.6 1.4-10.5 3.9L155 487.8a31.96 31.96 0 0 0 0 48.3L535.1 866c1.5 1.3 3.3 2 5.2 2h91.5c7.4 0 10.8-9.2 5.2-14L286.9 550H872c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="arrow-left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M872 474H286.9l350.2-304c5.6-4.9 2.2-14-5.2-14h-88.5c-3.9 0-7.6 1.4-10.5 3.9L155 487.8a31.96 31.96 0 0 0 0 48.3L535.1 866c1.5 1.3 3.3 2 5.2 2h91.5c7.4 0 10.8-9.2 5.2-14L286.9 550H872c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</div>
|
||||
<div
|
||||
class="ant-divider ant-divider-vertical"
|
||||
/>
|
||||
|
@ -19,23 +19,23 @@ describe('PageHeader', () => {
|
||||
},
|
||||
];
|
||||
const wrapper = mount(<PageHeader title="Page Title" breadcrumb={{ routes }} />);
|
||||
expect(wrapper.find('.ant-page-header-back-icon')).toHaveLength(0);
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
it('pageHeader should no contain back it back', () => {
|
||||
it('pageHeader should no contain back', () => {
|
||||
const wrapper = mount(<PageHeader title="Page Title" backIcon={false} />);
|
||||
expect(wrapper.find('.ant-page-header-back-icon')).toHaveLength(0);
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('pageHeader should contain back it back', () => {
|
||||
const callback = jest.fn(() => true);
|
||||
const wrapper = mount(<PageHeader title="Page Title" onBack={callback} />);
|
||||
expect(wrapper.find('.ant-page-header-back-icon')).toHaveLength(1);
|
||||
expect(wrapper.find('.ant-page-header-back')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('pageHeader onBack transfer', () => {
|
||||
const callback = jest.fn(() => true);
|
||||
const wrapper = mount(<PageHeader title="Page Title" onBack={callback} />);
|
||||
wrapper.find('.ant-page-header-back-icon').simulate('click');
|
||||
wrapper.find('div.ant-page-header-back-button').simulate('click');
|
||||
expect(callback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
@ -6,7 +6,8 @@ import { BreadcrumbProps } from '../breadcrumb';
|
||||
import Divider from '../divider';
|
||||
import Tag from '../tag';
|
||||
import Breadcrumb from '../breadcrumb';
|
||||
import Wave from '../_util/wave';
|
||||
import TransButton from '../_util/transButton';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
|
||||
export interface PageHeaderProps {
|
||||
backIcon?: React.ReactNode;
|
||||
@ -18,7 +19,7 @@ export interface PageHeaderProps {
|
||||
tags?: React.ReactElement<Tag> | React.ReactElement<Tag>[];
|
||||
footer?: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
onBack?: (e: React.MouseEvent<HTMLElement>) => void;
|
||||
onBack?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@ -31,17 +32,24 @@ const renderBack = (
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div
|
||||
className={`${prefixCls}-back-icon`}
|
||||
onClick={e => {
|
||||
if (onBack) {
|
||||
onBack(e);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Wave>{backIcon}</Wave>
|
||||
<Divider type="vertical" />
|
||||
</div>
|
||||
<LocaleReceiver componentName="PageHeader">
|
||||
{({ back }: { back: string }) => (
|
||||
<div className={`${prefixCls}-back`}>
|
||||
<TransButton
|
||||
onClick={(e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (onBack) {
|
||||
onBack(e);
|
||||
}
|
||||
}}
|
||||
className={`${prefixCls}-back-button`}
|
||||
aria-label={back}
|
||||
>
|
||||
{backIcon}
|
||||
</TransButton>
|
||||
<Divider type="vertical" />
|
||||
</div>
|
||||
)}
|
||||
</LocaleReceiver>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -14,14 +14,16 @@
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
&-back-icon {
|
||||
&-back {
|
||||
display: inline-block;
|
||||
padding: 4px 0;
|
||||
font-size: 16px;
|
||||
line-height: 100%;
|
||||
cursor: pointer;
|
||||
i:hover {
|
||||
color: @primary-color;
|
||||
&-button {
|
||||
.operation-unit();
|
||||
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,3 +6,4 @@
|
||||
@import 'iconfont';
|
||||
@import 'motion';
|
||||
@import 'reset';
|
||||
@import 'operation-unit';
|
||||
|
18
components/style/mixins/operation-unit.less
Normal file
18
components/style/mixins/operation-unit.less
Normal file
@ -0,0 +1,18 @@
|
||||
@import '../../style/themes/default';
|
||||
|
||||
.operation-unit() {
|
||||
color: @link-color;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
}
|
@ -283,10 +283,12 @@ exports[`renders ./components/typography/demo/interactive.md correctly 1`] = `
|
||||
class="ant-typography"
|
||||
>
|
||||
This is an editable text.
|
||||
<button
|
||||
<div
|
||||
aria-label="edit"
|
||||
class="ant-typography-edit"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: edit"
|
||||
@ -308,16 +310,18 @@ exports[`renders ./components/typography/demo/interactive.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-typography"
|
||||
>
|
||||
This is a copyable text.
|
||||
<button
|
||||
<div
|
||||
aria-label="copy"
|
||||
class="ant-typography-copy"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: copy"
|
||||
@ -339,16 +343,18 @@ exports[`renders ./components/typography/demo/interactive.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-typography"
|
||||
>
|
||||
Replace copy text.
|
||||
<button
|
||||
<div
|
||||
aria-label="copy"
|
||||
class="ant-typography-copy"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit"
|
||||
role="button"
|
||||
style="border:0;background:transparent;padding:0;line-height:inherit;display:inline-block"
|
||||
tabindex="0"
|
||||
>
|
||||
<i
|
||||
aria-label="icon: copy"
|
||||
@ -370,7 +376,7 @@ exports[`renders ./components/typography/demo/interactive.md correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -30,23 +30,6 @@
|
||||
.typography-title(@heading-4-size, 1.4);
|
||||
}
|
||||
|
||||
.operation-unit() {
|
||||
color: @link-color;
|
||||
text-decoration: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
color: @link-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
color: @link-active-color;
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Basic ===============
|
||||
.@{typography-prefix-cls} {
|
||||
color: @text-color;
|
||||
|
Loading…
Reference in New Issue
Block a user