Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ export default typescript.config([
'src/sentry/templates/sentry/**/*',
'stylelint.config.js',
'.artifacts/**/*',
// auto-generated by figma code connect
'**/*.figma.tsx',
]),
/**
* Rules are grouped by plugin. If you want to override a specific rule inside
Expand Down Expand Up @@ -466,6 +468,7 @@ export default typescript.config([
rules: {
'@sentry/scraps/no-core-import': 'error',
'@sentry/scraps/no-token-import': 'error',
'@sentry/scraps/prefer-info-text': 'error',
'@sentry/scraps/use-semantic-token': [
'error',
{enabledCategories: ['background', 'border', 'content']},
Expand Down
17 changes: 13 additions & 4 deletions static/app/components/core/info/infoText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,34 @@ import styled from '@emotion/styled';
import type {DistributedOmit} from 'type-fest';

import {Text, type TextProps} from '@sentry/scraps/text';
import {Tooltip} from '@sentry/scraps/tooltip';
import {Tooltip, type TooltipProps} from '@sentry/scraps/tooltip';

type InfoTextProps<T extends 'span' | 'p' | 'label' | 'div'> = DistributedOmit<
TextProps<T>,
'title'
'title' | 'variant'
> & {
title: React.ReactNode;
};
variant?: TooltipProps['underlineColor'] | 'inherit';
} & Pick<TooltipProps, 'position'>;

export function InfoText<T extends 'span' | 'p' | 'label' | 'div' = 'span'>({
title,
children,
position,
...textProps
}: InfoTextProps<T>) {
if (!title) {
return <Text {...textProps}>{children}</Text>;
}
return (
<Tooltip title={title} skipWrapper isHoverable showUnderline>
<Tooltip
title={title}
position={position}
skipWrapper
isHoverable
showUnderline
underlineColor={textProps.variant === 'inherit' ? undefined : textProps.variant}
>
<StyledText {...textProps} tabIndex={0}>
{children}
</StyledText>
Expand Down
6 changes: 2 additions & 4 deletions static/app/components/core/modal/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import {
} from 'sentry-test/reactTestingLibrary';

import {CompactSelect} from '@sentry/scraps/compactSelect';
import {InfoText} from '@sentry/scraps/info';
import {useModal} from '@sentry/scraps/modal';
import {Tooltip} from '@sentry/scraps/tooltip';

import {closeModal, openModal} from 'sentry/actionCreators/modal';

Expand Down Expand Up @@ -286,9 +286,7 @@ describe('GlobalModal', () => {
act(() =>
openModal(({Body}) => (
<Body>
<Tooltip title={<button onClick={buttonClick}>Click me</button>} isHoverable>
Hi
</Tooltip>
<InfoText title={<button onClick={buttonClick}>Click me</button>}>Hi</InfoText>
</Body>
))
);
Expand Down
16 changes: 8 additions & 8 deletions static/app/components/core/tooltip/tooltip.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('Tooltip', () => {
it('renders', async () => {
render(
<Tooltip title="test">
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);

Expand All @@ -47,14 +47,14 @@ describe('Tooltip', () => {
it('updates title', async () => {
const {rerender} = render(
<Tooltip title="test">
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);

// Change title
rerender(
<Tooltip title="bar">
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);

Expand All @@ -70,7 +70,7 @@ describe('Tooltip', () => {
it('disables and does not render', async () => {
render(
<Tooltip title="test" disabled>
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);

Expand All @@ -84,7 +84,7 @@ describe('Tooltip', () => {
it('resets visibility when becoming disabled', async () => {
const {rerender} = render(
<Tooltip title="test" disabled={false}>
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);

Expand All @@ -93,15 +93,15 @@ describe('Tooltip', () => {

rerender(
<Tooltip title="test" disabled>
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);
expect(screen.queryByText('test')).not.toBeInTheDocument();

// Becomes enabled again
rerender(
<Tooltip title="test" disabled={false}>
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);
expect(screen.queryByText('test')).not.toBeInTheDocument();
Expand All @@ -110,7 +110,7 @@ describe('Tooltip', () => {
it('does not render an empty tooltip', async () => {
render(
<Tooltip title="">
<span>My Button</span>
<button>My Button</button>
</Tooltip>
);
await userEvent.hover(screen.getByText('My Button'));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import styled from '@emotion/styled';

import {Tag} from '@sentry/scraps/badge';
import {InfoText} from '@sentry/scraps/info';
import {Flex} from '@sentry/scraps/layout';
import {ExternalLink} from '@sentry/scraps/link';
import {Tooltip} from '@sentry/scraps/tooltip';

import {FeedbackItemUsername} from 'sentry/components/feedback/feedbackItem/feedbackItemUsername';
import {FeedbackTimestampsTooltip} from 'sentry/components/feedback/feedbackItem/feedbackTimestampsTooltip';
Expand All @@ -26,8 +26,8 @@ export function MessageTitle({feedbackItem, eventData}: Props) {
<Flex gap="md">
{isSpam ? (
<Tag key="spam" variant="danger">
<Tooltip
isHoverable
<InfoText
variant="inherit"
position="left"
title={tct(
'This feedback was automatically marked as spam. Learn more by [link:reading our docs.]',
Expand All @@ -39,7 +39,7 @@ export function MessageTitle({feedbackItem, eventData}: Props) {
)}
>
{t('spam')}
</Tooltip>
</InfoText>
</Tag>
) : null}
<StyledTimeSince
Expand Down
2 changes: 1 addition & 1 deletion static/app/components/hovercard.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ describe('Hovercard', () => {
position="top"
body={
<Tooltip title="Inner tooltip content">
<span>Inner trigger</span>
<button>Inner trigger</button>
</Tooltip>
}
header="Hovercard Header"
Expand Down
28 changes: 15 additions & 13 deletions static/app/components/replays/table/replayTableColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {PlatformIcon} from 'platformicons';

import {LinkButton} from '@sentry/scraps/button';
import {Checkbox} from '@sentry/scraps/checkbox';
import {InfoText} from '@sentry/scraps/info';
import {Flex} from '@sentry/scraps/layout';
import {ExternalLink, Link} from '@sentry/scraps/link';
import {Tooltip} from '@sentry/scraps/tooltip';
Expand Down Expand Up @@ -97,13 +98,14 @@ export interface ReplayTableColumn {

export const ReplayActivityColumn: ReplayTableColumn = {
Header: () => (
<Tooltip
<InfoText
variant="inherit"
title={t(
'Activity represents how much user activity happened in a replay. It is determined by the number of errors encountered, duration, and UI events.'
)}
>
{t('Activity')}
</Tooltip>
</InfoText>
),
interactive: false,
sortKey: 'activity',
Expand Down Expand Up @@ -179,8 +181,8 @@ export const ReplayBrowserColumn: ReplayTableColumn = {

export const ReplayCountDeadClicksColumn: ReplayTableColumn = {
Header: () => (
<Tooltip
isHoverable
<InfoText
variant="inherit"
title={tct(
'A dead click is a user click that does not result in any page activity after 7 seconds. Requires SDK version >= [minSDK]. [link:Learn more.]',
{
Expand All @@ -190,7 +192,7 @@ export const ReplayCountDeadClicksColumn: ReplayTableColumn = {
)}
>
{t('Dead clicks')}
</Tooltip>
</InfoText>
),
interactive: false,
sortKey: 'count_dead_clicks',
Expand Down Expand Up @@ -223,8 +225,8 @@ export const ReplayCountDeadClicksColumn: ReplayTableColumn = {

export const ReplayCountErrorsColumn: ReplayTableColumn = {
Header: () => (
<Tooltip
isHoverable
<InfoText
variant="inherit"
title={tct(
'The error count only reflects errors generated within the Replay SDK. [inboundFilters:Inbound Filters] may have prevented those errors from being saved. [perfIssue:Performance] and other [replayIssue:error] types may have been added afterwards.',
{
Expand All @@ -241,7 +243,7 @@ export const ReplayCountErrorsColumn: ReplayTableColumn = {
)}
>
{t('Errors')}
</Tooltip>
</InfoText>
),
interactive: false,
sortKey: 'count_errors',
Expand Down Expand Up @@ -274,8 +276,8 @@ export const ReplayCountErrorsColumn: ReplayTableColumn = {

export const ReplayCountRageClicksColumn: ReplayTableColumn = {
Header: () => (
<Tooltip
isHoverable
<InfoText
variant="inherit"
title={tct(
'A rage click is 5 or more clicks on a dead element, which exhibits no page activity after 7 seconds. Requires SDK version >= [minSDK]. [link:Learn more.]',
{
Expand All @@ -285,7 +287,7 @@ export const ReplayCountRageClicksColumn: ReplayTableColumn = {
)}
>
{t('Rage clicks')}
</Tooltip>
</InfoText>
),
interactive: false,
sortKey: 'count_rage_clicks',
Expand Down Expand Up @@ -497,9 +499,9 @@ export const ReplaySelectColumn: ReplayTableColumn = {

export const ReplaySessionColumn: ReplayTableColumn = {
Header: () => (
<Tooltip title={t('By default, replays are sorted by time sent.')}>
<InfoText variant="inherit" title={t('By default, replays are sorted by time sent.')}>
{t('Replay')}
</Tooltip>
</InfoText>
),
interactive: true,
sortKey: 'started_at',
Expand Down
5 changes: 3 additions & 2 deletions static/app/utils/discover/fieldRenderers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import partial from 'lodash/partial';

import {Tag} from '@sentry/scraps/badge';
import {Button} from '@sentry/scraps/button';
import {InfoText} from '@sentry/scraps/info';
import {ExternalLink, Link} from '@sentry/scraps/link';
import {Tooltip} from '@sentry/scraps/tooltip';

Expand Down Expand Up @@ -332,9 +333,9 @@ export const FIELD_FORMATTERS: FieldFormatters = {
if (data[field] > 0 && data[field] < NUMBER_MIN_VALUE) {
return (
<NumberContainer>
<Tooltip title={formatTooltipValue(data[field], 'number')}>
<InfoText variant="inherit" title={formatTooltipValue(data[field], 'number')}>
<span>{`<${NUMBER_MIN_VALUE}`}</span>
</Tooltip>
</InfoText>
</NumberContainer>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {Flex} from '@sentry/scraps/layout';
import {Link} from '@sentry/scraps/link';
import {Tooltip} from '@sentry/scraps/tooltip';

import {Placeholder} from 'sentry/components/placeholder';
import {DetailSection} from 'sentry/components/workflowEngine/ui/detailSection';
Expand Down Expand Up @@ -48,11 +47,7 @@ function AssignToUser({userId}: {userId: string}) {
}

const title = user?.name ?? user?.email ?? t('Unknown user');
return (
<Tooltip title={title} showOnlyOnOverflow>
{t('Assign to %s', title)}
</Tooltip>
);
return t('Assign to %s', title);
}

function DetectorOwner({owner}: {owner: Detector['owner']}) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Fragment, memo, useCallback, type ComponentPropsWithRef} from 'react';
import styled from '@emotion/styled';

import {InfoText} from '@sentry/scraps/info';
import {Container, Flex, Stack} from '@sentry/scraps/layout';
import {ExternalLink, Link} from '@sentry/scraps/link';
import {Pagination} from '@sentry/scraps/pagination';
Expand Down Expand Up @@ -269,9 +270,9 @@ const BodyCell = memo(function BodyCell({
case 'user': {
if (!dataRow.user) {
return (
<Tooltip title={<UserNotInstrumentedTooltip />} isHoverable>
<Text variant="muted">&mdash;</Text>
</Tooltip>
<InfoText variant="muted" title={<UserNotInstrumentedTooltip />}>
&mdash;
</InfoText>
);
}
const displayName = getUserDisplayName(dataRow.user);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {useEffect, type ReactNode} from 'react';

import {FeatureBadge} from '@sentry/scraps/badge';
import {InfoText} from '@sentry/scraps/info';
import {Flex, Stack} from '@sentry/scraps/layout';
import {ExternalLink} from '@sentry/scraps/link';
import {TabList, Tabs} from '@sentry/scraps/tabs';
import {Tooltip} from '@sentry/scraps/tooltip';

import {useOrganizationSeerSetup} from 'sentry/components/events/autofix/useOrganizationSeerSetup';
import {t, tct} from 'sentry/locale';
Expand Down Expand Up @@ -40,8 +40,8 @@ function getReplayTabs({
[TabKey.AI]:
hasAiSummary && (!isVideoReplay || hasMobileSummary) ? (
<Flex align="center" gap="sm">
<Tooltip
isHoverable
<InfoText
variant="inherit"
title={tct(
'Powered by generative AI. Learn more about our [link:AI privacy principles].',
{
Expand All @@ -52,7 +52,7 @@ function getReplayTabs({
)}
>
{t('AI Summary')}
</Tooltip>
</InfoText>
<FeatureBadge type="new" />
</Flex>
) : null,
Expand Down
Loading
Loading