Compare commits

...

3 Commits

Author SHA1 Message Date
Elizabeth Thompson
2821c5760b test(dashboard): update Header delete-button query for new accessible name
DeleteComponentButton now labels its IconButton 'Delete component', so the
role/name query for the old icon-derived name 'delete' no longer matches.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 00:41:58 +00:00
Elizabeth Thompson
055c9dc136 Merge branch 'master' into fix/dashboard-icon-button-aria-label 2026-07-22 00:37:59 +00:00
Elizabeth Thompson
4f0434ba1d fix(a11y): add aria-label to dashboard IconButton and unlabeled call sites
Icon-only buttons (delete, row settings, column settings) had no
accessible name, making them invisible to screen readers despite being
keyboard-focusable via tabIndex=0. Wires the existing label prop through
as aria-label on the underlying div[role=button] and provides labels at
all three call sites that previously passed none.

WCAG 2.1 SC 4.1.2 (Name, Role, Value) — Level A.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 00:44:35 +00:00
5 changed files with 8 additions and 1 deletions

View File

@@ -18,6 +18,7 @@
*/
import { MouseEventHandler, FC } from 'react';
import { t } from '@apache-superset/core/translation';
import { Icons } from '@superset-ui/core/components/Icons';
import type { IconType } from '@superset-ui/core/components/Icons/types';
import IconButton from './IconButton';
@@ -33,6 +34,7 @@ const DeleteComponentButton: FC<DeleteComponentButtonProps> = ({
}) => (
<IconButton
onClick={onDelete}
label={t('Delete component')}
icon={<Icons.DeleteOutlined iconSize={iconSize ?? 'l'} />}
/>
);

View File

@@ -72,6 +72,7 @@ const IconButton = forwardRef<HTMLDivElement, IconButtonProps>(
ref={ref}
tabIndex={disabled ? -1 : 0}
role="button"
aria-label={label}
isDisabled={disabled}
aria-disabled={disabled}
data-test={dataTest}

View File

@@ -247,6 +247,7 @@ const Column = (props: ColumnProps) => {
/>
<IconButton
onClick={() => handleChangeFocus(true)}
label={t('Column settings')}
icon={<Icons.SettingOutlined iconSize="m" />}
/>
</HoverMenu>

View File

@@ -145,7 +145,9 @@ describe('Header', () => {
const deleteComponent = jest.fn();
setup({ editMode: true, deleteComponent });
const trashButton = screen.getByRole('button', { name: 'delete' });
const trashButton = screen.getByRole('button', {
name: 'Delete component',
});
fireEvent.click(trashButton);
expect(deleteComponent).toHaveBeenCalledTimes(1);

View File

@@ -293,6 +293,7 @@ const Row = memo((props: RowProps) => {
<DeleteComponentButton onDelete={handleDeleteComponent} />
<IconButton
onClick={() => handleChangeFocus(true)}
label={t('Row settings')}
icon={<Icons.SettingOutlined iconSize="l" />}
/>
</HoverMenu>