Navigation


Works only inside an ONLYOFFICE Apps portal: it needs the portal's API client, stores and translations, and is not part of the public API.
The file manager's header: breadcrumb title, back arrow, and the row of buttons that acts on the current folder. It is built for DocSpace's own document browser and expects that shape of data — a folder trail, two context menu getters and a device type you tell it about.
Use this when / not when
- This is portal-internal. It is shipped so the DocSpace client can use it; outside that layout most of its props have no natural source, and the parts it renders assume the portal's header.
- Use it when you are rebuilding a file browser with the same trail-and-actions header and can
supply a
Sectionaround it. - Not for an application's own navigation bar — that is
NavMenu, orTabsfor switching views. - It is not responsive by itself. Which buttons appear is decided by the
currentDeviceTypeyou pass, not by a media query, so a wrong value shows the wrong header at the right width. - It is pointer-only. Every clickable part is a
<div>with anonClick; see the accessibility section before shipping it to a keyboard user.
Import
import Navigation from "@onlyoffice/apps-ui-kit/components/navigation";
It is a default export, so the name is yours to choose. The root barrel carries it by name
as well — components/index.ts re-exports it as export { default as Navigation } — but prefer the
subpath: the barrel does not build without four optional peers, see
Which import form.
Needs ThemeProvider above it in the tree: every colour it uses is declared only under the light
and dark classes that provider puts on <body>, and the mirrored arrows come from its rtl
class. It also reads the enclosing Section's context for the height the
breadcrumb drop box may use — without one the drop box falls back to its own content height.
Stories
Default
The header of a nested folder: the back arrow, the parent folder's name, the current folder's name and a notice chip. Click the folder's name to open the drop box with the whole trail; change any other prop live in the Controls panel below.

Root Folder
The header of a root folder: with no parent to go back to, the back arrow, the parent folder's name and the drop-down arrow are gone, and clicking the name opens nothing (isRootFolder).
Trash Folder
A folder that holds deleted items, where the person needs the rule spelled out and has nothing to create: the chip shows the notice (titles.warningText), there is no plus button, and the folder button's menu opens shifted to the side (isTrashFolder).

With Info Panel
The info panel toggle at the end of the header, in its pressed look, so the person can tell the panel is open and click to close it (isInfoPanelVisible, toggleInfoPanel). The toggle appears only without hideInfoPanel.

With Navigation Button
A labelled button after the other controls, for the one action a folder needs at hand, such as opening its location (navigationButtonLabel, onNavigationButtonClick). It is not shown in the root folder.

With Action Buttons
The plus button and the folder button, each opening its own menu, so the person can create something here or act on the folder: click either one. canCreate alone shows no plus button and the menu getter alone shows no folder button; each needs its flag (isPlusButtonVisible, isContextButtonVisible).

With Ai Chat Button
An AI chat button at the end of the header, for a host that has a chat panel to open (toggleChatPanel). Its text comes from titles.aiChat and gives way to the bare icon when the header runs out of room; turn on isChatPanelVisible in the Controls panel below to see its pressed look.

Right To Left
The header in a right-to-left interface: the back arrow sits at the right edge and points right, the parent folder's name comes to the right of the current one and the drop-down arrow follows the name on its left.
Css Customization
Every overridable variable set on one wrapper -- the variables are listed under CSS variables on this page.
- First header — the heading, the second title, both arrows, the separator and the notice chip; click the folder's name to see the drop box variables.
- Second header — the variables its props switch on: the badge next to the folder's name (
badgeLabel), the pressed info panel toggle (isInfoPanelVisible) and the AI chat button (toggleChatPanel).

