Add new ESLint rule requiring explicit button types (#36738)

This commit is contained in:
Echo
2025-11-05 16:11:04 +01:00
committed by GitHub
parent 1a31c412ca
commit 6337e036f3
37 changed files with 101 additions and 26 deletions

View File

@@ -31,6 +31,7 @@ export const Section: FC<SectionProps> = ({
className='about__section__title'
tabIndex={0}
onClick={handleClick}
type='button'
>
<Icon
id={collapsed ? 'chevron-right' : 'chevron-down'}

View File

@@ -37,6 +37,7 @@ export const DomainPill: React.FC<{
onClick={handleClick}
aria-expanded={open}
aria-controls={accessibilityId}
type='button'
>
{domain}
</button>
@@ -154,6 +155,7 @@ export const DomainPill: React.FC<{
<button
onClick={handleExpandClick}
className='link-button'
type='button'
>
{x}
</button>
@@ -169,6 +171,7 @@ export const DomainPill: React.FC<{
<button
onClick={handleExpandClick}
className='link-button'
type='button'
>
{x}
</button>

View File

@@ -489,6 +489,7 @@ export const AltTextModal = forwardRef<ModalRef, Props & Partial<RestoreProps>>(
className='link-button'
onClick={handleDetectClick}
disabled={type !== 'image' || isDetecting}
type='button'
>
<FormattedMessage
id='alt_text_modal.add_text_from_image'

View File

@@ -557,7 +557,11 @@ export const Search: React.FC<{
)}
>
<span>{label}</span>
<button className='icon-button' onMouseDown={forget}>
<button
className='icon-button'
onMouseDown={forget}
type='button'
>
<Icon id='times' icon={CloseIcon} />
</button>
</div>
@@ -591,6 +595,7 @@ export const Search: React.FC<{
className={classNames('search__popout__menu__item', {
selected: selectedOption === i,
})}
type='button'
>
{label}
</button>
@@ -617,6 +622,7 @@ export const Search: React.FC<{
selectedOption ===
(quickActions.length || recent.length) + i,
})}
type='button'
>
{label}
</button>

View File

@@ -270,7 +270,7 @@ export const InlineFollowSuggestions: React.FC<{ hidden?: boolean }> = ({
</h3>
<div className='inline-follow-suggestions__header__actions'>
<button className='link-button' onClick={handleDismiss}>
<button className='link-button' onClick={handleDismiss} type='button'>
<FormattedMessage
id='follow_suggestions.dismiss'
defaultMessage="Don't show again"
@@ -309,6 +309,7 @@ export const InlineFollowSuggestions: React.FC<{ hidden?: boolean }> = ({
className='inline-follow-suggestions__body__scroll-button left'
onClick={handleLeftNav}
aria-label={intl.formatMessage(messages.previous)}
type='button'
>
<div className='inline-follow-suggestions__body__scroll-button__icon'>
<Icon id='' icon={ChevronLeftIcon} />
@@ -321,6 +322,7 @@ export const InlineFollowSuggestions: React.FC<{ hidden?: boolean }> = ({
className='inline-follow-suggestions__body__scroll-button right'
onClick={handleRightNav}
aria-label={intl.formatMessage(messages.next)}
type='button'
>
<div className='inline-follow-suggestions__body__scroll-button__icon'>
<Icon id='' icon={ChevronRightIcon} />

View File

@@ -381,6 +381,7 @@ const LoginForm: React.FC<{
className={classNames('search__popout__menu__item', {
selected: selectedOption === i,
})}
type='button'
>
{option
.split(domainRegExp)
@@ -451,7 +452,7 @@ const InteractionModal: React.FC<{
);
} else {
signupButton = (
<button className='link-button' onClick={handleSignupClick}>
<button className='link-button' onClick={handleSignupClick} type='button'>
<FormattedMessage
id='sign_in_banner.create_account'
defaultMessage='Create account'

View File

@@ -113,7 +113,7 @@ export const MoreLink: React.FC = () => {
return (
<Dropdown items={menu} placement='bottom-start'>
<button className='column-link column-link--transparent'>
<button className='column-link column-link--transparent' type='button'>
<Icon id='' icon={MoreHorizIcon} className='column-link__icon' />
<FormattedMessage id='navigation_bar.more' defaultMessage='More' />

View File

@@ -71,6 +71,7 @@ export const SignInBanner: React.FC = () => {
<button
className='button button--block'
onClick={openClosedRegistrationsModal}
type='button'
>
<FormattedMessage
id='sign_in_banner.create_account'

View File

@@ -45,6 +45,7 @@ export const FilteredNotificationsIconButton: React.FC<{
title={intl.formatMessage(messages.filteredNotifications)}
onClick={handleClick}
className={className}
type='button'
>
<Icon id='filtered-notifications' icon={InventoryIcon} />
</button>

View File

@@ -47,7 +47,7 @@ export const NotificationAnnualReport: React.FC<{
values={{ year }}
/>
</p>
<button onClick={handleClick} className='link-button'>
<button onClick={handleClick} className='link-button' type='button'>
<FormattedMessage
id='notification.annual_report.view'
defaultMessage='View #Wrapstodon'

View File

@@ -50,6 +50,7 @@ const BarButton: React.FC<
className={selectedFilter === type ? 'active' : ''}
onClick={onClick}
title={title}
type='button'
>
{children}
</button>

View File

@@ -245,6 +245,7 @@ export const Notifications: React.FC<{
title={intl.formatMessage(messages.markAsRead)}
onClick={handleMarkAsRead}
className='column-header__button'
type='button'
>
<Icon id='done-all' icon={DoneAllIcon} />
</button>

View File

@@ -9,7 +9,7 @@ export const SearchSection: React.FC<{
<div className='search-results__section__header'>
<h3>{title}</h3>
{onClickMore && (
<button onClick={onClickMore}>
<button onClick={onClickMore} type='button'>
<FormattedMessage
id='search_results.see_all'
defaultMessage='See all'

View File

@@ -232,12 +232,14 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
<button
onClick={handleSelectAll}
className={mappedType === 'all' ? 'active' : undefined}
type='button'
>
<FormattedMessage id='search_results.all' defaultMessage='All' />
</button>
<button
onClick={handleSelectAccounts}
className={mappedType === 'accounts' ? 'active' : undefined}
type='button'
>
<FormattedMessage
id='search_results.accounts'
@@ -247,6 +249,7 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
<button
onClick={handleSelectHashtags}
className={mappedType === 'hashtags' ? 'active' : undefined}
type='button'
>
<FormattedMessage
id='search_results.hashtags'
@@ -256,6 +259,7 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
<button
onClick={handleSelectStatuses}
className={mappedType === 'statuses' ? 'active' : undefined}
type='button'
>
<FormattedMessage
id='search_results.statuses'

View File

@@ -25,7 +25,12 @@ export const ActionsModal: React.FC<{
if (isActionItem(option)) {
element = (
<button onClick={onClick} data-index={i} disabled={disabled}>
<button
onClick={onClick}
data-index={i}
disabled={disabled}
type='button'
>
<DropdownMenuItemContent item={option} />
</button>
);

View File

@@ -113,7 +113,7 @@ export const BoostModal: React.FC<{
<div className='spacer' />
<button onClick={handleCancel} className='link-button'>
<button onClick={handleCancel} className='link-button' type='button'>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'

View File

@@ -58,7 +58,7 @@ export const ConfirmationModal: React.FC<
<div className='safety-action-modal__bottom'>
<div className='safety-action-modal__actions'>
<button onClick={onClose} className='link-button'>
<button onClick={onClose} className='link-button' type='button'>
{cancel ?? (
<FormattedMessage
id='confirmation_modal.cancel'
@@ -70,7 +70,11 @@ export const ConfirmationModal: React.FC<
{secondary && (
<>
<div className='spacer' />
<button onClick={handleSecondary} className='link-button'>
<button
onClick={handleSecondary}
className='link-button'
type='button'
>
{secondary}
</button>
</>

View File

@@ -196,7 +196,7 @@ export const DomainBlockModal: React.FC<{
<div className='spacer' />
<button onClick={handleCancel} className='link-button'>
<button onClick={handleCancel} className='link-button' type='button'>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'

View File

@@ -247,6 +247,7 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
className='media-modal__nav media-modal__nav--prev'
onClick={handlePrevClick}
aria-label={intl.formatMessage(messages.previous)}
type='button'
>
<Icon id='chevron-left' icon={ChevronLeftIcon} />
</button>
@@ -257,6 +258,7 @@ export const MediaModal: FC<MediaModalProps> = forwardRef<
className='media-modal__nav media-modal__nav--next'
onClick={handleNextClick}
aria-label={intl.formatMessage(messages.next)}
type='button'
>
<Icon id='chevron-right' icon={ChevronRightIcon} />
</button>
@@ -354,6 +356,7 @@ const MediaPagination: FC<MediaPaginationProps> = ({
active: i === index,
})}
onClick={handleChangeIndex(i)}
type='button'
>
{i + 1}
</button>

View File

@@ -127,7 +127,11 @@ const LoginOrSignUp: React.FC = () => {
);
} else {
signupButton = (
<button className='button' onClick={openClosedRegistrationsModal}>
<button
className='button'
onClick={openClosedRegistrationsModal}
type='button'
>
<FormattedMessage
id='sign_in_banner.create_account'
defaultMessage='Create account'
@@ -195,6 +199,7 @@ export const NavigationBar: React.FC = () => {
className={classNames('ui__navigation-bar__item', { active: open })}
onClick={handleClick}
aria-label={intl.formatMessage(messages.menu)}
type='button'
>
<Icon id='' icon={MenuIcon} />
</button>

View File

@@ -875,6 +875,7 @@ export const Video: React.FC<{
<button
className='media-gallery__actions__pill'
onClick={toggleReveal}
type='button'
>
<FormattedMessage
id='media_gallery.hide'