mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-07-27 00:19:55 +03:00
feat(rtk-query): improve a11y of rtk-query-monitor tab panel #1126
This commit is contained in:
parent
d9ecb32efc
commit
8154bde35b
|
@ -127,6 +127,7 @@ export class QueryForm extends React.PureComponent<
|
|||
{({ styling, base16Theme }) => {
|
||||
return (
|
||||
<form
|
||||
id="rtk-query-monitor-query-selection-form"
|
||||
action="#"
|
||||
onSubmit={this.handleSubmit}
|
||||
{...styling('queryForm')}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import { createSelector, Selector } from '@reduxjs/toolkit';
|
||||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { Action, AnyAction } from 'redux';
|
||||
import { QueryPreviewTabs } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { emptyRecord, identity } from '../utils/object';
|
||||
import { TreeView } from './TreeView';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
|
||||
export interface QueryPreviewActionsProps {
|
||||
isWideLayout: boolean;
|
||||
|
@ -11,6 +13,12 @@ export interface QueryPreviewActionsProps {
|
|||
|
||||
const keySep = ' - ';
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.actions),
|
||||
id: renderTabPanelId(QueryPreviewTabs.actions),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export class QueryPreviewActions extends PureComponent<QueryPreviewActionsProps> {
|
||||
selectFormattedActions: Selector<
|
||||
AnyAction[],
|
||||
|
@ -74,6 +82,7 @@ export class QueryPreviewActions extends PureComponent<QueryPreviewActionsProps>
|
|||
|
||||
return (
|
||||
<TreeView
|
||||
rootProps={rootProps}
|
||||
data={this.selectFormattedActions(actionsOfQuery)}
|
||||
isWideLayout={isWideLayout}
|
||||
shouldExpandNode={this.shouldExpandNode}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { ApiStats, RtkQueryApiState } from '../types';
|
||||
import { ApiStats, QueryPreviewTabs, RtkQueryApiState } from '../types';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { TreeView } from './TreeView';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
import { renderTabPanelId, renderTabPanelButtonId } from '../utils/a11y';
|
||||
|
||||
export interface QueryPreviewApiProps {
|
||||
apiStats: ApiStats | null;
|
||||
|
@ -9,6 +10,12 @@ export interface QueryPreviewApiProps {
|
|||
isWideLayout: boolean;
|
||||
}
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.apiConfig),
|
||||
id: renderTabPanelId(QueryPreviewTabs.apiConfig),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
||||
shouldExpandApiStateNode = (
|
||||
keyPath: (string | number)[],
|
||||
|
@ -33,7 +40,7 @@ export class QueryPreviewApi extends PureComponent<QueryPreviewApiProps> {
|
|||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling }) => (
|
||||
<article {...styling('tabContent')}>
|
||||
<article {...rootProps} {...styling('tabContent')}>
|
||||
<h2>{apiState.config.reducerPath}</h2>
|
||||
<TreeView
|
||||
before={<h3>State</h3>}
|
||||
|
|
|
@ -1,20 +1,26 @@
|
|||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { RtkResourceInfo } from '../types';
|
||||
import { TreeView } from './TreeView';
|
||||
import { QueryPreviewTabs, RtkResourceInfo } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
|
||||
export interface QueryPreviewDataProps {
|
||||
data: RtkResourceInfo['state']['data'];
|
||||
isWideLayout: boolean;
|
||||
}
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.data),
|
||||
id: renderTabPanelId(QueryPreviewTabs.data),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export class QueryPreviewData extends PureComponent<QueryPreviewDataProps> {
|
||||
shouldExpandNode = (
|
||||
keyPath: (string | number)[],
|
||||
value: unknown,
|
||||
layer: number
|
||||
): boolean => {
|
||||
const lastKey = keyPath[keyPath.length - 1];
|
||||
|
||||
return layer <= 1 && lastKey !== 'query' && lastKey !== 'mutation';
|
||||
return layer <= 1;
|
||||
};
|
||||
|
||||
render(): ReactNode {
|
||||
|
@ -22,6 +28,7 @@ export class QueryPreviewData extends PureComponent<QueryPreviewDataProps> {
|
|||
|
||||
return (
|
||||
<TreeView
|
||||
rootProps={rootProps}
|
||||
data={data}
|
||||
isWideLayout={isWideLayout}
|
||||
shouldExpandNode={this.shouldExpandNode}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { ReactNode } from 'react';
|
||||
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
|
||||
import { QueryPreviewTabs, TabOption } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { emptyArray } from '../utils/object';
|
||||
|
||||
export interface QueryPreviewHeaderProps {
|
||||
|
@ -28,7 +29,11 @@ export class QueryPreviewHeader extends React.Component<QueryPreviewHeaderProps>
|
|||
<div {...styling('previewHeader')}>
|
||||
<div {...styling('tabSelector')}>
|
||||
{tabs.map((tab) => (
|
||||
<div
|
||||
<button
|
||||
type="button"
|
||||
id={renderTabPanelButtonId(tab.value)}
|
||||
aria-selected={tab.value === selectedTab}
|
||||
role={'tab'}
|
||||
onClick={() => this.handleTabClick(tab)}
|
||||
key={tab.value}
|
||||
{...styling(
|
||||
|
@ -42,7 +47,7 @@ export class QueryPreviewHeader extends React.Component<QueryPreviewHeaderProps>
|
|||
<span>
|
||||
{renderTabLabel ? renderTabLabel(tab) : tab.label}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { createSelector, Selector } from '@reduxjs/toolkit';
|
||||
import { QueryStatus } from '@reduxjs/toolkit/dist/query';
|
||||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { RtkResourceInfo, RTKStatusFlags } from '../types';
|
||||
import { QueryPreviewTabs, RtkResourceInfo, RTKStatusFlags } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { formatMs } from '../utils/formatters';
|
||||
import { identity } from '../utils/object';
|
||||
import { getQueryStatusFlags } from '../utils/rtk-query';
|
||||
import { TreeView } from './TreeView';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
|
||||
type QueryTimings = {
|
||||
startedAt: string;
|
||||
|
@ -23,6 +24,12 @@ type FormattedQuery = {
|
|||
| { query: RtkResourceInfo['state'] }
|
||||
);
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.queryinfo),
|
||||
id: renderTabPanelId(QueryPreviewTabs.queryinfo),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export interface QueryPreviewInfoProps {
|
||||
resInfo: RtkResourceInfo;
|
||||
isWideLayout: boolean;
|
||||
|
@ -97,6 +104,7 @@ export class QueryPreviewInfo extends PureComponent<QueryPreviewInfoProps> {
|
|||
|
||||
return (
|
||||
<TreeView
|
||||
rootProps={rootProps}
|
||||
data={formattedQuery}
|
||||
isWideLayout={isWideLayout}
|
||||
shouldExpandNode={this.shouldExpandNode}
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { RtkQueryApiState } from '../types';
|
||||
import { TreeView } from './TreeView';
|
||||
import { QueryPreviewTabs, RtkQueryApiState } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(
|
||||
QueryPreviewTabs.querySubscriptions
|
||||
),
|
||||
id: renderTabPanelId(QueryPreviewTabs.querySubscriptions),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export interface QueryPreviewSubscriptionsProps {
|
||||
subscriptions: RtkQueryApiState['subscriptions'][keyof RtkQueryApiState['subscriptions']];
|
||||
|
@ -12,7 +21,11 @@ export class QueryPreviewSubscriptions extends PureComponent<QueryPreviewSubscri
|
|||
const { subscriptions } = this.props;
|
||||
|
||||
return (
|
||||
<TreeView data={subscriptions} isWideLayout={this.props.isWideLayout} />
|
||||
<TreeView
|
||||
rootProps={rootProps}
|
||||
data={subscriptions}
|
||||
isWideLayout={this.props.isWideLayout}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
import React, { ReactNode, PureComponent } from 'react';
|
||||
import { RtkQueryTag } from '../types';
|
||||
import { TreeView } from './TreeView';
|
||||
import { QueryPreviewTabs, RtkQueryTag } from '../types';
|
||||
import { renderTabPanelButtonId, renderTabPanelId } from '../utils/a11y';
|
||||
import { TreeView, TreeViewProps } from './TreeView';
|
||||
|
||||
interface QueryPreviewTagsState {
|
||||
data: { tags: RtkQueryTag[] };
|
||||
}
|
||||
|
||||
const rootProps: TreeViewProps['rootProps'] = {
|
||||
'aria-labelledby': renderTabPanelButtonId(QueryPreviewTabs.queryTags),
|
||||
id: renderTabPanelId(QueryPreviewTabs.queryTags),
|
||||
role: 'tabpanel',
|
||||
};
|
||||
|
||||
export interface QueryPreviewTagsProps {
|
||||
tags: RtkQueryTag[];
|
||||
isWideLayout: boolean;
|
||||
|
@ -26,6 +33,8 @@ export class QueryPreviewTags extends PureComponent<
|
|||
render(): ReactNode {
|
||||
const { isWideLayout, tags } = this.props;
|
||||
|
||||
return <TreeView data={tags} isWideLayout={isWideLayout} />;
|
||||
return (
|
||||
<TreeView rootProps={rootProps} data={tags} isWideLayout={isWideLayout} />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ export interface TreeViewProps
|
|||
before?: ReactNode;
|
||||
after?: ReactNode;
|
||||
children?: ReactNode;
|
||||
rootProps?: Partial<
|
||||
Omit<React.HTMLAttributes<HTMLDivElement>, 'className' | 'style'>
|
||||
>;
|
||||
}
|
||||
|
||||
export class TreeView extends React.PureComponent<TreeViewProps> {
|
||||
|
@ -80,13 +83,14 @@ export class TreeView extends React.PureComponent<TreeViewProps> {
|
|||
keyPath,
|
||||
shouldExpandNode,
|
||||
hideRoot,
|
||||
rootProps,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<StyleUtilsContext.Consumer>
|
||||
{({ styling, invertTheme, base16Theme }) => {
|
||||
return (
|
||||
<div {...styling('treeWrapper')}>
|
||||
<div {...rootProps} {...styling('treeWrapper')}>
|
||||
{before}
|
||||
<JSONTree
|
||||
keyPath={keyPath}
|
||||
|
|
|
@ -217,6 +217,8 @@ const getSheetFromColorMap = (map: ColorMap) => {
|
|||
padding: '0 8px',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
boxShadow: 'none',
|
||||
outline: 'none',
|
||||
color: map.TEXT_COLOR,
|
||||
'border-style': 'solid',
|
||||
'border-width': '1px',
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { QueryPreviewTabs } from '../types';
|
||||
|
||||
export function renderTabPanelId(value: QueryPreviewTabs): string {
|
||||
return `rtk-query-monitor-tab-panel-${value}`;
|
||||
}
|
||||
|
||||
export function renderTabPanelButtonId(value: QueryPreviewTabs): string {
|
||||
return renderTabPanelId(value) + '-button';
|
||||
}
|
Loading…
Reference in New Issue
Block a user