docs: new APITable comp to render large tables (#5891)

This commit is contained in:
Joshua Chen 2021-11-10 18:38:23 +08:00 committed by GitHub
parent 7a07963c42
commit ecce576bbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 277 additions and 138 deletions

View file

@ -0,0 +1,93 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {
Children,
ComponentProps,
ReactElement,
ReactNode,
isValidElement,
useRef,
useEffect,
forwardRef,
} from 'react';
import {useHistory} from '@docusaurus/router';
import styles from './styles.module.css';
interface Props {
readonly children: ReactElement<ComponentProps<'table'>>;
readonly name?: string;
}
// ReactNode equivalent of HTMLElement#innerText
function getText(node: ReactElement): string {
let curNode: ReactNode = node;
while (isValidElement(curNode)) {
[curNode] = Children.toArray(curNode.props.children);
}
return curNode as string;
}
const APITableRow = forwardRef(
(
{
name,
children,
}: {name: string | undefined; children: ReactElement<ComponentProps<'tr'>>},
ref: React.RefObject<HTMLTableRowElement>,
) => {
const entryName = getText(children);
const anchor = name ? `#${name}-${entryName}` : `#${entryName}`;
const history = useHistory();
return (
<tr
id={entryName}
tabIndex={0}
ref={history.location.hash === anchor ? ref : undefined}
onClick={() => {
history.push(anchor);
}}
onKeyDown={(e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
history.push(anchor);
}
}}>
{children.props.children}
</tr>
);
},
);
/*
* Note: this is not a quite robust component since it makes a lot of
* assumptions about how the children looks; however, those assumptions
* should be generally correct in the MDX context.
*/
export default function APITable({children, name}: Props): JSX.Element {
const [thead, tbody] = Children.toArray(
children.props.children,
) as ReactElement[];
const highlightedRow = useRef<HTMLTableRowElement>(null);
useEffect(() => {
highlightedRow.current?.focus();
}, [highlightedRow]);
const rows = Children.map(
tbody.props.children,
(row: ReactElement<ComponentProps<'tr'>>) => (
<APITableRow name={name} ref={highlightedRow}>
{row}
</APITableRow>
),
);
return (
<table className={styles.apiTable}>
{thead}
<tbody>{rows}</tbody>
</table>
);
}

View file

@ -0,0 +1,22 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.apiTable {
font-size: small;
}
.apiTable tbody tr {
transition: box-shadow 0.2s;
}
.apiTable tbody tr:focus,
.apiTable tbody tr:hover {
outline: none;
box-shadow: 0px 0px 7px 0px inset var(--ifm-color-warning);
cursor: pointer;
transition: box-shadow 0.2s;
}