mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
A11y : Fix option panes not accessible when collapsed (#46405)
* Turned div into text button to make it accessible * Only icon as button to avoid embedded buttons with overrides delete button * use icon in Button directly * Removed unused import * moving id for labelledBy to h6 elem instead of icon * Tweaking style, bigger caret * Fixed aria-expanded * Modifying and using CollapseToggle from unified alerting * Added restOfProps to CollapseToggle
This commit is contained in:
parent
2409405c34
commit
0b0d612372
@ -1,43 +1,45 @@
|
|||||||
import React, { FC, HTMLAttributes } from 'react';
|
import React, { FC, HTMLAttributes } from 'react';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { IconSize, useStyles, Icon } from '@grafana/ui';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
|
import { IconSize, useStyles2, Button } from '@grafana/ui';
|
||||||
|
|
||||||
interface Props extends HTMLAttributes<HTMLButtonElement> {
|
interface Props extends HTMLAttributes<HTMLButtonElement> {
|
||||||
isCollapsed: boolean;
|
isCollapsed: boolean;
|
||||||
onToggle: (isCollapsed: boolean) => void;
|
onToggle: (isCollapsed: boolean) => void;
|
||||||
|
// Todo: this should be made compulsory for a11y purposes
|
||||||
|
idControlled?: string;
|
||||||
size?: IconSize;
|
size?: IconSize;
|
||||||
className?: string;
|
className?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CollapseToggle: FC<Props> = ({ isCollapsed, onToggle, className, text, size = 'xl', ...restOfProps }) => {
|
export const CollapseToggle: FC<Props> = ({
|
||||||
const styles = useStyles(getStyles);
|
isCollapsed,
|
||||||
|
onToggle,
|
||||||
|
idControlled,
|
||||||
|
className,
|
||||||
|
text,
|
||||||
|
size = 'xl',
|
||||||
|
...restOfProps
|
||||||
|
}) => {
|
||||||
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<Button
|
||||||
aria-label={`${isCollapsed ? 'Expand' : 'Collapse'} alert group`}
|
fill="text"
|
||||||
|
aria-expanded={!isCollapsed}
|
||||||
|
aria-controls={idControlled}
|
||||||
className={cx(styles.expandButton, className)}
|
className={cx(styles.expandButton, className)}
|
||||||
|
icon={isCollapsed ? 'angle-right' : 'angle-down'}
|
||||||
onClick={() => onToggle(!isCollapsed)}
|
onClick={() => onToggle(!isCollapsed)}
|
||||||
{...restOfProps}
|
{...restOfProps}
|
||||||
>
|
/>
|
||||||
<Icon size={size} name={isCollapsed ? 'angle-right' : 'angle-down'} />
|
|
||||||
{text}
|
|
||||||
</button>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getStyles = () => ({
|
export const getStyles = (theme: GrafanaTheme2) => ({
|
||||||
expandButton: css`
|
expandButton: css`
|
||||||
background: none;
|
color: ${theme.colors.text.secondary};
|
||||||
border: none;
|
margin-right: ${theme.spacing(1)};
|
||||||
|
|
||||||
outline: none !important;
|
|
||||||
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, { FC, ReactNode, useCallback, useEffect, useState, useRef } from 'react';
|
import React, { FC, ReactNode, useCallback, useEffect, useState, useRef } from 'react';
|
||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import { GrafanaTheme2 } from '@grafana/data';
|
import { GrafanaTheme2 } from '@grafana/data';
|
||||||
import { Counter, Icon, useStyles2 } from '@grafana/ui';
|
import { Counter, useStyles2 } from '@grafana/ui';
|
||||||
import { PANEL_EDITOR_UI_STATE_STORAGE_KEY } from './state/reducers';
|
import { PANEL_EDITOR_UI_STATE_STORAGE_KEY } from './state/reducers';
|
||||||
import { useLocalStorage } from 'react-use';
|
import { useLocalStorage } from 'react-use';
|
||||||
import { selectors } from '@grafana/e2e-selectors';
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
import { useQueryParams } from 'app/core/hooks/useQueryParams';
|
||||||
|
import { CollapseToggle } from 'app/features/alerting/unified/components/CollapseToggle';
|
||||||
|
|
||||||
export interface OptionsPaneCategoryProps {
|
export interface OptionsPaneCategoryProps {
|
||||||
id: string;
|
id: string;
|
||||||
@ -101,12 +102,16 @@ export const OptionsPaneCategory: FC<OptionsPaneCategoryProps> = React.memo(
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<div className={headerStyles} onClick={onToggle} aria-label={selectors.components.OptionsGroup.toggle(id)}>
|
<div className={headerStyles} onClick={onToggle} aria-label={selectors.components.OptionsGroup.toggle(id)}>
|
||||||
<div className={cx(styles.toggle, 'editor-options-group-toggle')}>
|
<CollapseToggle isCollapsed={!isExpanded} idControlled={id} onToggle={onToggle} />
|
||||||
<Icon name={isExpanded ? 'angle-down' : 'angle-right'} />
|
<h6 id={`button-${id}`} className={styles.title}>
|
||||||
</div>
|
{renderTitle(isExpanded)}
|
||||||
<h6 className={styles.title}>{renderTitle(isExpanded)}</h6>
|
</h6>
|
||||||
</div>
|
</div>
|
||||||
{isExpanded && <div className={bodyStyles}>{children}</div>}
|
{isExpanded && (
|
||||||
|
<div className={bodyStyles} id={id} aria-labelledby={`button-${id}`}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -122,10 +127,6 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
boxNestedExpanded: css`
|
boxNestedExpanded: css`
|
||||||
margin-bottom: ${theme.spacing(2)};
|
margin-bottom: ${theme.spacing(2)};
|
||||||
`,
|
`,
|
||||||
toggle: css`
|
|
||||||
color: ${theme.colors.text.secondary};
|
|
||||||
margin-right: ${theme.spacing(1)};
|
|
||||||
`,
|
|
||||||
title: css`
|
title: css`
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -138,7 +139,7 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
padding: ${theme.spacing(1)};
|
padding: ${theme.spacing(0.5)};
|
||||||
color: ${theme.colors.text.primary};
|
color: ${theme.colors.text.primary};
|
||||||
font-weight: ${theme.typography.fontWeightMedium};
|
font-weight: ${theme.typography.fontWeightMedium};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user