Skip to content

Commit

Permalink
[docs] Basic API reference tables (#810)
Browse files Browse the repository at this point in the history
  • Loading branch information
vladmoroz authored Nov 13, 2024
1 parent 56a1fc4 commit ae81e33
Show file tree
Hide file tree
Showing 21 changed files with 383 additions and 96 deletions.
8 changes: 5 additions & 3 deletions docs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import withDocsInfra from '@mui/monorepo/docs/nextConfigDocsInfra.js';
import nextMdx from '@next/mdx';
import rehypePrettyCode from 'rehype-pretty-code';
import rehypeExtractToc from '@stefanprobst/rehype-extract-toc';
import remarkGfm from 'remark-gfm';
import { rehypeDemos } from './src/components/demo/rehypeDemos.mjs';
import { highlighter } from './src/syntax-highlighting/index.mjs';
import { rehypeInlineCode } from './src/syntax-highlighting/rehype-inline-code.mjs';
Expand All @@ -19,18 +20,19 @@ const getHighlighter = () => highlighter;

const withMdx = nextMdx({
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [
rehypeDemos,
rehypeInlineCode,
[
rehypePrettyCode,
{
getHighlighter,
theme: 'base-ui-theme',
bypassInlineCode: true,
grid: false,
theme: 'base-ui',
defaultLang: 'jsx',
},
],
rehypeInlineCode,
rehypeSlug,
rehypeExtractToc,
rehypeQuickNav,
Expand Down
2 changes: 1 addition & 1 deletion docs/src/app/(content)/getMarkdownPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const getMarkdownPage = async (basePath: string, slug: string) => {
rehypePrettyCode,
{
getHighlighter: () => highlighter,
theme: 'base-ui-theme',
theme: 'base-ui',
bypassInlineCode: true,
grid: false,
},
Expand Down
58 changes: 54 additions & 4 deletions docs/src/app/new/(content)/components/dialog/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,60 @@

<Demo path="./UnstyledDialogIntroduction" />

## API reference

Import the component and place its parts the following way.

```jsx title="Anatomy"
import { Dialog } from '@base_ui/react/Dialog';

<Dialog.Root>
<Dialog.Trigger />
<Dialog.Backdrop />
<Dialog.Popup>
<Dialog.Title />
<Dialog.Description />
<Dialog.Close />
</Dialog.Popup>
</Dialog.Root>;
```

### Root

Groups all parts of the dialog. Doesn’t render its own HTML element.

<PropsTable component="Dialog.Root" />

### Trigger

A button that opens the dialog. Renders a `<button>` element.

<PropsTable component="Dialog.Trigger" />

### Backdrop

An overlay displayed beneath the popup. Renders a `<div>` element.

<PropsTable component="Dialog.Backdrop" />

### Popup

A component that groups the dialog contents. Renders a `<div>` element.

<PropsTable component="Dialog.Popup" />

### Title

A heading that labels the dialog. Renders an `<h2>` element.

<PropsTable component="Dialog.Title" />

### Description

A paragraph with additional information about the dialog. Renders a `<p>` element.

<PropsTable component="Dialog.Description" />

## Examples

### State
Expand Down Expand Up @@ -57,7 +111,3 @@ It’s also common to use `onOpenChange` if your app needs to do something when
}}
>
```

### Syntax

The `<Dialog.Trigger>` part renders a native `<button>` element. Don’t take this paragraph too seriously though, I’m just testing the inline syntax highlighting.
4 changes: 4 additions & 0 deletions docs/src/components/Code.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.Code {
margin-left: 0.1em;
margin-right: 0.1em;
}
6 changes: 6 additions & 0 deletions docs/src/components/Code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import clsx from 'clsx';
import * as React from 'react';

export function Code({ className, ...props }: React.ComponentProps<'code'>) {
return <code className={clsx('Code', className)} {...props} />;
}
39 changes: 39 additions & 0 deletions docs/src/components/Popup.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@layer components {
.Popup {
max-width: var(--available-width);
max-height: var(--available-height);
border-radius: 0.375rem;
background-color: var(--color-popup);
overflow: hidden;
box-shadow:
0px 154px 62px 0px rgba(35, 39, 52, 0.01),
0px 87px 52px 0px rgba(35, 39, 52, 0.03),
0px 39px 39px 0px rgba(35, 39, 52, 0.04),
0px 10px 21px 0px rgba(35, 39, 52, 0.05);

outline: 1px solid var(--color-popup-border);
@media (prefers-color-scheme: dark) {
outline-offset: -1px;
}

transform-origin: var(--transform-origin);
transition-property: opacity, transform;
transition-timing-function: cubic-bezier(0.3, 1.065, 0.01, 0.975);
transition-duration: 220ms;

&[data-open] {
opacity: 1;
transform: scale(1);
}

&,
&[data-entering] {
opacity: 0;
transform: scale(0.98);
}

&[data-instant] {
transition-duration: 0s;
}
}
}
6 changes: 6 additions & 0 deletions docs/src/components/Popup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as React from 'react';
import clsx from 'clsx';

export function Popup({ className, ...props }: React.ComponentProps<'div'>) {
return <div className={clsx('Popup', className)} {...props} />;
}
77 changes: 77 additions & 0 deletions docs/src/components/PropsTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import * as React from 'react';
import * as jsxRuntime from 'react/jsx-runtime';
import { evaluate, EvaluateOptions } from '@mdx-js/mdx';
import rehypePrettyCode from 'rehype-pretty-code';
import { highlighter } from 'docs/src/syntax-highlighting';
import { getApiReferenceData } from 'docs/src/app/(content)/components/[slug]/getApiReferenceData';
import { rehypeInlineCode } from 'docs/src/syntax-highlighting/rehype-inline-code.mjs';
import { PropsTablePopover } from './PropsTablePopover';
import * as Table from './Table';

const getHighlighter = () => highlighter;

interface PropsTableProps extends React.ComponentProps<typeof Table.Root> {
component: string;
}

export async function PropsTable({ component, ...props }: PropsTableProps) {
const [data] = await getApiReferenceData([component]);

return (
<Table.Root {...props}>
<Table.Head>
<Table.Row>
<Table.HeaderCell className="w-[172px]">Prop</Table.HeaderCell>
<Table.HeaderCell className="w-full">Type</Table.HeaderCell>
<Table.HeaderCell className="w-[172px]">Default</Table.HeaderCell>
<Table.HeaderCell className="w-[36px]" aria-label="Description" />
</Table.Row>
</Table.Head>
<Table.Body>
{data.props.map(async (prop) => {
// TODO this is because rehypePrettyCode can't parse `<code>`
// written verbatim; I plan to figure out how to get the real markdown source in here.
prop.description = prop.description.replace('<code>', '`').replace('</code>', '`');
const { default: Description } = await evaluate(prop.description, {
...jsxRuntime,
rehypePlugins: [
rehypeInlineCode,
[
rehypePrettyCode,
{
getHighlighter,
grid: false,
theme: 'base-ui',
defaultLang: 'jsx',
},
],
],
} as unknown as EvaluateOptions);

return (
<Table.Row key={prop.name}>
<Table.HeaderCell scope="row">
<code>{prop.name}</code>
</Table.HeaderCell>
<Table.Cell>
<code className="text-violet">{prop.type.name}</code>
</Table.Cell>
<Table.Cell>
{prop.defaultValue ? (
<code className="text-blue">{prop.defaultValue}</code>
) : (
<code className="text-pale">undefined</code>
)}
</Table.Cell>
<Table.Cell>
<PropsTablePopover>
<Description />
</PropsTablePopover>
</Table.Cell>
</Table.Row>
);
})}
</Table.Body>
</Table.Root>
);
}
51 changes: 51 additions & 0 deletions docs/src/components/PropsTablePopover.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';
import { Popover } from '@base_ui/react/Popover';
import * as React from 'react';
import { ToolbarButton } from './ToolbarButton';
import { Popup } from './Popup';

interface PropsTablePopoverProps {
children: React.ReactElement<any>;
}

export function PropsTablePopover({ children }: PropsTablePopoverProps) {
return (
<Popover.Root>
<Popover.Trigger
render={
// TODO: rework this into an IconButton or a generic ghost button component
<ToolbarButton>
<span className="-mx-0.5 flex h-4 w-4 items-center justify-center">
<svg
width="14"
height="14"
viewBox="0 0 14 14"
fill="currentcolor"
xmlns="http://www.w3.org/2000/svg"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M7 0.5C3.41797 0.5 0.5 3.41797 0.5 7C0.5 10.582 3.41797 13.5 7 13.5C10.582 13.5 13.5 10.582 13.5 7C13.5 3.41797 10.582 0.5 7 0.5ZM7 1.5C10.043 1.5 12.5 3.95703 12.5 7C12.5 10.043 10.043 12.5 7 12.5C3.95703 12.5 1.5 10.043 1.5 7C1.5 3.95703 3.95703 1.5 7 1.5ZM6.5 3.5V4.5H7.5V3.5H6.5ZM6.5 6.5V9.5H5.5V10.5H6.5H7.5H8.5V9.5H7.5V6.5V5.5H6.5H5.5V6.5H6.5Z"
/>
</svg>
</span>
</ToolbarButton>
}
/>
<Popover.Positioner
alignment="start"
side="left"
alignmentOffset={4}
sideOffset={4}
collisionPadding={16}
>
<Popover.Popup render={<Popup className="p-4 text-sm" />}>
<div className="max-w-[300px]">
<Popover.Description render={children} />
</div>
</Popover.Popup>
</Popover.Positioner>
</Popover.Root>
);
}
35 changes: 35 additions & 0 deletions docs/src/components/Table.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@layer components {
.TableRoot {
@apply text-sm;
table-layout: fixed;
width: 100%;
}

.TableHeaderCell {
text-align: initial;
font-weight: normal;

&[scope='col'],
&[scope='colgroup'] {
font-weight: 500;
}
}

.TableCell,
.TableHeaderCell {
padding-top: 0.625rem;
padding-bottom: 0.625rem;
padding-left: 1rem;
padding-right: 1rem;

/* Not `border` because Safari renders transparent borders with glitches */
box-shadow: 0 1px var(--color-border);

&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
}
27 changes: 27 additions & 0 deletions docs/src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as React from 'react';

import clsx from 'clsx';

export function Root({ className, ...props }: React.ComponentProps<'table'>) {
return <table className={clsx('TableRoot', className)} {...props} />;
}

export function Head({ className, ...props }: React.ComponentProps<'thead'>) {
return <thead className={clsx('TableHead', className)} {...props} />;
}

export function Body({ className, ...props }: React.ComponentProps<'tbody'>) {
return <tbody className={clsx('TableBody', className)} {...props} />;
}

export function Row({ className, ...props }: React.ComponentProps<'tr'>) {
return <tr className={clsx('TableRow', className)} {...props} />;
}

export function HeaderCell({ className, ...props }: React.ComponentProps<'th'>) {
return <th scope="col" className={clsx('TableHeaderCell', className)} {...props} />;
}

export function Cell({ className, ...props }: React.ComponentProps<'td'>) {
return <td className={clsx('TableCell', className)} {...props} />;
}
Loading

0 comments on commit ae81e33

Please sign in to comment.