feat(dropdown accessibility): Wrap dropdown triggers with buttons for accessibility (#32189)

This commit is contained in:
Mehmet Salih Yavuz 2025-02-11 14:09:35 +03:00 committed by GitHub
parent a78968c68e
commit 60bbd72028
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 41 deletions

View File

@ -873,7 +873,9 @@ const SqlEditor: FC<Props> = ({
dropdownRender={() => renderDropdown()}
trigger={['click']}
>
<Button buttonSize="xsmall" type="link" showMarginRight={false}>
<Icons.MoreHoriz iconColor={theme.colors.grayscale.base} />
</Button>
</Dropdown>
</div>
</>

View File

@ -30,7 +30,7 @@ import {
import AutoSizer from 'react-virtualized-auto-sizer';
import Icons from 'src/components/Icons';
import type { SqlLabRootState } from 'src/SqlLab/types';
import { Skeleton, AntdBreadcrumb as Breadcrumb } from 'src/components';
import { Skeleton, AntdBreadcrumb as Breadcrumb, Button } from 'src/components';
import { Dropdown } from 'src/components/Dropdown';
import FilterableTable from 'src/components/FilterableTable';
import Tabs from 'src/components/Tabs';
@ -324,11 +324,13 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
)}
trigger={['click']}
>
<Button buttonSize="xsmall" type="link">
<Icons.DownSquareOutlined
iconSize="m"
style={{ marginTop: 2, marginLeft: 4 }}
aria-label={t('Table actions')}
/>
</Button>
</Dropdown>
</Title>
{isMetadataRefreshing ? (

View File

@ -29,6 +29,7 @@ import { Menu } from 'src/components/Menu';
import FaveStar from 'src/components/FaveStar';
import FacePile from 'src/components/FacePile';
import { handleChartDelete, CardStyles } from 'src/views/CRUD/utils';
import Button from 'src/components/Button';
interface ChartCardProps {
chart: Chart;
@ -172,8 +173,10 @@ export default function ChartCard({
isStarred={favoriteStatus}
/>
)}
<Dropdown dropdownRender={() => menu}>
<Dropdown dropdownRender={() => menu} trigger={['click', 'hover']}>
<Button buttonSize="xsmall" type="link">
<Icons.MoreVert iconColor={theme.colors.grayscale.base} />
</Button>
</Dropdown>
</ListViewCard.Actions>
}

View File

@ -34,6 +34,7 @@ import { PublishedLabel } from 'src/components/Label';
import FacePile from 'src/components/FacePile';
import FaveStar from 'src/components/FaveStar';
import { Dashboard } from 'src/views/CRUD/types';
import { Button } from 'src/components';
interface DashboardCardProps {
isChart?: boolean;
@ -179,8 +180,10 @@ function DashboardCard({
isStarred={favoriteStatus}
/>
)}
<Dropdown dropdownRender={() => menu}>
<Dropdown dropdownRender={() => menu} trigger={['hover', 'click']}>
<Button buttonSize="xsmall" type="link">
<Icons.MoreVert iconColor={theme.colors.grayscale.base} />
</Button>
</Dropdown>
</ListViewCard.Actions>
}

View File

@ -104,7 +104,7 @@ describe('SavedQueries', () => {
it('renders a submenu with clickable tables and buttons', async () => {
expect(wrapper.find(SubMenu)).toExist();
expect(wrapper.find('[role="tab"]')).toHaveLength(1);
expect(wrapper.find('button')).toHaveLength(2);
expect(wrapper.find('button')).toHaveLength(5);
clickTab(0);
await waitForComponentToPaint(wrapper);
expect(fetchMock.calls(/saved_query\/\?q/)).toHaveLength(2);

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
import { useState } from 'react';
import { useCallback, useState } from 'react';
import { Link } from 'react-router-dom';
import { styled, SupersetClient, t, useTheme } from '@superset-ui/core';
import SyntaxHighlighter from 'react-syntax-highlighter/dist/cjs/light';
@ -39,6 +39,7 @@ import {
PAGE_SIZE,
shortenSQL,
} from 'src/views/CRUD/utils';
import { Button } from 'src/components';
import SubMenu from './SubMenu';
import EmptyState from './EmptyState';
import { WelcomeTable } from './types';
@ -191,7 +192,8 @@ const SavedQueries = ({
filters: getFilterValues(tab, WelcomeTable.SavedQueries, user),
});
const renderMenu = (query: Query) => (
const renderMenu = useCallback(
(query: Query) => (
<Menu>
{canEdit && (
<Menu.Item>
@ -218,6 +220,8 @@ const SavedQueries = ({
</Menu.Item>
)}
</Menu>
),
[],
);
if (loading) return <LoadingCards cover={showThumbnails} />;
@ -315,10 +319,15 @@ const SavedQueries = ({
e.preventDefault();
}}
>
<Dropdown dropdownRender={() => renderMenu(q)}>
<Dropdown
dropdownRender={() => renderMenu(q)}
trigger={['click', 'hover']}
>
<Button buttonSize="xsmall" type="link">
<Icons.MoreVert
iconColor={theme.colors.grayscale.base}
/>
</Button>
</Dropdown>
</ListViewCard.Actions>
</QueryData>

View File

@ -26,6 +26,7 @@ import ListViewCard from 'src/components/ListViewCard';
import Icons from 'src/components/Icons';
import { Tag } from 'src/views/CRUD/types';
import { deleteTags } from 'src/features/tags/tags';
import { Button } from 'src/components';
interface TagCardProps {
tag: Tag;
@ -108,8 +109,10 @@ function TagCard({
e.preventDefault();
}}
>
<Dropdown dropdownRender={() => menu}>
<Dropdown dropdownRender={() => menu} trigger={['click', 'hover']}>
<Button buttonSize="xsmall" type="link">
<Icons.MoreVert iconColor={theme.colors.grayscale.base} />
</Button>
</Dropdown>
</ListViewCard.Actions>
}