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

* chore: init

* test: update test
This commit is contained in:
二货爱吃白萝卜 2024-11-14 11:50:00 +08:00 committed by GitHub
parent 7385f624c1
commit d704816731
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 30 additions and 9 deletions

View File

@ -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);
});
}); });

View File

@ -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}