diff --git a/packages/react-table/src/components/Table/SelectColumn.tsx b/packages/react-table/src/components/Table/SelectColumn.tsx index 57f4239ab3b..c2e2de64205 100644 --- a/packages/react-table/src/components/Table/SelectColumn.tsx +++ b/packages/react-table/src/components/Table/SelectColumn.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { Tooltip, TooltipProps } from '@patternfly/react-core/dist/esm/components/Tooltip'; export enum RowSelectVariant { radio = 'radio', @@ -11,6 +12,10 @@ export interface SelectColumnProps { className?: string; onSelect?: (event: React.FormEvent) => void; selectVariant?: RowSelectVariant; + /** text to display on the tooltip */ + tooltip?: React.ReactNode; + /** other props to pass to the tooltip */ + tooltipProps?: Omit; } export const SelectColumn: React.FunctionComponent = ({ @@ -19,13 +24,27 @@ export const SelectColumn: React.FunctionComponent = ({ className, onSelect = null as (event: React.FormEvent) => void, selectVariant, + tooltip, + tooltipProps, ...props -}: SelectColumnProps) => ( - - - {children} - -); +}: SelectColumnProps) => { + const inputRef = React.createRef(); + + const content = ( + + + {children} + + ); + + return tooltip ? ( + + {content} + + ) : ( + content + ); +}; SelectColumn.displayName = 'SelectColumn'; diff --git a/packages/react-table/src/components/Table/SortColumn.tsx b/packages/react-table/src/components/Table/SortColumn.tsx index 1526a533aee..9e5945195ca 100644 --- a/packages/react-table/src/components/Table/SortColumn.tsx +++ b/packages/react-table/src/components/Table/SortColumn.tsx @@ -5,6 +5,7 @@ import ArrowsAltVIcon from '@patternfly/react-icons/dist/esm/icons/arrows-alt-v- import { css } from '@patternfly/react-styles'; import styles from '@patternfly/react-styles/css/components/Table/table'; import { TableText } from './TableText'; +import { TooltipProps } from '@patternfly/react-core/dist/esm/components/Tooltip'; export enum SortByDirection { asc = 'asc', @@ -17,6 +18,9 @@ export interface SortColumnProps extends React.ButtonHTMLAttributes; + tooltipHasDefaultBehavior?: boolean; } export const SortColumn: React.FunctionComponent = ({ @@ -26,6 +30,9 @@ export const SortColumn: React.FunctionComponent = ({ onSort = null, sortDirection = '', type = 'button', + tooltip, + tooltipProps, + tooltipHasDefaultBehavior, ...props }: SortColumnProps) => { let SortedByIcon; @@ -45,7 +52,14 @@ export const SortColumn: React.FunctionComponent = ({ onBlur={() => setFocused(false)} >
- {children} + + {children} + diff --git a/packages/react-table/src/components/Table/TableText.tsx b/packages/react-table/src/components/Table/TableText.tsx index 0a967eb72aa..659e787263d 100644 --- a/packages/react-table/src/components/Table/TableText.tsx +++ b/packages/react-table/src/components/Table/TableText.tsx @@ -26,13 +26,15 @@ export interface TableTextProps extends React.HTMLProps { /** Determines which wrapping modifier to apply to the table text */ wrapModifier?: WrapModifier | 'wrap' | 'nowrap' | 'truncate' | 'breakWord' | 'fitContent'; /** text to display on the tooltip */ - tooltip?: string; + tooltip?: React.ReactNode; /** other props to pass to the tooltip */ tooltipProps?: Omit; /** callback used to create the tooltip if text is truncated */ onMouseEnter?: (event: any) => void; /** Determines if the TableText is focused by parent component */ focused?: boolean; + /** Determines if tooltip should have normal visbility behavior. If false, the tooltip will only be shown when children is not entirely visible */ + tooltipHasDefaultBehavior?: boolean; } export const TableText: React.FunctionComponent = ({ @@ -44,12 +46,13 @@ export const TableText: React.FunctionComponent = ({ tooltipProps = {}, onMouseEnter: onMouseEnterProp = () => {}, focused = false, + tooltipHasDefaultBehavior = false, ...props }: TableTextProps) => { const Component: TableTextVariant | 'span' | 'div' = variant; const textRef = React.createRef(); - const [tooltip, setTooltip] = React.useState(''); + const [tooltip, setTooltip] = React.useState(tooltipProp); const onMouseEnter = (event: any) => { if (event.target.offsetWidth < event.target.scrollWidth) { setTooltip(tooltipProp || event.target.innerText); @@ -70,7 +73,7 @@ export const TableText: React.FunctionComponent = ({ const text = ( } - onMouseEnter={onMouseEnter} + onMouseEnter={!tooltipHasDefaultBehavior ? onMouseEnter : undefined} className={css(className, wrapModifier && styles.modifiers[wrapModifier], styles.tableText)} {...props} > @@ -79,15 +82,22 @@ export const TableText: React.FunctionComponent = ({ ); React.useEffect(() => { - if (focused) { - onFocus(textRef.current); - } else { - setTooltip(''); + if (!tooltipHasDefaultBehavior) { + if (focused) { + onFocus(textRef.current); + } else { + setTooltip(''); + } } - }, [focused]); + }, [focused, tooltipHasDefaultBehavior]); return tooltip !== '' ? ( - + {text} ) : ( diff --git a/packages/react-table/src/components/Table/TableTypes.tsx b/packages/react-table/src/components/Table/TableTypes.tsx index 0a03be2b382..e0658d41f3e 100644 --- a/packages/react-table/src/components/Table/TableTypes.tsx +++ b/packages/react-table/src/components/Table/TableTypes.tsx @@ -132,6 +132,9 @@ export interface IExtra extends IExtraData { rowData?: IRowData; className?: string; ariaLabel?: string; + tooltip?: React.ReactNode; + tooltipProps?: Omit; + tooltipHasDefaultBehavior?: boolean; } export type IFormatterValueType = formatterValueType & { diff --git a/packages/react-table/src/components/Table/Th.tsx b/packages/react-table/src/components/Table/Th.tsx index 31a19bb2db2..aaa07a5bcfe 100644 --- a/packages/react-table/src/components/Table/Th.tsx +++ b/packages/react-table/src/components/Table/Th.tsx @@ -6,7 +6,7 @@ import { info, sortable, sortableFavorites, selectable, collapsible, cellWidth, import { ThInfoType, ThSelectType, ThExpandType, ThSortType, formatterValueType } from './base/types'; import { mergeProps } from './base/merge-props'; import { IVisibility } from './utils/decorators/classNames'; -import { Tooltip } from '@patternfly/react-core/dist/esm/components/Tooltip/Tooltip'; +import { Tooltip, TooltipProps } from '@patternfly/react-core/dist/esm/components/Tooltip'; import { BaseCellProps } from './Table'; import { IFormatterValueType, IColumn } from './TableTypes'; import cssStickyCellMinWidth from '@patternfly/react-tokens/dist/esm/c_table__sticky_cell_MinWidth'; @@ -34,6 +34,8 @@ export interface ThProps * To disable it completely you can set it to null. */ tooltip?: React.ReactNode; + /** other props to pass to the tooltip */ + tooltipProps?: Omit; /** Callback on mouse enter */ onMouseEnter?: (event: any) => void; /** Adds tooltip/popover info button */ @@ -68,6 +70,7 @@ const ThBase: React.FunctionComponent = ({ select = null, expand: collapse = null, tooltip = '', + tooltipProps, onMouseEnter: onMouseEnterProp = () => {}, width, visibility, @@ -99,7 +102,9 @@ const ThBase: React.FunctionComponent = ({ sortParams = sortableFavorites({ onSort: sort?.onSort, columnIndex: sort.columnIndex, - sortBy: sort.sortBy + sortBy: sort.sortBy, + tooltip: tooltip as string, + tooltipProps })(); } else { sortParams = sortable(children as IFormatterValueType, { @@ -109,7 +114,9 @@ const ThBase: React.FunctionComponent = ({ sortBy: sort.sortBy, onSort: sort?.onSort } - } as IColumn + } as IColumn, + tooltip: tooltip as string, + tooltipProps }); } } @@ -127,7 +134,9 @@ const ThBase: React.FunctionComponent = ({ allRowsSelected: select.isSelected, isHeaderSelectDisabled: !!select.isHeaderSelectDisabled } - } + }, + tooltip: tooltip as string, + tooltipProps }) : null; const collapseParams = collapse @@ -208,13 +217,15 @@ const ThBase: React.FunctionComponent = ({ ); const canMakeDefaultTooltip = tooltip === '' ? typeof transformedChildren === 'string' : true; - return tooltip !== null && canMakeDefaultTooltip && showTooltip ? ( + const childControlsTooltip = sortParams || selectParams; + return tooltip !== null && canMakeDefaultTooltip && !childControlsTooltip && showTooltip ? ( <> {cell} } content={tooltip || (tooltip === '' && children)} isVisible + {...tooltipProps} /> ) : ( diff --git a/packages/react-table/src/components/Table/utils/decorators/selectable.tsx b/packages/react-table/src/components/Table/utils/decorators/selectable.tsx index ef13464c8e1..b49c947aeeb 100644 --- a/packages/react-table/src/components/Table/utils/decorators/selectable.tsx +++ b/packages/react-table/src/components/Table/utils/decorators/selectable.tsx @@ -7,7 +7,7 @@ import checkStyles from '@patternfly/react-styles/css/components/Check/check'; export const selectable: ITransform = ( label: IFormatterValueType, - { rowIndex, columnIndex, rowData, column, property }: IExtra + { rowIndex, columnIndex, rowData, column, property, tooltip }: IExtra ) => { const { extraParams: { onSelect, selectVariant, allRowsSelected, isHeaderSelectDisabled } @@ -69,6 +69,7 @@ export const selectable: ITransform = ( selectVariant={selectVariant as RowSelectVariant} onSelect={selectClick} name={selectName} + tooltip={tooltip} > {label as React.ReactNode} diff --git a/packages/react-table/src/components/Table/utils/decorators/sortable.tsx b/packages/react-table/src/components/Table/utils/decorators/sortable.tsx index 5e85e1679cb..74c7c5d6561 100644 --- a/packages/react-table/src/components/Table/utils/decorators/sortable.tsx +++ b/packages/react-table/src/components/Table/utils/decorators/sortable.tsx @@ -15,12 +15,15 @@ export const sortableFavorites = (sort: any) => () => sortBy: sort.sortBy, onSort: sort?.onSort } - } + }, + tooltip: sort.tooltip, + tooltipProps: sort.tooltipProps, + tooltipHasDefaultBehavior: true }); export const sortable: ITransform = ( label: IFormatterValueType, - { columnIndex, column, property, className, ariaLabel }: IExtra + { columnIndex, column, property, className, ariaLabel, tooltip, tooltipProps, tooltipHasDefaultBehavior }: IExtra ) => { const { extraParams: { sortBy, onSort } @@ -56,6 +59,9 @@ export const sortable: ITransform = ( sortDirection={isSortedBy ? sortBy.direction : ''} onSort={sortClicked} aria-label={ariaLabel} + tooltip={tooltip} + tooltipProps={tooltipProps} + tooltipHasDefaultBehavior={tooltipHasDefaultBehavior} > {label as React.ReactNode}