Skip to content

Commit

Permalink
[8.x] fix: [Search:Search Applications page]Popover for Create button…
Browse files Browse the repository at this point in the history
… is inaccessible via keyboard (#201193) (#201466)

# Backport

This will backport the following commits from `main` to `8.x`:
- [fix: [Search:Search Applications page]Popover for Create button is
inaccessible via keyboard
(#201193)](#201193)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Alexey
Antonov","email":"alexwizp@gmail.com"},"sourceCommit":{"committedDate":"2024-11-22T19:38:24Z","message":"fix:
[Search:Search Applications page]Popover for Create button is
inaccessible via keyboard (#201193)\n\nCloses: #199760 \r\nPopovers,
dialogs which are accessible with mouse, should also be\r\naccessible
with keyboard. Otherwise users using only keyboard will miss\r\nthe
information present in popover, dialog.\r\n\r\nCloses: #199749\r\nUser
reaches the same button two times when navigating using only\r\nkeyboard
and it can get confusing. Better for element to get focus only\r\none
time when navigating in sequence from one element to another and
for\r\nthe user only to hear one announcement of the element.\r\n\r\n##
What was changed: \r\n1. `CreateSearchApplicationButton` component: \r\n
- `EuiPopover` was replaced to more a11y-friendly `EuiToolTip`\r\n -
extra `div` element with `tabindex` was removed. \r\n\r\n##
Screen\r\n\r\n\r\nhttps://github.com/user-attachments/assets/fbb62841-6f2f-45d0-bee3-39a11a4fc777","sha":"1b742e77f41c6b0674ee01c28b17171508cb5784","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Project:Accessibility","release_note:skip","v9.0.0","Team:Search","backport:prev-minor"],"title":"fix:
[Search:Search Applications page]Popover for Create button is
inaccessible via
keyboard","number":201193,"url":"https://github.com/elastic/kibana/pull/201193","mergeCommit":{"message":"fix:
[Search:Search Applications page]Popover for Create button is
inaccessible via keyboard (#201193)\n\nCloses: #199760 \r\nPopovers,
dialogs which are accessible with mouse, should also be\r\naccessible
with keyboard. Otherwise users using only keyboard will miss\r\nthe
information present in popover, dialog.\r\n\r\nCloses: #199749\r\nUser
reaches the same button two times when navigating using only\r\nkeyboard
and it can get confusing. Better for element to get focus only\r\none
time when navigating in sequence from one element to another and
for\r\nthe user only to hear one announcement of the element.\r\n\r\n##
What was changed: \r\n1. `CreateSearchApplicationButton` component: \r\n
- `EuiPopover` was replaced to more a11y-friendly `EuiToolTip`\r\n -
extra `div` element with `tabindex` was removed. \r\n\r\n##
Screen\r\n\r\n\r\nhttps://github.com/user-attachments/assets/fbb62841-6f2f-45d0-bee3-39a11a4fc777","sha":"1b742e77f41c6b0674ee01c28b17171508cb5784"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/201193","number":201193,"mergeCommit":{"message":"fix:
[Search:Search Applications page]Popover for Create button is
inaccessible via keyboard (#201193)\n\nCloses: #199760 \r\nPopovers,
dialogs which are accessible with mouse, should also be\r\naccessible
with keyboard. Otherwise users using only keyboard will miss\r\nthe
information present in popover, dialog.\r\n\r\nCloses: #199749\r\nUser
reaches the same button two times when navigating using only\r\nkeyboard
and it can get confusing. Better for element to get focus only\r\none
time when navigating in sequence from one element to another and
for\r\nthe user only to hear one announcement of the element.\r\n\r\n##
What was changed: \r\n1. `CreateSearchApplicationButton` component: \r\n
- `EuiPopover` was replaced to more a11y-friendly `EuiToolTip`\r\n -
extra `div` element with `tabindex` was removed. \r\n\r\n##
Screen\r\n\r\n\r\nhttps://github.com/user-attachments/assets/fbb62841-6f2f-45d0-bee3-39a11a4fc777","sha":"1b742e77f41c6b0674ee01c28b17171508cb5784"}}]}]
BACKPORT-->

Co-authored-by: Alexey Antonov <alexwizp@gmail.com>
  • Loading branch information
kibanamachine and alexwizp authored Nov 22, 2024
1 parent 53acc10 commit bb09b67
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 126 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import React, { type ReactNode } from 'react';

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { waitForEuiToolTipVisible } from '@elastic/eui/lib/test/rtl';

import { __IntlProvider as IntlProvider } from '@kbn/i18n-react';

import { CreateSearchApplicationButton } from './search_applications_list';

function Container({ children }: { children?: ReactNode }) {
return <IntlProvider locale="en">{children}</IntlProvider>;
}

describe('CreateSearchApplicationButton', () => {
test('disabled={false}', async () => {
render(
<Container>
<CreateSearchApplicationButton disabled={false} />
</Container>
);

await userEvent.hover(
await screen.findByTestId('enterprise-search-search-applications-creation-button')
);

await waitForEuiToolTipVisible();

expect(
await screen.findByTestId('create-search-application-button-popover-content')
).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';

import React from 'react';

import { mountWithIntl, shallowWithIntl } from '@kbn/test-jest-helpers';
import { shallowWithIntl } from '@kbn/test-jest-helpers';

import { Status } from '../../../../../common/types/api';

Expand Down Expand Up @@ -116,80 +116,3 @@ describe('SearchApplicationsList', () => {
expect(wrapper.find(LicensingCallout)).toHaveLength(0);
});
});

describe('CreateSearchApplicationButton', () => {
describe('disabled={true}', () => {
it('renders a disabled button that shows a popover when hovered', () => {
const wrapper = mountWithIntl(<CreateSearchApplicationButton disabled />);

const button = wrapper.find(
'button[data-test-subj="enterprise-search-search-applications-creation-button"]'
);

expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeTruthy();

let popover = wrapper.find(
'div[data-test-subj="create-search-application-button-popover-content"]'
);

expect(popover).toHaveLength(0);

const hoverTarget = wrapper.find(
'div[data-test-subj="create-search-application-button-hover-target"]'
);

expect(hoverTarget).toHaveLength(1);

hoverTarget.simulate('mouseEnter');

wrapper.update();

popover = wrapper.find(
'div[data-test-subj="create-search-application-button-popover-content"]'
);

expect(popover).toHaveLength(1);
expect(popover.text()).toMatch(
'This functionality may be changed or removed completely in a future release.'
);
});
});
describe('disabled={false}', () => {
it('renders a button and shows a popover when hovered', () => {
const wrapper = mountWithIntl(<CreateSearchApplicationButton disabled={false} />);

const button = wrapper.find(
'button[data-test-subj="enterprise-search-search-applications-creation-button"]'
);

expect(button).toHaveLength(1);
expect(button.prop('disabled')).toBeFalsy();

let popover = wrapper.find(
'div[data-test-subj="create-search-application-button-popover-content"]'
);

expect(popover).toHaveLength(0);

const hoverTarget = wrapper.find(
'div[data-test-subj="create-search-application-button-hover-target"]'
);

expect(hoverTarget).toHaveLength(1);

hoverTarget.simulate('mouseEnter');

wrapper.update();

popover = wrapper.find(
'div[data-test-subj="create-search-application-button-popover-content"]'
);

expect(popover).toHaveLength(1);
expect(popover.text()).toMatch(
'This functionality may be changed or removed completely in a future release.'
);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';

import { useActions, useValues } from 'kea';
import useThrottle from 'react-use/lib/useThrottle';
Expand All @@ -17,10 +17,9 @@ import {
EuiFlexItem,
EuiIcon,
EuiLink,
EuiPopover,
EuiPopoverTitle,
EuiSpacer,
EuiText,
EuiToolTip,
} from '@elastic/eui';

import { i18n } from '@kbn/i18n';
Expand Down Expand Up @@ -53,38 +52,10 @@ interface CreateSearchApplicationButtonProps {
export const CreateSearchApplicationButton: React.FC<CreateSearchApplicationButtonProps> = ({
disabled,
}) => {
const [showPopover, setShowPopover] = useState<boolean>(false);

return (
<EuiPopover
isOpen={showPopover}
closePopover={() => setShowPopover(false)}
button={
<div
data-test-subj="create-search-application-button-hover-target"
onMouseEnter={() => setShowPopover(true)}
onMouseLeave={() => setShowPopover(false)}
tabIndex={0}
>
<EuiButton
fill
iconType="plusInCircle"
data-test-subj="enterprise-search-search-applications-creation-button"
data-telemetry-id="entSearchApplications-list-createSearchApplication"
isDisabled={disabled}
onClick={() => KibanaLogic.values.navigateToUrl(SEARCH_APPLICATION_CREATION_PATH)}
>
{i18n.translate(
'xpack.enterpriseSearch.searchApplications.list.createSearchApplicationButton.label',
{
defaultMessage: 'Create',
}
)}
</EuiButton>
</div>
}
>
<EuiPopoverTitle>
<EuiToolTip
position="top"
title={
<EuiFlexGroup justifyContent="center" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiIcon type="beaker" />
Expand All @@ -96,23 +67,35 @@ export const CreateSearchApplicationButton: React.FC<CreateSearchApplicationButt
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPopoverTitle>
<div
style={{ width: '300px' }}
data-test-subj="create-search-application-button-popover-content"
}
content={
<EuiText size="s" data-test-subj="create-search-application-button-popover-content">
<FormattedMessage
id="xpack.enterpriseSearch.searchApplications.list.createSearchApplicationTechnicalPreviewPopover.body"
defaultMessage="This functionality may be changed or removed completely in a future release."
/>
</EuiText>
}
>
<EuiButton
fill
iconType="plusInCircle"
data-test-subj="enterprise-search-search-applications-creation-button"
data-telemetry-id="entSearchApplications-list-createSearchApplication"
isDisabled={disabled}
onClick={() => KibanaLogic.values.navigateToUrl(SEARCH_APPLICATION_CREATION_PATH)}
>
<EuiFlexGroup direction="column" gutterSize="m">
<EuiText size="s">
<FormattedMessage
id="xpack.enterpriseSearch.searchApplications.list.createSearchApplicationTechnicalPreviewPopover.body"
defaultMessage="This functionality may be changed or removed completely in a future release."
/>
</EuiText>
</EuiFlexGroup>
</div>
</EuiPopover>
{i18n.translate(
'xpack.enterpriseSearch.searchApplications.list.createSearchApplicationButton.label',
{
defaultMessage: 'Create',
}
)}
</EuiButton>
</EuiToolTip>
);
};

interface ListProps {
createSearchApplicationFlyoutOpen?: boolean;
}
Expand Down Expand Up @@ -223,6 +206,7 @@ export const SearchApplicationsList: React.FC<ListProps> = ({
<>
<div>
<EuiFieldSearch
data-test-subj="enterpriseSearchSearchApplicationsListFieldSearch"
value={searchQuery}
placeholder={i18n.translate(
'xpack.enterpriseSearch.searchApplications.list.searchBar.placeholder',
Expand Down

0 comments on commit bb09b67

Please sign in to comment.