[Glitch] feat: More obvious loading state when submitting a post
Port 644da36336 to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
1 parent
eb1674ec50
commit
73f77edf40
4 files changed
+86
-18
No files matched your search
@@ -3,12 +3,15 @@ import { useCallback } from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||
|
||||
interface BaseProps
|
||||
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
|
||||
block?: boolean;
|
||||
secondary?: boolean;
|
||||
compact?: boolean;
|
||||
dangerous?: boolean;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
interface PropsChildren extends PropsWithChildren<BaseProps> {
|
||||
@@ -34,6 +37,7 @@ export const Button: React.FC<Props> = ({
|
||||
secondary,
|
||||
compact,
|
||||
dangerous,
|
||||
loading,
|
||||
className,
|
||||
title,
|
||||
text,
|
||||
@@ -42,13 +46,18 @@ export const Button: React.FC<Props> = ({
|
||||
}) => {
|
||||
const handleClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
|
||||
(e) => {
|
||||
if (!disabled && onClick) {
|
||||
if (disabled || loading) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
} else if (onClick) {
|
||||
onClick(e);
|
||||
}
|
||||
},
|
||||
[disabled, onClick],
|
||||
[disabled, loading, onClick],
|
||||
);
|
||||
|
||||
const label = text ?? children;
|
||||
|
||||
return (
|
||||
<button
|
||||
className={classNames('button', className, {
|
||||
@@ -56,14 +65,27 @@ export const Button: React.FC<Props> = ({
|
||||
'button--compact': compact,
|
||||
'button--block': block,
|
||||
'button--dangerous': dangerous,
|
||||
loading,
|
||||
})}
|
||||
disabled={disabled}
|
||||
// Disabled buttons can't have focus, so we don't really
|
||||
// disable the button during loading
|
||||
disabled={disabled && !loading}
|
||||
aria-disabled={loading}
|
||||
// If the loading prop is used, announce label changes
|
||||
aria-live={loading !== undefined ? 'polite' : undefined}
|
||||
onClick={handleClick}
|
||||
title={title}
|
||||
type={type}
|
||||
{...props}
|
||||
>
|
||||
{text ?? children}
|
||||
{loading ? (
|
||||
<>
|
||||
<span className='button__label-wrapper'>{label}</span>
|
||||
<LoadingIndicator role='none' />
|
||||
</>
|
||||
) : (
|
||||
label
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -6,15 +6,34 @@ const messages = defineMessages({
|
||||
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading…' },
|
||||
});
|
||||
|
||||
export const LoadingIndicator: React.FC = () => {
|
||||
interface LoadingIndicatorProps {
|
||||
/**
|
||||
* Use role='none' to opt out of the current default role 'progressbar'
|
||||
* and aria attributes which we should re-visit to check if they're appropriate.
|
||||
* In Firefox the aria-label is not applied, instead an implied value of `50` is
|
||||
* used as the label.
|
||||
*/
|
||||
role?: string;
|
||||
}
|
||||
|
||||
export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({
|
||||
role = 'progressbar',
|
||||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const a11yProps =
|
||||
role === 'progressbar'
|
||||
? ({
|
||||
role,
|
||||
'aria-busy': true,
|
||||
'aria-live': 'polite',
|
||||
} as const)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<div
|
||||
className='loading-indicator'
|
||||
role='progressbar'
|
||||
aria-busy
|
||||
aria-live='polite'
|
||||
{...a11yProps}
|
||||
aria-label={intl.formatMessage(messages.loading)}
|
||||
>
|
||||
<CircularProgress size={50} strokeWidth={6} />
|
||||
|
||||
Reference in new issue
Block a user