Skip to content

Commit

Permalink
fix(flat-table-row-header): focus border partially covered in expande…
Browse files Browse the repository at this point in the history
…d rows

updated the flat table row header and the flat table cell to prevent covering the focus border

fixes: #6561
  • Loading branch information
mihai-albu-sage committed Jul 10, 2024
1 parent 3c7eae8 commit e2b8f2c
Show file tree
Hide file tree
Showing 7 changed files with 372 additions and 8 deletions.
62 changes: 62 additions & 0 deletions src/components/flat-table/__internal__/use-table-cell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,67 @@ export default (id: string) => {
const isFirstCell = id === firstCellId;
const isExpandableCell = expandable && isFirstCell && firstColumnExpandable;

const bringToFront = (
ev:
| React.MouseEvent<HTMLElement, MouseEvent>
| React.FocusEvent<HTMLElement>,
tagName: "TD" | "TH"
) => {
/* istanbul ignore if */
if (
!ev ||
!ev.nativeEvent ||
typeof ev.nativeEvent.composedPath !== "function"
) {
return;
}

const { nativeEvent } = ev;

// get the entire path of the event
const path = nativeEvent.composedPath();

// get the table from the path
const tableBody = path.find((el) => {
return el instanceof HTMLElement && el.tagName === "TBODY";
});

// if there is no table in the path we don't do anything
if (!tableBody) {
return;
}

// get all the th and td elements that are sticky
const stickyCells = Array.from(
(tableBody as HTMLElement).querySelectorAll("th, td")
).filter((el) => {
return (
el.getAttribute("data-sticky-align") === "left" ||
el.getAttribute("data-sticky-align") === "right" ||
el.classList.contains("isSticky")
);
});

// reset the z-index to the default value for all the sticky cells, in case other cells were clicked before
stickyCells.map((el) => {
(el as HTMLElement).classList.remove("bringToFront");
return el;
});

// find the current cell in the path
const cell = path.find(
(el) => el instanceof HTMLElement && el.tagName === tagName
);

// if the current cell is sticky, increase the z-index value
const cellIndex = stickyCells.indexOf(cell as HTMLTableCellElement);
if (cellIndex !== -1) {
(stickyCells[cellIndex] as HTMLTableCellElement).classList.add(
"bringToFront"
);
}
};

useEffect(() => {
const tabstopTimer = setTimeout(() => {
setTabIndex(isExpandableCell && getTabStopElementId() === id ? 0 : -1);
Expand All @@ -46,5 +107,6 @@ export default (id: string) => {
tabIndex,
isInHighlightedRow: highlighted,
isInSelectedRow: selected,
bringToFront,
};
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef } from "react";
import React, { useRef, useCallback } from "react";

Check failure on line 1 in src/components/flat-table/flat-table-cell/flat-table-cell.component.tsx

View workflow job for this annotation

GitHub Actions / Lint

'useCallback' is declared but its value is never read.
import { PaddingProps } from "styled-system";
import { TableBorderSize, TableCellAlign } from "..";

Expand Down Expand Up @@ -59,8 +59,13 @@ export const FlatTableCell = ({
isInHighlightedRow,
isInSelectedRow,
tabIndex,
bringToFront,
} = useTableCell(internalId.current);

const handleOnFocus = (ev: React.FocusEvent<HTMLElement>) => {
bringToFront(ev, "TD");
};

return (
<StyledFlatTableCell
leftPosition={leftPosition}
Expand All @@ -82,6 +87,7 @@ export const FlatTableCell = ({
data-highlighted={isInHighlightedRow && isExpandableCell}
{...rest}
id={internalId.current}
onFocus={handleOnFocus}
>
<StyledCellContent
title={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const FlatTableRowHeader = ({
tabIndex,
isInHighlightedRow,
isInSelectedRow,
bringToFront,
} = useTableCell(internalId.current);

const handleOnClick = useCallback(
Expand All @@ -74,6 +75,10 @@ export const FlatTableRowHeader = ({
[isExpandableCell, onClick]
);

const handleOnFocus = (ev: React.FocusEvent<HTMLElement>) => {
bringToFront(ev, "TH");
};

const handleOnKeyDown = useCallback(
(ev: React.KeyboardEvent<HTMLElement>) => {
if (isExpandableCell && onKeyDown) {
Expand Down Expand Up @@ -109,6 +114,7 @@ export const FlatTableRowHeader = ({
data-highlighted={isInHighlightedRow && isExpandableCell}
{...rest}
id={internalId.current}
onFocus={handleOnFocus}
>
<StyledFlatTableRowHeaderContent
title={
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from "react";
import { mount, ReactWrapper } from "enzyme";

import { render as rtlRender, screen } from "@testing-library/react";
import { StyledFlatTableRowHeader } from "./flat-table-row-header.style";
import FlatTableRowHeader, {
FlatTableRowHeaderProps,
Expand All @@ -11,6 +12,11 @@ import {
} from "../../../__spec_helper__/__internal__/test-utils";
import StyledIcon from "../../icon/icon.style";
import FlatTableRowContext from "../flat-table-row/__internal__/flat-table-row.context";
import FlatTable from "../flat-table.component";
import FlatTableBody from "../flat-table-body/flat-table-body.component";
import FlatTableRow from "../flat-table-row/flat-table-row.component";
import FlatTableCell from "../flat-table-cell/flat-table-cell.component";
import Button from "../../button/button.component";

describe("FlatTableRowHeader", () => {
testStyledSystemPadding(
Expand Down Expand Up @@ -321,6 +327,97 @@ describe("FlatTableRowHeader", () => {
);
}
);

it("increases the z-index of the sticky TH or TD if content is focused and they are part of a FlatTableBody", () => {
rtlRender(
<FlatTable>
<FlatTableBody>
<FlatTableRow>
<FlatTableCell data-role="cell">
<Button>cell button</Button>
</FlatTableCell>
<FlatTableRowHeader
data-role="header-one"
stickyAlignment="left"
p={0}
>
<Button>header one button</Button>
</FlatTableRowHeader>
<FlatTableCell>text content</FlatTableCell>
</FlatTableRow>
<FlatTableRow>
<FlatTableCell>text content</FlatTableCell>
<FlatTableRowHeader
data-role="header-two"
stickyAlignment="left"
p={0}
>
<Button>header two button</Button>
</FlatTableRowHeader>
<FlatTableCell>text content</FlatTableCell>
</FlatTableRow>
</FlatTableBody>
</FlatTable>
);

const headerOne = screen.getByTestId("header-one");
const headerOneButton = screen.getByRole("button", {
name: "header one button",
});

const headerTwo = screen.getByTestId("header-two");
const headerTwoButton = screen.getByRole("button", {
name: "header two button",
});

const cell = screen.getByTestId("cell");
const cellButton = screen.getByRole("button", { name: "cell button" });

headerOneButton.focus();

expect(cell).not.toHaveClass("bringToFront");
expect(headerOne).toHaveClass("bringToFront");
expect(headerTwo).not.toHaveClass("bringToFront");

headerTwoButton.focus();

expect(cell).not.toHaveClass("bringToFront");
expect(headerOne).not.toHaveClass("bringToFront");
expect(headerTwo).toHaveClass("bringToFront");

cellButton.focus();

expect(cell).toHaveClass("bringToFront");
expect(headerOne).not.toHaveClass("bringToFront");
expect(headerTwo).not.toHaveClass("bringToFront");
});

it("does not increase the z-index of the sticky TH or TD if they are not part of a FlatTableBody", () => {
rtlRender(
<FlatTableRow>
<FlatTableCell data-role="cell">
<Button>cell button</Button>
</FlatTableCell>
<FlatTableRowHeader
data-role="header-one"
stickyAlignment="left"
p={0}
>
<Button>header one button</Button>
</FlatTableRowHeader>
<FlatTableCell>text content</FlatTableCell>
</FlatTableRow>
);

const headerOne = screen.getByTestId("header-one");
const headerOneButton = screen.getByRole("button", {
name: "header one button",
});

headerOneButton.focus();

expect(headerOne).not.toHaveClass("bringToFront");
});
});

describe.each([
Expand Down
16 changes: 9 additions & 7 deletions src/components/flat-table/flat-table-row/flat-table-row.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ const firstColumnOldFocusStyling = `
outline-offset: -1px;
`;

const newFocusStyling = `
${addFocusStyling(true)}
z-index: 1000;
`;
const newFocusStyling = (theme: ThemeObject) => {
return `
${addFocusStyling(true)}
z-index: ${theme.zIndex.overlay + 5};
`;
};

const getLeftStickyStyling = (index: number, themeOptOut: boolean) =>
index === 0 &&
Expand Down Expand Up @@ -266,7 +268,7 @@ const StyledFlatTableRow = styled.tr<StyledFlatTableRowProps>`
top: 0;
bottom: 0px;
${!theme.focusRedesignOptOut
? newFocusStyling
? newFocusStyling(theme)
: /* istanbul ignore next */ oldFocusStyling}
pointer-events: none;
}
Expand Down Expand Up @@ -306,7 +308,7 @@ const StyledFlatTableRow = styled.tr<StyledFlatTableRowProps>`
border: none;
content: "";
height: ${rowHeight}px;
${newFocusStyling}
${newFocusStyling(theme)}
}
`}
`}
Expand Down Expand Up @@ -357,7 +359,7 @@ const StyledFlatTableRow = styled.tr<StyledFlatTableRowProps>`
:focus {
${!theme.focusRedesignOptOut
? newFocusStyling
? newFocusStyling(theme)
: /* istanbul ignore next */ firstColumnOldFocusStyling}
}
Expand Down
Loading

0 comments on commit e2b8f2c

Please sign in to comment.