Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions fern/products/docs/pages/customization/css-selectors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,62 @@ Mobile menu toggle button.
</Accordion>
</AccordionGroup>

## Tab menu components

Selectors for header [tab menus](/learn/docs/configuration/tabs#tab-menus). These classes apply only to the header menu. The sidebar selector that replaces a tab menu on mobile and with sidebar tabs uses the `.fern-variant-selector` classes.

| Selector | Element |
| --- | --- |
| `.fern-tab-menu` | Wrapper for one menu tab. Has `data-tab-slug` (the menu tab's slug) and `data-state` (`open` or `closed`). Also has `.fern-tab-menu-click-only` when [`layout.tab-menu.interact-on-click-only`](/learn/docs/configuration/site-level-settings#layouttab-menuinteract-on-click-only) is `true`. |
| `.fern-tab-menu-trigger` | Header tab button. Has `data-state` (`active` or `inactive`) and `aria-expanded`. |
| `.fern-tab-menu-chevron` | Chevron on the tab button |
| `.fern-tab-menu-panel` | Positioning and fade layer. Has `data-state`. |
| `.fern-tab-menu-card` | Floating card. Also has `.fern-dropdown`. |
| `.fern-tab-menu-scroll-area`, `.fern-tab-menu-scroll` | Scroll area root and its viewport |
| `.fern-tab-menu-columns`, `.fern-tab-menu-column` | Column container and each column |
| `.fern-tab-menu-group-header` | Group header |
| `.fern-tab-menu-header-spacer` | Spacer aligning columns without a group header |
| `.fern-tab-menu-item` | Tab entry. Has `data-state` (`checked` or `unchecked`). |
| `.fern-tab-menu-link` | Link entry |
| `.fern-tab-menu-item-text` | Wrapper for an entry's title and subtitle |
| `.fern-tab-menu-item-title`, `.fern-tab-menu-item-subtitle` | Entry title and subtitle |
| `.fern-tab-menu-item-check` | Checkmark on the current entry |

The menu's default styles read CSS custom properties, so setting a property on `:root` or a `.fern-tab-menu` wrapper restyles the menu without overriding its rules. The default styles sit in `@layer components`, so unlayered custom CSS overrides them regardless of specificity.

| Property | Default |
| --- | --- |
| `--fern-tab-menu-offset` | `0.5rem` |
| `--fern-tab-menu-padding` | `0.5rem` |
| `--fern-tab-menu-radius` | `1rem` |
| `--fern-tab-menu-shadow` | `0 16px 40px -12px rgb(0 0 0 / 18%), 0 2px 6px rgb(0 0 0 / 4%)` |
| `--fern-tab-menu-max-height` | `min(75vh, 40rem)` |
| `--fern-tab-menu-scrollbar-inset` | `0.75rem 0.375rem` |
| `--fern-tab-menu-column-min-width` | `12rem` |
| `--fern-tab-menu-column-max-width` | `17rem` |
| `--fern-tab-menu-column-gap` | `0.5rem` |
| `--fern-tab-menu-item-gap` | `0.25rem` |
| `--fern-tab-menu-item-padding` | `0.5rem 0.75rem` |
| `--fern-tab-menu-item-radius` | `0.5rem` |
| `--fern-tab-menu-item-hover-background` | `var(--accent-a3)` |
| `--fern-tab-menu-item-hover-color` | `var(--accent-a11)` |
| `--fern-tab-menu-item-selected-background` | `var(--accent-a3)` |
| `--fern-tab-menu-item-selected-color` | `var(--accent-a12)` |
| `--fern-tab-menu-group-header-color` | `var(--grayscale-a10)` |
| `--fern-tab-menu-item-title-font-size` | `0.875rem` |
| `--fern-tab-menu-item-subtitle-font-size` | `0.75rem` |

```css Example: Restyle tab menus
:root {
--fern-tab-menu-radius: 0.5rem;
--fern-tab-menu-item-selected-background: var(--accent-a4);
}

.fern-tab-menu[data-tab-slug="products"] .fern-tab-menu-item-title {
font-weight: 600;
}
```

## Sidebar components

Selectors for sidebar navigation and tabs.
Expand Down Expand Up @@ -3164,6 +3220,24 @@ The sections of this page document the most commonly customized selectors in det
<tr><td><code>.fern-step</code></td><td>Class</td></tr>
<tr><td><code>.fern-steps</code></td><td>Class</td></tr>
<tr><td><code>.fern-stream</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-card</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-chevron</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-click-only</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-column</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-columns</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-group-header</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-header-spacer</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-item</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-item-check</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-item-subtitle</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-item-text</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-item-title</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-link</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-panel</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-scroll</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-scroll-area</code></td><td>Class</td></tr>
<tr><td><code>.fern-tab-menu-trigger</code></td><td>Class</td></tr>
<tr><td><code>.fern-table</code></td><td>Class</td></tr>
<tr><td><code>.fern-table-collapse</code></td><td>Class</td></tr>
<tr><td><code>.fern-table-pagination</code></td><td>Class</td></tr>
Expand Down
11 changes: 11 additions & 0 deletions fern/products/docs/pages/navigation/site-level-settings.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ layout:
sidebar-width: 336px
searchbar-placement: header
tabs-placement: header
tab-menu:
default-column-height: 4
interact-on-click-only: true
switcher-placement: sidebar
content-alignment: left
hide-nav-links: true
Expand Down Expand Up @@ -648,6 +651,14 @@ layout:
<Note>This setting is ignored when `disable-header` is set to true.</Note>
</ParamField>

<ParamField path="layout.tab-menu.default-column-height" type="integer | 'no-limit'" required={false} toc={true}>
Maximum number of entries per column in every header [tab menu](/learn/docs/configuration/tabs#tab-menus) that doesn't set its own `tab-menu-column-height`. `no-limit` keeps a single column. When neither is set, each menu group gets one column with no height limit.
</ParamField>

<ParamField path="layout.tab-menu.interact-on-click-only" type="boolean" required={false} default="false" toc={true}>
When `true`, header [tab menus](/learn/docs/configuration/tabs#tab-menus) open and close only when the tab is selected, not on hover, and have no open animation. By default, they open on hover and close when the pointer leaves the tab and menu.
</ParamField>

<ParamField path="layout.switcher-placement" type="string" required={false} default="header" toc={true}>
Set the placement of the product and version switchers. Can be one of `header` or `sidebar`.

Expand Down
161 changes: 161 additions & 0 deletions fern/products/docs/pages/navigation/tabs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ max-toc-depth: 3

Tabs split a product or version into parallel bodies of content, each with its own sidebar. Tab variants give a single tab more than one version of its content, such as REST versus GraphQL or beginner versus advanced.

With tabs in the header, a [tab menu](#tab-menus) groups several tabs under one header tab, such as a product switcher.

Two tabs make sense when the content is unrelated, like guides and an API Reference. Variants of one tab make sense when it covers the same ground for a different reader.

## Tabs
Expand Down Expand Up @@ -109,6 +111,14 @@ theme:
External URL. When set, clicking the tab redirects to this URL. Tabs with `href` must not include `layout` or `variants`.
</ParamField>

<ParamField path="tab-menu" type="list" toc={true}>
Turns the tab into a [tab menu](#tab-menus) of other tabs, groups, and links. A tab with a `tab-menu` has no `layout` or `variants` of its own.
</ParamField>

<ParamField path="tab-menu-column-height" type="integer | 'no-limit'" toc={true}>
Maximum number of entries per column in this tab's menu. `no-limit` keeps a single column. Overrides [`layout.tab-menu.default-column-height`](/learn/docs/configuration/site-level-settings#layouttab-menudefault-column-height). Only applies to tabs with a `tab-menu`.
</ParamField>

<ParamField path="target" type="string" toc={true}>
Where the link opens. One of `_blank`, `_self`, `_parent`, or `_top`.
</ParamField>
Expand Down Expand Up @@ -236,6 +246,37 @@ navigation:
</video>
</Frame>

### Grouped variants

A `variants` list can also hold `group` entries and `link` entries. A `group` has a header and an `items` list of variants and links. A `link` adds an external URL to the selector. When the list has groups or links, the sidebar selector shows every entry in one stacked list under its group header.

```yaml title="docs.yml"
navigation:
- tab: sdks
variants:
- group: Server SDKs
items:
- title: Python
default: true
layout:
- page: Quickstart
path: ./pages/python/quickstart.mdx
- title: TypeScript
layout:
- page: Quickstart
path: ./pages/typescript/quickstart.mdx
- group: Mobile SDKs
items:
- title: Swift
layout:
- page: Quickstart
path: ./pages/swift/quickstart.mdx
- link: Community SDKs
href: https://github.com/example/community-sdks
```

Link entries take `link` (display text), `href`, and optional `icon` and `target`.

### Variant properties

<ParamField path="title" type="string" required={true} toc={true}>
Expand Down Expand Up @@ -281,3 +322,123 @@ navigation:
<ParamField path="feature-flag" type="string | object" toc={true}>
Conditional display configuration
</ParamField>

## Tab menus

A tab menu turns a header tab into a dropdown that lists other tabs, grouped into columns, along with external links. Use it to build a product switcher in the header instead of a long row of tabs. Tab menus require [tabs in the header](#tabs-placement-and-styling). With tabs in the sidebar, the menu's tabs show in a selector at the top of the sidebar instead.

To configure a tab menu:

- Declare the menu tab under `tabs` with a `tab-menu` list. Each entry is a tab, a `group` of tabs and links, or a link.
- Declare each tab in the menu only inside its menu entry, not under `tabs`.
- In `navigation`, add `- tab:` for the menu tab with no `layout` or `variants`. Its position sets where the menu sits in the header.
- In `navigation`, give each tab in the menu its own `- tab:` entry with a `layout`, or with `variants` to show a selector at the top of that tab's sidebar.

```yaml title="docs.yml"
layout:
tabs-placement: header

tabs:
products:
display-name: Products
tab-menu-column-height: 2
tab-menu:
- group: Platform
tabs:
- tab: agents
display-name: Agents
subtitle: Build AI agents
icon: fa-solid fa-robot
- tab: studio
display-name: Studio
- link: Status
href: https://status.example.com
guides:
display-name: Guides

navigation:
- tab: products # Menu tab: no layout or variants
- tab: agents
variants: # Selector at the top of the Agents sidebar
- title: Python
default: true
layout:
- page: Quickstart
path: ./pages/agents/python.mdx
- title: TypeScript
layout:
- page: Quickstart
path: ./pages/agents/typescript.mdx
- tab: studio
layout:
- page: Overview
path: ./pages/studio/overview.mdx
- tab: guides
layout:
- page: Getting started
path: ./pages/guides/getting-started.mdx
```

URLs for tabs in a menu nest under the menu tab, for example `/products/agents/python/quickstart`. Selecting a tab with variants opens its `default: true` variant, or the first variant.

Each `group` starts a new column, and ungrouped entries share one column. A column continues into a new one after the number of entries set by the tab's [`tab-menu-column-height`](#tab-menu-column-height), or the site-wide [`layout.tab-menu.default-column-height`](/learn/docs/configuration/site-level-settings#layouttab-menudefault-column-height). Menus open on hover by default. Set [`layout.tab-menu.interact-on-click-only`](/learn/docs/configuration/site-level-settings#layouttab-menuinteract-on-click-only) to `true` to open and close them only when the tab is selected, with no animation. To restyle menus, use the [tab menu CSS selectors](/learn/docs/customization/css-selectors-reference#tab-menu-components).

### Tab menu entry properties

Tabs in a `tab-menu`, directly or inside a `group`, accept these properties. The `tab` value is the ID that the tab's `- tab:` entry in `navigation` uses.

<ParamField path="tab-menu[].tab" type="string" required={true} toc={true}>
ID of the tab. Must match a `- tab:` entry in `navigation`.
</ParamField>

<ParamField path="tab-menu[].display-name" type="string" required={true} toc={true}>
Name shown in the menu
</ParamField>

<ParamField path="tab-menu[].subtitle" type="string" toc={true}>
Text displayed below the name
</ParamField>

<ParamField path="tab-menu[].icon" type="string" toc={true}>
<Markdown src="/products/docs/snippets/icons.mdx" />
</ParamField>

<ParamField path="tab-menu[].slug" type="string" toc={true}>
Custom URL slug for the tab
</ParamField>

<ParamField path="tab-menu[].skip-slug" type="boolean" toc={true}>
Exclude the tab slug from URLs
</ParamField>

<ParamField path="tab-menu[].hidden" type="boolean" toc={true}>
Hide the tab from the menu
</ParamField>

<ParamField path="tab-menu[].default" type="boolean" toc={true}>
When true, this tab displays by default for the menu tab. If not specified, the first tab is used.
</ParamField>

<ParamField path="tab-menu[].viewers" type="string | list" toc={true}>
Role-based access control for the tab
</ParamField>

<ParamField path="tab-menu[].feature-flag" type="string | object" toc={true}>
Conditional display configuration
</ParamField>

A `group` entry takes `group` (the column header) and a `tabs` list of tab and link entries. A link entry takes `link` (display text), `href`, and optional `icon` and `target`.

<llms-only>
### Tab menu errors

`fern check` reports these errors for tab menus:

- A tab in a `tab-menu` has no `- tab:` entry in `navigation`, or its entry has neither `layout` nor `variants`.
- A tab is listed in more than one `tab-menu`, or is both in a `tab-menu` and under `tabs`.
- The menu tab's `navigation` entry has its own `layout` or `variants`. Put pages under each menu entry's own `- tab:` entry.
- A menu entry's tab is in `navigation`, but its menu tab isn't. Add `- tab: <menu tab>` where the menu sits in the header.
- Two tabs in one menu get the same URL slug. Give each a different `display-name` or `slug`.

`fern check` warns when a tab has a `tab-menu` but tabs aren't in the header, and when `tab-menu-column-height` is set on a tab without a `tab-menu`.
</llms-only>
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ Use this to change the sidebar or any page URL.
| `availability` | Badge such as `beta` or `deprecated` |
| `slug`, `skip-slug` | Control the URL segment |
| `tabs` + `tab:` entries | Top-level tabs, each with its own navigation |
| `tab-menu` on a tab | Header dropdown grouping other tabs and links into columns. Requires `layout.tabs-placement: header`. Each tab in the menu keeps its own `- tab:` entry in `navigation`; the menu tab's entry has no `layout`. |
| `group` entries in `variants` | Variant selector split under group headers, with optional `link` entries |
| `versions` | Versioned docs, each version with its own `.yml` navigation |
| `products` | Product switcher. Each product has its own `.yml`, and the top-level `docs.yml` then has no `navigation` of its own. Requires a Team or Enterprise plan. |

Expand Down
Loading