mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-10 23:02:56 +02:00
docs: new APITable comp to render large tables (#5891)
This commit is contained in:
parent
7a07963c42
commit
ecce576bbc
14 changed files with 277 additions and 138 deletions
93
website/src/components/APITable/index.tsx
Normal file
93
website/src/components/APITable/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
22
website/src/components/APITable/styles.module.css
Normal file
22
website/src/components/APITable/styles.module.css
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue