Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

flexlayout-react

caplin95.7kISC0.8.17TypeScript support: included

A multi-tab docking layout manager

react, layout, dock, popout, tabs, tabset, splitter, drag, drop, reactjs, flexlayout, flex layout, layout manager, drag and drop, split view, docking library, docking layout

readme

FlexLayout

GitHub npm npm

FlexLayout is a layout manager that arranges React components in multiple tabsets, tabs can be resized and moved.

FlexLayout Demo Screenshot

Run the Demo

Try it now using CodeSandbox

API Doc

Screenshot of Caplin Liberator Explorer using FlexLayout

FlexLayout's only dependency is React.

Features:

  • splitters
  • tabs (scrolling or wrapped)
  • tab dragging and ordering
  • tabset dragging (move all the tabs in a tabset in one operation)
  • dock to tabset or edge of frame
  • maximize tabset (double click tabset header or use icon)
  • tab overflow (show menu when tabs overflow, scroll tabs using mouse wheel)
  • border tabsets
  • popout tabs into new browser windows
  • submodels, allow layouts inside layouts
  • tab renaming (double click tab text to rename)
  • theming - light, dark, underline, gray, rounded and combined
  • works on mobile devices (iPad, Android)
  • add tabs using drag, add to active tabset, add to tabset by id
  • tab and tabset attributes: enableTabStrip, enableDock, enableDrop...
  • customizable tabs and tabset rendering
  • component state is preserved when tabs are moved
  • Playwright tests
  • typescript type declarations

Installation

FlexLayout is in the npm repository. install using:

npm install flexlayout-react

Import FlexLayout in your modules:

import {Layout, Model} from 'flexlayout-react';

Include the light, dark, underline, gray, rounded or combined theme by either:

Adding an import in your js code:

import 'flexlayout-react/style/light.css';  

or by copying the relevant css from the node_modules/flexlayout-react/style directory to your public assets folder (e.g. public/style) and linking the css in your html:

<link rel="stylesheet" href="/style/light.css" />

How to change the theme dynamically in code

Usage

The <Layout> component renders the tabsets and splitters, it takes the following props:

Required props:

Prop Description
model the layout model
factory a factory function for creating React components

Additional optional props

The model is tree of Node objects that define the structure of the layout.

The factory is a function that takes a Node object and returns a React component that should be hosted by a tab in the layout.

The model can be created using the Model.fromJson(jsonObject) static method, and can be saved using the model.toJson() method.

Example Configuration:

const json = {
    global: {},
    borders: [],
    layout: {
        type: "row",
        weight: 100,
        children: [
            {
                type: "tabset",
                weight: 50,
                children: [
                    {
                        type: "tab",
                        name: "One",
                        component: "placeholder",
                    }
                ]
            },
            {
                type: "tabset",
                weight: 50,
                children: [
                    {
                        type: "tab",
                        name: "Two",
                        component: "placeholder",
                    }
                ]
            }
        ]
    }
};

Example Code

const model = Model.fromJson(json);

function App() {

  const factory = (node) => {
    const component = node.getComponent();

    if (component === "placeholder") {
      return <div>{node.getName()}</div>;
    }
  }

  return (
    <Layout
      model={model}
      factory={factory} />
  );
}

The above code would render two tabsets horizontally each containing a single tab that hosts a div component (returned from the factory). The tabs could be moved and resized by dragging and dropping. Additional tabs could be added to the layout by sending actions to the model.

Simple layout

Try it now using CodeSandbox

A simple Typescript example can be found here:

https://github.com/nealus/flexlayout-vite-example

The model json contains 4 top level elements:

  • global - (optional) where global options are defined
  • layout - where the main row/tabset/tabs layout hierarchy is defined
  • borders - (optional) where up to 4 borders are defined ("top", "bottom", "left", "right").
  • popouts - (optional) where the popout windows are defined

The layout element is built up using 3 types of 'node':

  • row - rows contains a list of tabsets and child rows, the top level 'row' will render horizontally (unless the global attribute rootOrientationVertical is set) , child 'rows' will render in the opposite orientation to their parent row.

  • tabset - tabsets contain a list of tabs and the index of the selected tab

  • tab - tabs specify the name of the component that they should host (that will be loaded via the factory) and the text of the actual tab.

