mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Accessibility: use Collapse
in QueryOptionGroup
(#70446)
* use collapse in QueryOptionGroup * fix unit tests * fix tests after merging main * adjust padding to match
This commit is contained in:
parent
c455b01078
commit
1441c90178
@ -10,7 +10,7 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
it('can change query type', async () => {
|
it('can change query type', async () => {
|
||||||
const { props } = setup();
|
const { props } = setup();
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.getByLabelText('Range')).toBeChecked();
|
expect(screen.getByLabelText('Range')).toBeChecked();
|
||||||
|
|
||||||
await userEvent.click(screen.getByLabelText('Instant'));
|
await userEvent.click(screen.getByLabelText('Instant'));
|
||||||
@ -24,7 +24,7 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
it('can change legend format', async () => {
|
it('can change legend format', async () => {
|
||||||
const { props } = setup();
|
const { props } = setup();
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
|
|
||||||
// First autosize input is a Legend
|
// First autosize input is a Legend
|
||||||
const element = screen.getAllByTestId('autosize-input')[0];
|
const element = screen.getAllByTestId('autosize-input')[0];
|
||||||
@ -40,7 +40,7 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
it('can change line limit to valid value', async () => {
|
it('can change line limit to valid value', async () => {
|
||||||
const { props } = setup({ expr: '{foo="bar"}' });
|
const { props } = setup({ expr: '{foo="bar"}' });
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
// Second autosize input is a Line limit
|
// Second autosize input is a Line limit
|
||||||
const element = screen.getAllByTestId('autosize-input')[1];
|
const element = screen.getAllByTestId('autosize-input')[1];
|
||||||
await userEvent.type(element, '10');
|
await userEvent.type(element, '10');
|
||||||
@ -57,7 +57,7 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
// We need to start with some value to be able to change it
|
// We need to start with some value to be able to change it
|
||||||
props.query.maxLines = 10;
|
props.query.maxLines = 10;
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
// Second autosize input is a Line limit
|
// Second autosize input is a Line limit
|
||||||
const element = screen.getAllByTestId('autosize-input')[1];
|
const element = screen.getAllByTestId('autosize-input')[1];
|
||||||
await userEvent.type(element, '-10');
|
await userEvent.type(element, '-10');
|
||||||
@ -74,7 +74,7 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
// We need to start with some value to be able to change it
|
// We need to start with some value to be able to change it
|
||||||
props.query.maxLines = 10;
|
props.query.maxLines = 10;
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
// Second autosize input is a Line limit
|
// Second autosize input is a Line limit
|
||||||
const element = screen.getAllByTestId('autosize-input')[1];
|
const element = screen.getAllByTestId('autosize-input')[1];
|
||||||
await userEvent.type(element, 'asd');
|
await userEvent.type(element, 'asd');
|
||||||
@ -102,19 +102,19 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
|
|
||||||
it('does not shows resolution field if resolution is not set', async () => {
|
it('does not shows resolution field if resolution is not set', async () => {
|
||||||
setup({ expr: 'rate({foo="bar"}[5m]' });
|
setup({ expr: 'rate({foo="bar"}[5m]' });
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
|
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not shows resolution field if resolution is set to default value 1', async () => {
|
it('does not shows resolution field if resolution is set to default value 1', async () => {
|
||||||
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 1 });
|
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 1 });
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
|
expect(screen.queryByText('Resolution')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does shows resolution field with warning if resolution is set to non-default value', async () => {
|
it('does shows resolution field with warning if resolution is set to non-default value', async () => {
|
||||||
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 2 });
|
setup({ expr: 'rate({foo="bar"}[5m]', resolution: 2 });
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.getByText('Resolution')).toBeInTheDocument();
|
expect(screen.getByText('Resolution')).toBeInTheDocument();
|
||||||
expect(
|
expect(
|
||||||
screen.getByText("The 'Resolution' is deprecated. Use 'Step' editor instead to change step parameter.")
|
screen.getByText("The 'Resolution' is deprecated. Use 'Step' editor instead to change step parameter.")
|
||||||
@ -130,13 +130,13 @@ describe('LokiQueryBuilderOptions', () => {
|
|||||||
|
|
||||||
it('shows error when invalid value in step', async () => {
|
it('shows error when invalid value in step', async () => {
|
||||||
setup({ expr: 'rate({foo="bar"}[5m]', step: 'a' });
|
setup({ expr: 'rate({foo="bar"}[5m]', step: 'a' });
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.getByText(/Invalid step/)).toBeInTheDocument();
|
expect(screen.getByText(/Invalid step/)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not shows error when valid value in step', async () => {
|
it('does not shows error when valid value in step', async () => {
|
||||||
setup({ expr: 'rate({foo="bar"}[5m]', step: '1m' });
|
setup({ expr: 'rate({foo="bar"}[5m]', step: '1m' });
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
|
expect(screen.queryByText(/Invalid step/)).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@ describe('PromQueryBuilderOptions', () => {
|
|||||||
it('Can change query type', async () => {
|
it('Can change query type', async () => {
|
||||||
const { props } = setup();
|
const { props } = setup();
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
expect(screen.getByLabelText('Range')).toBeChecked();
|
expect(screen.getByLabelText('Range')).toBeChecked();
|
||||||
|
|
||||||
await userEvent.click(screen.getByLabelText('Instant'));
|
await userEvent.click(screen.getByLabelText('Instant'));
|
||||||
@ -30,7 +30,7 @@ describe('PromQueryBuilderOptions', () => {
|
|||||||
it('Can set query type to "Both" on render for PanelEditor', async () => {
|
it('Can set query type to "Both" on render for PanelEditor', async () => {
|
||||||
setup({ instant: true, range: true });
|
setup({ instant: true, range: true });
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
|
|
||||||
expect(screen.getByLabelText('Both')).toBeChecked();
|
expect(screen.getByLabelText('Both')).toBeChecked();
|
||||||
});
|
});
|
||||||
@ -38,7 +38,7 @@ describe('PromQueryBuilderOptions', () => {
|
|||||||
it('Can set query type to "Both" on render for Explorer', async () => {
|
it('Can set query type to "Both" on render for Explorer', async () => {
|
||||||
setup({ instant: true, range: true }, CoreApp.Explore);
|
setup({ instant: true, range: true }, CoreApp.Explore);
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
|
|
||||||
expect(screen.getByLabelText('Both')).toBeChecked();
|
expect(screen.getByLabelText('Both')).toBeChecked();
|
||||||
});
|
});
|
||||||
@ -51,7 +51,7 @@ describe('PromQueryBuilderOptions', () => {
|
|||||||
it('Can change legend format to verbose', async () => {
|
it('Can change legend format to verbose', async () => {
|
||||||
const { props } = setup();
|
const { props } = setup();
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
|
|
||||||
let legendModeSelect = screen.getByText('Auto').parentElement!;
|
let legendModeSelect = screen.getByText('Auto').parentElement!;
|
||||||
await userEvent.click(legendModeSelect);
|
await userEvent.click(legendModeSelect);
|
||||||
@ -67,7 +67,7 @@ describe('PromQueryBuilderOptions', () => {
|
|||||||
it('Can change legend format to custom', async () => {
|
it('Can change legend format to custom', async () => {
|
||||||
const { props } = setup();
|
const { props } = setup();
|
||||||
|
|
||||||
await userEvent.click(screen.getByTitle('Click to edit options'));
|
await userEvent.click(screen.getByRole('button', { name: /Options/ }));
|
||||||
|
|
||||||
let legendModeSelect = screen.getByText('Auto').parentElement!;
|
let legendModeSelect = screen.getByText('Auto').parentElement!;
|
||||||
await userEvent.click(legendModeSelect);
|
await userEvent.click(legendModeSelect);
|
||||||
|
@ -4,7 +4,7 @@ import { useToggle } from 'react-use';
|
|||||||
|
|
||||||
import { getValueFormat, GrafanaTheme2 } from '@grafana/data';
|
import { getValueFormat, GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Stack } from '@grafana/experimental';
|
import { Stack } from '@grafana/experimental';
|
||||||
import { Icon, useStyles2 } from '@grafana/ui';
|
import { Collapse, useStyles2 } from '@grafana/ui';
|
||||||
import { QueryStats } from 'app/plugins/datasource/loki/types';
|
import { QueryStats } from 'app/plugins/datasource/loki/types';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
@ -25,22 +25,26 @@ export function QueryOptionGroup({ title, children, collapsedInfo, queryStats }:
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className={styles.wrapper}>
|
||||||
<Stack gap={0} direction="column">
|
<Collapse
|
||||||
<div className={styles.header} onClick={toggleOpen} title="Click to edit options">
|
className={styles.collapse}
|
||||||
<div className={styles.toggle}>
|
collapsible
|
||||||
<Icon name={isOpen ? 'angle-down' : 'angle-right'} />
|
isOpen={isOpen}
|
||||||
</div>
|
onToggle={toggleOpen}
|
||||||
<h6 className={styles.title}>{title}</h6>
|
label={
|
||||||
{!isOpen && (
|
<Stack gap={0} wrap={false}>
|
||||||
<div className={styles.description}>
|
<h6 className={styles.title}>{title}</h6>
|
||||||
{collapsedInfo.map((x, i) => (
|
{!isOpen && (
|
||||||
<span key={i}>{x}</span>
|
<div className={styles.description}>
|
||||||
))}
|
{collapsedInfo.map((x, i) => (
|
||||||
</div>
|
<span key={i}>{x}</span>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
{isOpen && <div className={styles.body}>{children}</div>}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className={styles.body}>{children}</div>
|
||||||
|
</Collapse>
|
||||||
{queryStats && <p className={styles.stats}>This query will process approximately {convertUnits()}.</p>}
|
{queryStats && <p className={styles.stats}>This query will process approximately {convertUnits()}.</p>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -48,29 +52,21 @@ export function QueryOptionGroup({ title, children, collapsedInfo, queryStats }:
|
|||||||
|
|
||||||
const getStyles = (theme: GrafanaTheme2) => {
|
const getStyles = (theme: GrafanaTheme2) => {
|
||||||
return {
|
return {
|
||||||
|
collapse: css({
|
||||||
|
backgroundColor: 'unset',
|
||||||
|
border: 'unset',
|
||||||
|
marginBottom: 0,
|
||||||
|
|
||||||
|
['> button']: {
|
||||||
|
padding: theme.spacing(0, 1),
|
||||||
|
},
|
||||||
|
}),
|
||||||
wrapper: css({
|
wrapper: css({
|
||||||
width: '100%',
|
width: '100%',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
alignItems: 'baseline',
|
alignItems: 'baseline',
|
||||||
}),
|
}),
|
||||||
switchLabel: css({
|
|
||||||
color: theme.colors.text.secondary,
|
|
||||||
cursor: 'pointer',
|
|
||||||
fontSize: theme.typography.bodySmall.fontSize,
|
|
||||||
'&:hover': {
|
|
||||||
color: theme.colors.text.primary,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
header: css({
|
|
||||||
display: 'flex',
|
|
||||||
cursor: 'pointer',
|
|
||||||
alignItems: 'baseline',
|
|
||||||
color: theme.colors.text.primary,
|
|
||||||
'&:hover': {
|
|
||||||
background: theme.colors.emphasize(theme.colors.background.primary, 0.03),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
title: css({
|
title: css({
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
@ -81,20 +77,16 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
description: css({
|
description: css({
|
||||||
color: theme.colors.text.secondary,
|
color: theme.colors.text.secondary,
|
||||||
fontSize: theme.typography.bodySmall.fontSize,
|
fontSize: theme.typography.bodySmall.fontSize,
|
||||||
|
fontWeight: theme.typography.bodySmall.fontWeight,
|
||||||
paddingLeft: theme.spacing(2),
|
paddingLeft: theme.spacing(2),
|
||||||
gap: theme.spacing(2),
|
gap: theme.spacing(2),
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
}),
|
}),
|
||||||
body: css({
|
body: css({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
paddingTop: theme.spacing(2),
|
|
||||||
gap: theme.spacing(2),
|
gap: theme.spacing(2),
|
||||||
flexWrap: 'wrap',
|
flexWrap: 'wrap',
|
||||||
}),
|
}),
|
||||||
toggle: css({
|
|
||||||
color: theme.colors.text.secondary,
|
|
||||||
marginRight: `${theme.spacing(1)}`,
|
|
||||||
}),
|
|
||||||
stats: css({
|
stats: css({
|
||||||
margin: '0px',
|
margin: '0px',
|
||||||
color: theme.colors.text.secondary,
|
color: theme.colors.text.secondary,
|
||||||
|
Loading…
Reference in New Issue
Block a user