Minimal example
import { useState } from "react";
import Navigation from "@onlyoffice/apps-ui-kit/components/navigation";
import { DeviceType } from "@onlyoffice/apps-ui-kit/enums";
const trail = [
{ id: "1", title: "Documents", isRootRoom: true },
{ id: "2", title: "Contracts", isRootRoom: false },
];
export function FolderHeader() {
const [infoPanel, setInfoPanel] = useState(false);
return (
<Navigation
title="Contracts"
navigationItems={trail}
isRootFolder={false}
currentDeviceType={DeviceType.desktop}
isDesktop
showText
showTitle
withLogo={false}
burgerLogo=""
titleIcon=""
rootRoomTitle="Documents"
showRootFolderTitle
showNavigationButton={false}
canCreate
isPlusButtonVisible
isContextButtonVisible
getContextOptionsPlus={() => [{ key: "folder", label: "New folder" }]}
getContextOptionsFolder={() => [{ key: "rename", label: "Rename" }]}
onClickFolder={(id) => console.info(id)}
onBackToParentFolder={() => console.info("back")}
isInfoPanelVisible={infoPanel}
toggleInfoPanel={() => setInfoPanel((value) => !value)}
isRoom={false}
isCurrentFolderInfo={false}
showFolderInfo={() => {}}
clearTrash={() => {}}
/>
);
}
Props
Recipes
Making the buttons appear
canCreate is not enough. The plus and context buttons are each gated by a second flag that has no
default, so a header configured only with the getters renders neither of them.
import Navigation from "@onlyoffice/apps-ui-kit/components/navigation";
import { DeviceType } from "@onlyoffice/apps-ui-kit/enums";
export function HeaderWithActions({ canCreate }: { canCreate: boolean }) {
return (
<Navigation
title="Contracts"
navigationItems={[{ id: "1", title: "Contracts", isRootRoom: true }]}
isRootFolder
currentDeviceType={DeviceType.desktop}
isDesktop
showText
showTitle
withLogo={false}
burgerLogo=""
titleIcon=""
rootRoomTitle=""
showRootFolderTitle={false}
showNavigationButton={false}
canCreate={canCreate}
isPlusButtonVisible={canCreate}
isContextButtonVisible
getContextOptionsPlus={() => [{ key: "folder", label: "New folder" }]}
getContextOptionsFolder={() => [{ key: "rename", label: "Rename" }]}
onClickFolder={() => {}}
onBackToParentFolder={() => {}}
isInfoPanelVisible={false}
toggleInfoPanel={() => {}}
isRoom={false}
isCurrentFolderInfo={false}
showFolderInfo={() => {}}
clearTrash={() => {}}
titles={{ actions: "Actions", contextMenu: "Folder actions" }}
/>
);
}
The breadcrumb drop box
The trail is not rendered inline. Clicking the folder name opens a list of every entry in
navigationItems, and choosing one calls onClickFolder. There is no prop for it: the box is
internal state, it refuses to open in the root folder or with an empty trail, and the next click
anywhere outside closes it.
import { useState } from "react";
import Navigation from "@onlyoffice/apps-ui-kit/components/navigation";
import { DeviceType } from "@onlyoffice/apps-ui-kit/enums";
const trail = [
{ id: "1", title: "Documents", isRootRoom: true },
{ id: "2", title: "2026", isRootRoom: false },
{ id: "3", title: "Contracts", isRootRoom: false },
];
export function Breadcrumbs() {
const [current, setCurrent] = useState("Contracts");
return (
<Navigation
title={current}
navigationItems={trail}
isRootFolder={false}
currentDeviceType={DeviceType.desktop}
isDesktop
showText
showTitle
withLogo={false}
burgerLogo=""
titleIcon=""
rootRoomTitle=""
showRootFolderTitle={false}
showNavigationButton={false}
canCreate={false}
getContextOptionsPlus={() => []}
getContextOptionsFolder={() => []}
onClickFolder={(id) =>
setCurrent(trail.find((item) => item.id === id)?.title ?? current)
}
onBackToParentFolder={() => {}}
isInfoPanelVisible={false}
toggleInfoPanel={() => {}}
isRoom={false}
isCurrentFolderInfo={false}
showFolderInfo={() => {}}
clearTrash={() => {}}
/>
);
}
Behaviour the types don't state
- It renders more than one element. The header container and the right-hand button row are siblings, and while the drop box is open a backdrop and the box itself are two more — four top-level nodes in a fragment. A flex or grid parent lays out all of them, which is why the portal puts it inside a header cell of its own.
canCreatealone shows no plus button, and the context menu getter alone shows no context button. Both are gated byisPlusButtonVisibleandisContextButtonVisible, which are optional and are not defaulted to true.getContextOptionsFolder()is called on every render, whether or not the button is rendered, andgetContextOptionsPlus()on every render of the plus button. Neither may be expensive or have side effects.hideInfoPanelis a flag wearing a callback's type. It is never called; its truthiness hides the info panel toggle, and a function is always truthy — so passing the handler the type asks for hides the button.- Six props are dead:
showText,isRoom,isCurrentFolderInfo,showFolderInfo,clearTrashandisEmptyFilesListare declared, four of them required, and nothing reads any of them.ignoreChangeView,isEmptyPageand arefyou pass are also ignored. - The layout follows
currentDeviceType, not the window. The AI chat button and the info panel toggle are in the right-hand row only ondesktop; below that they move into the button row, and the drop box's row heights change. The warning chip is drawn only ondesktop, and only whentitles.warningTextis set. Nothing measures the viewport except oneisTablet()call made during render, which does not re-run on resize. - A room title with a one-entry trail crashes on click. The line above the folder name reads
navigationItems[length - 2], so withrootRoomTitleset and a single crumb, clicking it throws. - The drop box needs a
Sectionfor its height.sectionHeightcomes from the kit's layout context, whose default is empty; without aSectionthe list sizes itself from its own rows. - The title icon's tooltip has a fixed id (
iconTooltip), so two of these on one page share one tooltip element. withLogoandburgerLogoare image URLs, not icon names, and the logo is rendered with an<img>whosesrcmay end up empty.- The whole component is memoised with
React.memo, so a getter recreated on every parent render defeats it.
CSS variables
The folder name itself keeps the Heading's own colour; --navigation-title-color reaches only
the room title. Between the phone and desktop breakpoints the heading's size is fixed at 21px, so
--navigation-heading-size applies on desktop and phone only. The badge, the pressed info panel
toggle and the AI chat button exist only when their props switch them on (badgeLabel,
isInfoPanelVisible, toggleChatPanel), and the drop box's variables show only while it is open.
The rest of the header's colours come from the theme classes and are not exposed.
Accessibility
- Nothing here is reachable from the keyboard. The folder name, the room title, the back arrow
and every button are
<div>s with anonClickand no role, notabindexand no key handler, so the breadcrumb drop box cannot be opened, and none of the actions can be taken, without a pointer. - The header is not a landmark: there is no
<nav>, noaria-labeland no breadcrumb semantics, so the trail is not announced as one. - The drop box is an ordinary positioned
<div>. Focus is not moved into it and not trapped, and the backdrop that closes it is not announced. - The buttons' only labels are the native
titleattributes you pass intitles, which a screen reader may or may not read and which nothing translates for you. - The logo is rendered with
alt="logo"whether or not it is meaningful.
Test ids
| Element | data-testid |
|---|---|
| The plus button | plus-button |
| The extra button | navigation_button |
| The AI chat button | ai-chat-button |
None of them are settable. The header container carries a row of data-* attributes instead —
data-is-root-folder, data-is-desktop, data-is-info-panel-visible and others — which the
stylesheet uses and a test can select on.
Related
Section— the layout this belongs in, and the source of the drop box's height.NavMenu— an application's own navigation, not a folder header.ContextMenu— what the two getters return a model for.