- Added: Floating panels can now be docked into the layout.
- Added: Floating panels can now be popped out into popout windows, shown only when every tab in the panel can live in a separate window and popouts are supported.
- Added: New global attribute
borderLeftTabDirection("up" | "down", default"up"). Setting it to"down"makes the left border tabs read top to bottom.
- Added:
ContextMenuBuilderfor building context menu items. - Added: New
useUndoReact hook that encapsulates undo/redo for a model. - Added:
renderPopoutContent,onPopoutOpenandonPopoutCloseLayout props for styling popout windows. - Fixed: css-in-js styles (emotion/MUI, styled-components) not appearing in popout windows in production builds; CSSOM-inserted rules are now copied into popouts.
- Added:
Actions.groupthat batches multiple actions together. - Added: New tab attribute
enablePin. - Added:
Model.addChangeListener()now accepts aModelChangeListenerobject with optionalonBeforeActionandonAfterActioncallbacks. The existing function form is kept for backwards compatibility. - Added:
TabNode.getWindow()andTabNode.getDocument()
- Added: Two new panels to the demo: 'Model Explorer' and 'Theme'
- Improved: Test coverage.
- Updated: Dev Dependencies.
- Updated: the data-layout-path attribute in sublayout elements
- Added: action for moving a floating panel
- Added: isAdjusting() method to actions to allow intermediate dragging actions to be ignored in Action log and when implementing undo/redo.
- Added: undo/redo buttons to demo
- Updated: Dev Dependencies.
- Fixed: flash of sublayout rendered via the factory when replacing the model with a modified copy of its json.
- Fixed:
ILayoutApi.editTabName(tabNodeId)in popouts - Fixed: context menu in 'New Features' demo layout
- Added: Pinnable tabs: new tab attribute
pinnedand actionActions.setTabPinned(tabId, pinned). Pinned tabs are grouped at the start of the tabstrip (with a pin indicator icon), cannot be closed via the ui, and cannot be dragged out of their tabset (they can be reordered within the pinned group). Newpinentry in theiconsLayout prop. - Added:
ILayoutApi.editTabName(tabNodeId)- starts the inline rename edit on a tab's button (the same edit that double clicking the tab text starts), e.g. from a context menu (see the demo's tab context menu). - Added: Overlay borders: new border attribute
borderType("split" | "overlay", default "split") and actionActions.setBorderType(borderNodeId, borderType). In overlay mode the selected border tab's panel overlays the main layout area instead of insetting it, and is closed by a pointer-down in the main layout; the border splitter still resizes the panel (see the demo's border toolbar toggle button for an example of switching border types from the ui). Not related to the existingenableAutoHideattribute (which hides the border strip when it has zero tabs). - Added: Accessibility: aria roles for tabs, tab panels, splitters and menus, keyboard operation (arrow keys move between tabs, Enter/Space selects, Ctrl+Delete closes, F2 renames, arrow keys resize a focused splitter, full keyboard support in the overflow menu) and visible keyboard focus outlines (new
--color-focusCSS variable in all themes). - Added: New Layout prop
keyMap- configures (or disables) the layout's command shortcuts:closeTab(default "Ctrl+Delete"),renameTab(default "F2"),focusTabToggle,focusNextTabset/focusPreviousTabsetandcloseOverlayBorder. Bindings are merged over the exporteddefaultKeyMapand advertised to assistive technology via aria-keyshortcuts. - Added:
Model.fromJsontakes an optional second parameter, the model currently in use by the layout; when given, the layout updates in place and tabs with matching ids keep their contents mounted (no flash or loss of state). Use when replacing the model with a modified copy of its json. - Added: Demo: Monaco editor and xterm.js terminal panels. Both demonstrate the rebuild-on-document-change pattern for components bound to their creating document, preserving their state (editor text, terminal buffer) across popout round trips.
- Updated: Dev Dependencies.
- Fixed: #525 - Popout title id causes close/reopen cascade.
- Exposed TabNode.setMoveableElement to allow workround for issue #524
- Updated: Dev Dependencies.
- Changed: Float panels can now move outside the bounds of the main layout.
- Added: New Layout prop
constrainFloatPanels, setting this to true will constrain floating panels to the main layout. - Fixed: #520 Actions.addNode causing duplicate lifecycle flow in web components
- Updated: Dev Dependencies.
- Floating Panels: Added support for 'float' type popouts that stay within the main window (simulated popouts).
- Layout Tabs: Add a sub layout to a tab, supports drag and drop from the main layout.
- Themes: Added three new themes.
- Demo Improvements:
- Added an Actions panel to visualize FlexLayout actions in real-time.
- Added an 'Attributes' option to view a tab's JSON configuration.
- Functional Component Refactor: The
Layoutcomponent has been refactored from a class to a functional component. AnyreftargetingLayoutmust now be typed asILayoutApiinstead ofLayoutin typescript.- Example:
const layoutRef = React.useRef<ILayoutApi | null>(null);
- Example:
- CSS Variable Migration: Removed global attributes
splitterSize,splitterExtra, andsplitterEnableHandle. These are now controlled via CSS variables:--splitter-size--splitter-active-size--splitter-handle-visibility
- Size Updates: Previously tabs re-rendered when their size changed, this no longer happens, use a ResizeObserver to listen for size changes.
- Tab Drag Speed: Removed the
tabDragSpeedglobal attribute. Use thetabDragSpeedprop on theLayoutcomponent instead. - Action Renaming: Standardized naming by renaming "Window" actions to "Popout" (e.g.,
closePopout,movePopoutToFront). - TabSet Enable Close: The Global
tabSetEnableCloseattribute has changed its meaning, it used to enable/disable the tabset close button, this is nowtabSetEnableCloseButton. ThetabSetEnableCloseattribute now defines whether the tabset can be closed (if a tabset cannot be closed it will always remain in the layout). - Popouts Attribute: The 'popouts' attribute in the JSON has been renamed 'subLayouts', layouts with 'popouts' will still load, but will be saved with 'subLayout' and have a 'type' attribute set to 'window'.
- Fixed: Maximum update depth exceeded error due to size jitter
- Fixed: Double model changed callbacks
- Updated: Dependencies.
- Updated: README.md links to use github.io.
- Fixed: Issues with tab redraw and scroll when page is scrolled down (corrects fix for [#488])
- Fixed: #488 Wrong tab position on scroll
- 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.
- 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.
Published with missing types in module exports
- 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.
Published with additional files by mistake.
- Fixed: #481 Numpad Enter doesn't confirm rename.
- Workaround: Addressed a
<StrictMode>issue in React 19 (react/react#29585) causing tabs to re-mount when moved.
- Fixed: #480
Actions.selectTabis called when closing a Tab. - Added:
isVisible()method toTabNode.
- Enabled: Escape key to close the overflow menu.
- Prevented: Initial reposition flash when there are hidden tabs.
- Removed: Roboto font from the demo.
- Improved: Tab scrolling into the visible area.
- Added: Sections about tab and tabset customization to the README.
- Restructured: SCSS files to remove the use of the deprecated
@importrule. - Added:
combined.csscontaining all themes. - Updated: Demo to use
combined.cssfor simple theme switching using class names. - Added: Option in the demo to show the layout structure.
- Changed: The mini scrollbar now only shows when tabs are hovered over.
- Added: Attribute
'enableTabScrollbar'toTabSetandBordernodes. 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.
- Prevented: Sticky buttons from scrolling when there are no tabs.
- Fixed: Border
'show'attribute. - Removed: Code to adjust popout positions when loading.
- Updated: Dependencies.
- Enabled: Use with React 19.
- Removed: Strict mode from the demo due to a bug in React 19 (react/react#29585) causing tabs to re-mount when moved.
- Used: CodeSandbox in
README.mdsince React 19 doesn't create UMD versions needed by JSFiddle.
- Fixed:
enableDragon 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.
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
addTabWithDragAndDropsignature has changed and must now be called from a drag start handler. - The
moveTabWithDragAndDropsignature has changed and must now be called from a drag start handler. - Removed
addTabWithDragAndDropIndirect. - Removed
onTabDrag(custom internal drag). - Removed the
fontprop; use CSS variables--font-sizeand--font-familyinstead. - Removed the
titleFactoryandiconFactoryprops; useonRenderTabinstead. - 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.
- Added: Arrow icon to edge indicators.
- Added: Attribute
tabsetClassNameto 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.
- New attribute on tabset:
enableSingleTabStretchwill stretch a single tab to take up all the remaining space and change the style to look like a header. Combined withenableDrop, 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
addTabToTabSetandaddTabToActiveTabSetnow return the addedTabNode. - Fixed: #352 -
Layout.getDomRectreturning null.
Action.setActiveTabsetcan now takeundefinedto unset the active tabset.- Added: Tab attribute
contentClassNameto add a class to the tab content.
- Added:
ITabSetRenderValues.overflowPositionto 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 istrue. - Added: Additional class names to edge indicators.
- 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.
- Fixed: Drag issue found when used in a devtool extension.
- Fixed: Double render in popout when in strict mode.
- Fixed: Popout size of tab with individual border size.
- Hid: Edge handles when disabled.
- Updated: Version of Cypress.
- Fixed: #379 -
uuidcould only be generated in secure contexts.
- Removed: Dependency on the
uuidpackage. - Added:
actionargument to theonModelChangecallback.
- Fixed: #340 - Error dragging a tabset into an empty tabset.
- Fixed: Popout windows when using
<React.StrictMode>. - Output now targets: ES6.
- Fixed: Right edge marker location when border
enableAutoHide. - Dragging out a selected border tab will now leave the border unselected.
- New Layout JSON tabs: Added to the demo.
- Added:
--color-iconCSS rootOrientationVertical.
- Fixed: #310 - Added new layout method:
moveTabWithDragAndDrop(node)to allow tab dragging to be started from custom code.
- Updated: Dependencies, in particular, changed React peer dependency to React 18.
- Made changes for: React 18.
- Fixed: #312, Chrome warning for wheel event listener.
- Fixed: #308, Allow dragging within a maximized tabset.
- Added:
onTabSetPlaceHolderprop to render the tabset area when there are no tabs.
- Added: More CSS variables, Underline theme, and updated dependencies.
- Fixed: #296.
- Fixed: #289, Allow setting attributes to undefined value.
- Code tidy.
- Updated dependencies.
- 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.
- Extended:
iconsprop to allow the use of functions to set icons. - Added:
onShowOverflowMenucallback for handling the display of the tab overflow menu.
- Used: Portal for the drag rectangle to preserve React context in
onRenderTab.
- 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:
altNameattribute toTabNode. This will be used as the name in the overflow menu if there is nonameattribute (e.g., the tab has just an icon). - Changed: The drag outline colors from red/green to light blue/green.
- Removed:
closeIconprop fromLayout; use theiconsproperty instead. - Changed:
onRenderDragRectcallback to take aReactElementrather than a string. The content now contains the tab button as rendered.
- Fixed: Copying stylesheet links for popout windows when
cssRulesthrow an exception. - Added: Option
enableUseVisibilityto allow the use ofvisibility: hiddenrather thandisplay: nonefor hiding elements.
- Added: Cypress Tests.
- Fixed: Bug with tab icon not showing.
- Added:
onRenderFloatingTabPlaceholdercallback 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:
onContextMenucallback prop for handling context menus on tabs and tabsets. - Added:
onAuxMouseClickcallback prop for handling mouse clicks on tabs and tabsets with alt, meta, shift keys, and also handles center mouse clicks.
- Added:
onRenderDragRectcallback prop for rendering the drag rectangles. - New border attribute:
enableAutoHide, to hide the border if it has zero tabs.
- 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:
borderWidthandborderHeight. 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, foronTabDrag.
- 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.
- Added new Layout prop:
onTabDragthat 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
toJsonmethod of the node public.
- 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.
- Added prop:
realtimeResizeto make tabs resize as their splitters are dragged. Warning: This can cause resizing to become choppy when tabs are slow to draw.
- New callback on Model: To allow
TabSetattributes to be set when a tab is moved in such a way that it creates a newTabSet. - Added: Config attributes to
TabSetandBorder. - Added:
headerButtonstoITabSetRenderValuesto allow a different set of buttons to be applied to headedTabSets.
- Added:
StickyButtonstoonRenderTabSetrender values to allow for the implementation of a Chrome-style + button. - Added: Example of the + button to the default layout in the demo app.
- Adjusted the selected tab when tabs are popped out to an external window.
TitleFactorycan now return an object withtitleContentandname(name is used for the tab overflow menu).- Corrected the position of
rootOrientationVerticalin the TypeScript JSON model.
- Fixed: #172 - Added global
rootOrientationVerticalattribute to allow vertical layout for the root 'row'. - Added: Missing exports for the TypeScript JSON model.
- Moved: CRA example to a separate repo.
- 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.
- Added: External drag and drop into the layout; see the new
onExternalDragprop. - 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.
- Fixed: #170 - Closing the last tab of a maximized tabset crashes the layout.
- Fixed: Issue running with React 17.0.1.
- Window title now updates when a tab is renamed.
- 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'.
- Fixed: Issues caused by double touch/mouse events in iOS.
- Prevented: iOS scroll during drag in the demo app.
- Added: Extra option to
onRenderTabto allow the name of the item in the overflow menu to be set. - New option:
closeTypefor tabs. - The maximized tabset now sets others to
display: nonerather than usingz-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.
- Various small fixes.
- 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 toflexlayout__tabset_tabbar....
- Keep the selected tab in the tabset/border when another tab is moved out.
- Added: Minimum size attributes on tabset and border.
- Added: Extra CSS classes on elements for border and splitter styling.
- Added:
fontproperty. - Font now defaults to
medium. - Tabs now auto-adjust to the current font.
- Added:
fontSizedropdown 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.
- Added:
iconsprop to allow default icons to be replaced. - Added:
tabLocationattribute to tabsets to allow top and bottom tab placement. - Modified: CSS; the default font is now 14px.
- 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.
- Changed: All components except
Layoutto use React Hooks. - Popouts now wait for stylesheets to load.
- Fixed: Problem rendering popouts in Safari.
- Fixed:
addTabWithDragAndDropnot working since 0.4.0.
- Use Sass to generate light and dark themes.
- Copy styles into popout tabs.
- 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
popoutattribute.
- Added: Overflow menu to border tabs.
- Fixed: Issues running on IE11.
- Removed: Deprecated React lifecycle methods. Will now work in React strict mode without warnings (for example, in apps created with Create React App).