TimeRangePicker: Improve screen reader support (#89409)

* Aria-expanded and tabs

* Remove weird prop

* Remove unused import

* Fix padding

* Use useId
This commit is contained in:
Tobias Skarhed
2024-06-19 16:45:05 +02:00
committed by GitHub
parent 781e394118
commit 4a74330a09

View File

@@ -1,6 +1,6 @@
import { css, cx } from '@emotion/css';
import { isString } from 'lodash';
import React, { useCallback, useState } from 'react';
import React, { useCallback, useId, useState } from 'react';
import { getTimeZoneInfo, GrafanaTheme2, TimeZone } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
@@ -9,8 +9,8 @@ import { useStyles2 } from '../../../themes';
import { t, Trans } from '../../../utils/i18n';
import { Button } from '../../Button';
import { Field } from '../../Forms/Field';
import { RadioButtonGroup } from '../../Forms/RadioButtonGroup/RadioButtonGroup';
import { Select } from '../../Select/Select';
import { Tab, TabContent, TabsBar } from '../../Tabs';
import { TimeZonePicker } from '../TimeZonePicker';
import { TimeZoneDescription } from '../TimeZonePicker/TimeZoneDescription';
import { TimeZoneOffset } from '../TimeZonePicker/TimeZoneOffset';
@@ -36,6 +36,10 @@ export const TimePickerFooter = (props: Props) => {
const [isEditing, setEditing] = useState(false);
const [editMode, setEditMode] = useState('tz');
const timeSettingsId = useId();
const timeZoneSettingsId = useId();
const fiscalYearSettingsId = useId();
const onToggleChangeTimeSettings = useCallback(
(event?: React.MouseEvent) => {
if (event) {
@@ -78,62 +82,79 @@ export const TimePickerFooter = (props: Props) => {
variant="secondary"
onClick={onToggleChangeTimeSettings}
size="sm"
aria-expanded={isEditing}
aria-controls={timeSettingsId}
icon={isEditing ? 'angle-up' : 'angle-down'}
>
<Trans i18nKey="time-picker.footer.change-settings-button">Change time settings</Trans>
</Button>
</section>
{isEditing ? (
<div className={style.editContainer}>
<div>
<RadioButtonGroup
value={editMode}
options={[
{ label: t('time-picker.footer.time-zone-option', 'Time zone'), value: 'tz' },
{ label: t('time-picker.footer.fiscal-year-option', 'Fiscal year'), value: 'fy' },
]}
onChange={setEditMode}
></RadioButtonGroup>
</div>
{editMode === 'tz' ? (
<section
data-testid={selectors.components.TimeZonePicker.containerV2}
className={cx(style.timeZoneContainer, style.timeSettingContainer)}
>
<TimeZonePicker
includeInternal={true}
onChange={(timeZone) => {
onToggleChangeTimeSettings();
if (isString(timeZone)) {
onChangeTimeZone(timeZone);
}
}}
onBlur={onToggleChangeTimeSettings}
menuShouldPortal={false}
/>
</section>
) : (
<section
data-testid={selectors.components.TimeZonePicker.containerV2}
className={cx(style.timeZoneContainer, style.timeSettingContainer)}
>
<Field
className={style.fiscalYearField}
label={t('time-picker.footer.fiscal-year-start', 'Fiscal year start month')}
<div className={style.editContainer} id={timeSettingsId}>
<TabsBar>
<Tab
label={t('time-picker.footer.time-zone-option', 'Time zone')}
active={editMode === 'tz'}
onChangeTab={() => {
setEditMode('tz');
}}
aria-controls={timeZoneSettingsId}
/>
<Tab
label={t('time-picker.footer.fiscal-year-option', 'Fiscal year')}
active={editMode === 'fy'}
onChangeTab={() => {
setEditMode('fy');
}}
aria-controls={fiscalYearSettingsId}
/>
</TabsBar>
<TabContent>
{editMode === 'tz' ? (
<section
role="tabpanel"
data-testid={selectors.components.TimeZonePicker.containerV2}
id={timeZoneSettingsId}
className={cx(style.timeZoneContainer, style.timeSettingContainer)}
>
<Select
value={fiscalYearStartMonth}
menuShouldPortal={false}
options={monthOptions}
onChange={(value) => {
if (onChangeFiscalYearStartMonth) {
onChangeFiscalYearStartMonth(value.value ?? 0);
<TimeZonePicker
includeInternal={true}
onChange={(timeZone) => {
onToggleChangeTimeSettings();
if (isString(timeZone)) {
onChangeTimeZone(timeZone);
}
}}
onBlur={onToggleChangeTimeSettings}
menuShouldPortal={false}
/>
</Field>
</section>
)}
</section>
) : (
<section
role="tabpanel"
data-testid={selectors.components.TimeZonePicker.containerV2}
id={fiscalYearSettingsId}
className={cx(style.timeZoneContainer, style.timeSettingContainer)}
>
<Field
className={style.fiscalYearField}
label={t('time-picker.footer.fiscal-year-start', 'Fiscal year start month')}
>
<Select
value={fiscalYearStartMonth}
menuShouldPortal={false}
options={monthOptions}
onChange={(value) => {
if (onChangeFiscalYearStartMonth) {
onChangeFiscalYearStartMonth(value.value ?? 0);
}
}}
/>
</Field>
</section>
)}
</TabContent>
</div>
) : null}
</div>
@@ -143,7 +164,7 @@ export const TimePickerFooter = (props: Props) => {
const getStyle = (theme: GrafanaTheme2) => ({
container: css({
borderTop: `1px solid ${theme.colors.border.weak}`,
padding: '11px',
padding: theme.spacing(1.5),
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
@@ -151,7 +172,8 @@ const getStyle = (theme: GrafanaTheme2) => ({
}),
editContainer: css({
borderTop: `1px solid ${theme.colors.border.weak}`,
padding: '11px',
padding: theme.spacing(1.5),
paddingTop: 0,
justifyContent: 'space-between',
alignItems: 'center',
}),