@@ -188,6 +280,18 @@ describe('KuiContextMenuPanel', () => {
component.find('[data-test-subj="button"]').matchesElement(document.activeElement)
).toBe(true);
});
+
+ it('is not set on anything if hasFocus is false', () => {
+ const component = mount(
+
+
+
+ );
+
+ expect(
+ component.find('[data-test-subj="button"]').matchesElement(document.activeElement)
+ ).toBe(true);
+ });
});
describe('keyboard navigation of items', () => {
@@ -208,13 +312,20 @@ describe('KuiContextMenuPanel', () => {
);
});
- it('focuses the first menu item by default, if there are items', () => {
+ it(`doesn't focus an item by default`, () => {
+ expect(component.find('[data-test-subj]').contains(document.activeElement)).toBe(false);
+ });
+
+ it('down arrow key focuses the first menu item', () => {
+ component.simulate('keydown', { keyCode: keyCodes.DOWN });
+
expect(
component.find('[data-test-subj="itemA"]').matchesElement(document.activeElement)
).toBe(true);
});
- it('down arrow key focuses the next menu item', () => {
+ it('subsequently, down arrow key focuses the next menu item', () => {
+ component.simulate('keydown', { keyCode: keyCodes.DOWN });
component.simulate('keydown', { keyCode: keyCodes.DOWN });
expect(
@@ -222,7 +333,16 @@ describe('KuiContextMenuPanel', () => {
).toBe(true);
});
- it('up arrow key focuses the previous menu item', () => {
+ it('down arrow key wraps to first menu item', () => {
+ component.simulate('keydown', { keyCode: keyCodes.UP });
+ component.simulate('keydown', { keyCode: keyCodes.DOWN });
+
+ expect(
+ component.find('[data-test-subj="itemA"]').matchesElement(document.activeElement)
+ ).toBe(true);
+ });
+
+ it('up arrow key focuses the last menu item', () => {
component.simulate('keydown', { keyCode: keyCodes.UP });
expect(
@@ -230,7 +350,26 @@ describe('KuiContextMenuPanel', () => {
).toBe(true);
});
- it('right arrow key shows next panel', () => {
+ it('subsequently, up arrow key focuses the previous menu item', () => {
+ component.simulate('keydown', { keyCode: keyCodes.UP });
+ component.simulate('keydown', { keyCode: keyCodes.UP });
+
+ expect(
+ component.find('[data-test-subj="itemB"]').matchesElement(document.activeElement)
+ ).toBe(true);
+ });
+
+ it('up arrow key wraps to last menu item', () => {
+ component.simulate('keydown', { keyCode: keyCodes.DOWN });
+ component.simulate('keydown', { keyCode: keyCodes.UP });
+
+ expect(
+ component.find('[data-test-subj="itemC"]').matchesElement(document.activeElement)
+ ).toBe(true);
+ });
+
+ it(`right arrow key shows next panel with focused item's index`, () => {
+ component.simulate('keydown', { keyCode: keyCodes.DOWN });
component.simulate('keydown', { keyCode: keyCodes.RIGHT });
sinon.assert.calledWith(showNextPanelHandler, 0);
});
diff --git a/ui_framework/src/components/popover/__snapshots__/popover.test.js.snap b/ui_framework/src/components/popover/__snapshots__/popover.test.js.snap
index 407ea3b3024d3..4ae95ac1a5f6c 100644
--- a/ui_framework/src/components/popover/__snapshots__/popover.test.js.snap
+++ b/ui_framework/src/components/popover/__snapshots__/popover.test.js.snap
@@ -42,6 +42,33 @@ exports[`KuiPopover props anchorPosition right is rendered 1`] = `
`;
+exports[`KuiPopover props isFocusable defaults to false 1`] = `
+
+`;
+
+exports[`KuiPopover props isFocusable renders true 1`] = `
+
+`;
+
exports[`KuiPopover props isOpen defaults to false 1`] = `
{
+ if (this.props.isFocusable) {
+ this.panel = node;
+ }
+ };
+
render() {
const {
anchorPosition,
button,
isOpen,
+ isFocusable,
withTitle,
children,
className,
@@ -100,17 +107,26 @@ export class KuiPopover extends Component {
let panel;
if (isOpen || this.state.isClosing) {
+ let tabIndex;
+ let initialFocus;
+
+ if (isFocusable) {
+ tabIndex = '0';
+ initialFocus = () => this.panel;
+ }
+
panel = (
this.panel,
+ initialFocus,
}}
>
{ this.panel = node; }}
+ panelRef={this.panelRef}
className={panelClasses}
paddingSize={panelPaddingSize}
+ tabIndex={tabIndex}
hasShadow
>
{children}
@@ -136,6 +152,7 @@ export class KuiPopover extends Component {
KuiPopover.propTypes = {
isOpen: PropTypes.bool,
+ isFocusable: PropTypes.bool,
withTitle: PropTypes.bool,
closePopover: PropTypes.func.isRequired,
button: PropTypes.node.isRequired,
@@ -147,6 +164,7 @@ KuiPopover.propTypes = {
KuiPopover.defaultProps = {
isOpen: false,
+ isFocusable: false,
anchorPosition: 'center',
panelPaddingSize: 'm',
};
diff --git a/ui_framework/src/components/popover/popover.test.js b/ui_framework/src/components/popover/popover.test.js
index c79c9097ecfc3..90aa26395195f 100644
--- a/ui_framework/src/components/popover/popover.test.js
+++ b/ui_framework/src/components/popover/popover.test.js
@@ -135,6 +135,35 @@ describe('KuiPopover', () => {
});
});
+ describe('isFocusable', () => {
+ test('defaults to false', () => {
+ const component = render(
+ }
+ closePopover={() => {}}
+ />
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+
+ test('renders true', () => {
+ const component = render(
+ }
+ closePopover={() => {}}
+ />
+ );
+
+ expect(component)
+ .toMatchSnapshot();
+ });
+ });
+
describe('panelClassName', () => {
test('is rendered', () => {
const component = render(