fix: make samples accessible by keyboard (#1401)

* fix: make samples accessible by keyboard

* chore: set outline-width and padding to collapser
This commit is contained in:
Anna Stasiuk 2020-10-13 14:56:03 +03:00 committed by GitHub
parent 0c782ec51f
commit 146b38c9d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 45 additions and 18 deletions

View File

@ -34,11 +34,11 @@ class Json extends React.PureComponent<JsonProps> {
<button onClick={this.collapseAll}> Collapse all </button>
</SampleControls>
<OptionsContext.Consumer>
{options => (
{(options) => (
<PrismDiv
className={this.props.className}
// tslint:disable-next-line
ref={node => (this.node = node!)}
ref={(node) => (this.node = node!)}
dangerouslySetInnerHTML={{
__html: jsonToHTML(this.props.data, options.jsonSampleExpandLevel),
}}
@ -65,9 +65,8 @@ class Json extends React.PureComponent<JsonProps> {
}
};
clickListener = (event: MouseEvent) => {
collapseElement = (target: HTMLElement) => {
let collapsed;
const target = event.target as HTMLElement;
if (target.className === 'collapser') {
collapsed = target.parentElement!.getElementsByClassName('collapsible')[0];
if (collapsed.parentElement.classList.contains('collapsed')) {
@ -78,12 +77,24 @@ class Json extends React.PureComponent<JsonProps> {
}
};
clickListener = (event: MouseEvent) => {
this.collapseElement(event.target as HTMLElement);
};
focusListener = (event: KeyboardEvent) => {
if (event.key === 'Enter') {
this.collapseElement(event.target as HTMLElement);
}
};
componentDidMount() {
this.node!.addEventListener('click', this.clickListener);
this.node!.addEventListener('focus', this.focusListener);
}
componentWillUnmount() {
this.node!.removeEventListener('click', this.clickListener);
this.node!.removeEventListener('focus', this.focusListener);
}
}

View File

@ -1,12 +1,13 @@
import { css } from '../../styled-components';
export const jsonStyles = css`
.redoc-json > .collapser {
.redoc-json code > .collapser {
display: none;
pointer-events: none;
}
font-family: ${props => props.theme.typography.code.fontFamily};
font-size: ${props => props.theme.typography.code.fontSize};
font-family: ${(props) => props.theme.typography.code.fontFamily};
font-size: ${(props) => props.theme.typography.code.fontSize};
white-space: ${({ theme }) => (theme.typography.code.wrap ? 'pre-wrap' : 'pre')};
contain: content;
@ -47,8 +48,32 @@ export const jsonStyles = css`
}
.collapser {
background-color: transparent;
border: 0;
color: #fff;
font-family: ${(props) => props.theme.typography.code.fontFamily};
font-size: ${(props) => props.theme.typography.code.fontSize};
padding-right: 6px;
padding-left: 6px;
padding-top: 0;
padding-bottom: 0;
display: flex;
align-items: center;
justify-content: center;
width: 15px;
height: 15px;
position: absolute;
top: 4px;
left: -1.5em;
cursor: default;
user-select: none;
-webkit-user-select: none;
padding: 2px;
&:focus {
outline-color: #fff;
outline-style: dotted;
outline-width: 1px;
}
}
ul {
@ -83,13 +108,4 @@ export const jsonStyles = css`
.collapsed > .ellipsis {
display: inherit;
}
.collapser {
position: absolute;
top: 1px;
left: -1.5em;
cursor: default;
user-select: none;
-webkit-user-select: none;
}
`;

View File

@ -73,7 +73,7 @@ function valueToHTML(value, maxExpandLevel: number) {
function arrayToHTML(json, maxExpandLevel: number) {
const collapsed = level > maxExpandLevel ? 'collapsed' : '';
let output = `<div class="collapser"></div>${punctuation(
let output = `<button class="collapser"></button>${punctuation(
'[',
)}<span class="ellipsis"></span><ul class="array collapsible">`;
let hasContents = false;
@ -98,7 +98,7 @@ function objectToHTML(json, maxExpandLevel: number) {
const collapsed = level > maxExpandLevel ? 'collapsed' : '';
const keys = Object.keys(json);
const length = keys.length;
let output = `<div class="collapser"></div>${punctuation(
let output = `<button class="collapser"></button>${punctuation(
'{',
)}<span class="ellipsis"></span><ul class="obj collapsible">`;
let hasContents = false;