From 6ba4d675be5c9e04fe7956124ce3328ffe97ec11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Pet=C5=99=C3=ADk?= Date: Tue, 28 Feb 2023 16:11:16 +0100 Subject: [PATCH] fix(Table) TableText tooltips not triggered via keyboard --- .../react-core/src/helpers/Popper/Popper.tsx | 21 +++++++++------ .../src/components/Table/HeaderCell.tsx | 1 + .../src/components/Table/SortColumn.tsx | 7 +++-- .../src/components/Table/TableText.tsx | 25 ++++++++++++++++-- .../src/components/TableComposable/Td.tsx | 24 ++++++++++++++--- .../src/components/TableComposable/Th.tsx | 26 ++++++++++++++++--- 6 files changed, 86 insertions(+), 18 deletions(-) diff --git a/packages/react-core/src/helpers/Popper/Popper.tsx b/packages/react-core/src/helpers/Popper/Popper.tsx index 5b33fa0faee..59f063df6a7 100644 --- a/packages/react-core/src/helpers/Popper/Popper.tsx +++ b/packages/react-core/src/helpers/Popper/Popper.tsx @@ -272,11 +272,10 @@ export const Popper: React.FunctionComponent = ({ return convertedPlacement as Placement; }; const getPlacementMemo = React.useMemo(getPlacement, [direction, position, placement]); - const getOppositePlacementMemo = React.useMemo(() => getOppositePlacement(getPlacement()), [ - direction, - position, - placement - ]); + const getOppositePlacementMemo = React.useMemo( + () => getOppositePlacement(getPlacement()), + [direction, position, placement] + ); const sameWidthMod: Modifier<'sameWidth', {}> = React.useMemo( () => ({ name: 'sameWidth', @@ -294,7 +293,12 @@ export const Popper: React.FunctionComponent = ({ [popperMatchesTriggerWidth] ); - const { styles: popperStyles, attributes, update, forceUpdate } = usePopper(refOrTrigger, popperElement, { + const { + styles: popperStyles, + attributes, + update, + forceUpdate + } = usePopper(refOrTrigger, popperElement, { placement: getPlacementMemo, modifiers: [ { @@ -352,7 +356,7 @@ export const Popper: React.FunctionComponent = ({ return popperRef ? ( localPopper ) : ( -
setPopperElement(node?.firstElementChild as HTMLElement)}> +
setPopperElement(node?.firstElementChild as HTMLElement)}> {localPopper}
); @@ -370,10 +374,11 @@ export const Popper: React.FunctionComponent = ({ return ( <> {!reference && trigger && React.isValidElement(trigger) && ( -
setTriggerElement(node?.firstElementChild as HTMLElement)}> +
setTriggerElement(node?.firstElementChild as HTMLElement)}> {trigger}
)} + {reference && trigger && React.isValidElement(trigger) && trigger} {ready && isVisible && getPopper()} ); diff --git a/packages/react-table/src/components/Table/HeaderCell.tsx b/packages/react-table/src/components/Table/HeaderCell.tsx index fc6c77d6bec..5199247d484 100644 --- a/packages/react-table/src/components/Table/HeaderCell.tsx +++ b/packages/react-table/src/components/Table/HeaderCell.tsx @@ -33,6 +33,7 @@ export const HeaderCell: React.FunctionComponent = ({ scope={scope} tooltip={tooltip} onMouseEnter={onMouseEnter} + focusable={false} textCenter={textCenter} component={component} className={className} diff --git a/packages/react-table/src/components/Table/SortColumn.tsx b/packages/react-table/src/components/Table/SortColumn.tsx index 93f0a16a417..1526a533aee 100644 --- a/packages/react-table/src/components/Table/SortColumn.tsx +++ b/packages/react-table/src/components/Table/SortColumn.tsx @@ -29,6 +29,7 @@ export const SortColumn: React.FunctionComponent = ({ ...props }: SortColumnProps) => { let SortedByIcon; + const [focused, setFocused] = React.useState(false); if (isSortedBy) { SortedByIcon = sortDirection === SortByDirection.asc ? LongArrowAltUpIcon : LongArrowAltDownIcon; } else { @@ -39,10 +40,12 @@ export const SortColumn: React.FunctionComponent = ({ {...props} type={type} className={css(className, styles.tableButton)} - onClick={event => onSort && onSort(event)} + onClick={(event) => onSort && onSort(event)} + onFocus={() => setFocused(true)} + 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 a29a80bdb1c..1b1852bbbcc 100644 --- a/packages/react-table/src/components/Table/TableText.tsx +++ b/packages/react-table/src/components/Table/TableText.tsx @@ -31,6 +31,8 @@ export interface TableTextProps extends React.HTMLProps { tooltipProps?: Omit; /** callback used to create the tooltip if text is truncated */ onMouseEnter?: (event: any) => void; + + focused?: boolean; } export const TableText: React.FunctionComponent = ({ @@ -41,9 +43,11 @@ export const TableText: React.FunctionComponent = ({ tooltip: tooltipProp = '', tooltipProps = {}, onMouseEnter: onMouseEnterProp = () => {}, + focused = false, ...props }: TableTextProps) => { const Component: TableTextVariant | 'span' | 'div' = variant; + const textRef = React.createRef(); const [tooltip, setTooltip] = React.useState(''); const onMouseEnter = (event: any) => { @@ -55,9 +59,18 @@ export const TableText: React.FunctionComponent = ({ onMouseEnterProp(event); }; + const onFocus = (element: HTMLElement) => { + if (element.offsetWidth < element.scrollWidth) { + setTooltip(tooltipProp || element.innerText); + } else { + setTooltip(''); + } + }; + const text = ( } + onMouseEnter={(event) => onMouseEnter(event)} className={css(className, wrapModifier && styles.modifiers[wrapModifier], styles.tableText)} {...props} > @@ -65,8 +78,16 @@ export const TableText: React.FunctionComponent = ({ ); + React.useEffect(() => { + if (focused) { + onFocus(textRef.current); + } else { + setTooltip(''); + } + }, [focused]); + return tooltip !== '' ? ( - + {text} ) : ( diff --git a/packages/react-table/src/components/TableComposable/Td.tsx b/packages/react-table/src/components/TableComposable/Td.tsx index 525e6acdf42..4268c4d6419 100644 --- a/packages/react-table/src/components/TableComposable/Td.tsx +++ b/packages/react-table/src/components/TableComposable/Td.tsx @@ -96,12 +96,15 @@ const TdBase: React.FunctionComponent = ({ ...props }: TdProps) => { const [showTooltip, setShowTooltip] = React.useState(false); + const [truncated, setTruncated] = React.useState(false); + const cellRef = innerRef ? innerRef : React.createRef(); const onMouseEnter = (event: any) => { if (event.target.offsetWidth < event.target.scrollWidth) { !showTooltip && setShowTooltip(true); } else { showTooltip && setShowTooltip(false); } + onMouseEnterProp(event); }; @@ -244,9 +247,19 @@ const TdBase: React.FunctionComponent = ({ (className && className.includes('pf-c-table__tree-view-title-cell')) || (mergedClassName && mergedClassName.includes('pf-c-table__tree-view-title-cell')); + React.useEffect(() => { + setTruncated( + (cellRef as React.RefObject).current.offsetWidth < + (cellRef as React.RefObject).current.scrollWidth + ); + }, [cellRef]); + const cell = ( setShowTooltip(false)} onMouseEnter={tooltip !== null ? onMouseEnter : onMouseEnterProp} className={css( className, @@ -259,7 +272,7 @@ const TdBase: React.FunctionComponent = ({ draggableParams && styles.tableDraggable, mergedClassName )} - ref={innerRef} + ref={cellRef} {...mergedProps} {...props} {...(isStickyColumn && { @@ -276,9 +289,14 @@ const TdBase: React.FunctionComponent = ({ const canMakeDefaultTooltip = tooltip === '' ? typeof children === 'string' : true; return tooltip !== null && canMakeDefaultTooltip && showTooltip ? ( - + <> {cell} - + } + content={tooltip || (tooltip === '' && children)} + isVisible + /> + ) : ( cell ); diff --git a/packages/react-table/src/components/TableComposable/Th.tsx b/packages/react-table/src/components/TableComposable/Th.tsx index 4d51d78a02d..4bfed937916 100644 --- a/packages/react-table/src/components/TableComposable/Th.tsx +++ b/packages/react-table/src/components/TableComposable/Th.tsx @@ -52,6 +52,8 @@ export interface ThProps stickyLeftOffset?: string; /** Indicates the is part of a subheader of a nested header */ isSubheader?: boolean; + + focusable?: boolean; } const ThBase: React.FunctionComponent = ({ @@ -76,9 +78,12 @@ const ThBase: React.FunctionComponent = ({ stickyMinWidth = '120px', stickyLeftOffset, isSubheader = false, + focusable = true, ...props }: ThProps) => { const [showTooltip, setShowTooltip] = React.useState(false); + const [truncated, setTruncated] = React.useState(false); + const cellRef = innerRef ? innerRef : React.createRef(); const onMouseEnter = (event: any) => { if (event.target.offsetWidth < event.target.scrollWidth) { !showTooltip && setShowTooltip(true); @@ -159,12 +164,22 @@ const ThBase: React.FunctionComponent = ({ ...mergedProps } = merged; + React.useEffect(() => { + setTruncated( + (cellRef as React.RefObject).current.offsetWidth < + (cellRef as React.RefObject).current.scrollWidth + ); + }, [cellRef]); + const cell = ( setShowTooltip(false)} data-label={dataLabel} onMouseEnter={tooltip !== null ? onMouseEnter : onMouseEnterProp} scope={component === 'th' && children ? scope : null} - ref={innerRef} + ref={cellRef} className={css( className, textCenter && styles.modifiers.center, @@ -190,9 +205,14 @@ const ThBase: React.FunctionComponent = ({ const canMakeDefaultTooltip = tooltip === '' ? typeof transformedChildren === 'string' : true; return tooltip !== null && canMakeDefaultTooltip && showTooltip ? ( - + <> {cell} - + } + content={tooltip || (tooltip === '' && children)} + isVisible + /> + ) : ( cell );