-
Notifications
You must be signed in to change notification settings - Fork 842
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[EuiPopover] Focus on parent popover panel by default, instead of fir…
…st tabbable child (#5784) * Remove logic that focuses first tabbable child by default * Add Cypress focus tests * Add changelog entry * Add an `initialFocus` documentation example + warning * Fix non-working trap focus `initialFocus` example + clean up ID generation * Fix EuiPopover continuing to hijack EuiContextMenu focus - because EuiPopover's `updateFocus` is called after the transition ends (350ms currently), it supercedes EuiContextMenu's `updateFocus` - I'm not a super huge fan of this DOM-heavy workaround but I can't think of any other options - very open to more ideas * Update EuiDataGrid E2E tests to account for new popover focus changes * PR feedback: copy Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com> Co-authored-by: Trevor Pierce <1Copenut@users.noreply.github.com>
- Loading branch information
Showing
9 changed files
with
248 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React, { useState } from 'react'; | ||
|
||
import { | ||
EuiButton, | ||
EuiFormRow, | ||
EuiPopover, | ||
EuiSpacer, | ||
EuiFieldText, | ||
} from '../../../../src/components'; | ||
|
||
export default () => { | ||
const [isPopoverOpen, setIsPopoverOpen] = useState(false); | ||
|
||
const onButtonClick = () => | ||
setIsPopoverOpen((isPopoverOpen) => !isPopoverOpen); | ||
const closePopover = () => setIsPopoverOpen(false); | ||
|
||
const button = ( | ||
<EuiButton iconType="arrowDown" iconSide="right" onClick={onButtonClick}> | ||
Show popover | ||
</EuiButton> | ||
); | ||
|
||
return ( | ||
<EuiPopover | ||
initialFocus="#name" | ||
button={button} | ||
isOpen={isPopoverOpen} | ||
closePopover={closePopover} | ||
> | ||
<EuiFormRow label="Enter name" id="name"> | ||
<EuiFieldText compressed name="input" /> | ||
</EuiFormRow> | ||
|
||
<EuiSpacer /> | ||
|
||
<EuiButton fill>Submit</EuiButton> | ||
</EuiPopover> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
/// <reference types="../../../cypress/support"/> | ||
|
||
import React, { useState } from 'react'; | ||
|
||
import { EuiButton } from '../button'; | ||
import { EuiPopover } from './popover'; | ||
|
||
const PopoverComponent = ({ children, ...rest }) => { | ||
const [isPopoverOpen, setIsPopoverOpen] = useState(false); | ||
const closePopover = () => setIsPopoverOpen(false); | ||
const togglePopover = () => | ||
setIsPopoverOpen((isPopoverOpen) => !isPopoverOpen); | ||
|
||
const button = ( | ||
<EuiButton onClick={togglePopover} data-test-subj="togglePopover"> | ||
Show popover | ||
</EuiButton> | ||
); | ||
|
||
return ( | ||
<EuiPopover | ||
panelProps={{ 'data-test-subj': 'popoverPanel' }} | ||
button={button} | ||
isOpen={isPopoverOpen} | ||
closePopover={closePopover} | ||
{...rest} | ||
> | ||
{children} | ||
</EuiPopover> | ||
); | ||
}; | ||
|
||
describe('EuiPopover', () => { | ||
describe('focus behavior', () => { | ||
it('focuses the panel wrapper by default', () => { | ||
cy.mount(<PopoverComponent>Test</PopoverComponent>); | ||
cy.get('[data-test-subj="togglePopover"]').click(); | ||
cy.focused().should('have.attr', 'data-test-subj', 'popoverPanel'); | ||
}); | ||
|
||
it('does not focus anything if `ownFocus` is false', () => { | ||
cy.mount(<PopoverComponent ownFocus={false}>Test</PopoverComponent>); | ||
cy.get('[data-test-subj="togglePopover"]').click(); | ||
cy.focused().should('have.attr', 'data-test-subj', 'togglePopover'); | ||
}); | ||
|
||
describe('initialFocus', () => { | ||
it('does not focus anything if `initialFocus` is false', () => { | ||
cy.mount( | ||
<PopoverComponent initialFocus={false}>Test</PopoverComponent> | ||
); | ||
cy.get('[data-test-subj="togglePopover"]').click(); | ||
cy.focused().should('have.attr', 'data-test-subj', 'togglePopover'); | ||
}); | ||
|
||
it('focuses selector strings', () => { | ||
cy.mount( | ||
<PopoverComponent initialFocus="#test"> | ||
<button id="test">Test</button> | ||
</PopoverComponent> | ||
); | ||
cy.get('[data-test-subj="togglePopover"]').click(); | ||
cy.focused().should('have.attr', 'id', 'test'); | ||
}); | ||
|
||
it('focuses functions returning DOM Nodes', () => { | ||
cy.mount( | ||
<PopoverComponent | ||
initialFocus={() => document.getElementById('test')} | ||
> | ||
<button id="test">Test</button> | ||
</PopoverComponent> | ||
); | ||
cy.get('[data-test-subj="togglePopover"]').click(); | ||
cy.focused().should('have.attr', 'id', 'test'); | ||
}); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.