Acronis UIKit
Components

SidebarSecondary

The secondary navigation panel, with collapsible sections and a resizable width.

Usage

import {
  SidebarSecondary,
  SidebarSecondaryHeader,
  SidebarSecondaryContent,
  SidebarSecondaryFooter,
  SidebarSecondarySection,
  SidebarSecondarySectionLabel,
  SidebarSecondaryMenu,
  SidebarSecondaryMenuItem,
  SidebarSecondaryMenuItemExtras,
  SidebarSecondaryCollapseTrigger,
} from '@acronis-platform/ui-react';

SidebarSecondary is the second-level navigation panel that sits beside SidebarPrimary. It supports expandable SidebarSecondarySections for grouping items. The panel itself owns a controlled/uncontrolled expanded width state and — unless you opt out with resizable={false} — a draggable resize edge on its inline-end border (see Resizing). The root renders a <nav> labelled "Section navigation" by default. SidebarSecondary and the menu-item parts are polymorphic via the render prop. Themed by the --ui-sidebar-secondary-* tokens.

The collapsed rail's vertical breadcrumb is rendered by the root automatically — it derives the parent label from SidebarSecondaryHeader and the current-page label from the selected SidebarSecondaryMenuItem, so there is nothing to wire up and no part to place.

Row labels truncate rather than wrap, and a label that is actually clipped gets a tooltip on hover (anchored to the row, opening to the inline-end side). In the collapsed rail every icon-only row shows its label as a tooltip so it stays identifiable.

Examples

A panel with two sections and a footer collapse trigger:

<SidebarSecondary>
  <SidebarSecondaryHeader label="Protection" />
  <SidebarSecondaryContent>
    <SidebarSecondarySection>
      <SidebarSecondarySectionLabel>Overview</SidebarSecondarySectionLabel>
      <SidebarSecondaryMenu>
        <SidebarSecondaryMenuItem href="#" icon={<LayoutGridIcon />} selected>
          Dashboard
        </SidebarSecondaryMenuItem>
        <SidebarSecondaryMenuItem href="#" icon={<ServerIcon />}>
          Workloads
        </SidebarSecondaryMenuItem>
      </SidebarSecondaryMenu>
    </SidebarSecondarySection>

    <SidebarSecondarySection>
      <SidebarSecondarySectionLabel>Resources</SidebarSecondarySectionLabel>
      <SidebarSecondaryMenu>
        <SidebarSecondaryMenuItem href="#" icon={<BoxIcon />} selected>
          Backups
        </SidebarSecondaryMenuItem>
        <SidebarSecondaryMenuItem href="#">Archived</SidebarSecondaryMenuItem>
      </SidebarSecondaryMenu>
    </SidebarSecondarySection>
  </SidebarSecondaryContent>

  <SidebarSecondaryFooter>
    <SidebarSecondaryMenu>
      <SidebarSecondaryCollapseTrigger icon={<ChevronLeftIcon />}>
        Collapse
      </SidebarSecondaryCollapseTrigger>
    </SidebarSecondaryMenu>
  </SidebarSecondaryFooter>
</SidebarSecondary>

An expandable section — the in-panel disclosure level, on top of the panel's own expanded/collapsed width:

<SidebarSecondarySection expandable defaultOpen>
  <SidebarSecondarySectionLabel>Settings</SidebarSecondarySectionLabel>
  <SidebarSecondaryMenu>
    <SidebarSecondaryMenuItem href="#">General</SidebarSecondaryMenuItem>
  </SidebarSecondaryMenu>
</SidebarSecondarySection>

Controlled collapse:

function ProtectionNav() {
  const [expanded, setExpanded] = React.useState(true);

  return (
    <SidebarSecondary expanded={expanded} onExpandedChange={setExpanded}>
      {/* … */}
    </SidebarSecondary>
  );
}

Resizing

resizable defaults to true, so the panel ships with a role="separator" edge on its inline-end border. Width is independent of the expanded/collapsed state and persists across collapse/expand cycles. The resting width stays token-driven (--ui-sidebar-secondary-expanded-container-width) until the user actually resizes or you pass a controlled width, so brand overrides of the token are honored out of the box. The drag range itself is fixed at the token's shipped default (256px) and twice that — it does not track a brand override of the token's value.

