diff options
| author | Haishan <[email protected]> | 2020-08-06 16:26:01 +0800 |
|---|---|---|
| committer | Haishan <[email protected]> | 2020-08-06 22:40:26 +0800 |
| commit | 2c9ee574ddd5d242021e5954ca6f6144f99eb7f2 (patch) | |
| tree | f085d8083f106f2decd1156c6ba715c34acd38ed /src | |
| parent | 941224c13ba87d2c3f36fb86652f046a5c76e00d (diff) | |
refactor: improve a11y
Diffstat (limited to 'src')
| -rw-r--r-- | src/components/APIConfig.js | 1 | ||||
| -rw-r--r-- | src/components/CollapsibleSectionHeader.module.css | 5 | ||||
| -rw-r--r-- | src/components/CollapsibleSectionHeader.tsx (renamed from src/components/CollapsibleSectionHeader.js) | 33 | ||||
| -rw-r--r-- | src/components/Selection.js | 16 | ||||
| -rw-r--r-- | src/components/SideBar.module.css | 2 | ||||
| -rw-r--r-- | src/components/proxies/ClosePrevConns.tsx | 1 | ||||
| -rw-r--r-- | src/components/proxies/Proxy.module.css | 6 | ||||
| -rw-r--r-- | src/components/proxies/Proxy.tsx | 65 | ||||
| -rw-r--r-- | src/components/shared/Select.tsx | 1 | ||||
| -rw-r--r-- | src/misc/keycode.ts | 6 |
10 files changed, 104 insertions, 32 deletions
diff --git a/src/components/APIConfig.js b/src/components/APIConfig.js index 282da42..bcda06e 100644 --- a/src/components/APIConfig.js +++ b/src/components/APIConfig.js @@ -78,6 +78,7 @@ function APIConfig({ apiConfig, dispatch }) { ); return ( + // eslint-disable-next-line jsx-a11y/no-static-element-interactions <div className={s0.root} ref={contentEl} onKeyDown={handleContentOnKeyDown}> <div className={s0.header}> <div className={s0.icon}> diff --git a/src/components/CollapsibleSectionHeader.module.css b/src/components/CollapsibleSectionHeader.module.css index 854a0c6..b654f35 100644 --- a/src/components/CollapsibleSectionHeader.module.css +++ b/src/components/CollapsibleSectionHeader.module.css @@ -2,10 +2,15 @@ display: flex; align-items: center; + &:focus { + outline: none; + } + .arrow { display: inline-flex; transform: rotate(0deg); transition: transform 0.3s; + &.isOpen { transform: rotate(180deg); } diff --git a/src/components/CollapsibleSectionHeader.js b/src/components/CollapsibleSectionHeader.tsx index 794aafb..77e7596 100644 --- a/src/components/CollapsibleSectionHeader.js +++ b/src/components/CollapsibleSectionHeader.tsx @@ -1,23 +1,40 @@ import cx from 'clsx'; -import React from 'react'; +import * as React from 'react'; import { ChevronDown } from 'react-feather'; +import { keyCodes } from '../misc/keycode'; import Button from './Button'; import s from './CollapsibleSectionHeader.module.css'; import { SectionNameType } from './shared/Basic'; type Props = { - name: string, - type: string, - qty?: number, - toggle?: () => void, - isOpen?: boolean, + name: string; + type: string; + qty?: number; + toggle?: () => void; + isOpen?: boolean; }; export default function Header({ name, type, toggle, isOpen, qty }: Props) { + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + e.preventDefault(); + if (e.keyCode === keyCodes.Enter || e.keyCode === keyCodes.Space) { + toggle(); + } + }, + [toggle] + ); return ( - <div className={s.header}> - <div onClick={toggle} style={{ cursor: 'pointer' }}> + <div + className={s.header} + onClick={toggle} + style={{ cursor: 'pointer' }} + tabIndex={0} + onKeyDown={handleKeyDown} + role="button" + > + <div> <SectionNameType name={name} type={type} /> </div> diff --git a/src/components/Selection.js b/src/components/Selection.js index 8302de3..764e7b3 100644 --- a/src/components/Selection.js +++ b/src/components/Selection.js @@ -11,21 +11,21 @@ export default function Selection({ onChange, }) { return ( - // TODO a11y - // tabIndex="0" <div className={s.root}> {optionPropsList.map((props, idx) => { const className = cx(s.item, { [s.itemActive]: idx === selectedIndex }); + const doSelect = (ev) => { + ev.preventDefault(); + if (idx !== selectedIndex) onChange(idx); + }; return ( <div key={idx} className={className} - onClick={(ev) => { - ev.preventDefault(); - if (idx !== selectedIndex) { - onChange(idx); - } - }} + tabIndex={0} + role="menuitem" + onKeyDown={doSelect} + onClick={doSelect} > <OptionComponent {...props} /> </div> diff --git a/src/components/SideBar.module.css b/src/components/SideBar.module.css index 275a007..7ecb3c3 100644 --- a/src/components/SideBar.module.css +++ b/src/components/SideBar.module.css @@ -90,6 +90,7 @@ justify-content: center; align-items: center; + outline: none; padding: 5px; color: var(--color-text); border-radius: 100%; @@ -104,7 +105,6 @@ .themeSwitchContainer { appearance: none; - outline: none; user-select: none; background: none; cursor: pointer; diff --git a/src/components/proxies/ClosePrevConns.tsx b/src/components/proxies/ClosePrevConns.tsx index 567a3e5..5617efe 100644 --- a/src/components/proxies/ClosePrevConns.tsx +++ b/src/components/proxies/ClosePrevConns.tsx @@ -29,6 +29,7 @@ export function ClosePrevConns({ }; return ( + // eslint-disable-next-line jsx-a11y/no-static-element-interactions <div onKeyDown={handleKeyDown}> <h2>Close Connections?</h2> <p> diff --git a/src/components/proxies/Proxy.module.css b/src/components/proxies/Proxy.module.css index f233193..03c4df8 100644 --- a/src/components/proxies/Proxy.module.css +++ b/src/components/proxies/Proxy.module.css @@ -9,6 +9,12 @@ flex-direction: column; justify-content: space-between; + outline: none; + border: 1px solid transparent; + &:focus { + border: 1px solid var(--color-focus-blue); + } + max-width: 280px; @media (--breakpoint-not-small) { min-width: 200px; diff --git a/src/components/proxies/Proxy.tsx b/src/components/proxies/Proxy.tsx index d456da5..0cbf561 100644 --- a/src/components/proxies/Proxy.tsx +++ b/src/components/proxies/Proxy.tsx @@ -1,5 +1,6 @@ import cx from 'clsx'; import * as React from 'react'; +import { keyCodes } from 'src/misc/keycode'; import { getDelay, getProxies, NonProxyTypes } from '../../store/proxies'; import { connect } from '../StateProvider'; @@ -76,17 +77,35 @@ function ProxySmallImpl({ } return ret; }, [name, latency]); + + const doSelect = React.useCallback(() => { + isSelectable && onClick && onClick(name); + }, [name, onClick, isSelectable]); + + const className = useMemo(() => { + return cx(s0.proxySmall, { + [s0.now]: now, + [s0.selectable]: isSelectable, + }); + }, [isSelectable, now]); + + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.keyCode === keyCodes.Enter) { + doSelect(); + } + }, + [doSelect] + ); + return ( <div title={title} - className={cx(s0.proxySmall, { - [s0.now]: now, - [s0.selectable]: isSelectable, - })} + className={className} style={{ background: color }} - onClick={() => { - isSelectable && onClick && onClick(name); - }} + onClick={doSelect} + onKeyDown={handleKeyDown} + role={isSelectable ? 'menuitem' : ''} /> ); } @@ -100,16 +119,32 @@ function ProxyImpl({ onClick, }: ProxyProps) { const color = useMemo(() => getLabelColor(latency), [latency]); + const doSelect = React.useCallback(() => { + isSelectable && onClick && onClick(name); + }, [name, onClick, isSelectable]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.keyCode === keyCodes.Enter) { + doSelect(); + } + }, + [doSelect] + ); + const className = useMemo(() => { + return cx(s0.proxy, { + [s0.now]: now, + [s0.error]: latency && latency.error, + [s0.selectable]: isSelectable, + }); + }, [isSelectable, now, latency]); + return ( <div - className={cx(s0.proxy, { - [s0.now]: now, - [s0.error]: latency && latency.error, - [s0.selectable]: isSelectable, - })} - onClick={() => { - isSelectable && onClick && onClick(name); - }} + tabIndex={0} + className={className} + onClick={doSelect} + onKeyDown={handleKeyDown} + role={isSelectable ? 'menuitem' : ''} > <div className={s0.proxyName}>{name}</div> <div className={s0.row}> diff --git a/src/components/shared/Select.tsx b/src/components/shared/Select.tsx index 03ac084..376fb3c 100644 --- a/src/components/shared/Select.tsx +++ b/src/components/shared/Select.tsx @@ -10,6 +10,7 @@ type Props = { export default function Select({ options, selected, onChange }: Props) { return ( + // eslint-disable-next-line jsx-a11y/no-onchange <select className={s.select} value={selected} onChange={onChange}> {options.map(([value, name]) => ( <option key={value} value={value}> diff --git a/src/misc/keycode.ts b/src/misc/keycode.ts new file mode 100644 index 0000000..d1dd935 --- /dev/null +++ b/src/misc/keycode.ts @@ -0,0 +1,6 @@ +export const keyCodes = { + Right: 39, + Left: 37, + Enter: 13, + Space: 32, +}; |
