summaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
authorHaishan <[email protected]>2020-08-06 16:26:01 +0800
committerHaishan <[email protected]>2020-08-06 22:40:26 +0800
commit2c9ee574ddd5d242021e5954ca6f6144f99eb7f2 (patch)
treef085d8083f106f2decd1156c6ba715c34acd38ed /src/components
parent941224c13ba87d2c3f36fb86652f046a5c76e00d (diff)
refactor: improve a11y
Diffstat (limited to 'src/components')
-rw-r--r--src/components/APIConfig.js1
-rw-r--r--src/components/CollapsibleSectionHeader.module.css5
-rw-r--r--src/components/CollapsibleSectionHeader.tsx (renamed from src/components/CollapsibleSectionHeader.js)33
-rw-r--r--src/components/Selection.js16
-rw-r--r--src/components/SideBar.module.css2
-rw-r--r--src/components/proxies/ClosePrevConns.tsx1
-rw-r--r--src/components/proxies/Proxy.module.css6
-rw-r--r--src/components/proxies/Proxy.tsx65
-rw-r--r--src/components/shared/Select.tsx1
9 files changed, 98 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}>