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

Add keyboard navigation to table #2172

Merged
merged 119 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
e823d57
Prototype as of 4/3
msmithNI Apr 4, 2024
b974ba5
Merge from main
msmithNI Apr 30, 2024
4dad3d3
Updated keyboard nav code
msmithNI May 2, 2024
07cc96b
Lint/prettier
msmithNI May 2, 2024
f57ac31
Add TODO
msmithNI May 2, 2024
6f2126b
Merge from main
msmithNI May 2, 2024
893db0c
Merge branch 'main' into users/masmith/table-keyboard-interaction-temp
msmithNI May 2, 2024
e185f0d
Fix test, less console.log noise when body focused
msmithNI May 3, 2024
65ab3dd
Remove no-op call
msmithNI May 6, 2024
078fccb
Bugfix for Safari Mac issue, temporary fix for scrolling down via Dow…
msmithNI May 10, 2024
afaa3cb
Remove tabIndexOverride
msmithNI May 10, 2024
247b51a
Undo no-op change
msmithNI May 10, 2024
0ba987e
Feature complete keyboard nav
msmithNI May 17, 2024
0a92870
Cleanup / fix F2 for single-element cells
msmithNI May 17, 2024
7a7ce21
prettier
msmithNI May 17, 2024
e29b789
Fix action menu Shift-Tab issue
msmithNI May 17, 2024
5110178
Prettier
msmithNI May 17, 2024
4248deb
Simplify onTabPressed
msmithNI May 20, 2024
531eac3
Fix anchor view tabbableChildren implementation, get rid of extra vie…
msmithNI May 20, 2024
249c1bf
Cleanup (methods to set focus type, Tab for headers uses similar logi…
msmithNI May 21, 2024
c6244a1
Merge branch 'main' into users/masmith/table-keyboard-interaction-temp
msmithNI May 22, 2024
8f3c5ce
Fix build
msmithNI May 22, 2024
cacf215
Uptake tabindex changes
msmithNI May 22, 2024
adfb7a7
Fix column header tabIndex behavior
msmithNI May 22, 2024
b23ea0d
Fix issues scrolling with a focused cell (+ switch back to observers)
msmithNI May 22, 2024
0a26787
Fix build
msmithNI May 22, 2024
0d5ff72
Refactoring/cleanup
msmithNI May 29, 2024
6dbad6d
Cleanup
msmithNI May 30, 2024
44f0936
Remove (flatten) TableFocusState into kbd nav code
msmithNI May 30, 2024
f6e6a34
Fix some issues with anchor columns / action menus
msmithNI May 30, 2024
e472265
Add anchor to lastName in Storybook (for testing)
msmithNI May 30, 2024
cccd1d2
Fix another 'single interactive element' corner case with Tab
msmithNI May 30, 2024
9a32fb3
Remove 'single interactive element' special case
msmithNI May 30, 2024
c80b0f0
Update Enter (when cell focused) to focus content, but not activate it
msmithNI May 31, 2024
8929dff
Update code switching back to cell focusState on scroll
msmithNI May 31, 2024
2fafcfd
Fix row selection checkbox focusing issue
msmithNI Jun 3, 2024
7519dfc
Misc cleanup/fixes
msmithNI Jun 6, 2024
e964c6e
Tests
msmithNI Jun 6, 2024
fd1adde
Undo Storybook changes
msmithNI Jun 6, 2024
e7dbe26
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 6, 2024
fea98c0
Remove unused type
msmithNI Jun 6, 2024
4a77b50
Fix test (fix initial focusing behavior)
msmithNI Jun 6, 2024
f60bc9e
Remove debug/console.log code
msmithNI Jun 6, 2024
5fc5350
Prettier
msmithNI Jun 6, 2024
c5da0fa
Tag problematic tests
msmithNI Jun 6, 2024
0db28a3
Change files
msmithNI Jun 6, 2024
d907186
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 6, 2024
c79c50c
Add table keyboard nav docs in Storybook
msmithNI Jun 6, 2024
7cce0f0
Cleanup, fix action menu button blur, get rid of focus ring from view…
msmithNI Jun 7, 2024
c3db84d
Prettier
msmithNI Jun 7, 2024
b7e2d5c
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 7, 2024
462a90b
Remove unused method
msmithNI Jun 7, 2024
e177944
Add @internal to new volatile properties
msmithNI Jun 7, 2024
e807d83
Fix comparison operator / add test
msmithNI Jun 7, 2024
5c60db5
PR feedback
msmithNI Jun 7, 2024
9958420
Rename row/groupRow.dataIndex to rowStateIndex
msmithNI Jun 7, 2024
89fba97
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 7, 2024
6908721
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 10, 2024
dd917f0
Reset focus state when a column is hidden/unhidden; add some tests fo…
msmithNI Jun 10, 2024
04e9eb4
F2 will return to cell focus from cellContent/cellActionMenu focus (w…
msmithNI Jun 10, 2024
cc0409a
Prettier
msmithNI Jun 10, 2024
52ea034
Test cleanup
msmithNI Jun 10, 2024
b698342
Update keyboard nav docs
msmithNI Jun 10, 2024
32ca89a
Switch inNavigationMode to be a getter derived from focusType
msmithNI Jun 10, 2024
ed4007c
Cleanup
msmithNI Jun 10, 2024
6c652cd
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 10, 2024
5b108b2
Simplify getCurrentRow(), revamp some non-null assertions on rows
msmithNI Jun 10, 2024
31d1ffe
Prettier
msmithNI Jun 10, 2024
d995ab3
Lint storybook mdx
msmithNI Jun 11, 2024
ac246d0
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 11, 2024
0bf59c2
Update table.mdx
msmithNI Jun 11, 2024
9c50a13
Fix Tab behavior on group rows
msmithNI Jun 11, 2024
efdd7f1
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
rajsite Jun 12, 2024
c717ffa
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 12, 2024
e0a3d6e
Fix issues with focus state becoming out-of-date after various mouse …
msmithNI Jun 12, 2024
06532e6
PR feedback
msmithNI Jun 12, 2024
7bee46d
Update types.spec.ts
msmithNI Jun 12, 2024
b838769
Additional tests
msmithNI Jun 12, 2024
ec59df1
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 13, 2024
5155616
Uptake sortable column mixin changes
msmithNI Jun 13, 2024
a0504a6
Add new tests to cover some cases from commit "Fix issues with focus …
msmithNI Jun 13, 2024
3b05484
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 17, 2024
5916582
PR feedback (add disconnect() / uptake parameterizeSpec for tests), f…
msmithNI Jun 17, 2024
3387588
Update tests. Add a parameterizeSuite block for interactive column te…
msmithNI Jun 17, 2024
e6ed7f4
Fix table stealing focus on scroll after it's already lost focus
msmithNI Jun 18, 2024
f22db9b
Add comments / switch quote style
msmithNI Jun 18, 2024
2578ca2
Prettier
msmithNI Jun 18, 2024
3a6b07f
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 18, 2024
e8aa429
More tests, fix selectionMode=none + Space key issue
msmithNI Jun 18, 2024
9b00aeb
Add tests covering action menu button UpArrow/DownArrow
msmithNI Jun 18, 2024
1bba114
Prevent Firefox changing focus on Up/DownArrow at table extents
msmithNI Jun 18, 2024
06c9d19
Fix focus type reverting from cell/rowSelectionCheckbox to row type a…
msmithNI Jun 18, 2024
6998884
Prettier
msmithNI Jun 18, 2024
06b3139
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 18, 2024
5846514
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 20, 2024
258d64e
Add keyboard focus matrix tests
msmithNI Jun 20, 2024
522b919
PR feedback
msmithNI Jun 20, 2024
d9d1df7
Fix page objects from cell template update
msmithNI Jun 20, 2024
9c41d3d
Prettier
msmithNI Jun 20, 2024
9846033
Add tests covering focus when table data changes (more/less/zero rows)
msmithNI Jun 20, 2024
280ae22
Merge branch 'main' into users/masmith/table-keyboard-interaction-2
msmithNI Jun 20, 2024
1bec49c
PR feedback
msmithNI Jun 23, 2024
e52d724
Rename rowStateIndex to resolvedRowIndex
msmithNI Jun 23, 2024
a414692
Feedback
msmithNI Jun 23, 2024
ed24822
Prettier
msmithNI Jun 23, 2024
4f28dfb
Update table-matrix.stories.ts
msmithNI Jun 23, 2024
b41ab67
setActionMenuButtonFocused / setElementFocusable / getActiveElement u…
msmithNI Jun 23, 2024
f5d452d
Add isVisualRow helper
msmithNI Jun 23, 2024
24944bf
Move event listeners
msmithNI Jun 23, 2024
3a545d3
Update virtualizer pageSize property
msmithNI Jun 23, 2024
0f73291
Revamp tests
msmithNI Jun 24, 2024
2b484f7
Remove duplicate tests (these exist further up in the file already)
msmithNI Jun 24, 2024
82390f2
Fix issue where if an anchor in a cell is focused, and a data update …
msmithNI Jun 24, 2024
f9c820d
Add comments to tabindex instances in templates that are managed by k…
msmithNI Jun 24, 2024
af9047a
Re-add aria-hidden on row expand/collapse button (was removed when th…
msmithNI Jun 24, 2024
c2e0e6e
PR feedback
msmithNI Jun 24, 2024
397b4fc
Update template comments to be single-line
msmithNI Jun 25, 2024
79f3f8c
Fix LeftArrow behavior on a group row selection checkbox (should refo…
msmithNI Jun 25, 2024
627bf13
Prettier
msmithNI Jun 25, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
"type": "minor",
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
"comment": "Add keyboard navigation functionality to the table component",
rajsite marked this conversation as resolved.
Show resolved Hide resolved
"packageName": "@ni/nimble-components",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,22 @@ TableColumnAnchorColumnConfig
return '';
}

/** @internal */
@volatile
public get showAnchor(): boolean {
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
return typeof this.cellRecord?.href === 'string';
}

public override focusedRecycleCallback(): void {
this.anchor?.blur();
}

public override get tabbableChildren(): HTMLElement[] {
if (this.showAnchor) {
return [this.anchor!];
}
return [];
}
}

const anchorCellView = TableColumnAnchorCellView.compose({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ export const template = html<TableColumnAnchorCellView>`
}}"
class="${x => (x.isPlaceholder ? 'placeholder' : '')}"
>
${when(x => typeof x.cellRecord?.href === 'string', html<TableColumnAnchorCellView>`
${when(x => x.showAnchor, html<TableColumnAnchorCellView>`
<${anchorTag}
${ref('anchor')}
${overflow('hasOverflow')}
${'' /* tabindex managed dynamically by KeyboardNavigationManager */}
tabindex="-1"
href="${x => x.cellRecord?.href}"
hreflang="${x => x.columnConfig?.hreflang}"
ping="${x => x.columnConfig?.ping}"
Expand All @@ -33,7 +35,7 @@ export const template = html<TableColumnAnchorCellView>`
>
${x => x.text}
</${anchorTag}>`)}
${when(x => typeof x.cellRecord?.href !== 'string', html<TableColumnAnchorCellView>`
${when(x => !x.showAnchor, html<TableColumnAnchorCellView>`
<span
${overflow('hasOverflow')}
title=${x => (x.hasOverflow ? x.text : null)}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { html, ref } from '@microsoft/fast-element';
import { parameterizeSpec } from '@ni/jasmine-parameterized';
import { keyArrowDown, keyEscape, keyTab } from '@microsoft/fast-web-utilities';
import { tableTag, type Table } from '../../../table';
import { TableColumnAnchor, tableColumnAnchorTag } from '..';
import { waitForUpdatesAsync } from '../../../testing/async-helpers';
Expand All @@ -8,6 +9,7 @@ import { TableColumnSortDirection, TableRecord } from '../../../table/types';
import { TablePageObject } from '../../../table/testing/table.pageobject';
import { wackyStrings } from '../../../utilities/tests/wacky-strings';
import type { Anchor } from '../../../anchor';
import { sendKeyDownEvent } from '../../../utilities/tests/component';

interface SimpleTableRecord extends TableRecord {
label?: string | null;
Expand Down Expand Up @@ -164,6 +166,16 @@ describe('TableColumnAnchor', () => {
expect(pageObject.getCellTitle(0, 0)).toBe('');
});

it('cell view tabbableChildren is an empty array', async () => {
const cellContents = 'value';
await table.setData([{ label: cellContents }]);
await connect();
await waitForUpdatesAsync();

const cellView = pageObject.getRenderedCellView(0, 0);
expect(cellView.tabbableChildren).toEqual([]);
});

describe('various string values render as expected', () => {
parameterizeSpec(wackyStrings, (spec, name) => {
spec(`data "${name}" renders correctly`, async () => {
Expand Down Expand Up @@ -247,6 +259,16 @@ describe('TableColumnAnchor', () => {
).toBeFalse();
});

it('cell view tabbableChildren returns the anchor', async () => {
await table.setData([{ link: 'foo' }]);
await connect();
await waitForUpdatesAsync();

const cellView = pageObject.getRenderedCellView(0, 0);
const anchor = pageObject.getRenderedCellAnchor(0, 0);
expect(cellView.tabbableChildren).toEqual([anchor]);
});

const linkOptionData = [
{ name: 'hreflang', accessor: (x: Anchor) => x.hreflang },
{ name: 'ping', accessor: (x: Anchor) => x.ping },
Expand Down Expand Up @@ -616,5 +638,61 @@ describe('TableColumnAnchor', () => {
placeholder
);
});

it('for cells with placeholder, cellView tabbableChildren is an empty array', async () => {
await initializeColumnAndTable([{}], 'placeholder');

const cellView = pageObject.getRenderedCellView(0, 0);
expect(cellView.tabbableChildren).toEqual([]);
});
});

describe('keyboard navigation', () => {
beforeEach(async () => {
const tableData = [
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
{
id: '1',
label: 'Link 1a',
link: 'http://www.ni.com/a1'
}
];
await table.setData(tableData);
column.groupIndex = null;
await connect();
await waitForUpdatesAsync();
table.focus();
await waitForUpdatesAsync();
});

afterEach(async () => {
await disconnect();
});

function isAnchorFocused(anchor: Anchor): boolean {
return anchor.shadowRoot?.activeElement !== null;
}

describe('with cell[0, 0] focused,', () => {
beforeEach(async () => {
await sendKeyDownEvent(table, keyArrowDown);
});

it('anchors in cells are reachable via Tab', async () => {
await sendKeyDownEvent(table, keyTab);

expect(
isAnchorFocused(pageObject.getRenderedCellAnchor(0, 0))
).toBe(true);
});

it('when an anchor is focused, pressing Esc will blur the anchor', async () => {
await sendKeyDownEvent(table, keyTab);
await sendKeyDownEvent(table, keyEscape);

expect(
isAnchorFocused(pageObject.getRenderedCellAnchor(0, 0))
).toBe(false);
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ export abstract class TableCellView<
@observable
public recordId?: string;

/**
* Gets the child elements in this cell view that should be able to be reached via Tab/ Shift-Tab,
* if any.
*/
public get tabbableChildren(): HTMLElement[] {
msmithNI marked this conversation as resolved.
Show resolved Hide resolved
return [];
}

private delegatedEvents: readonly string[] = [];

/**
Expand Down
27 changes: 27 additions & 0 deletions packages/nimble-components/src/table/components/cell/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {
} from '../../../table-column/base/types';
import { styles } from './styles';
import { template } from './template';
import type { TableCellView } from '../../../table-column/base/cell-view';

declare global {
interface HTMLElementTagNameMap {
Expand Down Expand Up @@ -47,11 +48,21 @@ export class TableCell<
@observable
public cellViewTemplate?: ViewTemplate<TableCell>;

/** @internal */
@observable
public cellViewContainer!: HTMLElement;

@observable
public nestingLevel = 0;

public readonly actionMenuButton?: MenuButton;

/** @internal */
public get cellView(): TableCellView<TCellRecord> {
return this.cellViewContainer
.firstElementChild as TableCellView<TCellRecord>;
}

public onActionMenuBeforeToggle(
event: CustomEvent<MenuButtonToggleEventDetail>
): void {
Expand All @@ -64,6 +75,22 @@ export class TableCell<
this.menuOpen = event.detail.newState;
this.$emit('cell-action-menu-toggle', event.detail);
}

public onActionMenuBlur(): void {
this.$emit('cell-action-menu-blur', this);
}

public onCellViewFocusIn(): void {
this.$emit('cell-view-focus-in', this);
}

public onCellFocusIn(): void {
this.$emit('cell-focus-in', this);
}

public onCellBlur(): void {
this.$emit('cell-blur', this);
}
}

const nimbleTableCell = TableCell.compose({
Expand Down
19 changes: 19 additions & 0 deletions packages/nimble-components/src/table/components/cell/styles.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { css } from '@microsoft/fast-element';
import { display } from '../../../utilities/style/display';
import {
borderHoverColor,
borderWidth,
controlHeight,
controlSlimHeight,
mediumPadding
} from '../../../theme-provider/design-tokens';
import { focusVisible } from '../../../utilities/style/focus';

export const styles = css`
${display('flex')}
Expand All @@ -22,6 +25,15 @@ export const styles = css`
--ni-private-table-cell-action-menu-display: block;
}

:host(${focusVisible}) {
outline: calc(2 * ${borderWidth}) solid ${borderHoverColor};
outline-offset: -2px;
}

.cell-view-container {
display: contents;
}

.cell-view {
overflow: hidden;
}
Expand All @@ -34,4 +46,11 @@ export const styles = css`
height: ${controlSlimHeight};
align-self: center;
}

${
/* This CSS class is applied dynamically by KeyboardNavigationManager */ ''
}
.action-menu.cell-action-menu-focused {
display: block;
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,23 @@ import { tableCellActionMenuLabel } from '../../../label-provider/table/label-to

// prettier-ignore
export const template = html<TableCell>`
<template role="cell" style="--ni-private-table-cell-nesting-level: ${x => x.nestingLevel}">
${x => x.cellViewTemplate}
<template role="cell" style="--ni-private-table-cell-nesting-level: ${x => x.nestingLevel}"
@focusin="${x => x.onCellFocusIn()}"
@blur="${x => x.onCellBlur()}"
>
<div ${ref('cellViewContainer')} class="cell-view-container" @focusin="${x => x.onCellViewFocusIn()}">
${x => x.cellViewTemplate}
</div>
${when(x => x.hasActionMenu, html<TableCell>`
<${menuButtonTag} ${ref('actionMenuButton')}
content-hidden
appearance="${ButtonAppearance.ghost}"
${'' /* tabindex managed dynamically by KeyboardNavigationManager */}
tabindex="-1"
@beforetoggle="${(x, c) => x.onActionMenuBeforeToggle(c.event as CustomEvent<MenuButtonToggleEventDetail>)}"
@toggle="${(x, c) => x.onActionMenuToggle(c.event as CustomEvent<MenuButtonToggleEventDetail>)}"
@click="${(_, c) => c.event.stopPropagation()}"
@blur="${x => x.onActionMenuBlur()}"
class="action-menu"
title="${x => (x.actionMenuLabel ? x.actionMenuLabel : tableCellActionMenuLabel.getValueFor(x))}"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class TableCellPageObject<T extends TableCellRecord = TableCellRecord> {
public constructor(private readonly tableCellElement: TableCell<T>) {}

public getRenderedCellView(): TableCellView {
const cellView = this.tableCellElement.shadowRoot!.firstElementChild;
const cellView = this.tableCellElement.cellViewContainer.firstElementChild;
if (!(cellView instanceof TableCellView)) {
throw new Error(
'Cell view not found in cell - ensure cellViewTag is set for column'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { TableCellRecord } from '../../../../table-column/base/types';
import { TableCellPageObject } from './table-cell.pageobject';
import { TableCellView } from '../../../../table-column/base/cell-view';
import { createCellViewTemplate } from '../../../../table-column/base/cell-view/template';
import { createEventListener } from '../../../../utilities/tests/component';

interface SimpleTableCellRecord extends TableCellRecord {
stringData: string;
Expand Down Expand Up @@ -79,4 +80,67 @@ describe('TableCell', () => {
const renderedContent = pageObject.getRenderedCellContent();
expect(renderedContent).toBe('bar');
});

it('fires cell-view-focus-in/cell-focus-in/cell-blur events when cell contents are focused/blurred', async () => {
await connect();
await waitForUpdatesAsync();

const cellViewFocusInListener = createEventListener(
element,
'cell-view-focus-in'
);
const cellFocusInListener = createEventListener(
element,
'cell-focus-in'
);
const cellBlurListener = createEventListener(element, 'cell-blur');
const renderedCellView = pageObject.getRenderedCellView();
const span = renderedCellView.shadowRoot
?.firstElementChild as HTMLSpanElement;
span.tabIndex = 0;
span.focus();
await cellViewFocusInListener.promise;
await cellFocusInListener.promise;

expect(cellViewFocusInListener.spy).toHaveBeenCalledOnceWith(
jasmine.objectContaining({ detail: element })
);
expect(cellFocusInListener.spy).toHaveBeenCalledOnceWith(
jasmine.objectContaining({ detail: element })
);
expect(cellBlurListener.spy).not.toHaveBeenCalled();

span.blur();
await cellBlurListener.promise;

expect(cellBlurListener.spy).toHaveBeenCalledOnceWith(
jasmine.objectContaining({ detail: element })
);
});

it('fires the cell-view-focus-in event when cell contents are focused, after the cell is already focused', async () => {
await connect();
await waitForUpdatesAsync();

const cellViewFocusInListener = createEventListener(
element,
'cell-view-focus-in'
);
const renderedCellView = pageObject.getRenderedCellView();
element.tabIndex = 0;
element.focus();
await waitForUpdatesAsync();

expect(cellViewFocusInListener.spy).not.toHaveBeenCalled();

const span = renderedCellView.shadowRoot
?.firstElementChild as HTMLSpanElement;
span.tabIndex = 0;
span.focus();
await cellViewFocusInListener.promise;

expect(cellViewFocusInListener.spy).toHaveBeenCalledOnceWith(
jasmine.objectContaining({ detail: element })
);
});
});
Loading
Loading