Skip to contentAsheeUIAsheeUI

DocsLayout

The documentation composition, a navigation column, an article, and an optional table of contents beside it.

DocsLayout is the arrangement a documentation page is built in: the site's navigation column, the article, and, when the article is long enough to need one, a table of contents. It composes the application shell and the split layout instead of restating them, so the sticky navigation, the stacked narrow screen and the responsive columns are the behaviour those primitives already provide.

What it adds is the page's structure: a main the skip link leads to, a named navigation column, a named contents region, and the skip link itself as the first focusable element.

Usage

import {
  DocsLayout,
  Link,
  Navbar,
  Sidebar,
  Typography,
  VStack,
} from "@asheeui/web";

<DocsLayout
  header={<Navbar brand="AsheeUI" links={links} />}
  navigation={<Sidebar items={sections} activeKey="layout" />}
  toc={
    <VStack gap="xs">
      <Link href="#grid" variant="muted" size="sm">
        The grid
      </Link>
    </VStack>
  }
>
  <Typography role="display">Layouts</Typography>
  <Typography role="body-md">A page is composed from the layout layer.</Typography>
</DocsLayout>;

navigation is the only required slot. children is the article, header and footer sit around everything, and toc decides whether the page has two columns or three.

Two columns, or three

toc is what decides. Left out, the page is a navigation column and the article:

A changelog, a migration note or a reference page that is read from top to bottom rarely needs an outline of itself, and stating no toc is how the page says so. Supplied, the contents take a third column from the xl breakpoint (1280 pixels), 16rem wide and placed after the article; below it they are hidden, because they repeat headings that are still in the article. That is why the same page is complete at every width without a drawer, a disclosure or a second copy of the article's outline.

stickyToc keeps the contents in view while the article scrolls, top: 0, position: sticky, from the same xl breakpoint. Turn it off for a contents list shorter than the viewport that reads better in the flow. stickyNavigation does the same for the navigation column from lg: it is passed through to the shell's stickySidebar, so a documentation page whose navigation is a short list can let the column leave with the article rather than pinning it.

A documentation page leads with navigation, so the composition renders a skip link as its first focusable element: an anchor to the article's identifier, visually hidden until it is focused. The article is a main with that identifier and tabIndex={-1}, so following the link moves focus into the content rather than only scrolling to it. mainId names the identifier, main-content by default, and skipLink={false} removes the link for a page whose navigation is already short enough to walk through.

Both region names are configuration rather than markup, and so is the wording of the link:

import { AsheeUIProvider } from "@asheeui/web";

<AsheeUIProvider
  config={{
    components: {
      docslayout: {
        navigationLabel: "Guides",
        tocLabel: "Sections",
        skipLinkLabel: "Skip to the article",
      },
    },
  }}
>
  <App />
</AsheeUIProvider>;

Props

Seven options are registered by the component, so each resolves from the instance, then from components.docslayout, then from the registration: navigationLabel Documentation, tocLabel On this page, navigationWidth md, stickyNavigation true, stickyToc true, skipLink true and skipLinkLabel Skip to content. navigationWidth takes the same sm/md/lg column widths SidebarLayout does, 14rem, 16rem and 20rem from lg. mainId is instance-only and defaults to main-content: an identifier belongs to the page, and a page with more than one composition on it gives each one its own. The four slots and as are instance-only too.

Accessibility

  • The article is the main landmark, carrying mainId and tabIndex={-1}, so the skip link both scrolls to it and moves the reader into it.
  • The skip link is the first focusable element of the page. It is visually hidden until focused, so it does not appear to a pointer reader, and it is the first thing Tab reaches.
  • The navigation column is a complementary landmark named by navigationLabel, and the contents are a second one named by tocLabel, rendered only when toc is supplied, so a landmark list names both regions rather than offering two asides of which one is unnamed.
  • The shell supplies no heading at all. The article's first heading is the page's <h1>, and the contents list you pass is markup rather than an outline, so give its visible title the treatment the rest of the page uses for a label rather than a second heading level.
  • Below xl the contents column is hidden, not moved: nothing in it is reachable at that width, which is the point, because the article's own headings stay where they were written.

The widths and the spacing between the columns are the Layout and spacing vocabulary; which shell a product should start from is the argument in Page compositions.

Native

@asheeui/native ships the same contract as its own DocsLayout: one column, with the navigation, the article and the contents stacked in the order the web's narrow layout gives them, and the whole screen a scroller because three stacked regions do not fit a phone at once. The platform has no landmark vocabulary, so navigationLabel and tocLabel become the titles that head the two sections, and navigationWidth, stickyNavigation, skipLink and stickyToc resolve through the contract without changing the rendering: the platform stacks and scrolls the whole screen, so there is nothing to pin. See React Native.