fix: Loading state changes button width (#25926)

Fixes #25890
This commit is contained in:
Pawan Kumar 2023-08-03 23:04:17 +05:30 committed by GitHub
parent 4ea8c95d9a
commit 56c795206e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 84 additions and 49 deletions

View File

@ -33,6 +33,11 @@ export interface ButtonProps extends Omit<HeadlessButtonProps, "className"> {
iconPosition?: (typeof BUTTON_ICON_POSITIONS)[keyof typeof BUTTON_ICON_POSITIONS];
/** Makes the button visually and functionaly disabled but focusable */
visuallyDisabled?: boolean;
/** Indicates the loading text that will be used by screen readers
* when the button is in loading state
* @default Loading...
*/
loadingText?: string;
}
export const Button = forwardRef(
@ -44,6 +49,7 @@ export const Button = forwardRef(
icon,
iconPosition = "start",
isLoading,
loadingText = "Loading...",
// eslint-disable-next-line -- TODO add onKeyUp when the bug is fixed https://github.com/adobe/react-spectrum/issues/4350
onKeyUp,
variant = "filled",
@ -53,24 +59,21 @@ export const Button = forwardRef(
const { visuallyHiddenProps } = useVisuallyHidden();
const renderChildren = () => {
if (isLoading) {
return (
<>
return (
<>
<span aria-hidden={isLoading ? true : undefined} data-content="">
{icon}
<Text lineClamp={1} textAlign="center">
{children}
</Text>
</span>
<span aria-hidden={!isLoading ? true : undefined} data-loader="">
<HeadlessIcon>
<Spinner />
</HeadlessIcon>
{/* TODO(pawan): How to make sure "Loading..." text is internationalized? */}
<span {...visuallyHiddenProps}>Loading...</span>
</>
);
}
return (
<>
{icon}
<Text lineClamp={1} textAlign="center">
{children}
</Text>
<span {...visuallyHiddenProps}>{loadingText}</span>
</span>
</>
);
};
@ -93,7 +96,7 @@ export const Button = forwardRef(
{...rest}
>
{renderChildren()}
<DragContainer data-hidden="" />
<DragContainer aria-hidden="true" />
</StyledButton>
);
},

View File

@ -35,7 +35,6 @@ export const buttonStyles = css<StyledButtonProps>`
background-color: transparent;
color: var(--color-fg-${$color});
border-color: var(--color-bd-${$color});
border-width: var(--border-width-1);
&[data-hovered]:not([aria-disabled]) {
background-color: var(--color-bg-${$color}-subtle-hover);
@ -52,7 +51,6 @@ export const buttonStyles = css<StyledButtonProps>`
background: transparent;
color: var(--color-fg-${$color});
border-color: transparent;
border-width: 0;
&[data-hovered]:not([aria-disabled]) {
background: var(--color-bg-${$color}-subtle-hover);
@ -70,41 +68,18 @@ export const StyledButton = styled(HeadlessButton)<StyledButtonProps>`
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
outline: 0;
padding: var(--spacing-2) var(--spacing-4);
block-size: var(--sizing-8);
border-radius: var(--border-radius-1);
cursor: pointer;
user-select: none;
min-inline-size: var(--sizing-8);
position: relative;
font-weight: 600;
border-width: 0;
border-style: solid;
font-family: inherit;
&[data-icon-position="start"] *:not([data-hidden]) + *:not([data-hidden]) {
margin-inline-start: var(--spacing-1);
}
&[data-icon-position="end"] *:not([data-hidden]) + *:not([data-hidden]) {
margin-inline-end: var(--spacing-1);
}
${buttonStyles}
&[data-icon-position="end"] {
flex-direction: row-reverse;
}
/** Note: adding direct selector ">" here because blueprint also has data-icon attribute on their icons */
& > [data-icon] {
display: flex;
justify-content: center;
align-items: center;
height: var(--sizing-4);
width: var(--sizing-4);
}
border-style: solid;
border-width: var(--border-width-1);
padding-inline: var(--spacing-4);
block-size: var(--sizing-8);
min-inline-size: var(--sizing-8);
border-radius: var(--border-radius-1);
// Note: adding important here as ADS is overriding the color of blueprint icon globally
// TODO(pawan): Remove this once ADS team removes the global override
@ -112,6 +87,44 @@ export const StyledButton = styled(HeadlessButton)<StyledButtonProps>`
color: currentColor !important;
}
${buttonStyles}
/**
* ----------------------------------------------------------------------------
* CONTENT
*-----------------------------------------------------------------------------
*/
& [data-content] {
display: flex;
justify-content: center;
align-items: center;
}
&[data-icon-position="start"] {
[data-content] *:not([data-hidden]) + *:not([data-hidden]) {
margin-inline-start: var(--spacing-1);
}
}
&[data-icon-position="end"] {
[data-content] *:not([data-hidden]) + *:not([data-hidden]) {
margin-inline-end: var(--spacing-1);
}
}
&[data-icon-position="end"] [data-content] {
flex-direction: row-reverse;
}
/** Note: adding direct selector ">" here because blueprint also has data-icon attribute on their icons */
& [data-content] > [data-icon] {
display: flex;
justify-content: center;
align-items: center;
height: var(--sizing-4);
width: var(--sizing-4);
}
/**
* ----------------------------------------------------------------------------
* FOCUSSED
@ -133,14 +146,33 @@ export const StyledButton = styled(HeadlessButton)<StyledButtonProps>`
/**
* ----------------------------------------------------------------------------
* LOADING
* LOADING AND LOADER
*-----------------------------------------------------------------------------
*/
&[data-loading] {
cursor: default;
/** adding opacity 1 here because we are lowering opacity for aria-disabled and when loading is true, aria-disabled is also true */
opacity: 1;
}
&[data-loading] [data-content] {
visibility: hidden;
}
& [data-loader] {
display: none;
}
&[data-loading] [data-loader] {
display: block;
position: absolute;
inset: 0;
display: flex;
justify-content: center;
align-items: center;
border-radius: inherit;
}
`;
/**