QueryRow: Make toggle actions screen-readers accessible (#67998)

This commit is contained in:
Giordano Ricci
2023-05-10 11:57:08 +01:00
committed by GitHub
parent 0b6ae0d119
commit b99e9668a9
7 changed files with 93 additions and 47 deletions

View File

@@ -1,24 +1,24 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import React from 'react';
import React, { ComponentPropsWithoutRef } from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { QueryOperationAction, QueryOperationActionProps } from './QueryOperationAction';
const setup = (propOverrides?: Partial<QueryOperationActionProps>) => {
const props: QueryOperationActionProps = {
icon: 'panel-add',
title: 'test',
onClick: jest.fn(),
disabled: false,
...propOverrides,
};
render(<QueryOperationAction {...props} />);
};
import { QueryOperationAction, QueryOperationToggleAction } from './QueryOperationAction';
describe('QueryOperationAction tests', () => {
function setup(propOverrides?: Partial<ComponentPropsWithoutRef<typeof QueryOperationAction>>) {
const props: ComponentPropsWithoutRef<typeof QueryOperationAction> = {
icon: 'panel-add',
title: 'test',
onClick: jest.fn(),
disabled: false,
...propOverrides,
};
render(<QueryOperationAction {...props} />);
}
it('should render component', () => {
setup();
@@ -51,3 +51,36 @@ describe('QueryOperationAction tests', () => {
expect(clickSpy).not.toHaveBeenCalled();
});
});
describe('QueryOperationToggleAction', () => {
function setup(active: boolean) {
const props: ComponentPropsWithoutRef<typeof QueryOperationToggleAction> = {
icon: 'panel-add',
title: 'test',
onClick: () => {},
active,
};
return render(<QueryOperationToggleAction {...props} />);
}
it('should correctly set pressed state', () => {
setup(false);
expect(
screen.getByRole('button', {
name: selectors.components.QueryEditorRow.actionButton('test'),
pressed: false,
})
).toBeInTheDocument();
setup(true);
expect(
screen.getByRole('button', {
name: selectors.components.QueryEditorRow.actionButton('test'),
pressed: true,
})
).toBeInTheDocument();
});
});

View File

@@ -5,33 +5,43 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { IconButton, IconName, useStyles2 } from '@grafana/ui';
export interface QueryOperationActionProps {
interface BaseQueryOperationActionProps {
icon: IconName;
title: string;
onClick: (e: React.MouseEvent) => void;
disabled?: boolean;
active?: boolean;
}
export const QueryOperationAction = ({ icon, active, disabled, title, onClick }: QueryOperationActionProps) => {
function BaseQueryOperationAction(props: QueryOperationActionProps | QueryOperationToggleActionProps) {
const styles = useStyles2(getStyles);
return (
<div className={cx(styles.icon, active && styles.active)}>
<div className={cx(styles.icon, 'active' in props && props.active && styles.active)}>
<IconButton
name={icon}
tooltip={title}
name={props.icon}
tooltip={props.title}
className={styles.icon}
disabled={!!disabled}
onClick={onClick}
disabled={!!props.disabled}
onClick={props.onClick}
type="button"
aria-label={selectors.components.QueryEditorRow.actionButton(title)}
aria-label={selectors.components.QueryEditorRow.actionButton(props.title)}
{...('active' in props && { 'aria-pressed': props.active })}
/>
</div>
);
};
}
QueryOperationAction.displayName = 'QueryOperationAction';
interface QueryOperationActionProps extends BaseQueryOperationActionProps {}
export function QueryOperationAction(props: QueryOperationActionProps) {
return <BaseQueryOperationAction {...props} />;
}
interface QueryOperationToggleActionProps extends BaseQueryOperationActionProps {
active: boolean;
}
export const QueryOperationToggleAction = (props: QueryOperationToggleActionProps) => {
return <BaseQueryOperationAction {...props} />;
};
const getStyles = (theme: GrafanaTheme2) => {
return {