Skip to content

Commit

Permalink
[EuiBasicTable] Implement nameTooltip API in columns prop (#8273)
Browse files Browse the repository at this point in the history
  • Loading branch information
acstll authored Feb 6, 2025
1 parent 3db18cb commit 1ea74d9
Show file tree
Hide file tree
Showing 18 changed files with 210 additions and 123 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/eui/changelogs/upcoming/8273.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Updated table components to support adding tooltips to header cells
- Added `columns.nameTooltip` on `EuiBasicTable`
- Added `tooltipProps` prop on `EuiTableHeaderCell`
2 changes: 1 addition & 1 deletion packages/eui/i18ntokens.json
Original file line number Diff line number Diff line change
Expand Up @@ -7181,4 +7181,4 @@
},
"filepath": "src/components/tree_view/tree_view.tsx"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ const columns: Array<EuiBasicTableColumn<User>> = [
{
field: 'location',
name: 'Location',
nameTooltip: {
content: 'The city and country in which this person resides',
},
truncateText: true,
textOnly: true,
render: (location: User['location']) => {
Expand Down
70 changes: 16 additions & 54 deletions packages/eui/src-docs/src/views/tables/sorting/sorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import {
EuiTableSortingType,
Criteria,
EuiHealth,
EuiIcon,
EuiLink,
EuiToolTip,
EuiFlexGroup,
EuiFlexItem,
EuiSwitch,
Expand Down Expand Up @@ -76,19 +74,10 @@ const columns: Array<EuiBasicTableColumn<User>> = [
},
{
field: 'github',
name: (
<EuiToolTip content="Their mascot is the Octokitty">
<>
Github{' '}
<EuiIcon
size="s"
color="subdued"
type="questionInCircle"
className="eui-alignTop"
/>
</>
</EuiToolTip>
),
name: 'GibHub',
nameTooltip: {
content: 'Their mascot is the Octokitty',
},
render: (username: User['github']) => (
<EuiLink href="#" target="_blank">
{username}
Expand All @@ -97,37 +86,19 @@ const columns: Array<EuiBasicTableColumn<User>> = [
},
{
field: 'dateOfBirth',
name: (
<EuiToolTip content="Colloquially known as a 'birthday'">
<>
Date of Birth{' '}
<EuiIcon
size="s"
color="subdued"
type="questionInCircle"
className="eui-alignTop"
/>
</>
</EuiToolTip>
),
name: 'Date of Birth',
nameTooltip: {
content: "Colloquially known as a 'birthday'",
},
render: (dateOfBirth: User['dateOfBirth']) =>
formatDate(dateOfBirth, 'dobLong'),
},
{
field: 'location',
name: (
<EuiToolTip content="The city and country in which this person resides">
<>
Nationality{' '}
<EuiIcon
size="s"
color="subdued"
type="questionInCircle"
className="eui-alignTop"
/>
</>
</EuiToolTip>
),
name: 'Nationality',
nameTooltip: {
content: 'The city and country in which this person resides',
},
render: (location: User['location']) => {
return `${location.city}, ${location.country}`;
},
Expand All @@ -136,19 +107,10 @@ const columns: Array<EuiBasicTableColumn<User>> = [
},
{
field: 'online',
name: (
<EuiToolTip content="Free to talk or busy with business">
<>
Online{' '}
<EuiIcon
size="s"
color="subdued"
type="questionInCircle"
className="eui-alignTop"
/>
</>
</EuiToolTip>
),
name: 'Online',
nameTooltip: {
content: 'Free to talk or busy with business',
},
render: (online: User['online']) => {
const color = online ? 'success' : 'danger';
const label = online ? 'Online' : 'Offline';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ const columns: Array<EuiBasicTableColumn<User>> = [
{
field: 'location',
name: 'Location',
nameTooltip: {
content: 'The city and country in which this person resides',
},
truncateText: true,
textOnly: true,
render: (location: User['location']) => {
Expand Down
3 changes: 3 additions & 0 deletions packages/eui/src/components/basic_table/basic_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ export class EuiBasicTable<T extends object = any> extends Component<
field,
width,
name,
nameTooltip,
align,
dataType,
sortable,
Expand All @@ -765,6 +766,7 @@ export class EuiBasicTable<T extends object = any> extends Component<

const sharedProps = {
width,
tooltipProps: nameTooltip,
description,
mobileOptions,
align: columnAlign,
Expand Down Expand Up @@ -1280,6 +1282,7 @@ export class EuiBasicTable<T extends object = any> extends Component<
sortable,
footer,
mobileOptions,
nameTooltip,
...rest
} = column as EuiTableFieldDataColumnType<T>;
const columnAlign = align || this.getAlignForDataType(dataType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ const columns: Array<EuiBasicTableColumn<User>> = [
{
field: 'location',
name: 'Location',
nameTooltip: {
content: 'The city and country in which this person resides',
},
truncateText: true,
textOnly: true,
render: (location: User['location']) => {
Expand Down
32 changes: 32 additions & 0 deletions packages/eui/src/components/basic_table/table_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import { Pagination } from './pagination_bar';
import { Action } from './action_types';
import { Primitive } from '../../services/sort/comparators';
import { CommonProps } from '../common';
import { IconType } from '../icon';
import {
EuiTableRowCellProps,
EuiTableRowCellMobileOptionsShape,
} from '../table/table_row_cell';
import { EuiToolTipProps, EuiIconTipProps } from '../tool_tip';

export type ItemId<T> = string | number | ((item: T) => string);
export type ItemIdResolved = string | number;
Expand All @@ -31,6 +33,24 @@ export interface EuiTableFooterProps<T> {
items: T[];
pagination?: Pagination;
}

export type EuiTableColumnNameTooltipProps = {
/** The main content of the tooltip */
content: ReactNode;
/**
* The icon type to display
* @default 'questionInCircle'
*/
icon?: IconType;
/** Additional props for EuiIcon */
iconProps?: EuiIconTipProps['iconProps'];
/** Additional props for the EuiToolip */
tooltipProps?: Omit<EuiToolTipProps, 'children' | 'delay' | 'position'> & {
delay?: EuiToolTipProps['delay'];
position?: EuiToolTipProps['position'];
};
};

export interface EuiTableFieldDataColumnType<T>
extends CommonProps,
Omit<TdHTMLAttributes<HTMLTableCellElement>, 'width' | 'align'> {
Expand All @@ -44,6 +64,10 @@ export interface EuiTableFieldDataColumnType<T>
* The display name of the column
*/
name: ReactNode;
/**
* Allows adding an icon with a tooltip displayed next to the name
*/
nameTooltip?: EuiTableColumnNameTooltipProps;
/**
* A description of the column (will be presented as a title over the column header)
*/
Expand Down Expand Up @@ -118,6 +142,10 @@ export type EuiTableComputedColumnType<T> = CommonProps &
* The display name of the column
*/
name?: ReactNode;
/**
* Allows configuring an icon with a tooltip, to be displayed next to the name
*/
nameTooltip?: EuiTableColumnNameTooltipProps;
/**
* If provided, allows this column to be sorted on. Must return the value to sort against.
*/
Expand All @@ -141,6 +169,10 @@ export type EuiTableActionsColumnType<T extends object> = {
* The display name of the column
*/
name?: ReactNode;
/**
* Allows configuring an icon with a tooltip, to be displayed next to the name
*/
nameTooltip?: EuiTableColumnNameTooltipProps;
} & Pick<EuiTableFieldDataColumnType<T>, 'description' | 'width'>;

export interface EuiTableSortingType<T> {
Expand Down
16 changes: 16 additions & 0 deletions packages/eui/src/components/table/table_header_cell.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,19 @@ export const Playground: Story = {
onSort: false,
},
};

export const Tooltip: Story = {
parameters: {
controls: {
include: ['tooltipProps'],
},
},
args: {
children: 'Header cell content',
// @ts-ignore - overwrite meta default to align with base behavior
onSort: false,
tooltipProps: {
content: 'tooltip content',
},
},
};
56 changes: 55 additions & 1 deletion packages/eui/src/components/table/table_header_cell.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

import React from 'react';
import { requiredProps } from '../../test/required_props';
import { render } from '../../test/rtl';
import { render, waitForEuiToolTipVisible } from '../../test/rtl';
import { fireEvent } from '@testing-library/react';

import { RIGHT_ALIGNMENT, CENTER_ALIGNMENT } from '../../services';
import { WARNING_MESSAGE } from './utils';
Expand Down Expand Up @@ -185,4 +186,57 @@ describe('EuiTableHeaderCell', () => {
expect(container.firstChild).toMatchSnapshot();
});
});

describe('tooltip', () => {
it('renders an icon with tooltip', async () => {
const { getByTestSubject } = renderInTableHeader(
<EuiTableHeaderCell
tooltipProps={{
content: 'This is the content of the tooltip',
icon: 'iInCircle',
iconProps: {
'data-test-subj': 'icon',
},
tooltipProps: {
'data-test-subj': 'tooltip',
},
}}
>
Test
</EuiTableHeaderCell>
);

expect(getByTestSubject('icon')).toHaveAttribute(
'data-euiicon-type',
'iInCircle'
);

fireEvent.focus(getByTestSubject('icon'));
await waitForEuiToolTipVisible();

expect(getByTestSubject('tooltip')).toHaveTextContent(
'This is the content of the tooltip'
);
});

it('renders the icon next to the text', () => {
const { getByTestSubject, queryByText } = renderInTableHeader(
<EuiTableHeaderCell
tooltipProps={{
content: 'This is the content of the tooltip',
iconProps: {
'data-test-subj': 'icon',
},
}}
onSort={() => {}}
>
Test
</EuiTableHeaderCell>
);

expect(queryByText('Test')?.nextSibling).toEqual(
getByTestSubject('icon').parentElement
);
});
});
});
19 changes: 19 additions & 0 deletions packages/eui/src/components/table/table_header_cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import { EuiScreenReaderOnly } from '../accessibility';
import { CommonProps, NoArgCallback } from '../common';
import { EuiIcon } from '../icon';
import { EuiInnerText } from '../inner_text';
import { EuiIconTip } from '../tool_tip';

import type { EuiTableRowCellMobileOptionsShape } from './table_row_cell';
import type { EuiTableColumnNameTooltipProps } from '../basic_table/table_types';
import { resolveWidthAsStyle } from './utils';
import { useEuiTableIsResponsive } from './mobile/responsive_context';
import { EuiTableCellContent } from './_table_cell_content';
Expand All @@ -43,6 +45,8 @@ export type EuiTableHeaderCellProps = CommonProps &
onSort?: NoArgCallback<void>;
scope?: TableHeaderCellScope;
width?: string | number;
/** Allows adding an icon with a tooltip displayed next to the name */
tooltipProps?: EuiTableColumnNameTooltipProps;
description?: string;
/**
* Shows the sort indicator but removes the button
Expand All @@ -59,6 +63,7 @@ export type EuiTableHeaderCellProps = CommonProps &
const CellContents = ({
className,
align,
tooltipProps,
description,
children,
canSort,
Expand All @@ -67,6 +72,7 @@ const CellContents = ({
}: {
className?: string;
align: HorizontalAlignment;
tooltipProps?: EuiTableColumnNameTooltipProps;
description: EuiTableHeaderCellProps['description'];
children: EuiTableHeaderCellProps['children'];
canSort?: boolean;
Expand Down Expand Up @@ -104,6 +110,17 @@ const CellContents = ({
<span>{description}</span>
</EuiScreenReaderOnly>
)}
{tooltipProps && (
<EuiIconTip
content={tooltipProps.content}
type={tooltipProps.icon || 'questionInCircle'}
size="m"
color="subdued"
position="top"
iconProps={tooltipProps.iconProps}
{...tooltipProps.tooltipProps}
/>
)}
{isSorted ? (
<EuiIcon
className="euiTableSortIcon"
Expand Down Expand Up @@ -134,6 +151,7 @@ export const EuiTableHeaderCell: FunctionComponent<EuiTableHeaderCellProps> = ({
width,
style,
readOnly,
tooltipProps,
description,
append,
...rest
Expand Down Expand Up @@ -162,6 +180,7 @@ export const EuiTableHeaderCell: FunctionComponent<EuiTableHeaderCellProps> = ({
const cellContentsProps = {
css: styles.euiTableHeaderCell__content,
align,
tooltipProps,
description,
canSort,
isSorted,
Expand Down
Loading

0 comments on commit 1ea74d9

Please sign in to comment.