The layout structure is defined with rows within rows that contain tabsets that themselves contain tabs.

Within the demo app you can show the layout structure by ticking the 'Show layout' checkbox, rows are shown in blue, tabsets in orange.

FlexLayout Demo Showing Layout

The optional borders element is made up of border nodes

  • border - borders contain a list of tabs and the index of the selected tab, they can only be used in the borders top level element.

The tree structure for the JSON model is well defined as Typescript interfaces, see JSON Model

Each type of node has a defined set of requires/optional attributes.

Weights on rows and tabsets specify the relative weight of these nodes within the parent row, the actual values do not matter just their relative values (ie two tabsets of weights 30,70 would render the same if they had weights of 3,7).

NOTE: the easiest way to create your initial layout JSON is to use the demo app, modify one of the existing layouts by dragging/dropping and adding nodes then press the 'Show Layout JSON in console' button to print the JSON to the browser developer console.

By changing global or node attributes you can change the layout appearance and functionality, for example:

Setting tabSetEnableTabStrip:false in the global options would change the layout into a multi-splitter (without tabs or drag and drop).

 global: {tabSetEnableTabStrip:false},

Dynamically Changing the Theme

The 'combined.css' theme contains all the other themes and can be used for theme switching.

When using combined.css, add a className (of the form "flexlayout__theme_[theme name]") to the div containing the <Layout> to select the applied theme.

For example:

    <div ref={containerRef} className="flexlayout__theme_light">
        <Layout model={model} factory={factory} />
    </div>

Change the theme in code by changing the className on the containing div.

For example:

    containerRef.current!.className = "flexlayout__theme_dark"

Customizing Tabs

You can use the <Layout> prop onRenderTab to customize the tab rendering:

FlexLayout Tab structure

Update the renderValues parameter as needed:

renderValues.leading : the red block

renderValues.content : the green block

renderValues.buttons : the yellow block

For example:

onRenderTab = (node: TabNode, renderValues: ITabRenderValues) => {
    // renderValues.leading = <img style={{width:"1em", height:"1em"}}src="images/folder.svg"/>;
    // renderValues.content += " *";
    renderValues.buttons.push(<img key="menu" style={{width:"1em", height:"1em"}} src="images/menu.svg"/>);
}

Customizing Tabsets

You can use the <Layout> prop onRenderTabSet to customize the tabset rendering:

FlexLayout Tab structure

Update the renderValues parameter as needed:

renderValues.leading : the blue block

renderValues.stickyButtons : the red block

renderValues.buttons : the green block

For example:

onRenderTabSet = (node: (TabSetNode | BorderNode), renderValues: ITabSetRenderValues) => {
    renderValues.stickyButtons.push(
        <button
            key="Add"
            title="Add"
            className="flexlayout__tab_toolbar_button"
            onClick={() => {
                model.doAction(Actions.addNode({
                    component: "placeholder",
                    name: "Added " + nextAddIndex.current++
                }, node.getId(), DockLocation.CENTER, -1, true));
            }}
        ><AddIcon/></button>);

    renderValues.buttons.push(<img key="menu" style={{width:"1em", height:"1em"}} src="images/menu.svg"/>);
}

Model Actions

Once the model json has been loaded all changes to the model are applied through actions.

You apply actions using the Model.doAction() method.

This method takes a single argument, created by one of the action generators (accessed as FlexLayout.Actions.<actionName>):

Actions doc

Examples

model.doAction(FlexLayout.Actions.addNode(
    {type:"tab", component:"grid", name:"a grid", id:"5"},
    "1", FlexLayout.DockLocation.CENTER, 0));

This example adds a new grid component to the center of tabset with id "1" and at the 0'th tab position (use value -1 to add to the end of the tabs).

model.doAction(FlexLayout.Actions.updateModelAttributes({
    splitterSize:40
}));

The above example would increase the size of the splitters, this could be used to make adjusting the layout easier on a small device.

