Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EuiBasicTable] Implement nameTooltip API in columns prop #8273

Merged
merged 23 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c976d4f
[EuiBasicTable] Implement nameTooltip API in columns prop
acstll Jan 13, 2025
3c9f088
[EuiBasicTable] Add unit tests for nameTooltip API
acstll Jan 20, 2025
9af31c4
Update changelog
acstll Jan 20, 2025
7818378
Restore stories
acstll Jan 20, 2025
c069667
[EuiTableHeaderCell] Add story for tooltip
acstll Jan 20, 2025
64c49e8
[EuiTableHeaderCell] Make tooltip position default to 'top'
acstll Jan 20, 2025
a64274a
Update docs for Tables
acstll Jan 20, 2025
90870fb
[EuiTableHeaderCell] Add reference for VRT
acstll Jan 20, 2025
66734fc
Improve comment
acstll Jan 20, 2025
a063c50
Refactor EuiIconTipProps and export
acstll Jan 22, 2025
194683e
Update changelog
acstll Jan 22, 2025
34f4cfa
Refactor API to use iconTip for transparency
acstll Jan 22, 2025
b7b988e
Update docs
acstll Jan 22, 2025
78cb22c
Fix type import for EuiIconTip stories
acstll Jan 22, 2025
14ad751
Fix wrong prop name in changelog
acstll Jan 22, 2025
0f096ad
Add parameters.loki in EuiTableHeaderCell stories (WIP)
acstll Jan 22, 2025
4751ea5
Fix prop name in story
acstll Jan 23, 2025
dd6d255
Revert changes in i18ntokens.json
acstll Feb 4, 2025
a471856
Make API as originally intended (nameTooltip)
acstll Feb 4, 2025
e175489
Remove loki parameters in stories for now
acstll Feb 4, 2025
c316ae4
Merge remote-tracking branch 'upstream/main' into basic-table-nametoo…
acstll Feb 4, 2025
52806be
Rename story, remove comment
acstll Feb 5, 2025
40f906b
Merge remote-tracking branch 'upstream/main' into basic-table-nametoo…
acstll Feb 5, 2025
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
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