Skip to content

Commit bdf4517

Browse files
committed
refactor: include tfoot in table navigation (refs SFKUI-7709)
1 parent 4e1e6a0 commit bdf4517

File tree

3 files changed

+40
-30
lines changed

3 files changed

+40
-30
lines changed

packages/vue-labs/src/components/FTable/FTable.cy.ts

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,8 +1260,9 @@ describe("5 tabstop", () => {
12601260
table.cell({ row: 1, col: 1 }).should("have.attr", "tabindex", "0");
12611261
});
12621262

1263-
it("should set correct tabstop for all types of headers and cells on navigation", () => {
1264-
const { buttonBeforeTable } = mountNavigationTestbed();
1263+
it("should set correct tabstop for all types of headers, cells and footer on navigation", () => {
1264+
const slots = { footer: "footer" };
1265+
const { buttonBeforeTable } = mountNavigationTestbed(slots);
12651266
cy.get(buttonBeforeTable).focus();
12661267
cy.focused().press(Cypress.Keyboard.Keys.TAB);
12671268
// {1, 1}: expand button
@@ -1381,10 +1382,23 @@ describe("5 tabstop", () => {
13811382
.should("have.prop", "tagName", "TD")
13821383
.should("not.have.text")
13831384
.should("have.attr", "tabindex", 0);
1385+
cy.focused().press(Cypress.Keyboard.Keys.DOWN);
1386+
// {3, 1}: expand footer
1387+
cy.focused()
1388+
.should("have.prop", "tagName", "TD")
1389+
.should("have.text", "footer")
1390+
.should("have.attr", "tabindex", 0);
1391+
cy.focused().press(Cypress.Keyboard.Keys.UP);
1392+
// {2, 1}: expand for child (empty)
1393+
cy.focused()
1394+
.should("have.prop", "tagName", "TD")
1395+
.should("not.have.text")
1396+
.should("have.attr", "tabindex", 0);
13841397
});
13851398

1386-
it("should set correct tabstop for all types of headers and cells on click", () => {
1387-
mountNavigationTestbed();
1399+
it("should set correct tabstop for all types of headers, cells and footer on click", () => {
1400+
const slots = { footer: "footer" };
1401+
mountNavigationTestbed(slots);
13881402

13891403
// {1, 1}: expand button
13901404
table.cell({ row: 1, col: 1 }).click();
@@ -1493,6 +1507,12 @@ describe("5 tabstop", () => {
14931507
.should("have.prop", "tagName", "TD")
14941508
.should("not.have.text")
14951509
.should("have.attr", "tabindex", 0);
1510+
// {3, 1}: expand footer
1511+
table.footer().click();
1512+
cy.focused()
1513+
.should("have.prop", "tagName", "TD")
1514+
.should("have.text", "footer")
1515+
.should("have.attr", "tabindex", 0);
14961516
});
14971517

14981518
it("should allow tab navigation in and out of expanded row", () => {
@@ -1526,23 +1546,6 @@ describe("5 tabstop", () => {
15261546
cy.focused().press(Cypress.Keyboard.Keys.TAB);
15271547
table.cell({ row: 2, col: 2 }).should("have.focus");
15281548
});
1529-
1530-
it("should not change footer tabindex", () => {
1531-
const footerButtonSelector = "footerButton";
1532-
const slots = {
1533-
footer: renderButton("Footer button", {
1534-
dataTest: footerButtonSelector,
1535-
}),
1536-
};
1537-
mountNavigationTestbed(slots);
1538-
const footerButton = getTestSelector(footerButtonSelector);
1539-
1540-
table.cell({ row: 1, col: 3 }).click();
1541-
cy.focused().press(Cypress.Keyboard.Keys.TAB);
1542-
cy.get(footerButton).should("have.focus");
1543-
cy.focused().realPress(["Shift", "Tab"]);
1544-
table.cell({ row: 1, col: 3 }).should("have.focus");
1545-
});
15461549
});
15471550

15481551
describe("Radio button single‑select functionality in table", () => {

packages/vue-labs/src/components/FTable/FTable.vue

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ function onClick(e: MouseEvent): void {
176176
function onTableFocusin(e: FocusEvent): void {
177177
assertRef(tableRef);
178178
179-
for (const it of tableRef.value.querySelectorAll(`:not(tfoot)[tabindex="0"]`)) {
179+
for (const it of tableRef.value.querySelectorAll(`[tabindex="0"]`)) {
180180
if (it !== e.target) {
181181
it.setAttribute("tabindex", "-1");
182182
}
@@ -204,8 +204,7 @@ function onTableFocusout(e: FocusEvent): void {
204204
return;
205205
}
206206
207-
const outsideTable =
208-
Boolean(tableRef.value.tFoot?.contains(relatedTarget)) || !tableRef.value.contains(relatedTarget);
207+
const outsideTable = !tableRef.value.contains(relatedTarget);
209208
210209
if (outsideTable) {
211210
const cell = target.closest<HTMLElement>("td, th");
@@ -301,11 +300,20 @@ onMounted(() => {
301300
</script>
302301

303302
<template>
304-
<table ref="table" :role :class="tableClasses" :aria-rowcount>
303+
<table
304+
ref="table"
305+
:role
306+
:class="tableClasses"
307+
:aria-rowcount
308+
@focusin="onTableFocusin"
309+
@focusout="onTableFocusout"
310+
@click="onClick"
311+
@keydown="onKeydown"
312+
>
305313
<caption v-if="hasCaption" data-test="caption">
306314
<slot name="caption"></slot>
307315
</caption>
308-
<thead @focusin="onTableFocusin" @focusout="onTableFocusout" @click="onClick" @keydown="onKeydown">
316+
<thead>
309317
<tr class="table-ng__row" aria-rowindex="1">
310318
<th v-if="isTreegrid" scope="col" tabindex="-1" class="table-ng__column"></th>
311319
<i-table-header-selectable
@@ -328,7 +336,7 @@ onMounted(() => {
328336
</tr>
329337
</thead>
330338

331-
<tbody @focusin="onTableFocusin" @focusout="onTableFocusout" @click="onClick" @keydown="onKeydown">
339+
<tbody>
332340
<template v-if="isEmpty">
333341
<tr class="table-ng__row--empty">
334342
<td :colspan="columnCount" class="table-ng__cell">

packages/vue-labs/src/components/FTable/use-tabstop.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,8 @@ export function useTabstop(
6565

6666
// resolve current tabstop details
6767
assertRef(tableRef);
68-
const oldTabstopElement = tableRef.value.querySelector<HTMLElement>(
69-
`:not(tfoot)[tabindex="0"]`,
70-
);
68+
const oldTabstopElement =
69+
tableRef.value.querySelector<HTMLElement>(`[tabindex="0"]`);
7170
assertSet(oldTabstopElement);
7271
const oldTabstopFocused = oldTabstopElement === document.activeElement;
7372

0 commit comments

Comments
 (0)