Note: you can get the id of a node (e.g., the node returned by the addNode action) using the method node.getId(). If an id wasn't assigned when the node was created, then one will be created for you of the form #<uuid> (e.g. #0c459064-8dee-444e-8636-eb9ab910fb27).

Note: You can intercept actions resulting from GUI changes before they are applied by implementing the onAction callback property of the Layout.

Optional Layout Props

There are many optional properties that can be applied to the layout:

Layout Properties doc

JSON Model Definition

The JSON model is well defined as a set of TypeScript interfaces, see the doc for details of all the attributes allowed:

Model Config Attributes

Model Attributes doc

Global Config Attributes

Global Attributes doc

Row Config Attributes

Row Attributes doc

TabSet Config Attributes

Tabset Attributes doc

Note: tabsets will be dynamically created as tabs are moved, and deleted when all their tabs are removed (unless enableDeleteWhenEmpty is false).

Tab Config attributes

Tab Attributes doc

Border Config attributes

Border Attributes doc

Layout Component Methods to Create New Tabs

There are methods on the Layout Component for adding tabs:

Layout Methods doc

Example:

layoutRef.current.addTabToTabSet("NAVIGATION", {type:"tab", component:"grid", name:"a grid"});

This would add a new grid component to the tabset with id "NAVIGATION" (where layoutRef is a ref to the Layout element, see https://reactjs.org/docs/refs-and-the-dom.html ).

Tab Node Events

You can handle events on nodes by adding a listener, this would typically be done when the component is mounted in a useEffect method:

Example:

    function MyComponent({node}) {

      useEffect(() => {
        // save subject in flexlayout node tree
        node.setEventListener("save", () => {
             node.getConfig().subject = subject;
           };
        }, []);
    }
Event parameters Description
resize {rect} called when tab is resized during layout, called before it is rendered with the new size
close none called when a tab is closed
visibility {visible} called when the visibility of a tab changes
save none called before a tabnode is serialized to json, use to save node config by adding data to the object returned by node.getConfig()

Popout Windows

Tabs can be rendered into external browser windows (for use in multi-monitor setups) by configuring them with the enablePopout attribute. When this attribute is present an additional icon is shown in the tab header bar allowing the tab to be popped out into an external window.

For popouts to work there needs to be an additional html page 'popout.html' hosted at the same location as the main page (copy the one from the demo app). The popout.html is the host page for the popped out tab, the styles from the main page will be copied into it at runtime.

Because popouts are rendering into a different document to the main layout any code in the popped out tab that uses the global document or window objects for event listeners will not work correctly (for example custom popup menus where the code uses document.addEventListener(...)), they need to instead use the document/window of the popout. To get the document/window of the popout use the following method on one of the elements rendered in the popout (for example a ref or target in an event handler):

    const currentDocument = selfRef.current.ownerDocument;
    const currentWindow = currentDocument.defaultView!;

In the above code selfRef is a React ref to the toplevel element in the tab being rendered.

Note: libraries may support popout windows by allowing you to specify the document to use, for example see the getDocument() callback in agGrid at https://www.ag-grid.com/javascript-grid-callbacks/

Limitations of Popouts

  • FlexLayout uses React Portals to draw the popout window content, this means all the code runs in the main Window's JS context, so effectively the popout windows are just extensions of the area on which the main window can render panels.

  • Your code must use the popout window/document in popout windows when adding event listeners (e.g popoutDocument.addEventListener(...)).

  • Timers throttle when main window is in the background you could implement a webworker timer replacement if needed (which will not throttle)

  • Many third party controls will use the global document for some event listeners, these will not work correctly without modification
  • Some third party controls will suspend when the global document is hidden you can use the tab overlay attribute to 'gray out' these tabs when the main window is hidden
  • Resize observers may be throttled (or stay attached to the main window), so you may need to use some other way to resize the component when in a popout.
  • Popouts will not size and position correctly when the browser is zoomed (ie set to 50% zoom)
  • Popouts cannot reload in maximized or minimized states
  • by default flexlayout will maintain react state when moving tabs between windows, but you can use the enableWindowReMount tab attribute to force the component to re-mount.

See this article about using React portals in this way: https://dev.to/noriste/the-challenges-of-rendering-an-openlayers-map-in-a-popup-through-react-2elh

Running the Demo and Building the Project

First install dependencies:

pnpm install

Run the Demo app:

pnpm dev

The 'pnpm dev' command will watch for changes to FlexLayout and the Demo, so you can make changes to the FlexLayout code and see the changes in your browser.

Once the demo is running you can run the Playwright tests by running (in another terminal window)

pnpm playwright
PlaywrightUI

To build the npm distribution run 'pnpm build'.

Alternative Layout Managers

Name Repository
rc-dock https://github.com/ticlo/rc-dock
Dockview https://dockview.dev/
lumino https://github.com/jupyterlab/lumino
golden-layout https://github.com/golden-layout/golden-layout
react-mosaic https://github.com/nomcopter/react-mosaic

changelog

0.8.17 - 2025-05-03

  • Fixed: Issues with tab redraw and scroll when page is scrolled down (corrects fix for [#488])

0.8.16 - 2025-04-30

  • Fixed: #488 Wrong tab position on scroll

0.8.15 - 2025-04-25

  • Added: Option to tabset customization to allow the creation of a control to the left of the tabs (see the 'New Features' layout in the demo for an example).
  • Changed: Only re-render tabs when they are visible.

0.8.14 - 2025-04-18

  • Removed: UMD builds.
  • Changed: Package type is now 'module'.
  • Changed: Demo build now uses Vite.
  • Added: Icons are now exported.
  • Added: Error boundary now has a retry button.

0.8.13 - 2025-04-15 (deprecated)

Published with missing types in module exports

0.8.12 - 2025-04-15

  • Updated: Dependencies.
  • Fixed: Initial tab flash.
  • Disabled: Popout of MUI tabs in demo (because Emotion generated styles in production cannot be copied to the popout window).
  • Converted: Cypress tests to Playwright.
  • Updated: Demo app to use React hooks.

0.8.11 - 2025-04-09 (deprecated)

Published with additional files by mistake.

0.8.10 - 2025-04-09

0.8.9 - 2025-04-04

  • Fixed: #480 Actions.selectTab is called when closing a Tab.
  • Added: isVisible() method to TabNode.

0.8.8 - 2025-03-22

  • Enabled: Escape key to close the overflow menu.
  • Prevented: Initial reposition flash when there are hidden tabs.
  • Removed: Roboto font from the demo.

0.8.7 - 2025-03-17

  • Improved: Tab scrolling into the visible area.
  • Added: Sections about tab and tabset customization to the README.

0.8.6 - 2025-03-15

  • Restructured: SCSS files to remove the use of the deprecated @import rule.
  • Added: combined.css containing all themes.
  • Updated: Demo to use combined.css for simple theme switching using class names.
  • Added: Option in the demo to show the layout structure.

0.8.5 - 2025-03-08

  • Changed: The mini scrollbar now only shows when tabs are hovered over.

0.8.4 - 2025-03-03

  • Added: Attribute 'enableTabScrollbar' to TabSet and Border nodes. Enabling this attribute will show a mini 'scrollbar' for the tabs to indicate the scroll position. See the Demo app's default layout for an example.

0.8.3 - 2025-02-21

  • Prevented: Sticky buttons from scrolling when there are no tabs.
  • Fixed: Border 'show' attribute.
  • Removed: Code to adjust popout positions when loading.

0.8.2 - 2025-02-15

  • Updated: Dependencies.
  • Enabled: Use with React 19.
  • Removed: Strict mode from the demo due to a bug in React 19 (https://github.com/facebook/react/issues/29585) causing tabs to re-mount when moved.
  • Used: CodeSandbox in README.md since React 19 doesn't create UMD versions needed by JSFiddle.

0.8.1 - 2024-09-24

  • Fixed: enableDrag on tab and tabset nodes.
  • Fixed: Calculation for min/max tabset height from min/max tab height.
  • Modified: Stylesheet code in the demo to reduce flash.

0.8.0 - 2024-09-12

New Features:

  • Wrap tabs option.
  • Improved popouts, no longer keep a placeholder tab.
  • Drag from the overflow menu.
  • Improved splitter resizing.
  • Now uses HTML drag and drop to allow cross-window dragging.
  • Rendering now uses flexbox rather than absolute positions, which should make styling easier.
  • Rounded theme.
  • Updated dependencies.

Breaking Changes:

  • The addTabWithDragAndDrop signature has changed and must now be called from a drag start handler.
  • The moveTabWithDragAndDrop signature has changed and must now be called from a drag start handler.
  • Removed addTabWithDragAndDropIndirect.
  • Removed onTabDrag (custom internal drag).
  • Removed the font prop; use CSS variables --font-size and --font-family instead.
  • Removed the titleFactory and iconFactory props; use onRenderTab instead.
  • Removed the tabset header option.
  • Removed attributes: for insets, tabset header, row/tabset width and height, legacymenu, etc.
  • Several CSS changes reflect the use of flexbox.

0.7.15 - 2023-11-14

  • Added: Arrow icon to edge indicators.

0.7.14 - 2023-11-10

  • Added: Attribute tabsetClassName to tab nodes. This will add the class name to the parent tabset when there is a single stretched tab. Updated the mosaic layout in the demo to use this to color headers.

0.7.13 - 2023-10-22

  • New attribute on tabset: enableSingleTabStretch will stretch a single tab to take up all the remaining space and change the style to look like a header. Combined with enableDrop, this can be used to create a Mosaic-style layout (headed panels without tabs). See the new Mosaic Style layout in the Demo.
  • The layout methods addTabToTabSet and addTabToActiveTabSet now return the added TabNode.
  • Fixed: #352 - Layout.getDomRect returning null.

0.7.12

  • Action.setActiveTabset can now take undefined to unset the active tabset.
  • Added: Tab attribute contentClassName to add a class to the tab content.

0.7.11

  • Added: ITabSetRenderValues.overflowPosition to allow the overflow button position to be specified. If left undefined, the position will be after sticky buttons as before.
  • New model attribute: enableRotateBorderIcons. This allows the tab icons in the left and right borders to rotate with the text or not; the default is true.
  • Added: Additional class names to edge indicators.

0.7.10

  • Fixed: #399 - The overflow button in a tabset is now placed after any sticky buttons (additional buttons that stick to the last tab of a tabset) but before any other buttons.
  • Enabled: Sticky buttons in border tabsets.

0.7.9

  • Fixed: Drag issue found when used in a devtool extension.
  • Fixed: Double render in popout when in strict mode.

0.7.8

  • Fixed: Popout size of tab with individual border size.
  • Hid: Edge handles when disabled.
  • Updated: Version of Cypress.

0.7.7

  • Fixed: #379 - uuid could only be generated in secure contexts.

0.7.6

  • Removed: Dependency on the uuid package.
  • Added: action argument to the onModelChange callback.

0.7.5

  • Fixed: #340 - Error dragging a tabset into an empty tabset.

0.7.4

  • Fixed: Popout windows when using <React.StrictMode>.
  • Output now targets: ES6.

0.7.3

  • Fixed: Right edge marker location when border enableAutoHide.
  • Dragging out a selected border tab will now leave the border unselected.

0.7.2

  • New Layout JSON tabs: Added to the demo.
  • Added: --color-icon CSS rootOrientationVertical.

0.7.1

  • Fixed: #310 - Added new layout method: moveTabWithDragAndDrop(node) to allow tab dragging to be started from custom code.

0.7.0

  • Updated: Dependencies, in particular, changed React peer dependency to React 18.
  • Made changes for: React 18.

0.6.10

  • Fixed: #312, Chrome warning for wheel event listener.

0.6.9

  • Fixed: #308, Allow dragging within a maximized tabset.

0.6.8

  • Added: onTabSetPlaceHolder prop to render the tabset area when there are no tabs.

0.6.7

  • Added: More CSS variables, Underline theme, and updated dependencies.

0.6.6

0.6.5

  • Fixed: #289, Allow setting attributes to undefined value.

0.6.4

  • Code tidy.
  • Updated dependencies.

0.6.3

  • Changed: To using named rather than default import/exports. This will require changing top-level imports:
      // from:
      import FlexLayout from 'flexlayout-react';
      // to:
      import * as FlexLayout from 'flexlayout-react';
  • Added: Typedoc link to README.

0.6.2

  • Extended: icons prop to allow the use of functions to set icons.
  • Added: onShowOverflowMenu callback for handling the display of the tab overflow menu.

0.6.1

  • Used: Portal for the drag rectangle to preserve React context in onRenderTab.

0.6.0

  • Changed: Icons to use SVG images, which will now scale with the font size.
  • Improved: Element spacing, removed most margin/padding spacers.
  • The overflow menu and drag rectangle will now show the tab icon and content as rendered in the tab.
  • Added: altName attribute to TabNode. This will be used as the name in the overflow menu if there is no name attribute (e.g., the tab has just an icon).
  • Changed: The drag outline colors from red/green to light blue/green.
  • Removed: closeIcon prop from Layout; use the icons property instead.
  • Changed: onRenderDragRect callback to take a ReactElement rather than a string. The content now contains the tab button as rendered.

0.5.21

  • Fixed: Copying stylesheet links for popout windows when cssRules throw an exception.
  • Added: Option enableUseVisibility to allow the use of visibility: hidden rather than display: none for hiding elements.

0.5.20

  • Added: Cypress Tests.
  • Fixed: Bug with tab icon not showing.

0.5.19

  • Added: onRenderFloatingTabPlaceholder callback prop for rendering the floating tab placeholder.
  • Changed: Style sheets to use CSS custom properties (variables) for several values.
  • Fixed: Selected index in a single empty tabset.
  • Added: onContextMenu callback prop for handling context menus on tabs and tabsets.
  • Added: onAuxMouseClick callback prop for handling mouse clicks on tabs and tabsets with alt, meta, shift keys, and also handles center mouse clicks.

0.5.18

  • Added: onRenderDragRect callback prop for rendering the drag rectangles.
  • New border attribute: enableAutoHide, to hide the border if it has zero tabs.

0.5.17

  • New global option: splitterExtra, to allow splitters to have extended hit test areas. This makes it easier to use narrow splitters.
  • Added new TabNode attributes: borderWidth and borderHeight. These allow for individual border sizes for certain tabs.
  • Fixed: #263 - Border splitters not taking the minimum size of the center into account.
  • Improved: Algorithm for finding the drop location.
  • Additional parameter: cursor, for onTabDrag.

0.5.16

  • Added: 'New Features' layout to the demo.
  • New tab attribute: helpText, to show a tooltip over tabs.
  • New model action: deleteTabset, to delete a tabset and all its child tabs.
  • New tabset attribute: enableClose, to close the tabset.

0.5.15

  • Added new Layout prop: onTabDrag that allows tab dragging to be intercepted.
  • Added example of onTabDrag: In the demo app, the example shows a list where tabs can be dragged into, moved in the list, and dragged back out into the layout.
  • Node IDs that are not assigned a value are now auto-generated using a UUID rather than a rolling number (e.g., previous ID: #3, new ID: #0c459064-8dee-444e-8636-eb9ab910fb27).
  • Made: The toJson method of the node public.

0.5.14

  • Fixed: An issue with copying styles for a floating window when using a CSS-in-JS solution.
  • Fixed: #227 - Edge rects are not moved if the window is resized while dragging.

0.5.13

  • Added prop: realtimeResize to make tabs resize as their splitters are dragged. Warning: This can cause resizing to become choppy when tabs are slow to draw.

0.5.12

  • New callback on Model: To allow TabSet attributes to be set when a tab is moved in such a way that it creates a new TabSet.
  • Added: Config attributes to TabSet and Border.
  • Added: headerButtons to ITabSetRenderValues to allow a different set of buttons to be applied to headed TabSets.

0.5.11

  • Added: StickyButtons to onRenderTabSet render values to allow for the implementation of a Chrome-style + button.
  • Added: Example of the + button to the default layout in the demo app.

0.5.10

  • Adjusted the selected tab when tabs are popped out to an external window.

0.5.9

  • TitleFactory can now return an object with titleContent and name (name is used for the tab overflow menu).
  • Corrected the position of rootOrientationVertical in the TypeScript JSON model.

0.5.8

  • Fixed: #172 - Added global rootOrientationVertical attribute to allow vertical layout for the root 'row'.
  • Added: Missing exports for the TypeScript JSON model.
  • Moved: CRA example to a separate repo.

0.5.7

  • Added: TypeScript typings for the model JSON.
  • Fixed: Drag rectangle showing as a dot before the first position was found (when dragging into the layout).
  • Fixed: #191 - Global Attributes for class names not working.
  • Fixed: #212 - TypeScript issue with ILayoutState.

0.5.6

  • Added: External drag and drop into the layout; see the new onExternalDrag prop.
  • Updated: Demo to accept dragged links, HTML, and text.
  • Tab scrolling direction changed to match VSCode.
  • Improved positioning of a single tab when the overflow menu is shown.
  • Some small changes to theme colors.

0.5.5

  • Fixed: #170 - Closing the last tab of a maximized tabset crashes the layout.

0.5.4

  • Fixed: Issue running with React 17.0.1.
  • Window title now updates when a tab is renamed.

0.5.3

  • Changed: Class name strings to enum values.
  • Replaced: TSLint with ESLint.
  • Added: Create-React-App (CRA) example.
  • New theme: 'light' (lighter and without box shadows, gradients).
  • Renamed: Existing 'light' theme to 'gray'.

0.5.2

  • Fixed: Issues caused by double touch/mouse events in iOS.
  • Prevented: iOS scroll during drag in the demo app.
  • Added: Extra option to onRenderTab to allow the name of the item in the overflow menu to be set.
  • New option: closeType for tabs.
  • The maximized tabset now sets others to display: none rather than using z-index.
  • Disabled: Maximize if only one tabset.
  • Splitters will now default to 8px on desktop and 12px on mobile (so they can be tapped more easily).
  • Close element is enlarged on mobile.

0.5.1

  • Various small fixes.

0.5.0

  • Overflowing tabs now scroll to keep the selected tab in view. They can also be manually scrolled using the mouse wheel.
  • Now works on scrolling pages.
  • NOTE: Several CSS classes with names starting with flexlayout__tabset_header... have been renamed to flexlayout__tabset_tabbar....

0.4.9

  • Keep the selected tab in the tabset/border when another tab is moved out.

0.4.8

  • Added: Minimum size attributes on tabset and border.
  • Added: Extra CSS classes on elements for border and splitter styling.

0.4.7

  • Added: font property.
  • Font now defaults to medium.
  • Tabs now auto-adjust to the current font.
  • Added: fontSize dropdown to the demo.
  • Modified: CSS for the above font size changes and to remove some fixed sizes.
  • Added: New attributes to control the auto-selection of tabs.

0.4.6

  • Added: icons prop to allow default icons to be replaced.
  • Added: tabLocation attribute to tabsets to allow top and bottom tab placement.
  • Modified: CSS; the default font is now 14px.

0.4.5

  • Fixed: Use of global objects for use when server-side rendering.
  • Added: Error boundary around tab contents to prevent tab rendering exceptions from crashing the app.

0.4.4

  • Changed: All components except Layout to use React Hooks.
  • Popouts now wait for stylesheets to load.
  • Fixed: Problem rendering popouts in Safari.

0.4.3

  • Fixed: addTabWithDragAndDrop not working since 0.4.0.

0.4.2

  • Use Sass to generate light and dark themes.

0.4.1

  • Copy styles into popout tabs.

0.4.0

  • Added: Ability to pop out tabs into new browser windows. Press the 'reload from file' button in the demo app to load new layouts with the popout attribute.

0.3.11

  • Added: Overflow menu to border tabs.
  • Fixed: Issues running on IE11.

0.3.10

  • Removed: Deprecated React lifecycle methods. Will now work in React strict mode without warnings (for example, in apps created with Create React App).