Skip to content

Latest commit

 

History

History
340 lines (225 loc) · 12.5 KB

writing-documentation.md

File metadata and controls

340 lines (225 loc) · 12.5 KB

Writing documentation

Code for the Elastic UI documentation site can be found in the packages/website directory. The site is built with Docusaurus.

Files and folders

Documentation is written in Markdown.

Files are stored in the docs folder and document files use MDX, thus the .mdx file extension. This format allows writing React code alongside Markdown. It's also possible to import React code from .tsx files, which is useful for more complex examples.

Check out the MDX syntax documentation here.

Tip

For formatting content always prefer using Markdown over React

The folder structure matches the navigation and content structure, similar to common static site builders like Jekyll. For instance, for editing the Components / Containers / Accordion page, the content will be found in the docs/components/containers/accordion.mdx file.

Files and folder names must use kebab-case, unlike the EUI convention to use snake_case. This makes it easier to keep URLs consistent without having to override Docusaurus defaults in the front matter.

Custom components available

There are a few React components that can be used in .mdx files without being imported. They are part of the MDX scope. Some of them, documented below, are:

Front matter

The front matter is a section at the top of a Markdown file that contains metadata about the document. It's enclosed in triple dashes (---) and written in YAML format.

A few important aspects of the document can be configured here:

  • id (unique to the document)
  • slug (to customize the URL)
  • sidebar_label
  • sidebar_position
  • title (if different from the h1)
  • description

Check the Docusaurus docs for a full list of fields.

Collapsible sidebar items

To create a collapsible item in the sidebar, just add a folder in the file system containing one or more .mdx files. In Docusaurus these are called category items, and they can be configured by adding a _category_.yml file to the folder. By default the category label will be the folder name, this can be changed with the label field in the _category_.yml file. Other useful fields are position and collapsed.

It's possible to make a collapsible item be a document as well, though this is not recommended. Set the link field to have type: doc and id: <DOCUMENT_ID>, with the id from the document it should point to. If the id is not explicitly set in the document file's front matter, it's the relative path starting from the docs folder, without the file extension, e.g. docs/components/containers/accordion.

Read more about category metadata and file structure in the Docusaurus docs.

Warning

Nesting items in the sidebar should be avoided when possible, deeply nested items can make the menu harder to use

Documenting components

All component pages should follow the following architecture:

  • Intro
  • Component: a bare-bones example of the component in its default form
  • Usage (optional): examples of different states and use-cases
  • Guidelines (optional): e.g. dos and don'ts
  • Props

Partials

A document can be split into different files when content is too long, for easier editing.

Markdown files prefixed with an underscore will be ignored when generating the sidebar navigation. These hidden files can be imported and rendered in the main document.

For example, the document for the Modal page is containers/modal/index.mdx:

containers/
  modal/
    _guidelines.mdx
    _usage.mdx
    index.mdx

Usage and Guidelines sections have their own file that can be imported:

import Usage from './_usage.mdx';

## Usage

<Usage />

## Guidelines

import Guidelines from './_guidelines.mdx';

<Guidelines />

Read more about importing Markdown files in the Docusaurus docs.

Writing content

As previously mentioned, using Markdown is highly encouraged. It makes it easier for anybody to contribute to the documentation.

During the build step of the website, elements with a counterpart in EUI will be accordingly replaced, e.g. a link with EuiLink, a inline code block with EuiCode, etc.

Headings

Headings in Markdown are created with a hash symbol in a new line. The number of hashes will determine the heading level, # for 1, ## for 2, etc.

Important

Do not use heading levels for styling, use them to properly structure the document hierarchically

Links

Markdown is the recommended syntax for creating links. Docusaurus will take care of rendering it correctly.

