mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
refactor: Button inner logic & use effect to get focus (#51624)
Some checks are pending
Publish Any Commit / build (push) Waiting to run
🔀 Sync mirror to Gitee / mirror (push) Waiting to run
✅ test / lint (push) Waiting to run
✅ test / test-react-legacy (16, 1/2) (push) Waiting to run
✅ test / test-react-legacy (16, 2/2) (push) Waiting to run
✅ test / test-react-legacy (17, 1/2) (push) Waiting to run
✅ test / test-react-legacy (17, 2/2) (push) Waiting to run
✅ test / test-node (push) Waiting to run
✅ test / test-react-latest (dom, 1/2) (push) Waiting to run
✅ test / test-react-latest (dom, 2/2) (push) Waiting to run
✅ test / test-react-latest-dist (dist, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist, 2/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 2/2) (push) Blocked by required conditions
✅ test / test-coverage (push) Blocked by required conditions
✅ test / build (push) Waiting to run
✅ test / test lib/es module (es, 1/2) (push) Waiting to run
✅ test / test lib/es module (es, 2/2) (push) Waiting to run
✅ test / test lib/es module (lib, 1/2) (push) Waiting to run
✅ test / test lib/es module (lib, 2/2) (push) Waiting to run
👁️ Visual Regression Persist Start / test image (push) Waiting to run
Some checks are pending
Publish Any Commit / build (push) Waiting to run
🔀 Sync mirror to Gitee / mirror (push) Waiting to run
✅ test / lint (push) Waiting to run
✅ test / test-react-legacy (16, 1/2) (push) Waiting to run
✅ test / test-react-legacy (16, 2/2) (push) Waiting to run
✅ test / test-react-legacy (17, 1/2) (push) Waiting to run
✅ test / test-react-legacy (17, 2/2) (push) Waiting to run
✅ test / test-node (push) Waiting to run
✅ test / test-react-latest (dom, 1/2) (push) Waiting to run
✅ test / test-react-latest (dom, 2/2) (push) Waiting to run
✅ test / test-react-latest-dist (dist, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist, 2/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 1/2) (push) Blocked by required conditions
✅ test / test-react-latest-dist (dist-min, 2/2) (push) Blocked by required conditions
✅ test / test-coverage (push) Blocked by required conditions
✅ test / build (push) Waiting to run
✅ test / test lib/es module (es, 1/2) (push) Waiting to run
✅ test / test lib/es module (es, 2/2) (push) Waiting to run
✅ test / test lib/es module (lib, 1/2) (push) Waiting to run
✅ test / test lib/es module (lib, 2/2) (push) Waiting to run
👁️ Visual Regression Persist Start / test image (push) Waiting to run
* chore: init * test: update test
This commit is contained in:
parent
7385f624c1
commit
d704816731
@ -474,4 +474,10 @@ describe('Button', () => {
|
|||||||
'--ant-button-solid-text-color': '#000',
|
'--ant-button-solid-text-color': '#000',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('autoFocus should work', () => {
|
||||||
|
const { container } = render(<Button autoFocus>button</Button>);
|
||||||
|
|
||||||
|
expect(container.querySelector('button')).toBe(document.activeElement);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { Children, createRef, useContext, useEffect, useMemo, useState } from 'react';
|
import React, { Children, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import omit from 'rc-util/lib/omit';
|
import omit from 'rc-util/lib/omit';
|
||||||
import { composeRef } from 'rc-util/lib/ref';
|
import { useComposeRef } from 'rc-util/lib/ref';
|
||||||
|
|
||||||
import { devUseWarning } from '../_util/warning';
|
import { devUseWarning } from '../_util/warning';
|
||||||
import Wave from '../_util/wave';
|
import Wave from '../_util/wave';
|
||||||
@ -119,6 +119,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
classNames: customClassNames,
|
classNames: customClassNames,
|
||||||
style: customStyle = {},
|
style: customStyle = {},
|
||||||
autoInsertSpace,
|
autoInsertSpace,
|
||||||
|
autoFocus,
|
||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
@ -162,13 +163,15 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
|
|
||||||
const [hasTwoCNChar, setHasTwoCNChar] = useState<boolean>(false);
|
const [hasTwoCNChar, setHasTwoCNChar] = useState<boolean>(false);
|
||||||
|
|
||||||
const internalRef = createRef<HTMLButtonElement | HTMLAnchorElement>();
|
const buttonRef = useRef<HTMLButtonElement | HTMLAnchorElement>();
|
||||||
|
|
||||||
const buttonRef = composeRef(ref, internalRef);
|
const mergedRef = useComposeRef(ref, buttonRef);
|
||||||
|
|
||||||
const needInserted =
|
const needInserted =
|
||||||
Children.count(children) === 1 && !icon && !isUnBorderedButtonVariant(mergedVariant);
|
Children.count(children) === 1 && !icon && !isUnBorderedButtonVariant(mergedVariant);
|
||||||
|
|
||||||
|
// ========================= Effect =========================
|
||||||
|
// Loading
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let delayTimer: ReturnType<typeof setTimeout> | null = null;
|
let delayTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
if (loadingOrDelay.delay > 0) {
|
if (loadingOrDelay.delay > 0) {
|
||||||
@ -190,12 +193,13 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
return cleanupTimer;
|
return cleanupTimer;
|
||||||
}, [loadingOrDelay]);
|
}, [loadingOrDelay]);
|
||||||
|
|
||||||
|
// Two chinese characters check
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// FIXME: for HOC usage like <FormatMessage />
|
// FIXME: for HOC usage like <FormatMessage />
|
||||||
if (!buttonRef || !(buttonRef as any).current || !mergedInsertSpace) {
|
if (!buttonRef.current || !mergedInsertSpace) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const buttonText = (buttonRef as any).current.textContent;
|
const buttonText = buttonRef.current.textContent || '';
|
||||||
if (needInserted && isTwoCNChar(buttonText)) {
|
if (needInserted && isTwoCNChar(buttonText)) {
|
||||||
if (!hasTwoCNChar) {
|
if (!hasTwoCNChar) {
|
||||||
setHasTwoCNChar(true);
|
setHasTwoCNChar(true);
|
||||||
@ -203,8 +207,16 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
} else if (hasTwoCNChar) {
|
} else if (hasTwoCNChar) {
|
||||||
setHasTwoCNChar(false);
|
setHasTwoCNChar(false);
|
||||||
}
|
}
|
||||||
}, [buttonRef]);
|
});
|
||||||
|
|
||||||
|
// Auto focus
|
||||||
|
useEffect(() => {
|
||||||
|
if (autoFocus && buttonRef.current) {
|
||||||
|
buttonRef.current.focus();
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// ========================= Events =========================
|
||||||
const handleClick = React.useCallback(
|
const handleClick = React.useCallback(
|
||||||
(e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
(e: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement, MouseEvent>) => {
|
||||||
// FIXME: https://github.com/ant-design/ant-design/issues/30207
|
// FIXME: https://github.com/ant-design/ant-design/issues/30207
|
||||||
@ -217,6 +229,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
[props.onClick, innerLoading, mergedDisabled],
|
[props.onClick, innerLoading, mergedDisabled],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ========================== Warn ==========================
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
const warning = devUseWarning('Button');
|
const warning = devUseWarning('Button');
|
||||||
|
|
||||||
@ -233,6 +246,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================== Size ==========================
|
||||||
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
|
const { compactSize, compactItemClassnames } = useCompactItemContext(prefixCls, direction);
|
||||||
|
|
||||||
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
|
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
|
||||||
@ -245,6 +259,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
|
|
||||||
const linkButtonRestProps = omit(rest as ButtonProps & { navigate: any }, ['navigate']);
|
const linkButtonRestProps = omit(rest as ButtonProps & { navigate: any }, ['navigate']);
|
||||||
|
|
||||||
|
// ========================= Render =========================
|
||||||
const classes = classNames(
|
const classes = classNames(
|
||||||
prefixCls,
|
prefixCls,
|
||||||
hashId,
|
hashId,
|
||||||
@ -301,7 +316,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
href={mergedDisabled ? undefined : linkButtonRestProps.href}
|
href={mergedDisabled ? undefined : linkButtonRestProps.href}
|
||||||
style={fullStyle}
|
style={fullStyle}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
ref={buttonRef as React.Ref<HTMLAnchorElement>}
|
ref={mergedRef as React.Ref<HTMLAnchorElement>}
|
||||||
tabIndex={mergedDisabled ? -1 : 0}
|
tabIndex={mergedDisabled ? -1 : 0}
|
||||||
>
|
>
|
||||||
{iconNode}
|
{iconNode}
|
||||||
@ -318,7 +333,7 @@ const InternalCompoundedButton = React.forwardRef<
|
|||||||
style={fullStyle}
|
style={fullStyle}
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
disabled={mergedDisabled}
|
disabled={mergedDisabled}
|
||||||
ref={buttonRef as React.Ref<HTMLButtonElement>}
|
ref={mergedRef as React.Ref<HTMLButtonElement>}
|
||||||
>
|
>
|
||||||
{iconNode}
|
{iconNode}
|
||||||
{kids}
|
{kids}
|
||||||
|
Loading…
Reference in New Issue
Block a user