mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
fix: [Obs Alerts > Rules][SCREEN READER] Icons and repeated controls need unique accessible labels: 0001 (#188075)
Closes: https://github.com/elastic/observability-dev/issues/3638 ## Description Observability has a lot of icons that are used for controls and table row actions. These icons often have the same aria-label repeated across rows. While this meets the letter of SC 1.3.1: Info and Relationships, the repeated generic labels do not usually answer question what users are editing, or what users are deleting. We want to provide clear labels for each row to make the implicit relationships sighted users depend on, explicit for screen reader users. ## What was changed?: 1. `title`, `arial-label` attributes were updated for mentioned places ## Screen <img width="1546" alt="image" src="3bd626b4
-2154-48b7-a6cd-22580cfd3d4b"> <img width="1546" alt="image" src="2863c9d9
-b09b-4150-9d02-b89a3c2fd9f6">
This commit is contained in:
parent
dfa0549b85
commit
5756b299a3
15 changed files with 48 additions and 28 deletions
|
@ -15,6 +15,7 @@ interface SandboxProps {
|
|||
|
||||
const mockSnoozeSettings: RuleSnoozeSettings = {
|
||||
muteAll: true,
|
||||
name: '',
|
||||
};
|
||||
|
||||
export const RulesListNotifyBadgeSandbox = ({ triggersActionsUi }: SandboxProps) => {
|
||||
|
|
|
@ -898,10 +898,12 @@ describe('Detections Rules API', () => {
|
|||
expect(result).toEqual({
|
||||
'1': {
|
||||
muteAll: false,
|
||||
name: '',
|
||||
activeSnoozes: [],
|
||||
},
|
||||
'2': {
|
||||
muteAll: false,
|
||||
name: '',
|
||||
activeSnoozes: [],
|
||||
isSnoozedUntil: new Date('2023-04-24T19:31:46.765Z'),
|
||||
},
|
||||
|
|
|
@ -252,6 +252,7 @@ export const fetchRulesSnoozeSettings = async ({
|
|||
|
||||
return response.data?.reduce((result, { id, ...snoozeSettings }) => {
|
||||
result[id] = {
|
||||
name: snoozeSettings.name ?? '',
|
||||
muteAll: snoozeSettings.mute_all ?? false,
|
||||
activeSnoozes: snoozeSettings.active_snoozes ?? [],
|
||||
isSnoozedUntil: snoozeSettings.is_snoozed_until
|
||||
|
|
|
@ -70,6 +70,7 @@ interface RuleSnoozeSettingsResponse {
|
|||
* Rule's SO id
|
||||
*/
|
||||
id: string;
|
||||
name: string;
|
||||
mute_all: boolean;
|
||||
snooze_schedule?: RuleSnooze;
|
||||
active_snoozes?: string[];
|
||||
|
|
|
@ -191,8 +191,8 @@ describe('RulesTableContextProvider', () => {
|
|||
{ id: '2', name: 'rule 2' },
|
||||
] as Rule[],
|
||||
rulesSnoozeSettings: {
|
||||
'1': { muteAll: true, snoozeSchedule: [] },
|
||||
'2': { muteAll: false, snoozeSchedule: [] },
|
||||
'1': { muteAll: true, snoozeSchedule: [], name: 'rule 1' },
|
||||
'2': { muteAll: false, snoozeSchedule: [], name: 'rule 2' },
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -217,18 +217,20 @@ describe('RulesTableContextProvider', () => {
|
|||
{ id: '2', name: 'rule 2' },
|
||||
] as Rule[],
|
||||
rulesSnoozeSettings: {
|
||||
'1': { muteAll: true, snoozeSchedule: [] },
|
||||
'2': { muteAll: false, snoozeSchedule: [] },
|
||||
'1': { muteAll: true, snoozeSchedule: [], name: 'rule 1' },
|
||||
'2': { muteAll: false, snoozeSchedule: [], name: 'rule 2' },
|
||||
},
|
||||
});
|
||||
|
||||
expect(state.rulesSnoozeSettings.data).toEqual({
|
||||
'1': {
|
||||
muteAll: true,
|
||||
name: 'rule 1',
|
||||
snoozeSchedule: [],
|
||||
},
|
||||
'2': {
|
||||
muteAll: false,
|
||||
name: 'rule 2',
|
||||
snoozeSchedule: [],
|
||||
},
|
||||
});
|
||||
|
|
|
@ -42231,7 +42231,6 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.disableTitle": "Désactiver",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.editTitle": "Modifier la règle",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.enableTitle": "Activer",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.popoverButtonTitle": "Actions",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.snoozeActions": "Répéter les notifications",
|
||||
"xpack.triggersActionsUI.sections.rulesList.daysLabel": "jours",
|
||||
"xpack.triggersActionsUI.sections.rulesList.deleteSchedule": "Supprimer le calendrier",
|
||||
|
@ -42268,14 +42267,12 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerButton": "Afficher tout",
|
||||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerTitle": "Liste de règles filtrées par paramètres d'URL.",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.noSnoozeAppliedTooltip": "Notifier lors de la génération d'alertes",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.openSnoozePanel": "Ouvrir le panneau Répéter",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.snoozedIndefinitelyTooltip": "Notifications répétées indéfiniment",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.timeRemaining": "Temps restant",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeFailed": "Impossible de modifier les paramètres de répétition de la règle",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeSuccess": "Répétition de la notification des règles ajoutée",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.unsnoozeSuccess": "Répétition de la notification des règles annulée",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.apiKeyOwnerTitle": "Propriétaire de la clé d'API",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteAriaLabel": "Supprimer",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteButtonTooltip": "Supprimer",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitle": "Durée",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitleTooltip": "Temps passé sur l'exécution de la règle (mm:ss).",
|
||||
|
|
|
@ -42205,7 +42205,6 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.disableTitle": "無効にする",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.editTitle": "ルールを編集",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.enableTitle": "有効にする",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.popoverButtonTitle": "アクション",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.snoozeActions": "通知をスヌーズ",
|
||||
"xpack.triggersActionsUI.sections.rulesList.daysLabel": "日",
|
||||
"xpack.triggersActionsUI.sections.rulesList.deleteSchedule": "スケジュールを削除",
|
||||
|
@ -42242,14 +42241,12 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerButton": "すべて表示",
|
||||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerTitle": "ルールリストはURLパラメーターによってフィルタリングされます。",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.noSnoozeAppliedTooltip": "アラートが生成されたときに通知",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.openSnoozePanel": "スヌーズパネルを開く",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.snoozedIndefinitelyTooltip": "通知は無期限にスヌーズされました",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.timeRemaining": "残り時間",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeFailed": "ルールスヌーズ設定を変更できません",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeSuccess": "ルール通知が正常にスヌーズされました",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.unsnoozeSuccess": "ルール通知が正常にスヌーズ解除されました",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.apiKeyOwnerTitle": "APIキー所有者",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteAriaLabel": "削除",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteButtonTooltip": "削除",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitle": "期間",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitleTooltip": "ルールを実行するのにかかる時間(mm:ss)。",
|
||||
|
|
|
@ -42253,7 +42253,6 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.disableTitle": "禁用",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.editTitle": "编辑规则",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.enableTitle": "启用",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.popoverButtonTitle": "操作",
|
||||
"xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.snoozeActions": "暂停通知",
|
||||
"xpack.triggersActionsUI.sections.rulesList.daysLabel": "天",
|
||||
"xpack.triggersActionsUI.sections.rulesList.deleteSchedule": "删除计划",
|
||||
|
@ -42290,14 +42289,12 @@
|
|||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerButton": "全部显示",
|
||||
"xpack.triggersActionsUI.sections.rulesList.ruleParamBannerTitle": "按 URL 参数筛选的规则列表。",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.noSnoozeAppliedTooltip": "生成告警时发送通知",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.openSnoozePanel": "打开暂停面板",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.snoozedIndefinitelyTooltip": "通知已无期限暂停",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.timeRemaining": "剩余时间",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeFailed": "无法更改规则暂停设置",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.snoozeSuccess": "已成功暂停规则通知",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListSnoozePanel.unsnoozeSuccess": "已成功取消暂停规则通知",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.apiKeyOwnerTitle": "API 密钥所有者",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteAriaLabel": "删除",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteButtonTooltip": "删除",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitle": "持续时间",
|
||||
"xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.durationTitleTooltip": "运行规则所需的时间长度 (mm:ss)。",
|
||||
|
|
|
@ -129,7 +129,12 @@ export const CollapsedItemActions: React.FunctionComponent<ComponentOpts> = ({
|
|||
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rulesList.collapsedItemActons.popoverButtonTitle',
|
||||
{ defaultMessage: 'Actions' }
|
||||
{
|
||||
defaultMessage: 'Actions for "{name}" column',
|
||||
values: {
|
||||
name: item.name,
|
||||
},
|
||||
}
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -27,6 +27,7 @@ describe('RulesListNotifyBadge', () => {
|
|||
const wrapper = mountWithIntl(
|
||||
<RulesListNotifyBadge
|
||||
snoozeSettings={{
|
||||
name: 'rule 1',
|
||||
isSnoozedUntil: null,
|
||||
muteAll: false,
|
||||
}}
|
||||
|
@ -47,6 +48,7 @@ describe('RulesListNotifyBadge', () => {
|
|||
const wrapper = mountWithIntl(
|
||||
<RulesListNotifyBadge
|
||||
snoozeSettings={{
|
||||
name: 'rule 1',
|
||||
muteAll: false,
|
||||
isSnoozedUntil: moment('1990-02-01').toDate(),
|
||||
}}
|
||||
|
@ -68,6 +70,7 @@ describe('RulesListNotifyBadge', () => {
|
|||
const wrapper = mountWithIntl(
|
||||
<RulesListNotifyBadge
|
||||
snoozeSettings={{
|
||||
name: 'rule 1',
|
||||
muteAll: true,
|
||||
isSnoozedUntil: moment('1990-02-01').toDate(),
|
||||
}}
|
||||
|
@ -88,6 +91,7 @@ describe('RulesListNotifyBadge', () => {
|
|||
const wrapper = mountWithIntl(
|
||||
<RulesListNotifyBadge
|
||||
snoozeSettings={{
|
||||
name: 'rule 1',
|
||||
muteAll: false,
|
||||
isSnoozedUntil: null,
|
||||
}}
|
||||
|
@ -124,6 +128,7 @@ describe('RulesListNotifyBadge', () => {
|
|||
const wrapper = mountWithIntl(
|
||||
<RulesListNotifyBadge
|
||||
snoozeSettings={{
|
||||
name: 'rule 1',
|
||||
muteAll: true,
|
||||
}}
|
||||
onRuleChanged={onRuleChanged}
|
||||
|
|
|
@ -93,6 +93,11 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
|
||||
const focusTrapButtonRef = useRef<HTMLButtonElement>(null);
|
||||
|
||||
const snoozeButtonAriaLabel = useMemo(
|
||||
() => (snoozeSettings?.name ? OPEN_SNOOZE_PANEL_ARIA_LABEL(snoozeSettings.name) : undefined),
|
||||
[snoozeSettings]
|
||||
);
|
||||
|
||||
const {
|
||||
notifications: { toasts },
|
||||
} = useKibana().services;
|
||||
|
@ -189,7 +194,7 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
isLoading={isLoading}
|
||||
disabled={isLoading || isDisabled}
|
||||
data-test-subj="rulesListNotifyBadge-snoozed"
|
||||
aria-label={OPEN_SNOOZE_PANEL_ARIA_LABEL}
|
||||
aria-label={snoozeButtonAriaLabel}
|
||||
minWidth={85}
|
||||
iconType="bellSlash"
|
||||
color="accent"
|
||||
|
@ -199,7 +204,7 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
<EuiText size="xs">{formattedSnoozeText}</EuiText>
|
||||
</EuiButton>
|
||||
);
|
||||
}, [formattedSnoozeText, isLoading, isDisabled, openPopover]);
|
||||
}, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover, formattedSnoozeText]);
|
||||
|
||||
const scheduledSnoozeButton = useMemo(() => {
|
||||
return (
|
||||
|
@ -211,14 +216,14 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
minWidth={85}
|
||||
iconType="calendar"
|
||||
color="text"
|
||||
aria-label={OPEN_SNOOZE_PANEL_ARIA_LABEL}
|
||||
aria-label={snoozeButtonAriaLabel}
|
||||
onClick={openPopover}
|
||||
buttonRef={focusTrapButtonRef}
|
||||
>
|
||||
<EuiText size="xs">{formattedSnoozeText}</EuiText>
|
||||
</EuiButton>
|
||||
);
|
||||
}, [formattedSnoozeText, isLoading, isDisabled, openPopover]);
|
||||
}, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover, formattedSnoozeText]);
|
||||
|
||||
const unsnoozedButton = useMemo(() => {
|
||||
// This show on hover is needed because we need style sheets to achieve the
|
||||
|
@ -232,14 +237,14 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
disabled={isLoading || isDisabled}
|
||||
display={isLoading ? 'base' : 'empty'}
|
||||
data-test-subj="rulesListNotifyBadge-unsnoozed"
|
||||
aria-label={OPEN_SNOOZE_PANEL_ARIA_LABEL}
|
||||
aria-label={snoozeButtonAriaLabel}
|
||||
className={isPopoverOpen || isLoading ? '' : showOnHoverClass}
|
||||
iconType="bell"
|
||||
onClick={openPopover}
|
||||
buttonRef={focusTrapButtonRef}
|
||||
/>
|
||||
);
|
||||
}, [isPopoverOpen, isLoading, isDisabled, showOnHover, openPopover]);
|
||||
}, [showOnHover, isLoading, isDisabled, snoozeButtonAriaLabel, isPopoverOpen, openPopover]);
|
||||
|
||||
const indefiniteSnoozeButton = useMemo(() => {
|
||||
return (
|
||||
|
@ -249,14 +254,14 @@ export const RulesListNotifyBadge: React.FunctionComponent<RulesListNotifyBadgeP
|
|||
disabled={isLoading || isDisabled}
|
||||
display="base"
|
||||
data-test-subj="rulesListNotifyBadge-snoozedIndefinitely"
|
||||
aria-label={OPEN_SNOOZE_PANEL_ARIA_LABEL}
|
||||
aria-label={snoozeButtonAriaLabel}
|
||||
iconType="bellSlash"
|
||||
color="accent"
|
||||
onClick={openPopover}
|
||||
buttonRef={focusTrapButtonRef}
|
||||
/>
|
||||
);
|
||||
}, [isLoading, isDisabled, openPopover]);
|
||||
}, [isLoading, isDisabled, snoozeButtonAriaLabel, openPopover]);
|
||||
|
||||
const button = useMemo(() => {
|
||||
if (isScheduled) {
|
||||
|
|
|
@ -16,6 +16,7 @@ import { RulesListNotifyBadgePropsWithApi } from './types';
|
|||
|
||||
const rule = {
|
||||
id: uuidv4(),
|
||||
name: '',
|
||||
activeSnoozes: [],
|
||||
isSnoozedUntil: undefined,
|
||||
muteAll: false,
|
||||
|
|
|
@ -28,10 +28,16 @@ export const SNOOZE_FAILED_MESSAGE = i18n.translate(
|
|||
}
|
||||
);
|
||||
|
||||
export const OPEN_SNOOZE_PANEL_ARIA_LABEL = i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.openSnoozePanel',
|
||||
{ defaultMessage: 'Open snooze panel' }
|
||||
);
|
||||
export const OPEN_SNOOZE_PANEL_ARIA_LABEL = (name: string) =>
|
||||
i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.openSnoozePanel',
|
||||
{
|
||||
defaultMessage: 'Open "{name}" snooze panel',
|
||||
values: {
|
||||
name,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const getSecondsTranslation = (value: number) =>
|
||||
i18n.translate('xpack.triggersActionsUI.sections.rulesList.rulesListNotifyBadge.seconds', {
|
||||
|
|
|
@ -767,7 +767,7 @@ export const RulesListTable = (props: RulesListTableProps) => {
|
|||
iconType={'trash'}
|
||||
aria-label={i18n.translate(
|
||||
'xpack.triggersActionsUI.sections.rulesList.rulesListTable.columns.deleteAriaLabel',
|
||||
{ defaultMessage: 'Delete' }
|
||||
{ defaultMessage: 'Delete "{name}"', values: { name: rule.name } }
|
||||
)}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
|
|
@ -265,7 +265,7 @@ export type RuleUpdates = Omit<Rule, 'id' | 'executionStatus' | 'lastRun' | 'nex
|
|||
|
||||
export type RuleSnoozeSettings = Pick<
|
||||
Rule,
|
||||
'activeSnoozes' | 'isSnoozedUntil' | 'muteAll' | 'snoozeSchedule'
|
||||
'activeSnoozes' | 'isSnoozedUntil' | 'muteAll' | 'snoozeSchedule' | 'name'
|
||||
>;
|
||||
|
||||
export interface RuleTableItem extends Rule {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue