Search: Make search icon keyboard navigable (#37865)

* Make search icon keyboard navigable

* Update text

* Update test

* Remove unused line

* Add global focus-visible styles for button
This commit is contained in:
Tobias Skarhed
2021-08-16 15:51:44 +02:00
committed by GitHub
parent 1735f9a56b
commit 89572926c3
5 changed files with 24 additions and 76 deletions

View File

@@ -55,6 +55,9 @@ export function getElementStyles(theme: GrafanaTheme2) {
button {
letter-spacing: ${theme.typography.body.letterSpacing};
&:focus-visible {
outline: ${getFocusStyles(theme)};
}
&:focus {
outline: none;
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { shallow } from 'enzyme';
import { render, screen } from '@testing-library/react';
import TopSection from './TopSection';
jest.mock('../../config', () => ({
@@ -9,33 +9,21 @@ jest.mock('../../config', () => ({
{ id: '2', hideFromMenu: true },
{ id: '3', hideFromMenu: false },
{ id: '4', hideFromMenu: true },
{ id: '4', hideFromMenu: false },
],
},
}));
const setup = (propOverrides?: object) => {
const props = Object.assign(
{
mainLinks: [],
},
propOverrides
);
return shallow(<TopSection {...props} />);
};
describe('Render', () => {
it('should render component', () => {
const wrapper = setup();
it('should render search when empty', () => {
render(<TopSection />);
expect(wrapper).toMatchSnapshot();
expect(screen.getByText('Search dashboards')).toBeInTheDocument();
});
it('should render items', () => {
const wrapper = setup({
mainLinks: [{ id: 1 }, { id: 2 }, { id: 3 }, { id: 4 }, { id: 5 }],
});
it('should render items and search item', () => {
render(<TopSection />);
expect(wrapper).toMatchSnapshot();
expect(screen.getByTestId('top-section-items').children.length).toBe(3);
});
});

View File

@@ -8,7 +8,7 @@ const TopSection: FC<any> = () => {
const navTree = cloneDeep(config.bootData.navTree);
const mainLinks = filter(navTree, (item) => !item.hideFromMenu);
const searchLink = {
text: 'Search',
text: 'Search dashboards',
icon: 'search',
};
@@ -17,7 +17,7 @@ const TopSection: FC<any> = () => {
};
return (
<div className="sidemenu__top">
<div data-testid="top-section-items" className="sidemenu__top">
<TopSectionItem link={searchLink} onClick={onOpenSearch} />
{mainLinks.map((link, index) => {
return <TopSectionItem link={link} key={`${link.id}-${index}`} />;

View File

@@ -1,7 +1,8 @@
import React, { FC } from 'react';
import SideMenuDropDown from './SideMenuDropDown';
import { Icon, Link } from '@grafana/ui';
import { Icon, Link, useStyles2 } from '@grafana/ui';
import { NavModelItem } from '@grafana/data';
import { css, cx } from '@emotion/css';
export interface Props {
link: NavModelItem;
@@ -9,6 +10,13 @@ export interface Props {
}
const TopSectionItem: FC<Props> = ({ link, onClick }) => {
const resetButtonStyles = useStyles2(
() =>
css`
background-color: transparent;
`
);
const linkContent = (
<span className="icon-circle sidemenu-icon">
{link.icon && <Icon name={link.icon as any} size="xl" />}
@@ -28,9 +36,9 @@ const TopSectionItem: FC<Props> = ({ link, onClick }) => {
{linkContent}
</Link>
) : (
<a className="sidemenu-link" onClick={onClick} aria-label={link.text}>
<button className={cx(resetButtonStyles, 'sidemenu-link')} onClick={onClick} aria-label={link.text}>
{linkContent}
</a>
</button>
);
return (
<div className="sidemenu-item dropdown">

View File

@@ -1,51 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Render should render component 1`] = `
<div
className="sidemenu__top"
>
<TopSectionItem
link={
Object {
"icon": "search",
"text": "Search",
}
}
onClick={[Function]}
/>
<TopSectionItem
key="3-0"
link={
Object {
"hideFromMenu": false,
"id": "3",
}
}
/>
</div>
`;
exports[`Render should render items 1`] = `
<div
className="sidemenu__top"
>
<TopSectionItem
link={
Object {
"icon": "search",
"text": "Search",
}
}
onClick={[Function]}
/>
<TopSectionItem
key="3-0"
link={
Object {
"hideFromMenu": false,
"id": "3",
}
}
/>
</div>
`;