diff --git a/packages/eui/changelogs/upcoming/9643.md b/packages/eui/changelogs/upcoming/9643.md new file mode 100644 index 000000000000..99c5de144b3c --- /dev/null +++ b/packages/eui/changelogs/upcoming/9643.md @@ -0,0 +1,23 @@ +- Replaced native browser `title` attributes with `EuiToolTip` across the following components for screen-reader-friendly tooltips: + - `EuiAvatar` + - `EuiBadge` + - `EuiBasicTable` + - `EuiBreadcrumbs` + - `EuiButtonGroup` + - `EuiComboBox` + - `EuiDataGrid` + - `EuiAutoRefresh` + - `EuiSuperDatePicker` + - `EuiFacetButton` + - `EuiFilterButton` + - `EuiFieldPassword` + - `EuiRange` + - `EuiInlineEditText` and `EuiInlineEditTitle` + - `EuiListGroupItem` + - `EuiMarkdownEditor` + - `EuiPagination` + - `EuiSearchBar` + - `EuiSelectable` + - `EuiSideNav` + - `EuiTable` + - `EuiTextTruncate` diff --git a/packages/eui/src/components/avatar/__snapshots__/avatar.test.tsx.snap b/packages/eui/src/components/avatar/__snapshots__/avatar.test.tsx.snap index 8c74f3a7dd26..96066e6b4bff 100644 --- a/packages/eui/src/components/avatar/__snapshots__/avatar.test.tsx.snap +++ b/packages/eui/src/components/avatar/__snapshots__/avatar.test.tsx.snap @@ -1,360 +1,475 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EuiAvatar allows a name composed entirely of whitespace 1`] = ` - + + + `; exports[`EuiAvatar is rendered 1`] = ` - + + + `; exports[`EuiAvatar props casing capitalize is rendered 1`] = ` - + + + `; exports[`EuiAvatar props casing lowercase is rendered 1`] = ` - + + + `; exports[`EuiAvatar props casing none is rendered 1`] = ` - + + + `; exports[`EuiAvatar props casing uppercase is rendered 1`] = ` - + + + `; exports[`EuiAvatar props color as null is rendered 1`] = ` - + + + `; exports[`EuiAvatar props color as plain is rendered 1`] = ` - + + + `; exports[`EuiAvatar props color as string is rendered 1`] = ` - + + + `; exports[`EuiAvatar props color as subdued is rendered 1`] = ` - + + + `; exports[`EuiAvatar props iconType and iconColor as null is rendered 1`] = ` - + + `; exports[`EuiAvatar props iconType and iconColor is rendered 1`] = ` - + + `; exports[`EuiAvatar props iconType and iconSize is rendered 1`] = ` - + + `; exports[`EuiAvatar props iconType is rendered 1`] = ` - + + `; exports[`EuiAvatar props imageUrl is rendered 1`] = ` - + `; exports[`EuiAvatar props isDisabled is rendered 1`] = ` - + + + `; exports[`EuiAvatar props size l is rendered 1`] = ` - + + + `; exports[`EuiAvatar props size m is rendered 1`] = ` - + + + `; exports[`EuiAvatar props size s is rendered 1`] = ` - + + + `; exports[`EuiAvatar props size xl is rendered 1`] = ` - + + + `; exports[`EuiAvatar props type is rendered 1`] = ` - + + + `; diff --git a/packages/eui/src/components/avatar/avatar.test.tsx b/packages/eui/src/components/avatar/avatar.test.tsx index f0d3fc0fd168..228c6f666336 100644 --- a/packages/eui/src/components/avatar/avatar.test.tsx +++ b/packages/eui/src/components/avatar/avatar.test.tsx @@ -7,6 +7,7 @@ */ import React from 'react'; +import { fireEvent } from '@testing-library/react'; import { shouldRenderCustomStyles } from '../../test/internal'; import { requiredProps } from '../../test/required_props'; import { render } from '../../test/rtl'; @@ -168,6 +169,20 @@ describe('EuiAvatar', () => { }); }); + describe('tooltip', () => { + it('shows a tooltip with the avatar name on hover', () => { + const { getByRole, queryByRole } = render(); + expect(queryByRole('tooltip')).not.toBeInTheDocument(); + fireEvent.mouseOver(getByRole('img')); + expect(getByRole('tooltip')).toHaveTextContent('Jane Doe'); + }); + + it('is keyboard focusable', () => { + const { getByRole } = render(); + expect(getByRole('img')).toHaveAttribute('tabindex', '0'); + }); + }); + test('should throw error if color is not a hex', () => { const component = () => render(); diff --git a/packages/eui/src/components/avatar/avatar.tsx b/packages/eui/src/components/avatar/avatar.tsx index 746537783964..3e2a661fdca0 100644 --- a/packages/eui/src/components/avatar/avatar.tsx +++ b/packages/eui/src/components/avatar/avatar.tsx @@ -22,6 +22,7 @@ import { } from '../../services/color'; import { toInitials, useEuiMemoizedStyles, useEuiTheme } from '../../services'; import { IconType, EuiIcon, IconSize, IconColor } from '../icon'; +import { EuiToolTip } from '../tool_tip'; import { euiAvatarStyles } from './avatar.styles'; @@ -201,29 +202,32 @@ export const EuiAvatar: FunctionComponent = ({ }, [iconColor, avatarStyle?.color, isForcedColors, euiTheme]); return ( -
- {!imageUrl && - (iconType ? ( - - ) : ( - - ))} -
+ +
+ {!imageUrl && + (iconType ? ( + + ) : ( + + ))} +
+
); }; diff --git a/packages/eui/src/components/badge/__snapshots__/badge.test.tsx.snap b/packages/eui/src/components/badge/__snapshots__/badge.test.tsx.snap index bfae33aca0a4..42cd6d713251 100644 --- a/packages/eui/src/components/badge/__snapshots__/badge.test.tsx.snap +++ b/packages/eui/src/components/badge/__snapshots__/badge.test.tsx.snap @@ -2,18 +2,23 @@ exports[`EuiBadge is disabled 1`] = ` - Content + + Content + @@ -21,18 +26,23 @@ exports[`EuiBadge is disabled 1`] = ` exports[`EuiBadge is rendered 1`] = ` - Content + + Content + @@ -45,39 +55,47 @@ exports[`EuiBadge is rendered with href and rel provided 1`] = ` - - Content - + + Content + + `; exports[`EuiBadge is rendered with href provided 1`] = ` - - - Content + + Content + - - + + `; exports[`EuiBadge is rendered with iconOnClick and href provided 1`] = ` @@ -87,16 +105,20 @@ exports[`EuiBadge is rendered with iconOnClick and href provided 1`] = ` - - Content - + + Content + + `; @@ -108,68 +130,86 @@ exports[`EuiBadge is rendered with iconOnClick and onClick provided 1`] = ` - + + `; exports[`EuiBadge is rendered with iconOnClick provided 1`] = ` - Content + + Content + `; exports[`EuiBadge is rendered with onClick provided 1`] = ` - + + `; exports[`EuiBadge props color accent is rendered 1`] = ` - Content + + Content + @@ -177,17 +217,22 @@ exports[`EuiBadge props color accent is rendered 1`] = ` exports[`EuiBadge props color accepts hex 1`] = ` - Content + + Content + @@ -195,17 +240,22 @@ exports[`EuiBadge props color accepts hex 1`] = ` exports[`EuiBadge props color accepts rgba 1`] = ` - Content + + Content + @@ -213,16 +263,21 @@ exports[`EuiBadge props color accepts rgba 1`] = ` exports[`EuiBadge props color danger is rendered 1`] = ` - Content + + Content + @@ -230,16 +285,21 @@ exports[`EuiBadge props color danger is rendered 1`] = ` exports[`EuiBadge props color default is rendered 1`] = ` - Content + + Content + @@ -247,16 +307,21 @@ exports[`EuiBadge props color default is rendered 1`] = ` exports[`EuiBadge props color hollow is rendered 1`] = ` - Content + + Content + @@ -264,16 +329,21 @@ exports[`EuiBadge props color hollow is rendered 1`] = ` exports[`EuiBadge props color neutral is rendered 1`] = ` - Content + + Content + @@ -281,16 +351,21 @@ exports[`EuiBadge props color neutral is rendered 1`] = ` exports[`EuiBadge props color primary is rendered 1`] = ` - Content + + Content + @@ -298,16 +373,21 @@ exports[`EuiBadge props color primary is rendered 1`] = ` exports[`EuiBadge props color risk is rendered 1`] = ` - Content + + Content + @@ -315,16 +395,21 @@ exports[`EuiBadge props color risk is rendered 1`] = ` exports[`EuiBadge props color success is rendered 1`] = ` - Content + + Content + @@ -332,16 +417,21 @@ exports[`EuiBadge props color success is rendered 1`] = ` exports[`EuiBadge props color warning is rendered 1`] = ` - Content + + Content + @@ -349,21 +439,27 @@ exports[`EuiBadge props color warning is rendered 1`] = ` exports[`EuiBadge props iconSide left is rendered 1`] = ` - - Content + @@ -371,43 +467,55 @@ exports[`EuiBadge props iconSide left is rendered 1`] = ` exports[`EuiBadge props iconSide right is rendered 1`] = ` - Content + + Content + + - `; exports[`EuiBadge props iconType is rendered 1`] = ` - - Content + @@ -415,17 +523,22 @@ exports[`EuiBadge props iconType is rendered 1`] = ` exports[`EuiBadge props style is rendered 1`] = ` - Content + + Content + @@ -433,17 +546,22 @@ exports[`EuiBadge props style is rendered 1`] = ` exports[`EuiBadge props style is rendered with accent 1`] = ` - Content + + Content + @@ -451,17 +569,22 @@ exports[`EuiBadge props style is rendered with accent 1`] = ` exports[`EuiBadge props style is rendered with danger 1`] = ` - Content + + Content + @@ -469,17 +592,22 @@ exports[`EuiBadge props style is rendered with danger 1`] = ` exports[`EuiBadge props style is rendered with default 1`] = ` - Content + + Content + @@ -487,17 +615,22 @@ exports[`EuiBadge props style is rendered with default 1`] = ` exports[`EuiBadge props style is rendered with hollow 1`] = ` - Content + + Content + @@ -505,17 +638,22 @@ exports[`EuiBadge props style is rendered with hollow 1`] = ` exports[`EuiBadge props style is rendered with hollow 2`] = ` - Content + + Content + @@ -523,17 +661,22 @@ exports[`EuiBadge props style is rendered with hollow 2`] = ` exports[`EuiBadge props style is rendered with neutral 1`] = ` - Content + + Content + @@ -541,17 +684,22 @@ exports[`EuiBadge props style is rendered with neutral 1`] = ` exports[`EuiBadge props style is rendered with primary 1`] = ` - Content + + Content + @@ -559,17 +707,22 @@ exports[`EuiBadge props style is rendered with primary 1`] = ` exports[`EuiBadge props style is rendered with risk 1`] = ` - Content + + Content + @@ -577,17 +730,22 @@ exports[`EuiBadge props style is rendered with risk 1`] = ` exports[`EuiBadge props style is rendered with success 1`] = ` - Content + + Content + @@ -595,17 +753,22 @@ exports[`EuiBadge props style is rendered with success 1`] = ` exports[`EuiBadge props style is rendered with warning 1`] = ` - Content + + Content + diff --git a/packages/eui/src/components/badge/badge.test.tsx b/packages/eui/src/components/badge/badge.test.tsx index 9b40305d69be..4534731d862b 100644 --- a/packages/eui/src/components/badge/badge.test.tsx +++ b/packages/eui/src/components/badge/badge.test.tsx @@ -236,9 +236,10 @@ describe('EuiBadge', () => { it('applies correct sizing styles to the main element', () => { const { container } = render(Badge); + const badge = container.querySelector('.euiBadge'); - expect(container.firstChild).toHaveStyleRule('padding-block', '0'); - expect(container.firstChild).toHaveStyleRule( + expect(badge).toHaveStyleRule('padding-block', '0'); + expect(badge).toHaveStyleRule( 'padding-inline', mathWithUnits( [theme.euiTheme.size.s, theme.euiTheme.border.width.thin], @@ -249,9 +250,10 @@ describe('EuiBadge', () => { it('applies custom sizing styles to the main element when rendering an icon-only variant', () => { const { container } = render(); + const badge = container.querySelector('.euiBadge'); - expect(container.firstChild).toHaveStyleRule('padding-block', '0'); - expect(container.firstChild).toHaveStyleRule( + expect(badge).toHaveStyleRule('padding-block', '0'); + expect(badge).toHaveStyleRule( 'padding-inline', mathWithUnits( [theme.euiTheme.size.xs, theme.euiTheme.border.width.thin], @@ -315,24 +317,19 @@ describe('EuiBadge', () => { ); const colors = colorsMap[color]; + const badge = result.container.querySelector('.euiBadge'); - expect(result.container.firstChild).toHaveStyleRule( + expect(badge).toHaveStyleRule( '--euiBadgeBackgroundColor', colors.backgroundColor ); - expect(result.container.firstChild).toHaveStyleRule( - '--euiBadgeTextColor', - colors.textColor - ); + expect(badge).toHaveStyleRule('--euiBadgeTextColor', colors.textColor); if (Object.hasOwn(colors, 'borderColor')) { - expect(result.container.firstChild).toHaveStyleRule( - 'border-color', - colors.borderColor - ); + expect(badge).toHaveStyleRule('border-color', colors.borderColor); } else { - expect(result.container.firstChild).not.toHaveStyleRule('border-color'); + expect(badge).not.toHaveStyleRule('border-color'); } }; diff --git a/packages/eui/src/components/badge/badge.tsx b/packages/eui/src/components/badge/badge.tsx index c1385bebfad5..68e5df2e03f3 100644 --- a/packages/eui/src/components/badge/badge.tsx +++ b/packages/eui/src/components/badge/badge.tsx @@ -26,6 +26,7 @@ import { validateHref } from '../../services/security/href_validator'; import { CommonProps, ExclusiveUnion, PropsOf } from '../common'; import { EuiInnerText } from '../inner_text'; import { EuiIcon, IconType } from '../icon'; +import { EuiToolTip } from '../tool_tip'; import { getTextColor, getIsValidColor, @@ -266,24 +267,25 @@ export const EuiBadge: FunctionComponent = ({ ); } optionalIcon = ( - + + + ); } else { optionalIcon = ( @@ -293,6 +295,7 @@ export const EuiBadge: FunctionComponent = ({ className="euiBadge__icon" css={iconCssStyles} color="inherit" // forces the icon to inherit its parent color + aria-hidden /> ); } @@ -323,18 +326,19 @@ export const EuiBadge: FunctionComponent = ({ {iconSide === 'left' && optionalIcon} {(ref, innerText) => ( - )} - {...(rest as HTMLAttributes)} - > - {children} - + + )} + {...(rest as HTMLAttributes)} + > + {children} + + )} {iconSide === 'right' && optionalIcon} @@ -343,16 +347,18 @@ export const EuiBadge: FunctionComponent = ({ ) : ( {(ref, innerText) => ( - - {content} - + + + {content} + + )} ); @@ -360,19 +366,20 @@ export const EuiBadge: FunctionComponent = ({ return ( {(ref, innerText) => ( - } - title={innerText} - {...(relObj as HTMLAttributes)} - {...(rest as HTMLAttributes)} - > - {content} - + + } + {...(relObj as HTMLAttributes)} + {...(rest as HTMLAttributes)} + > + {content} + + )} ); @@ -380,16 +387,18 @@ export const EuiBadge: FunctionComponent = ({ return ( {(ref, innerText) => ( - - {content} - + + + {content} + + )} ); diff --git a/packages/eui/src/components/badge/badge_group/__snapshots__/badge_group.test.tsx.snap b/packages/eui/src/components/badge/badge_group/__snapshots__/badge_group.test.tsx.snap index a72eb9ce8a19..b871ef99313a 100644 --- a/packages/eui/src/components/badge/badge_group/__snapshots__/badge_group.test.tsx.snap +++ b/packages/eui/src/components/badge/badge_group/__snapshots__/badge_group.test.tsx.snap @@ -25,16 +25,21 @@ exports[`EuiBadgeGroup is rendered 1`] = ` data-test-subj="test subject string" > - Content + + Content + diff --git a/packages/eui/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap b/packages/eui/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap index 65ee7a064cb1..7f4a9a100a12 100644 --- a/packages/eui/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap +++ b/packages/eui/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap @@ -82,10 +82,15 @@ exports[`EuiBasicTable renders (bare-bones) 1`] = ` class="euiTableCellContent emotion-euiTableCellContent-euiTableHeaderCell__content" > - Name + + Name + -
- - +
+ + +
-
+