[This is a link](https://example.com)

To link between documents, use relative file paths, including the file extension, e.g. [EuiPanel](../containers/panel/index.mdx)

Read more about Markdown links in the Docusaurus docs.

Admonitions

The syntax for creating admonitions is wrapping a paragraph in three colons, e.g. :::. The type of admonition and title can be defined after the first three colons. This will render EuiCallOut.

:::info This is the title

Here's some content

:::

There are 5 types of admonitions supported, with icon and color respectively.

  • note
  • tip
  • info
  • accessibility
  • warning
  • danger

Code blocks

A code block or code snippet can be created by wrapping text in backticks, e.g. `code`.

For a simple one-liner, single backticks are enough. To create a multiline snippet or code block, use three backticks. For syntax highlighting, the language name can be added right after the first three backticks.

```html  
<span>Hello World</span>  
```

Code blocks can be used to generate live demos, where a React component that is exported in the snippet will be rendered on the page. To do that, append the word "interactive" after the language name, usually tsx.

```tsx interactive  
export default () => (
  <div>Hello World</div>
)
```

More advanced usage with the Demo component can be found right below.

Live demos

When plain code blocks are not enough, the Demo component can be used. It's available without being imported so it can be used straightaway.

Note

They're called "live" demos because the source code can be edited right there on the page and the preview will update

The benefits of the Demo component over plain code blocks are mainly:

  • that the scope of the demo can be extended with imports from the document, and already exposes all React and EUI exports, and
  • it's possible to add a wrapper component for the preview and adjust the padding

Demo props

  • children - A tsx code block
  • scope - An object to extend the scope of the demo with additional properties
  • isSourceOpen - Whether the source code editor is open by default (false)
  • previewPadding - Adjust the padding of the preview
  • previewWrapper - A wrapper component for the preview

Check the source code here.

Usage example

Tip

Remember to wrap imports in ```mdx-code-block`

```mdx-code-block
import previewWrapper from './preview_wrapper.tsx';
```

<Demo previewWrapper={previewWrapper}>
```tsx
import React, { useState } from 'react';
import { EuiButton } from '@elastic/eui';

export default () => {
  const [counter, setCounter] = useState<number>(0);
  const updateCounter = () => setCounter(x => x + 1);

  return (
    <EuiButton onClick={updateCounter}>
      Clicked {counter} times
    </EuiButton>
  )
}
```
</Demo>

Full-screen example

The convention for creating full-screen examples, where the entire browser screen is needed to demo a certain component combination or pattern, is to create a Storybook story and link to it from the docs.

There's a StorybookLink component that makes this easy and consistent, by handling the URL appropriately depending on the environment.

It's expected for the link to be preceded by a heading and a short description.

The story's id can be found in the URL. It's the part after /index.html?path=/story/.

## A heading for the example

Here it's explained what the examples represents.

```mdx-code-block
import { StorybookLink } from '@site/src/components';
```

<StorybookLink id="<STORY_ID>" />

Tables

The preferred way to display content in tables is by leveraging EuiBasicTable and not Markdown tables.

Just like with partials, the code for the table can be separated in its own file and imported into the MDX document where it'll be displayed. For example:

components/
  my-component/
    nice_table.tsx
    index.mdx

nice_table.tsx can export a component that renders EuiBasicTable:

import { css } from '@emotion/react';

import {
  EuiBasicTable,
  EuiBasicTableColumn,
  // ...
} from '@elastic/eui';

export const NiceTable = () => {
  const items = [
    // ...
  ];
  const columns = [
    // ...
  ];

  return <EuiBasicTable items={items} columns={columns} tableLayout="auto" />;
}

And then in index.mdx the table can be rendered:

## A heading for the table

```mdx-code-block
import { NiceTable } from './nice_table';
```

<NiceTable />

Dos and Don'ts

For dos and don'ts sections there's a Guideline component with the appropriate styles built-in. To display one next to the other, a EuiFlexGroup can be used:

<EuiFlexGroup gutterSize="m">
  <Guideline type="do" text="Lorem ipsum dolor sit amet consectetur adipiscing elit.">
    <div>Yep content</div>
  </Guideline>
  <Guideline type="dont" text="Quisque faucibus ex sapien vitae pellentesque sem placerat.">
    <div>Nope content</div>
  </Guideline>
</EuiFlexGroup>

Guideline props

  • children - The content inside, can be other components
  • type - do, dont or default
  • text - The actual guideline text
  • panelPadding (optional) - To adjust the padding of the panel
  • panelStyle (optional) - To further customize the panel styles

Figma embed

It's possible to embed a Figma file right into a page. The FigmaEmbed component accepts a url from a Figma file and a title:

<FigmaEmbed url="https://www.figma.com/file/Uo8i…DX-0" title="Title of the embed" />

Props table

The Props table should always go last in a document. There is a PropTable component available without being imported that will take the props information from the @elastic/eui-docgen package in the definition prop.

If more than one table is needed because the component has many exports, place one table after the other. It should look like this:

## Props

```mdx-code-block
import docgen from '@elastic/eui-docgen/dist/components/page';
```

<PropTable definition={docgen.EuiPage} />

<PropTable definition={docgen.EuiPageBody} />

<PropTable definition={docgen.EuiPageSidebar} />

To customize the table PropTable also takes a headingLevel prop (h1–h6) and a showTitle boolean.