InteractionResult
Drag the edgeResizes between 256px (the token's default) and 512px
Drag past half the min widthCollapses the panel to the rail
Click the edgeToggles expanded/collapsed
Double-click the edgeResets to the default width
/ Shrinks/grows by 16px; past the minimum collapses the rail
Enter / SpaceToggles expanded/collapsed
HomeExpands (if collapsed) and resets to the default width

Arrow keys follow the writing direction — under dir="rtl" grows and shrinks. The rows above assume the default collapsible={true}; see Locking the collapse state for how each one behaves when collapsing is disabled.

The edge is labelled 'Resize sidebar' and its hover tooltip explains the drag/click/double-click gestures. All of that copy is English by default and must be localized by the consumer — or suppressed with null:

<SidebarSecondary
  resizeAriaLabel="Redimensionar la barra lateral"
  resizeTooltipExpanded={
    <>
      <span className="font-semibold">Redimensionar:</span> Arrastrar
    </>
  }
  resizeTooltipCollapsed={null} // no tooltip while collapsed
>
  {/* … */}
</SidebarSecondary>

To opt out of resizing entirely, pass resizable={false} — the edge is not rendered and the width follows the tokens alone.

Locking the collapse state

collapsible defaults to true. Pass collapsible={false} to stop the user changing the panel's expanded/collapsed state:

<SidebarSecondary collapsible={false}>{/* … */}</SidebarSecondary>

Every interaction in the Resizing table that would collapse or expand the panel becomes inert, and the footer SidebarSecondaryCollapseTrigger renders natively disabled (with no aria-expanded, since it has no state to flip):

InteractionWith collapsible={false}
Drag past half the min width (while expanded)Clamps to 256px instead of collapsing
Drag the edge (while collapsed)Nothing
Click the edgeNothing
Double-click the edgeStill resets the width; never expands
(shrink, while expanded)Clamps to 256px instead of collapsing
(shrink, while collapsed)Nothing
(grow, while collapsed)Nothing
Enter / SpaceNothing
HomeResets to the default width; does not expand
Footer collapse triggerdisabled, and shows no Expand tooltip

While the panel is expanded, resizing itself stays fully live — only the collapse transition is suppressed. Combine with resizable={false} to lock the width outright.

collapsible does not force expanded to a value: collapsible={false} with defaultExpanded={false} renders a permanently collapsed rail, and a controlled expanded prop keeps full authority either way.

In that permanently-collapsed state the resize edge remains a focusable tab stop with its accessible name, but it is mostly inert: dragging it, clicking it and both Arrow keys do nothing observable, and Enter / Space are fully inert.

Two gestures survive — Home and a double-click on the edge. Both reset the stored width to defaultWidth; neither is gated on collapsible (in the double-click handler, only the expand is). They fire onWidthChange only when defaultWidth differs from the current stored width — a width write that resolves to the current value is a no-op, so on a panel whose width has never moved these two gestures write nothing at all. When the width has moved, nothing moves back on screen at that moment — the rail stays collapsed — but a controlled consumer sees the new width, and it applies as soon as the panel is expanded via the expanded prop.

With collapsible={false} every tooltip on the panel is adjusted for you, so the copy never advertises a gesture that does nothing:

  • The footer collapse trigger — its expandTooltip is suppressed outright. The button is disabled, so an "Expand" hint would promise an action the user can't take. This one is not overridable: passing expandTooltip explicitly does not bring the tooltip back.

The two resize-edge tooltip defaults narrow instead:

  • Expanded — the default drops the "Collapse: Click" line and reads "Resize: Drag" / "Reset size: Double click". Both of those still work.
  • Collapsed — the default narrows to "Reset size: Double click" alone. Dragging the edge only ever tries to expand (gated off) and clicking bails, so the double-click is the one pointer gesture still worth describing.

An explicit resizeTooltipExpanded / resizeTooltipCollapsed value always wins over the default, collapsible notwithstanding — pass null to suppress a tooltip, or a node to replace the default copy.

API Reference

SidebarSecondary

Prop

Type

SidebarSecondaryHeader

Prop

Type

SidebarSecondarySection

Prop

Type

SidebarSecondarySectionLabel

actions renders trailing header controls (e.g. a ghost ButtonIcon) as a sibling of the expandable section's toggle, never nested inside it — so activating an action doesn't toggle the section. unreadRollup is a summary badge that only shows while an expandable section is closed; it is ignored on static sections.

<SidebarSecondarySectionLabel
  actions={
    <ButtonIcon variant="ghost" aria-label="Add policy">
      <PlusIcon />
    </ButtonIcon>
  }
  unreadRollup={<Tag variant="info">3</Tag>}
>
  Policies
</SidebarSecondarySectionLabel>

Prop

Type

SidebarSecondaryMenuItem

Prop

Type

SidebarSecondaryMenuItemExtras

Prop

Type

SidebarSecondaryCollapseTrigger

A single icon covers both directions — it rotates 180° between the expanded and collapsed states. While collapsed the button's label is sr-only and expandTooltip (default 'Expand', so localize it) is shown on hover instead — unless the panel is collapsible={false}, in which case the trigger is disabled and no tooltip is shown at all, even if you pass an explicit expandTooltip. extras is the same trailing slot as on a menu item, for a shortcut hint.

Prop

Type

The remaining structural parts (SidebarSecondaryContent, SidebarSecondaryMenu, SidebarSecondaryFooter) accept the standard attributes of the element they render.

Edit on GitHub

On this page