diff options
author | Shin'ya Ueoka <ueokande@i-beam.org> | 2020-08-16 16:39:57 +0900 |
---|---|---|
committer | Shin'ya Ueoka <ueokande@i-beam.org> | 2020-09-21 12:48:18 +0900 |
commit | 264d69c933370b3321dfcd83d823222e730e3fe0 (patch) | |
tree | 9d70c4a6cc8c5eb8c8565098e31e8eda7f3ccf9c /src/console | |
parent | a70122acd6595ba26f084d22185c40f6da65b5ac (diff) |
Improve a11y in completion items
Diffstat (limited to 'src/console')
-rw-r--r-- | src/console/components/console/Completion.tsx | 48 | ||||
-rw-r--r-- | src/console/components/console/CompletionItem.tsx | 18 | ||||
-rw-r--r-- | src/console/components/console/CompletionTitle.tsx | 10 |
3 files changed, 54 insertions, 22 deletions
diff --git a/src/console/components/console/Completion.tsx b/src/console/components/console/Completion.tsx index aefee32..56c5de3 100644 --- a/src/console/components/console/Completion.tsx +++ b/src/console/components/console/Completion.tsx @@ -63,29 +63,51 @@ class Completion extends React.Component<Props, State> { } render() { - let eles = []; - let index = 0; + let itemIndex = 0; + let viewIndex = 0; + const groups: Array<JSX.Element> = []; + const viewOffset = this.state.viewOffset; + const viewSize = this.props.size; - for (const group of this.props.completions) { - eles.push(<CompletionTitle key={`group-${index}`} title={group.name} />); + this.props.completions.forEach((group, groupIndex) => { + const items = []; + const title = ( + <CompletionTitle + id={`title-${groupIndex}`} + key={`group-${groupIndex}`} + shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize} + title={group.name} + /> + ); + ++viewIndex; for (const item of group.items) { - eles.push( + items.push( <CompletionItem - key={`item-${index}`} + shown={viewOffset <= viewIndex && viewIndex < viewOffset + viewSize} + key={`item-${itemIndex}`} icon={item.icon} caption={item.caption} url={item.url} - highlight={index === this.props.select} + highlight={itemIndex === this.props.select} + role="menuitem" /> ); - ++index; + ++viewIndex; + ++itemIndex; } - } - - const viewOffset = this.state.viewOffset; - eles = eles.slice(viewOffset, viewOffset + this.props.size); + groups.push( + <div + key={`group-${groupIndex}`} + role="group" + aria-describedby={`title-${groupIndex}`} + > + {title} + <ul>{items}</ul> + </div> + ); + }); - return <ul>{eles}</ul>; + return <div role="menu">{groups}</div>; } } diff --git a/src/console/components/console/CompletionItem.tsx b/src/console/components/console/CompletionItem.tsx index da07bf0..76db5b5 100644 --- a/src/console/components/console/CompletionItem.tsx +++ b/src/console/components/console/CompletionItem.tsx @@ -1,7 +1,11 @@ import React from "react"; import styled from "../Theme"; -const Container = styled.li<{ icon: string; highlight: boolean }>` +const Container = styled.li<{ + shown: boolean; + icon: string; + highlight: boolean; +}>` backgroundimage: ${({ icon }) => "url(" + icon + ")"}; background-color: ${({ highlight, theme }) => highlight @@ -11,6 +15,7 @@ const Container = styled.li<{ icon: string; highlight: boolean }>` highlight ? theme.completionSelectedForeground : theme.completionItemForeground}; + display: ${({ shown }) => (shown ? "display" : "none")}; padding-left: 1.5rem; background-position: 0 center; background-size: contain; @@ -34,16 +39,19 @@ const Description = styled.span` `; interface Props { + shown: boolean; highlight: boolean; caption?: string; url?: string; icon?: string; } -const CompletionItem: React.FC<Props> = ({ highlight, caption, url, icon }) => ( - <Container icon={icon || ""} highlight={highlight}> - <Caption>{caption}</Caption> - <Description>{url}</Description> +const CompletionItem: React.FC<React.HTMLAttributes<HTMLElement> & Props> = ( + props +) => ( + <Container icon={props.icon || ""} {...props}> + <Caption>{props.caption}</Caption> + <Description>{props.url}</Description> </Container> ); diff --git a/src/console/components/console/CompletionTitle.tsx b/src/console/components/console/CompletionTitle.tsx index 55c3c2e..ec2fc8b 100644 --- a/src/console/components/console/CompletionTitle.tsx +++ b/src/console/components/console/CompletionTitle.tsx @@ -1,7 +1,8 @@ import React from "react"; import styled from "../Theme"; -const Li = styled.li` +const Li = styled.li<{ shown: boolean }>` + display: ${({ shown }) => (shown ? "display" : "none")}; background-color: ${({ theme }) => theme.completionTitleBackground}; color: ${({ theme }) => theme.completionTitleForeground}; font-weight: bold; @@ -10,11 +11,12 @@ const Li = styled.li` `; interface Props { + shown: boolean; title: string; } -const CompletionTitle: React.FC<Props> = ({ title }) => { - return <Li>{title}</Li>; -}; +const CompletionTitle: React.FC<React.HTMLAttributes<HTMLElement> & Props> = ( + props +) => <Li {...props}>{props.title}</Li>; export default CompletionTitle; |