mirror of
https://github.com/reduxjs/redux-devtools.git
synced 2025-02-19 21:10:55 +03:00
Initial Basic Accessibility Added
This commit is contained in:
parent
c5aef77b85
commit
e8b07a9c11
|
@ -1,6 +1,6 @@
|
|||
import React, { useCallback, useState } from 'react';
|
||||
import JSONArrow from './JSONArrow.js';
|
||||
import type { CircularCache, CommonInternalProps } from './types.js';
|
||||
import type { CircularCache, CommonInternalProps, KeyPath } from './types.js';
|
||||
|
||||
interface Props extends CommonInternalProps {
|
||||
data: unknown;
|
||||
|
@ -10,6 +10,7 @@ interface Props extends CommonInternalProps {
|
|||
renderChildNodes: (props: Props, from: number, to: number) => React.ReactNode;
|
||||
circularCache: CircularCache;
|
||||
level: number;
|
||||
keyPath: KeyPath;
|
||||
}
|
||||
|
||||
export default function ItemRange(props: Props) {
|
||||
|
@ -32,6 +33,7 @@ export default function ItemRange(props: Props) {
|
|||
expanded={false}
|
||||
onClick={handleClick}
|
||||
arrowStyle="double"
|
||||
ariaLabel={`Expand Array from ${from} to ${to}`}
|
||||
/>
|
||||
{`${from} ... ${to}`}
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,9 @@ interface Props {
|
|||
arrowStyle?: 'single' | 'double';
|
||||
expanded: boolean;
|
||||
nodeType: string;
|
||||
onClick: React.MouseEventHandler<HTMLDivElement>;
|
||||
onClick: React.MouseEventHandler<HTMLButtonElement>;
|
||||
ariaControls?: string;
|
||||
ariaLabel?: string
|
||||
}
|
||||
|
||||
export default function JSONArrow({
|
||||
|
@ -15,15 +17,17 @@ export default function JSONArrow({
|
|||
expanded,
|
||||
nodeType,
|
||||
onClick,
|
||||
ariaControls,
|
||||
ariaLabel
|
||||
}: Props) {
|
||||
return (
|
||||
<div {...styling('arrowContainer', arrowStyle)} onClick={onClick}>
|
||||
<button {...styling('arrowContainer', arrowStyle)} aria-label={ariaLabel} aria-expanded={expanded} aria-controls={ariaControls} onClick={onClick}>
|
||||
<div {...styling(['arrow', 'arrowSign'], nodeType, expanded, arrowStyle)}>
|
||||
{'\u25B6'}
|
||||
{arrowStyle === 'double' && (
|
||||
<div {...styling(['arrowSign', 'arrowSignInner'])}>{'\u25B6'}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import getCollectionEntries from './getCollectionEntries.js';
|
|||
import JSONNode from './JSONNode.js';
|
||||
import ItemRange from './ItemRange.js';
|
||||
import type { CircularCache, CommonInternalProps } from './types.js';
|
||||
import getAriaPropsFromKeyPath from './getAriaPropsFromKeyPath.js';
|
||||
|
||||
/**
|
||||
* Renders nested values (eg. objects, arrays, lists, etc.)
|
||||
|
@ -62,6 +63,7 @@ function renderChildNodes(
|
|||
from={entry.from}
|
||||
to={entry.to}
|
||||
renderChildNodes={renderChildNodes}
|
||||
keyPath={[entry.from, ...keyPath]}
|
||||
/>,
|
||||
);
|
||||
} else {
|
||||
|
@ -141,6 +143,8 @@ export default function JSONNestedNode(props: Props) {
|
|||
);
|
||||
const stylingArgs = [keyPath, nodeType, expanded, expandable] as const;
|
||||
|
||||
const {ariaControls, ariaLabel} = getAriaPropsFromKeyPath(keyPath)
|
||||
|
||||
return hideRoot ? (
|
||||
<li {...styling('rootNode', ...stylingArgs)}>
|
||||
<ul {...styling('rootNodeChildren', ...stylingArgs)}>
|
||||
|
@ -155,6 +159,8 @@ export default function JSONNestedNode(props: Props) {
|
|||
nodeType={nodeType}
|
||||
expanded={expanded}
|
||||
onClick={handleClick}
|
||||
ariaControls={ariaControls}
|
||||
ariaLabel={ariaLabel}
|
||||
/>
|
||||
)}
|
||||
<label
|
||||
|
@ -169,7 +175,7 @@ export default function JSONNestedNode(props: Props) {
|
|||
>
|
||||
{renderedItemString}
|
||||
</span>
|
||||
<ul {...styling('nestedNodeChildren', ...stylingArgs)}>
|
||||
<ul {...styling('nestedNodeChildren', ...stylingArgs)} id={expandable ? ariaControls : undefined}>
|
||||
{renderedChildren}
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -122,6 +122,11 @@ const getDefaultThemeStyling = (theme: Base16Theme): StylingConfig => {
|
|||
arrowContainer: ({ style }, arrowStyle) => ({
|
||||
style: {
|
||||
...style,
|
||||
background: 'none',
|
||||
color: 'inherit',
|
||||
border: 'none',
|
||||
padding: 0,
|
||||
font: 'inherit',
|
||||
display: 'inline-block',
|
||||
paddingRight: '0.5em',
|
||||
paddingLeft: arrowStyle === 'double' ? '1em' : 0,
|
||||
|
|
21
packages/react-json-tree/src/getAriaPropsFromKeyPath.ts
Normal file
21
packages/react-json-tree/src/getAriaPropsFromKeyPath.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { KeyPath } from "./types.js";
|
||||
|
||||
const replaceSpacesRegex = / /g;
|
||||
|
||||
const getAriaPropsFromKeyPath = (
|
||||
keyPath: KeyPath
|
||||
) => {
|
||||
let ariaControls = '';
|
||||
let ariaLabel = 'JSON Tree Node: ';
|
||||
for(let i = keyPath.length - 1; i >= 0; i--) {
|
||||
const key = keyPath[i];
|
||||
ariaControls += `${key}`.replace(replaceSpacesRegex, '-');
|
||||
ariaLabel += `${key} `;
|
||||
}
|
||||
|
||||
ariaLabel = ariaLabel.trim();
|
||||
|
||||
return { ariaControls, ariaLabel };
|
||||
}
|
||||
|
||||
export default getAriaPropsFromKeyPath;
|
Loading…
Reference in New Issue
Block a user