mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-05 17:31:12 +00:00

Some checks failed
Check i18n / check-i18n (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Check formatting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Chromatic / Run Chromatic (push) Has been cancelled
CSS Linting / lint (push) Has been cancelled
JavaScript Linting / lint (push) Has been cancelled
JavaScript Testing / test (push) Has been cancelled
95 lines
2.1 KiB
TypeScript
95 lines
2.1 KiB
TypeScript
import type { PropsWithChildren, JSX } from 'react';
|
|
import { useCallback } from 'react';
|
|
|
|
import classNames from 'classnames';
|
|
|
|
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
|
|
|
interface BaseProps
|
|
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children'> {
|
|
block?: boolean;
|
|
secondary?: boolean;
|
|
plain?: boolean;
|
|
compact?: boolean;
|
|
dangerous?: boolean;
|
|
loading?: boolean;
|
|
}
|
|
|
|
interface PropsChildren extends PropsWithChildren<BaseProps> {
|
|
text?: undefined;
|
|
}
|
|
|
|
interface PropsWithText extends BaseProps {
|
|
text: JSX.Element | string;
|
|
children?: undefined;
|
|
}
|
|
|
|
type Props = PropsWithText | PropsChildren;
|
|
|
|
/**
|
|
* Primary UI component for user interaction that doesn't result in navigation.
|
|
*/
|
|
|
|
export const Button: React.FC<Props> = ({
|
|
type = 'button',
|
|
onClick,
|
|
disabled,
|
|
block,
|
|
secondary,
|
|
plain,
|
|
compact,
|
|
dangerous,
|
|
loading,
|
|
className,
|
|
title,
|
|
text,
|
|
children,
|
|
...props
|
|
}) => {
|
|
const handleClick = useCallback<React.MouseEventHandler<HTMLButtonElement>>(
|
|
(e) => {
|
|
if (disabled || loading) {
|
|
e.stopPropagation();
|
|
e.preventDefault();
|
|
} else if (onClick) {
|
|
onClick(e);
|
|
}
|
|
},
|
|
[disabled, loading, onClick],
|
|
);
|
|
|
|
const label = text ?? children;
|
|
|
|
return (
|
|
<button
|
|
className={classNames('button', className, {
|
|
'button-secondary': secondary,
|
|
'button--plain': plain,
|
|
'button--compact': compact,
|
|
'button--block': block,
|
|
'button--dangerous': dangerous,
|
|
loading,
|
|
})}
|
|
// 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}
|
|
>
|
|
{loading ? (
|
|
<>
|
|
<span className='button__label-wrapper'>{label}</span>
|
|
<LoadingIndicator role='none' />
|
|
</>
|
|
) : (
|
|
label
|
|
)}
|
|
</button>
|
|
);
|
|
};
|