TwoStateToggle
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.
Pill that switches the portal between its classic view and the new dashboard. It is portal-internal: the destination URLs and the storage key are written into the component, so it does nothing useful outside ONLYOFFICE's own application.
Use this when / not when
- Use only inside the portal, to offer the switch between the classic DocSpace view and the new dashboard.
- Not as a general two-way switch. It navigates to
/dashboardand/, writes theuseDocSpacekey inlocalStorage, and cannot be pointed anywhere else. - Not for an on/off setting —
ToggleButtonis that, and it reports throughonChangeinstead of navigating. - Not for a choice between two views inside one page; it reloads or routes away.
Import
import { TwoStateToggle } from "@onlyoffice/apps-ui-kit/components/two-state-toggle";
Also exported from the root barrel @onlyoffice/apps-ui-kit.
Needs ThemeProvider from @onlyoffice/apps-ui-kit/providers/theme. Every string it prints is
an English default you are expected to replace; nothing here is translated for you.
Stories
Default
The toggle in the NEW position, as a first visit finds it. Click it to open the confirmation dialog that guards the way back to the classic view; change any other prop live in the Controls panel below.
Showing Old State
Toggle in the OLD position. Clicking it switches to NEW immediately (calls onNavigate("/dashboard")).
Without Title
Toggle without the text label — only the pill is rendered.
Custom Labels
All text strings are customizable — useful when the toggle is reused in other contexts. Click the toggle to see the dialog texts.
Right To Left
The toggle in a right-to-left layout: the title moves to the right of the pill, OLD takes the right half and NEW the left, and the thumb sits on the left over NEW. The wrapper carries dir="rtl" for the layout; the thumb's leftward slide comes from the theme's interfaceDirection (the Direction toolbar).
Css Customization
All three overridable variables set on one wrapper -- the variables are listed under CSS variables on this page. Press Tab to focus the switch and see the ring take the custom accent.
Minimal example
Pass your router's navigate, or the switch reloads the whole page.
import { TwoStateToggle } from "@onlyoffice/apps-ui-kit/components/two-state-toggle";
export function DesignSwitch({
navigate,
}: {
navigate: (url: string) => void;
}) {
return <TwoStateToggle onNavigate={navigate} />;
}
Props
Recipes
Translated
Every label is a prop with an English default, including the five strings of the confirmation dialog.
import { TwoStateToggle } from "@onlyoffice/apps-ui-kit/components/two-state-toggle";
export function TranslatedSwitch({
t,
navigate,
}: {
t: (key: string) => string;
navigate: (url: string) => void;
}) {
return (
<TwoStateToggle
title={t("DesignTitle")}
labelOld={t("DesignOld")}
labelNew={t("DesignNew")}
confirmTitle={t("SwitchTitle")}
confirmBody={t("SwitchBody")}
confirmHint={t("SwitchHint")}
confirmOk={t("Switch")}
confirmCancel={t("Cancel")}
onNavigate={navigate}
/>
);
}
Behaviour the types don't state
- The destinations are hard-coded. Switching to the new view goes to
/dashboard, switching back goes to/. Neither is a prop. - The state lives in
localStorageunderuseDocSpace, written as"new"or"old", and it is read once during the first render. Anything absent or not"old"counts as the new view. - A storage failure is swallowed, not reported. Both the read and the write are wrapped, so disabled site data, a private mode or a sandboxed frame no longer throws — but a failed read silently reports the new view and a failed write is dropped, leaving the toggle correct on screen and forgotten on the next load. The read still happens during the first render, so a server-rendered page and its hydration can disagree about which half is selected.
- The two directions are not symmetrical. Leaving the new view opens a confirmation
ModalDialog; returning to it happens immediately, with no dialog. Confirming writes"old"and navigates to/; cancelling or closing the dialog changes nothing. - Without
onNavigatethe page reloads, because the component assignswindow.location.href. Pass your router's navigate to keep the application alive. - There is no controlled mode. No prop sets which side is active, and nothing reports a change other than the navigation itself.
titleandconfirmHintare each removed by passing an empty string.- Right-to-left puts the OLD half on the right and slides the thumb leftwards to NEW. The
halves follow the
diraround the pill, but the leftward slide comes from thertlclass thatThemeProviderputs on the document for an RTLinterfaceDirection; withdir="rtl"alone the thumb slides the wrong way, out of the pill.
CSS variables
The thumb and the label beside it are white and read no variable.
Accessibility
- The pill is a real
<button>withrole="switch"andaria-checked, so it is focusable with Tab and toggled by Enter or Space as a click would. It is announced as on while the new view is active and off in the classic view. Keyboard focus draws a ring around the pill in the accent colour. - Its name is
ariaLabel, the English "Switch DocSpace design" by default, which is not translated for you.title,labelOldandlabelNewdo not change it. - The OLD and NEW labels are
aria-hidden, which is right — but it means the only thing announced isariaLabelplus the checked state, so translateariaLabelalong with the visible labels. - The confirmation dialog is
ModalDialogand inherits its focus behaviour.
Test ids
The component sets no data-testid of its own. Query it by its role="switch", or pass a
className and use that.
Related
ToggleButton— the general on/off switch.ModalDialog— the confirmation it opens.Button— the two buttons in that dialog.