diff --git a/static/app/components/events/autofix/v3/prIterationFeedbackForm.spec.tsx b/static/app/components/events/autofix/v3/prIterationFeedbackForm.spec.tsx index 466856d1d690..2e96c2a74bdb 100644 --- a/static/app/components/events/autofix/v3/prIterationFeedbackForm.spec.tsx +++ b/static/app/components/events/autofix/v3/prIterationFeedbackForm.spec.tsx @@ -75,7 +75,10 @@ describe('PrIterationFeedbackForm', () => { // The ticket asks for the form to stay visible, just greyed out. expect(screen.getByRole('textbox')).toBeDisabled(); - expect(screen.getByRole('button', {name: 'Submit'})).toBeDisabled(); + expect(screen.getByRole('button', {name: 'Submit'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); await userEvent.hover(screen.getByRole('button', {name: 'Submit'})); expect( diff --git a/static/app/components/events/autofix/v3/prIterationFeedbackForm.tsx b/static/app/components/events/autofix/v3/prIterationFeedbackForm.tsx index 1b6757b54766..ed246a2b36f4 100644 --- a/static/app/components/events/autofix/v3/prIterationFeedbackForm.tsx +++ b/static/app/components/events/autofix/v3/prIterationFeedbackForm.tsx @@ -120,16 +120,15 @@ export function PrIterationFeedbackForm({ {onClose && ( - + ); diff --git a/static/app/components/events/interfaces/debugMeta/debugImageDetails/candidate/actions.tsx b/static/app/components/events/interfaces/debugMeta/debugImageDetails/candidate/actions.tsx index 60d4b6e0030d..caf1e1f3b2c6 100644 --- a/static/app/components/events/interfaces/debugMeta/debugImageDetails/candidate/actions.tsx +++ b/static/app/components/events/interfaces/debugMeta/debugImageDetails/candidate/actions.tsx @@ -54,32 +54,30 @@ export function Actions({ {({hasAccess}) => ( - - } + href={downloadUrl} + disabled={!hasRole} + tooltipProps={{title: noPermissionToDownloadDebugFilesInfo}} + > + {t('Download')} + + onDelete(debugFileId)} + disabled={!hasAccess} + > + - - - + {hasSeen ? t('Mark Unread') : t('Mark Read')} + - + {t('Delete')} + ); } diff --git a/static/app/components/modals/dataWidgetViewerModal.tsx b/static/app/components/modals/dataWidgetViewerModal.tsx index 195748b323f3..098096bf3c20 100644 --- a/static/app/components/modals/dataWidgetViewerModal.tsx +++ b/static/app/components/modals/dataWidgetViewerModal.tsx @@ -828,13 +828,15 @@ function OpenButton({ !widgetTypeSupportsExploreMultiQuery(widget.widgetType); if (multiQueryUnsupported) { return ( - - - + {openLabel} + ); } path = getWidgetExploreUrl(widget, dashboardFilters, selection, organization)!; @@ -861,22 +863,21 @@ function OpenButton({ } return ( - - { - trackAnalytics('dashboards_views.widget_viewer.open_source', { - organization, - widget_type: widget.widgetType ?? WidgetType.ERRORS, - display_type: widget.displayType, - }); - }} - > - {openLabel} - - + { + trackAnalytics('dashboards_views.widget_viewer.open_source', { + organization, + widget_type: widget.widgetType ?? WidgetType.ERRORS, + display_type: widget.displayType, + }); + }} + > + {openLabel} + ); } diff --git a/static/app/components/preprod/preprodBuildsTableCommon.tsx b/static/app/components/preprod/preprodBuildsTableCommon.tsx index 3bc994adabcf..4797807409c7 100644 --- a/static/app/components/preprod/preprodBuildsTableCommon.tsx +++ b/static/app/components/preprod/preprodBuildsTableCommon.tsx @@ -100,23 +100,19 @@ export function PreprodBuildsRowCells({ variant="icon" /> ) : ( - - - - ), - onConfirm: () => { - bulkDelete([deletePayload], { - onSuccess: () => { - addSuccessMessage( - tct('Replays are being deleted. [settings:View progress]', { - settings: , - }) - ); - // TODO: get the list to refetch - refetchAuditLog(); - }, - onError: error => { - const count = - selectedIds === 'all' - ? Number.MAX_SAFE_INTEGER - : selectedIds.length; - const reason = getBulkDeleteErrorReason(error); - addErrorMessage( - reason - ? tn( - 'Failed to delete replay: %2$s', - 'Failed to delete replays: %2$s', - count, - reason - ) - : tn('Failed to delete replay', 'Failed to delete replays', count) - ); - }, - onSettled: () => {}, - }); + + ), + onConfirm: () => { + bulkDelete([deletePayload], { + onSuccess: () => { + addSuccessMessage( + tct('Replays are being deleted. [settings:View progress]', { + settings: , + }) + ); + // TODO: get the list to refetch + refetchAuditLog(); + }, + onError: error => { + const count = + selectedIds === 'all' ? Number.MAX_SAFE_INTEGER : selectedIds.length; + const reason = getBulkDeleteErrorReason(error); + addErrorMessage( + reason + ? tn( + 'Failed to delete replay: %2$s', + 'Failed to delete replays: %2$s', + count, + reason + ) + : tn('Failed to delete replay', 'Failed to delete replays', count) + ); }, - }) - } - size="xs" - > - {t('Delete')} - - - + onSettled: () => {}, + }); + }, + }) + } + size="xs" + > + {t('Delete')} + ); } diff --git a/static/app/views/authV2/authLogin/components/organizationAuth.spec.tsx b/static/app/views/authV2/authLogin/components/organizationAuth.spec.tsx index f9ed9bbf817a..78f47a691d7d 100644 --- a/static/app/views/authV2/authLogin/components/organizationAuth.spec.tsx +++ b/static/app/views/authV2/authLogin/components/organizationAuth.spec.tsx @@ -71,14 +71,14 @@ describe('OrganizationAuth', () => { ); const ssoButton = screen.getByRole('button', {name: 'SSO'}); - expect(ssoButton).toBeDisabled(); + expect(ssoButton).toHaveAttribute('aria-disabled', 'true'); expect( screen.getByText('Members sign in with email and password') ).toBeInTheDocument(); expect( screen.queryByText('This organization does not have Single Sign-On configured') ).not.toBeInTheDocument(); - await userEvent.hover(ssoButton.parentElement!); + await userEvent.hover(ssoButton); expect( await screen.findByText('This organization does not have Single Sign-On configured') ).toBeInTheDocument(); diff --git a/static/app/views/authV2/authLogin/components/organizationAuth.tsx b/static/app/views/authV2/authLogin/components/organizationAuth.tsx index 8da3bc5b4036..0d567bf88048 100644 --- a/static/app/views/authV2/authLogin/components/organizationAuth.tsx +++ b/static/app/views/authV2/authLogin/components/organizationAuth.tsx @@ -6,7 +6,6 @@ import {Avatar} from '@sentry/scraps/avatar'; import {Button, LinkButton} from '@sentry/scraps/button'; import {Flex, Stack} from '@sentry/scraps/layout'; import {Text} from '@sentry/scraps/text'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {IconClose, IconMegaphone} from 'sentry/icons'; import {IdentityIcon} from 'sentry/icons/identityIcon'; @@ -65,19 +64,17 @@ export function OrganizationAuth({
setIsSubmitting(true)}> - - - + {t('SSO')} +
); diff --git a/static/app/views/automations/components/disabledAlert.spec.tsx b/static/app/views/automations/components/disabledAlert.spec.tsx index 6f4de5b6f9e5..5860f9be9576 100644 --- a/static/app/views/automations/components/disabledAlert.spec.tsx +++ b/static/app/views/automations/components/disabledAlert.spec.tsx @@ -87,7 +87,7 @@ describe('DisabledAlert', () => { }); const enableButton = screen.getByRole('button', {name: 'Enable'}); - expect(enableButton).toBeDisabled(); + expect(enableButton).toHaveAttribute('aria-disabled', 'true'); await userEvent.hover(enableButton); expect( diff --git a/static/app/views/automations/components/disabledAlert.tsx b/static/app/views/automations/components/disabledAlert.tsx index a1fd2852e525..1dbbe997e7a4 100644 --- a/static/app/views/automations/components/disabledAlert.tsx +++ b/static/app/views/automations/components/disabledAlert.tsx @@ -1,6 +1,5 @@ import {Alert} from '@sentry/scraps/alert'; import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {IconPlay} from 'sentry/icons'; import {t} from 'sentry/locale'; @@ -44,17 +43,16 @@ export function DisabledAlert({automation}: DisabledAlertProps) { - - + } > {t('This alert is disabled and will not send notifications.')} diff --git a/static/app/views/dashboards/widgetCard/toolbar.tsx b/static/app/views/dashboards/widgetCard/toolbar.tsx index 8aca4af9a3ad..891fdf05ac4d 100644 --- a/static/app/views/dashboards/widgetCard/toolbar.tsx +++ b/static/app/views/dashboards/widgetCard/toolbar.tsx @@ -3,7 +3,6 @@ import styled from '@emotion/styled'; import color from 'color'; import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {IconCopy, IconDelete, IconEdit, IconGrabbable} from 'sentry/icons'; import {t} from 'sentry/locale'; @@ -41,37 +40,27 @@ export function Toolbar({ /> )} {onEdit && ( - - - + {t('Enable')} + )} {showDisable && ( - - - - )} - - + )} + diff --git a/static/app/views/detectors/list/allMonitors.spec.tsx b/static/app/views/detectors/list/allMonitors.spec.tsx index 2fc2e4e49d09..4e3f0dbedb2c 100644 --- a/static/app/views/detectors/list/allMonitors.spec.tsx +++ b/static/app/views/detectors/list/allMonitors.spec.tsx @@ -599,7 +599,10 @@ describe('DetectorsList', () => { await userEvent.click(firstRowCheckbox); // Verify that delete button is disabled - expect(screen.getByRole('button', {name: 'Delete'})).toBeDisabled(); + expect(screen.getByRole('button', {name: 'Delete'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); }); it('shows option to select all query results when page is selected', async () => { @@ -695,9 +698,18 @@ describe('DetectorsList', () => { const enabledCheckbox = within(enabledRow!).getByRole('checkbox'); await userEvent.click(enabledCheckbox); - expect(screen.getByRole('button', {name: 'Enable'})).toBeDisabled(); - expect(screen.getByRole('button', {name: 'Disable'})).toBeDisabled(); - expect(screen.getByRole('button', {name: 'Delete'})).toBeDisabled(); + expect(screen.getByRole('button', {name: 'Enable'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); + expect(screen.getByRole('button', {name: 'Disable'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); + expect(screen.getByRole('button', {name: 'Delete'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); }); }); }); diff --git a/static/app/views/discover/results.tsx b/static/app/views/discover/results.tsx index eb341a75429c..271a96f2298f 100644 --- a/static/app/views/discover/results.tsx +++ b/static/app/views/discover/results.tsx @@ -1365,22 +1365,20 @@ function SaveQueryButton({ if (!isNewQuery && isEditingQuery) { return ( - - - + + {t('Save Changes')} + { additionalWrapper: ProviderWrapper, }); const refreshButton = await screen.findByRole('button', {name: 'Refresh'}); - expect(refreshButton).toBeDisabled(); + expect(refreshButton).toHaveAttribute('aria-disabled', 'true'); }); }); diff --git a/static/app/views/explore/logs/logsTab.tsx b/static/app/views/explore/logs/logsTab.tsx index b167d3fa9654..5bd927a9cee0 100644 --- a/static/app/views/explore/logs/logsTab.tsx +++ b/static/app/views/explore/logs/logsTab.tsx @@ -7,7 +7,6 @@ import {DropdownMenu} from '@sentry/scraps/dropdownMenu'; import {Container, Flex, Grid} from '@sentry/scraps/layout'; import {useModal} from '@sentry/scraps/modal'; import {TabList, Tabs} from '@sentry/scraps/tabs'; -import {Tooltip} from '@sentry/scraps/tooltip'; import * as Layout from 'sentry/components/layouts/thirds'; import type {DatePageFilterProps} from 'sentry/components/pageFilters/date/datePageFilter'; @@ -538,19 +537,14 @@ function LogsTabContentInner({datePageFilterProps}: LogsTabProps) { {tableTab === 'logs' && ( - - - + {t('Set Up Replays')} + ) : ( - - {t('You do not have permission to create a project.')} - - } - disabled={!disabled} + + {t('You do not have permission to create a project.')} + + ), + }} > - - {t('Create Project')} - - + {t('Create Project')} + ); return ( diff --git a/static/app/views/explore/tables/index.tsx b/static/app/views/explore/tables/index.tsx index ec152e77f2bf..c02e9b738e82 100644 --- a/static/app/views/explore/tables/index.tsx +++ b/static/app/views/explore/tables/index.tsx @@ -5,7 +5,6 @@ import {Button} from '@sentry/scraps/button'; import {Flex} from '@sentry/scraps/layout'; import {useModal} from '@sentry/scraps/modal'; import {TabList, Tabs} from '@sentry/scraps/tabs'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {IconEdit} from 'sentry/icons/iconEdit'; import {t} from 'sentry/locale'; @@ -150,17 +149,20 @@ export function ExploreTables(props: ExploreTablesProps) { {t('Edit Table')} ) : ( - } + size="sm" + tooltipProps={{ + title: + tab === Tab.TRACE + ? t('Editing columns is available for span samples only') + : t('Use the Group By and Visualize controls to change table columns'), + }} > - - + {t('Edit Table')} + )} {tab === Tab.SPAN && ( diff --git a/static/app/views/issueDetails/groupDistributions/tagsDistributionDrawer.tsx b/static/app/views/issueDetails/groupDistributions/tagsDistributionDrawer.tsx index 20d88598125f..bdbf4520470a 100644 --- a/static/app/views/issueDetails/groupDistributions/tagsDistributionDrawer.tsx +++ b/static/app/views/issueDetails/groupDistributions/tagsDistributionDrawer.tsx @@ -2,7 +2,6 @@ import {Fragment, useState} from 'react'; import {Button} from '@sentry/scraps/button'; import {Grid} from '@sentry/scraps/layout'; -import {Tooltip} from '@sentry/scraps/tooltip'; import { EventDrawerBody, @@ -79,9 +78,13 @@ export function TagsDistributionDrawer({ }} /> {includeFeatureFlagsTab ? ( - - - + {t('Create Project')} +
{!isModalVisible && ( diff --git a/static/app/views/settings/featureFlags/changeTracking/index.spec.tsx b/static/app/views/settings/featureFlags/changeTracking/index.spec.tsx index f8ea4a739e8a..a831f8cfc3b3 100644 --- a/static/app/views/settings/featureFlags/changeTracking/index.spec.tsx +++ b/static/app/views/settings/featureFlags/changeTracking/index.spec.tsx @@ -186,7 +186,7 @@ describe('OrganizationFeatureFlagsIndex', () => { expect(await secretsTable.findByText('launchdarkly')).toBeInTheDocument(); expect( secretsTable.getByLabelText('Remove secret for launchdarkly provider') - ).toBeDisabled(); + ).toHaveAttribute('aria-disabled', 'true'); }); }); }); diff --git a/static/app/views/settings/featureFlags/changeTracking/index.tsx b/static/app/views/settings/featureFlags/changeTracking/index.tsx index afb10545e2c3..57cc2a1a18b2 100644 --- a/static/app/views/settings/featureFlags/changeTracking/index.tsx +++ b/static/app/views/settings/featureFlags/changeTracking/index.tsx @@ -6,7 +6,6 @@ import {LinkButton} from '@sentry/scraps/button'; import {Flex} from '@sentry/scraps/layout'; import {ExternalLink} from '@sentry/scraps/link'; import type {TableColumnConfig} from '@sentry/scraps/table'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {hasEveryAccess} from 'sentry/components/acl/access'; @@ -83,20 +82,16 @@ function AddNewProvider({ organizationSlug: string; }) { return ( - - - {t('Add New Provider')} - - + {t('Add New Provider')} + ); } diff --git a/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.spec.tsx b/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.spec.tsx index 496ec756a47e..58c59dc386e1 100644 --- a/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.spec.tsx +++ b/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.spec.tsx @@ -67,7 +67,7 @@ describe('OrganizationFeatureFlagsProviderRow', () => { expect( screen.getByRole('button', {name: 'Remove secret for launchdarkly provider'}) - ).toBeDisabled(); + ).toHaveAttribute('aria-disabled', 'true'); }); it('allows to remove', async () => { diff --git a/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.tsx b/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.tsx index bf598a08095a..bb4da6a8a33c 100644 --- a/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.tsx +++ b/static/app/views/settings/featureFlags/changeTracking/organizationFeatureFlagsProviderRow.tsx @@ -1,6 +1,5 @@ import {Button} from '@sentry/scraps/button'; import {Text} from '@sentry/scraps/text'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {Confirm} from 'sentry/components/confirm'; import {LoadingIndicator} from 'sentry/components/loadingIndicator'; @@ -44,30 +43,30 @@ export function OrganizationFeatureFlagsProviderRow({ - removeSecret(secret.id) : undefined} + message={t( + 'Are you sure you want to remove the secret for %s provider? It will not be usable anymore, and this cannot be undone.', + secret.provider )} - disabled={!!removeSecret} > - removeSecret(secret.id) : undefined} - message={t( - 'Are you sure you want to remove the secret for %s provider? It will not be usable anymore, and this cannot be undone.', - secret.provider - )} + - - + {t('Remove')} + + ); diff --git a/static/app/views/settings/organizationAuthTokens/authTokenRow.spec.tsx b/static/app/views/settings/organizationAuthTokens/authTokenRow.spec.tsx index 5f8a666b9b70..a80285f2c2aa 100644 --- a/static/app/views/settings/organizationAuthTokens/authTokenRow.spec.tsx +++ b/static/app/views/settings/organizationAuthTokens/authTokenRow.spec.tsx @@ -149,7 +149,10 @@ describe('OrganizationAuthTokensAuthTokenRow', () => { ); - expect(screen.getByRole('button', {name: 'Revoke My Token'})).toBeDisabled(); + expect(screen.getByRole('button', {name: 'Revoke My Token'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); }); it('allows to revoke', async () => { diff --git a/static/app/views/settings/organizationAuthTokens/authTokenRow.tsx b/static/app/views/settings/organizationAuthTokens/authTokenRow.tsx index 3a0ba8ab6ca1..a49e83f84cc8 100644 --- a/static/app/views/settings/organizationAuthTokens/authTokenRow.tsx +++ b/static/app/views/settings/organizationAuthTokens/authTokenRow.tsx @@ -3,7 +3,6 @@ import styled from '@emotion/styled'; import {Button} from '@sentry/scraps/button'; import {Link} from '@sentry/scraps/link'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {Confirm} from 'sentry/components/confirm'; import {Placeholder} from 'sentry/components/placeholder'; @@ -119,28 +118,28 @@ export function OrganizationAuthTokensAuthTokenRow({ - revokeToken(token) : undefined} + message={t( + 'Are you sure you want to revoke %s token? It will not be usable anymore, and this cannot be undone.', + tokenPreview(token.tokenLastCharacters || '', 'sntrys_') + )} > - revokeToken(token) : undefined} - message={t( - 'Are you sure you want to revoke %s token? It will not be usable anymore, and this cannot be undone.', - tokenPreview(token.tokenLastCharacters || '', 'sntrys_') - )} + - - + {t('Revoke')} + + ); diff --git a/static/app/views/settings/organizationAuthTokens/index.spec.tsx b/static/app/views/settings/organizationAuthTokens/index.spec.tsx index 8a2db46cfe9f..7d41580c0db3 100644 --- a/static/app/views/settings/organizationAuthTokens/index.spec.tsx +++ b/static/app/views/settings/organizationAuthTokens/index.spec.tsx @@ -301,7 +301,10 @@ describe('OrganizationAuthTokensIndex', () => { expect(await screen.findByText('My Token 1')).toBeInTheDocument(); - expect(screen.getByLabelText('Revoke My Token 1')).toBeDisabled(); + expect(screen.getByLabelText('Revoke My Token 1')).toHaveAttribute( + 'aria-disabled', + 'true' + ); }); }); }); diff --git a/static/app/views/settings/organizationIntegrations/addIntegrationButton.tsx b/static/app/views/settings/organizationIntegrations/addIntegrationButton.tsx index f6a4b70a76e5..2065ebf5eeaa 100644 --- a/static/app/views/settings/organizationIntegrations/addIntegrationButton.tsx +++ b/static/app/views/settings/organizationIntegrations/addIntegrationButton.tsx @@ -1,6 +1,5 @@ import type {ButtonProps} from '@sentry/scraps/button'; import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {t} from 'sentry/locale'; import type {IntegrationWithConfig} from 'sentry/types/integrations'; @@ -44,7 +43,6 @@ export function AddIntegrationButton({ const {startFlow} = useAddIntegration(); - // This is hooked to the button since the button is only rendered when all the flags/plan checks pass. useAutoOpenInstallModal({ provider, organization, @@ -55,34 +53,32 @@ export function AddIntegrationButton({ }); return ( - - - + } + startFlow({ + provider, + organization, + onInstall: onAddIntegration, + analyticsParams, + suppressSuccessMessage, + onCancel, + onError, + }); + }} + > + {label} + ); } diff --git a/static/app/views/settings/organizationIntegrations/directEnableButton.spec.tsx b/static/app/views/settings/organizationIntegrations/directEnableButton.spec.tsx index cf6b89e08779..9adbc4a8b594 100644 --- a/static/app/views/settings/organizationIntegrations/directEnableButton.spec.tsx +++ b/static/app/views/settings/organizationIntegrations/directEnableButton.spec.tsx @@ -53,6 +53,9 @@ describe('DirectEnableButton', () => { organization, }); - expect(screen.getByRole('button', {name: 'Enable Integration'})).toBeDisabled(); + expect(screen.getByRole('button', {name: 'Enable Integration'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); }); }); diff --git a/static/app/views/settings/organizationIntegrations/directEnableButton.tsx b/static/app/views/settings/organizationIntegrations/directEnableButton.tsx index b95a61cbf060..939a4c227e8c 100644 --- a/static/app/views/settings/organizationIntegrations/directEnableButton.tsx +++ b/static/app/views/settings/organizationIntegrations/directEnableButton.tsx @@ -1,7 +1,6 @@ import {useMutation, useQueryClient} from '@tanstack/react-query'; import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {addErrorMessage} from 'sentry/actionCreators/indicator'; import {t} from 'sentry/locale'; @@ -58,18 +57,18 @@ export function DirectEnableButton({ }); return ( - enable()} > - - + {t('Enable Integration')} + ); } diff --git a/static/app/views/settings/organizationIntegrations/installedIntegration.tsx b/static/app/views/settings/organizationIntegrations/installedIntegration.tsx index 666ccc0e5dbb..2214740cc889 100644 --- a/static/app/views/settings/organizationIntegrations/installedIntegration.tsx +++ b/static/app/views/settings/organizationIntegrations/installedIntegration.tsx @@ -199,28 +199,26 @@ export class InstalledIntegration extends Component { )}
- - } + data-test-id="integration-remove-button" + tooltipProps={{ + title: t( + 'You must be an organization owner, manager or admin to uninstall' + ), + }} > - - - + {t('Uninstall')} + +
{ // The reinstall button (which auto-opens the install modal) must never // render for members without access; a disabled Update button shows instead. - expect(await screen.findByRole('button', {name: 'Update'})).toBeDisabled(); + expect(await screen.findByRole('button', {name: 'Update'})).toHaveAttribute( + 'aria-disabled', + 'true' + ); expect(screen.queryByTestId('integration-upgrade-button')).not.toBeInTheDocument(); }); }); diff --git a/static/app/views/settings/organizationIntegrations/integrationDetailedView.tsx b/static/app/views/settings/organizationIntegrations/integrationDetailedView.tsx index aa2e91857b32..41d537b16e92 100644 --- a/static/app/views/settings/organizationIntegrations/integrationDetailedView.tsx +++ b/static/app/views/settings/organizationIntegrations/integrationDetailedView.tsx @@ -8,7 +8,6 @@ import {Button} from '@sentry/scraps/button'; import {AutoSaveForm, FieldGroup} from '@sentry/scraps/form'; import {Flex} from '@sentry/scraps/layout'; import {Text} from '@sentry/scraps/text'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {addErrorMessage} from 'sentry/actionCreators/indicator'; import {updateOrganization} from 'sentry/actionCreators/organizations'; @@ -89,11 +88,16 @@ function IntegrationUpgradeButton({ }) { if (!canManageIntegrations(organization)) { return ( - - - + ); } diff --git a/static/app/views/settings/organizationTeams/teamNotifications.tsx b/static/app/views/settings/organizationTeams/teamNotifications.tsx index 7d9a56f6edc9..bffa56ac27bb 100644 --- a/static/app/views/settings/organizationTeams/teamNotifications.tsx +++ b/static/app/views/settings/organizationTeams/teamNotifications.tsx @@ -4,7 +4,6 @@ import styled from '@emotion/styled'; import {Button} from '@sentry/scraps/button'; import {Flex} from '@sentry/scraps/layout'; import {ExternalLink} from '@sentry/scraps/link'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {hasEveryAccess} from 'sentry/components/acl/access'; @@ -125,22 +124,23 @@ function TeamNotificationSettingsPanel({ /> - onDelete(externalTeam)} + message={t('Are you sure you want to remove this Slack team link?')} > - } disabled={!hasWriteAccess} - onConfirm={() => onDelete(externalTeam)} - message={t('Are you sure you want to remove this Slack team link?')} + tooltipProps={{ + title: t( + 'You must be an organization owner, manager or admin to remove a Slack team link' + ), + }} > - - - + {t('Unlink')} + + )); diff --git a/static/app/views/settings/organizationTeams/teamProjects.tsx b/static/app/views/settings/organizationTeams/teamProjects.tsx index 0e6efd719678..100a92c9ea8e 100644 --- a/static/app/views/settings/organizationTeams/teamProjects.tsx +++ b/static/app/views/settings/organizationTeams/teamProjects.tsx @@ -7,7 +7,6 @@ import {Button} from '@sentry/scraps/button'; import {CompactSelect, type SelectOption} from '@sentry/scraps/compactSelect'; import {OverlayTrigger} from '@sentry/scraps/overlayTrigger'; import {Pagination} from '@sentry/scraps/pagination'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator'; import {hasEveryAccess} from 'sentry/components/acl/access'; @@ -167,24 +166,22 @@ export default function TeamProjects() { sortProjects(linkedProjects).map(project => ( - } + aria-label={t('Remove')} + tooltipProps={{ + title: t( + 'You do not have enough permission to change project association.' + ), + }} + onClick={() => { + handleLinkProject(project, 'remove'); + }} > - - + {t('Remove')} + )) ) : linkedProjectsLoading ? null : ( diff --git a/static/app/views/settings/project/tempest/CredentialRow.tsx b/static/app/views/settings/project/tempest/CredentialRow.tsx index 70d56e3efdbc..5ecf5550c1fb 100644 --- a/static/app/views/settings/project/tempest/CredentialRow.tsx +++ b/static/app/views/settings/project/tempest/CredentialRow.tsx @@ -37,27 +37,27 @@ export function CredentialRow({ - removeCredential({id: credential.id}) : undefined + } + disabled={isRemoving || !removeCredential} > - removeCredential({id: credential.id}) : undefined - } + - - + {t('Remove')} + + ); diff --git a/static/app/views/settings/project/tempest/addCredentialsButton.tsx b/static/app/views/settings/project/tempest/addCredentialsButton.tsx index 409a014da46c..95f12926ad67 100644 --- a/static/app/views/settings/project/tempest/addCredentialsButton.tsx +++ b/static/app/views/settings/project/tempest/addCredentialsButton.tsx @@ -1,5 +1,4 @@ import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {openAddTempestCredentialsModal} from 'sentry/actionCreators/modal'; import {IconAdd} from 'sentry/icons/iconAdd'; @@ -19,27 +18,23 @@ export function AddCredentialsButton({project, origin}: AddCredentialsButtonProp const hasWriteAccess = useHasTempestWriteAccess(project); return ( - } + tooltipProps={{title: t('You do not have permission to add new credentials.')}} + onClick={() => { + openAddTempestCredentialsModal({organization, project, origin}); + trackAnalytics('tempest.credentials.add_modal_opened', { + organization, + project_slug: project.slug, + origin, + }); + }} > - - + {t('Add Credentials')} + ); } diff --git a/static/app/views/settings/projectSourceMaps/debugIdBundleDeleteButton.tsx b/static/app/views/settings/projectSourceMaps/debugIdBundleDeleteButton.tsx index 0820905d8d80..182cc15b9d97 100644 --- a/static/app/views/settings/projectSourceMaps/debugIdBundleDeleteButton.tsx +++ b/static/app/views/settings/projectSourceMaps/debugIdBundleDeleteButton.tsx @@ -1,6 +1,5 @@ import type {ButtonProps} from '@sentry/scraps/button'; import {Button} from '@sentry/scraps/button'; -import {Tooltip} from '@sentry/scraps/tooltip'; import {Access} from 'sentry/components/acl/access'; import {Confirm} from 'sentry/components/confirm'; @@ -19,20 +18,22 @@ export function DebugIdBundleDeleteButton({ return ( {({hasAccess}) => ( - - } + size={size} disabled={!hasAccess} + tooltipProps={{ + title: t('You do not have permission to delete source maps.'), + }} > - - - + {t('Delete Source Maps')} + + )} ); diff --git a/tests/acceptance/test_auth_react.py b/tests/acceptance/test_auth_react.py index 24418145754e..2be9a7552d22 100644 --- a/tests/acceptance/test_auth_react.py +++ b/tests/acceptance/test_auth_react.py @@ -295,7 +295,7 @@ def test_organization_without_sso(self) -> None: xpath="//*[contains(normalize-space(.), 'Members sign in with email and password')]" ) sso_button = self.browser.element(xpath="//button[normalize-space(.)='SSO']") - assert not sso_button.is_enabled() + assert sso_button.get_attribute("aria-disabled") == "true" # Password authentication remains available for the selected organization. self.submit_visible_credentials(user.email, PASSWORD)