Flex Layout

Advanced docking layout system with resizable panels, floating windows, and theme integration.

Full documentation: https://flexlayout.2plot.dev — the dedicated flexlayout-dash documentation site, with the complete API reference and deeper examples. This page is the quick-start overview.

flexlayout-dash is a Dash component library that provides a flexible, dock-able layout system for building professional dashboard interfaces. It features resizable and draggable panels, floating windows with pop-out support, multiple layout types (horizontal, vertical, nested), collapsible sidebar borders, theme integration with Mantine, state persistence, and extensive customization options for creating IDE-style layouts, dashboards, and complex multi-panel applications.

Installation

Visit GitHub Repo

⭐️ Star this component on GitHub! Stay up to date on new releases and browse the codebase.

pip install flexlayout-dash

Requirements:


Quick Start

Create a simple two-panel layout with resizable divider.

# File: docs/flexlayout_dash/introduction.py

"""
Dash Flex Layout - Quick Start Example
======================================
A simple two-panel layout with resizable divider.
"""

import dash_mantine_components as dmc
import flexlayout_dash as dfl

# Define the layout model with 50/50 horizontal split
model = {
    "global": {
        "tabEnableClose": False,           # Prevent closing tabs
        "tabEnableRenderOnDemand": False,  # Keep all tabs mounted for callbacks
    },
    "layout": {
        "type": "row",  # Horizontal split
        "children": [
            {
                "type": "tabset",
                "weight": 50,  # 50% of width
                "children": [
                    {
                        "type": "tab",
                        "name": "Left Panel",
                        "id": "left-panel",
                    }
                ]
            },
            {
                "type": "tabset",
                "weight": 50,  # 50% of width
                "children": [
                    {
                        "type": "tab",
                        "name": "Right Panel",
                        "id": "right-panel",
                    }
                ]
            }
        ]
    }
}

# Create tab components with content
tabs = [
    dfl.Tab(
        id="left-panel",
        children=[
            dmc.Stack([
                dmc.Title("Welcome to Flex Layout", order=3),
                dmc.Text(
                    "This is a simple two-panel layout with a resizable divider. "
                    "Drag the divider in the middle to adjust panel sizes.",
                    size="sm"
                ),
                dmc.Badge("Left Panel", color="blue", size="lg", mt="md"),
            ], p="md")
        ]
    ),
    dfl.Tab(
        id="right-panel",
        children=[
            dmc.Stack([
                dmc.Title("Right Panel", order=3),
                dmc.Text(
                    "Panels automatically adjust their size based on the weight property. "
                    "Both panels have equal weight (50), so they split evenly.",
                    size="sm"
                ),
                dmc.Badge("Right Panel", color="green", size="lg", mt="md"),
            ], p="md")
        ]
    ),
]

# Main component for rendering
component = dmc.Stack([
    dmc.Alert(
        children="Try resizing the panels by dragging the divider!",
        title="Quick Start",
        color="blue",
    ),
    dmc.Box(
        style={"height": "400px", "width": "100%", "position": "relative"},
        children=dfl.DashFlexLayout(
            id='flex-layout-intro',
            model=model,
            children=tabs,
            style={"height": "100%", "width": "100%"},
            useStateForModel=True,
            supportsPopout=False,
        )
    )
], gap="md")

Two-Panel Layouts

Split your interface horizontally or vertically using the weight system. The weight determines how much space each panel occupies relative to others.

import flexlayout_dash as dfl

# 50/50 split
model = {
    "global": {"tabEnableClose": False, "tabEnableRenderOnDemand": False},
    "layout": {
        "type": "row",  # Horizontal split
        "children": [
            {"type": "tabset", "weight": 50, "children": [{"type": "tab", "name": "Left", "id": "left"}]},
            {"type": "tabset", "weight": 50, "children": [{"type": "tab", "name": "Right", "id": "right"}]}
        ]
    }
}

# Create tabs
tabs = [
    dfl.Tab(id="left", children=[...]),
    dfl.Tab(id="right", children=[...])
]

# Render layout
dfl.DashFlexLayout(
    id='layout',
    model=model,
    children=tabs,
    useStateForModel=True,
    supportsPopout=False,
)

Weight System:


Multiple Tabs

Organize multiple views within a single panel using tabs. Users can click tabs to switch between different content.

# File: docs/flexlayout_dash/two_panel_layout.py

"""
Dash Flex Layout - Multiple Tabs Example
=========================================
Single tabset with multiple tabs for navigation.
"""

import dash_mantine_components as dmc
import flexlayout_dash as dfl
from dash_iconify import DashIconify

# Define the layout model with single tabset
model = {
    "global": {
        "tabEnableClose": False,
        "tabEnableFloat": True,            # Allow floating tabs
        "tabEnableRenderOnDemand": False,  # Keep all tabs mounted
    },
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "tabset",
                "weight": 100,  # Full width
                "selected": 0,   # Initially selected tab (Overview)
                "children": [
                    {"type": "tab", "name": "Overview", "id": "tab-overview"},
                    {"type": "tab", "name": "Details", "id": "tab-details"},
                    {"type": "tab", "name": "Settings", "id": "tab-settings"}
                ]
            }
        ]
    }
}

# Create tab components
tabs = [
    dfl.Tab(
        id="tab-overview",
        children=[
            dmc.Card([
                dmc.Group([
                    DashIconify(icon="mdi:view-dashboard", width=32, color="blue"),
                    dmc.Title("Overview", order=3)
                ], gap="sm"),
                dmc.Text(
                    "This tab shows an overview of your data. Multiple tabs allow you to organize "
                    "different views within the same panel.",
                    size="sm",
                    mt="md"
                ),
                dmc.SimpleGrid([
                    dmc.Paper([
                        dmc.Text("Total Users", size="xs", c="dimmed"),
                        dmc.Title("1,234", order=2),
                    ], p="md", withBorder=True),
                    dmc.Paper([
                        dmc.Text("Active Now", size="xs", c="dimmed"),
                        dmc.Title("567", order=2),
                    ], p="md", withBorder=True),
                    dmc.Paper([
                        dmc.Text("Revenue", size="xs", c="dimmed"),
                        dmc.Title("$12.3k", order=2),
                    ], p="md", withBorder=True),
                ], cols=3, mt="xl")
            ], p="xl")
        ]
    ),
    dfl.Tab(
        id="tab-details",
        children=[
            dmc.Card([
                dmc.Group([
                    DashIconify(icon="mdi:information-outline", width=32, color="green"),
                    dmc.Title("Details", order=3)
                ], gap="sm"),
                dmc.Text(
                    "Detailed information and analytics are shown in this tab. "
                    "Switch between tabs to see different content.",
                    size="sm",
                    mt="md"
                ),
                dmc.Stack([
                    dmc.Text("• Flexible tab navigation", size="sm"),
                    dmc.Text("• Organize content into logical groups", size="sm"),
                    dmc.Text("• Easy to understand structure", size="sm"),
                    dmc.Text("• Customizable tab names and icons", size="sm"),
                ], gap="xs", mt="xl")
            ], p="xl")
        ]
    ),
    dfl.Tab(
        id="tab-settings",
        children=[
            dmc.Card([
                dmc.Group([
                    DashIconify(icon="mdi:cog-outline", width=32, color="orange"),
                    dmc.Title("Settings", order=3)
                ], gap="sm"),
                dmc.Text(
                    "Configuration and preferences go here. Each tab can contain "
                    "any Dash components you need.",
                    size="sm",
                    mt="md"
                ),
                dmc.Stack([
                    dmc.Switch(label="Enable notifications", checked=True, mt="lg"),
                    dmc.Switch(label="Auto-save changes", checked=False),
                    dmc.Switch(label="Dark mode", checked=False),
                ], gap="md", mt="xl")
            ], p="xl")
        ]
    ),
]

# Main component for rendering
component = dmc.Stack([
    dmc.Alert(
        children="Click on different tabs to navigate between views!",
        title="Multiple Tabs",
        color="teal",
    ),
    dmc.Box(
        style={"height": "450px", "width": "100%", "position": "relative"},
        children=dfl.DashFlexLayout(
            id='flex-layout-tabs',
            model=model,
            children=tabs,
            style={"height": "100%", "width": "100%"},
            useStateForModel=True,
            supportsPopout=False,
        )
    )
], gap="md")

Tab Configuration:


Vertical Layouts

Use "type": "column" to create vertical splits with top/bottom panels.

model = {
    "global": {"tabEnableClose": False, "tabEnableRenderOnDemand": False},
    "layout": {
        "type": "column",  # Vertical split
        "children": [
            {"type": "tabset", "weight": 40, "children": [{"type": "tab", "name": "Top", "id": "top"}]},
            {"type": "tabset", "weight": 60, "children": [{"type": "tab", "name": "Bottom", "id": "bottom"}]}
        ]
    }
}

Use Cases:


Nested Layouts

Combine rows and columns to create complex multi-panel interfaces. Perfect for IDE-style layouts and advanced dashboards.

# File: docs/flexlayout_dash/ide_layout.py

"""
Dash Flex Layout - Nested Layout Example
==========================================
Simple nested layout demonstrating rows within columns.
"""

import dash_mantine_components as dmc
import flexlayout_dash as dfl

# Define nested layout model (no borders for simplicity)
model = {
    "global": {
        "tabEnableClose": False,
        "tabEnableRenderOnDemand": False,
    },
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "column",
                "weight": 70,
                "children": [
                    {
                        "type": "tabset",
                        "weight": 60,
                        "children": [
                            {"type": "tab", "name": "Editor", "id": "editor"}
                        ]
                    },
                    {
                        "type": "tabset",
                        "weight": 40,
                        "children": [
                            {"type": "tab", "name": "Terminal", "id": "terminal"}
                        ]
                    }
                ]
            },
            {
                "type": "tabset",
                "weight": 30,
                "children": [
                    {"type": "tab", "name": "Preview", "id": "preview"}
                ]
            }
        ]
    }
}

# Create tab components
tabs = [
    # Editor Tab (top left)
    dfl.Tab(
        id="editor",
        children=[
            dmc.Box(
                p="md",
                children=[
                    dmc.Title("Code Editor", order=4, mb="md"),
                    dmc.Code(
                        block=True,
                        children="""from dash import Dash
import dash_mantine_components as dmc

app = Dash(__name__)

app.layout = dmc.Container([
    dmc.Title("Hello Dash"),
    dmc.Text("Nested layouts!")
])

if __name__ == '__main__':
    app.run(debug=True)""",
                        style={
                            "fontSize": "13px",
                        }
                    )
                ]
            )
        ]
    ),
    # Terminal Tab (bottom left)
    dfl.Tab(
        id="terminal",
        children=[
            dmc.Box(
                p="md",
                children=[
                    dmc.Title("Terminal", order=4, mb="md"),
                    dmc.Code(
                        block=True,
                        children="""$ python app.py
Dash is running on http://127.0.0.1:8050/

 * Debug mode: on""",
                        style={
                            "fontSize": "13px",
                            "backgroundColor": "var(--mantine-color-dark-6)",
                            "color": "var(--mantine-color-green-4)",
                        }
                    )
                ]
            )
        ]
    ),
    # Preview Tab (right side)
    dfl.Tab(
        id="preview",
        children=[
            dmc.Box(
                p="md",
                children=[
                    dmc.Title("Live Preview", order=4, mb="md"),
                    dmc.Paper(
                        p="xl",
                        withBorder=True,
                        children=[
                            dmc.Title("Hello Dash", order=2, mb="xs"),
                            dmc.Text("Nested layouts!", c="dimmed")
                        ]
                    )
                ]
            )
        ]
    ),
]

# Main component for rendering
component = dmc.Stack(
    gap="md",
    children=[
        dmc.Alert(
            color="violet",
            variant="light",
            children=[
                dmc.Text("Nested Layouts", fw=700, mb="xs"),
                dmc.Text("Nested layout with a vertical split on the left (Editor/Terminal) and Preview panel on the right.")
            ]
        ),
        dmc.Box(
            style={"height": "500px", "width": "100%", "position": "relative"},
            children=dfl.DashFlexLayout(
                id='flex-layout-nested',
                model=model,
                children=tabs,
                style={"height": "100%", "width": "100%"},
                useStateForModel=True,
                supportsPopout=False,
            )
        )
    ]
)

Nested Example:

model = {
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "column",  # Nested vertical split
                "weight": 70,
                "children": [
                    {"type": "tabset", "weight": 60, "children": [...]},
                    {"type": "tabset", "weight": 40, "children": [...]}
                ]
            },
            {"type": "tabset", "weight": 30, "children": [...]}  # Right sidebar
        ]
    }
}

Borders (Sidebars)

Create collapsible sidebars on the left, right, or bottom edges using borders. Perfect for navigation, tools, or secondary content.

model = {
    "global": {...},
    "borders": [
        {
            "type": "border",
            "location": "left",  # "left", "right", or "bottom"
            "size": 250,         # Width in pixels
            "selected": 0,       # Initially selected tab
            "children": [
                {"type": "tab", "name": "Files", "id": "files"},
                {"type": "tab", "name": "Search", "id": "search"}
            ]
        }
    ],
    "layout": {
        "type": "row",
        "children": [...]  # Main content area
    }
}

Border Features:


Theme Integration

Flex Layout automatically detects your app's color scheme from MantineProvider and adjusts colors accordingly.

# File: docs/flexlayout_dash/theming_example.py

"""
Liquid Glass Themes Example for Dash Flex Layout
=================================================
Showcases Apple WWDC 2025 inspired liquid glass design with light/dark themes.
This example is completely isolated and won't affect other DashFlexLayout instances.
"""
from dash import callback, Input, Output
import dash_mantine_components as dmc
from dash_iconify import DashIconify
import flexlayout_dash as dfl

# Inline style definitions for glass effects
GLASS_CONTAINER_STYLE_DARK = {
    "background": "linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%)",
    "borderRadius": "16px",
    "padding": "4px",
    "position": "relative",
    "transition": "background 0.3s ease",
}

GLASS_CONTAINER_STYLE_LIGHT = {
    "background": "linear-gradient(135deg, #e8f4f8 0%, #d4e5f7 50%, #c1d5eb 100%)",
    "borderRadius": "16px",
    "padding": "4px",
    "position": "relative",
    "transition": "background 0.3s ease",
}

GLASS_PANEL_STYLE_DARK = {
    "backdropFilter": "blur(20px) saturate(180%)",
    "WebkitBackdropFilter": "blur(20px) saturate(180%)",
    "background": "linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.05) 100%)",
    "border": "1px solid rgba(255, 255, 255, 0.15)",
    "boxShadow": "0 8px 32px rgba(0, 0, 0, 0.5), inset 0 1px 0 rgba(255, 255, 255, 0.1)",
    "borderRadius": "12px",
    "padding": "1rem",
    "height": "100%",
    "overflow": "auto",
}

GLASS_PANEL_STYLE_LIGHT = {
    "backdropFilter": "blur(20px) saturate(180%)",
    "WebkitBackdropFilter": "blur(20px) saturate(180%)",
    "background": "linear-gradient(135deg, rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0.5) 100%)",
    "border": "1px solid rgba(255, 255, 255, 0.5)",
    "boxShadow": "0 8px 32px rgba(31, 38, 135, 0.25), inset 0 1px 0 rgba(255, 255, 255, 0.8)",
    "borderRadius": "12px",
    "padding": "1rem",
    "height": "100%",
    "overflow": "auto",
}

FEATURE_CARD_STYLE_DARK = {
    "backdropFilter": "blur(16px) saturate(160%)",
    "WebkitBackdropFilter": "blur(16px) saturate(160%)",
    "background": "rgba(45, 55, 72, 0.6)",
    "border": "1px solid rgba(255, 255, 255, 0.1)",
    "borderRadius": "10px",
    "padding": "1rem",
    "marginBottom": "0.5rem",
}

FEATURE_CARD_STYLE_LIGHT = {
    "backdropFilter": "blur(16px) saturate(160%)",
    "WebkitBackdropFilter": "blur(16px) saturate(160%)",
    "background": "rgba(255, 255, 255, 0.7)",
    "border": "1px solid rgba(0, 0, 0, 0.05)",
    "borderRadius": "10px",
    "padding": "1rem",
    "marginBottom": "0.5rem",
}

# Define layout model
model = {
    "global": {
        "tabEnableClose": False,
        "tabEnableRenderOnDemand": False,
    },
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "tabset",
                "weight": 30,
                "children": [
                    {"type": "tab", "name": "Overview", "id": "theme-overview"}
                ]
            },
            {
                "type": "tabset",
                "weight": 40,
                "children": [
                    {"type": "tab", "name": "Features", "id": "theme-features"}
                ]
            },
            {
                "type": "tabset",
                "weight": 30,
                "children": [
                    {"type": "tab", "name": "Metrics", "id": "theme-metrics"}
                ]
            }
        ]
    }
}


def create_overview_panel(theme="dark"):
    """Create overview panel with theme switcher."""
    glass_style = GLASS_PANEL_STYLE_DARK if theme == "dark" else GLASS_PANEL_STYLE_LIGHT

    return dmc.Box(
        id="theme-overview",
        style=glass_style,
        children=[
            dmc.Stack(
                gap="md",
                children=[
                    dmc.Group(
                        justify="space-between",
                        children=[
                            dmc.Group(
                                gap="sm",
                                children=[
                                    DashIconify(icon="mdi:palette-advanced", width=32, color="#4FC3F7"),
                                    dmc.Stack(
                                        gap=0,
                                        children=[
                                            dmc.Title("Liquid Glass", order=4),
                                            dmc.Text("Apple WWDC 2025", size="xs", c="dimmed"),
                                        ]
                                    ),
                                ]
                            ),
                            dmc.SegmentedControl(
                                id="flex-theme-switcher",
                                data=[
                                    {"value": "dark", "label": "🌙 Dark"},
                                    {"value": "light", "label": "☀️ Light"},
                                ],
                                value=theme,
                                color="blue",
                                radius="lg",
                                size="sm",
                            ),
                        ]
                    ),
                    dmc.Divider(opacity=0.2),
                    dmc.Text(
                        "Experience Apple's next-generation glassmorphism design with backdrop blur, translucency, and gradient overlays.",
                        size="sm",
                        c="dimmed",
                    ),
                    dmc.Group(
                        gap="xs",
                        mt="sm",
                        children=[
                            dmc.Badge("20px Blur", variant="dot", color="cyan", size="sm"),
                            dmc.Badge("180% Saturation", variant="dot", color="violet", size="sm"),
                            dmc.Badge("Glass Morphism", variant="dot", color="orange", size="sm"),
                        ]
                    ),
                ]
            )
        ]
    )


def create_features_panel(theme="dark"):
    """Create features showcase panel."""
    card_style = FEATURE_CARD_STYLE_DARK if theme == "dark" else FEATURE_CARD_STYLE_LIGHT

    return dmc.Box(
        id="theme-features",
        style=GLASS_PANEL_STYLE_DARK if theme == "dark" else GLASS_PANEL_STYLE_LIGHT,
        children=[
            dmc.Stack(
                gap="sm",
                children=[
                    dmc.Title("Key Features", order=5, mb="xs"),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                gap="sm",
                                mb="xs",
                                children=[
                                    DashIconify(icon="mdi:blur", width=18, color="#4FC3F7"),
                                    dmc.Text("Backdrop Blur", fw=600, size="sm"),
                                ]
                            ),
                            dmc.Text(
                                "Advanced blur effects with 20px radius and 180% saturation.",
                                size="xs",
                                c="dimmed",
                            ),
                        ]
                    ),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                gap="sm",
                                mb="xs",
                                children=[
                                    DashIconify(icon="mdi:opacity", width=18, color="#9C27B0"),
                                    dmc.Text("Translucency", fw=600, size="sm"),
                                ]
                            ),
                            dmc.Text(
                                "Semi-transparent gradients that adapt to light and dark modes.",
                                size="xs",
                                c="dimmed",
                            ),
                        ]
                    ),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                gap="sm",
                                mb="xs",
                                children=[
                                    DashIconify(icon="mdi:gradient-vertical", width=18, color="#FFC107"),
                                    dmc.Text("Liquid Borders", fw=600, size="sm"),
                                ]
                            ),
                            dmc.Text(
                                "Smooth gradient borders with animated effects.",
                                size="xs",
                                c="dimmed",
                            ),
                        ]
                    ),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                gap="sm",
                                mb="xs",
                                children=[
                                    DashIconify(icon="mdi:theme-light-dark", width=18, color="#00BCD4"),
                                    dmc.Text("Theme Aware", fw=600, size="sm"),
                                ]
                            ),
                            dmc.Text(
                                "Automatically adapts to light and dark color schemes.",
                                size="xs",
                                c="dimmed",
                            ),
                        ]
                    ),
                ]
            )
        ]
    )


def create_metrics_panel(theme="dark"):
    """Create metrics panel."""
    card_style = FEATURE_CARD_STYLE_DARK if theme == "dark" else FEATURE_CARD_STYLE_LIGHT

    return dmc.Box(
        id="theme-metrics",
        style=GLASS_PANEL_STYLE_DARK if theme == "dark" else GLASS_PANEL_STYLE_LIGHT,
        children=[
            dmc.Stack(
                gap="md",
                children=[
                    dmc.Title("Design Metrics", order=5),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                justify="space-between",
                                align="center",
                                children=[
                                    dmc.Stack(
                                        gap=0,
                                        children=[
                                            dmc.Text("Blur Radius", size="xs", c="dimmed"),
                                            dmc.Title("20px", order=4, c="cyan"),
                                        ]
                                    ),
                                    DashIconify(icon="mdi:blur-radial", width=28, color="#4FC3F7", style={"opacity": 0.6}),
                                ]
                            ),
                        ]
                    ),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                justify="space-between",
                                align="center",
                                children=[
                                    dmc.Stack(
                                        gap=0,
                                        children=[
                                            dmc.Text("Saturation", size="xs", c="dimmed"),
                                            dmc.Title("180%", order=4, c="violet"),
                                        ]
                                    ),
                                    DashIconify(icon="mdi:palette", width=28, color="#9C27B0", style={"opacity": 0.6}),
                                ]
                            ),
                        ]
                    ),
                    dmc.Box(
                        style=card_style,
                        children=[
                            dmc.Group(
                                justify="space-between",
                                align="center",
                                children=[
                                    dmc.Stack(
                                        gap=0,
                                        children=[
                                            dmc.Text("Opacity", size="xs", c="dimmed"),
                                            dmc.Title("65%", order=4, c="orange"),
                                        ]
                                    ),
                                    DashIconify(icon="mdi:opacity", width=28, color="#FFC107", style={"opacity": 0.6}),
                                ]
                            ),
                        ]
                    ),
                ]
            )
        ]
    )


# Create tabs with default dark theme
tabs_dark = [
    dfl.Tab(id="theme-overview", children=[create_overview_panel("dark")]),
    dfl.Tab(id="theme-features", children=[create_features_panel("dark")]),
    dfl.Tab(id="theme-metrics", children=[create_metrics_panel("dark")]),
]

# Main component
component = dmc.Stack(
    gap="md",
    children=[
        dmc.Alert(
            color="indigo",
            variant="light",
            children=[
                dmc.Text("Liquid Glass Theme Demo", fw=700, mb="xs"),
                dmc.Text("Toggle between light and dark themes to see the glassmorphism effect adapt dynamically!")
            ]
        ),
        dmc.Box(
            id="flex-glass-container",
            style=GLASS_CONTAINER_STYLE_DARK,
            children=[
                dmc.Box(
                    style={"height": "450px", "position": "relative"},
                    children=dfl.DashFlexLayout(
                        id='flex-layout-glass-theme',
                        model=model,
                        children=tabs_dark,
                        style={"height": "100%", "width": "100%"},
                        useStateForModel=True,
                        supportsPopout=False,
                    )
                )
            ]
        )
    ]
)


# Callback to switch themes
@callback(
    Output("flex-glass-container", "style"),
    Output("flex-layout-glass-theme", "children"),
    Input("flex-theme-switcher", "value"),
)
def switch_flex_glass_theme(theme_value):
    """Toggle between liquid glass light and dark themes."""
    if theme_value == "light":
        tabs = [
            dfl.Tab(id="theme-overview", children=[create_overview_panel("light")]),
            dfl.Tab(id="theme-features", children=[create_features_panel("light")]),
            dfl.Tab(id="theme-metrics", children=[create_metrics_panel("light")]),
        ]
        return GLASS_CONTAINER_STYLE_LIGHT, tabs
    else:
        tabs = [
            dfl.Tab(id="theme-overview", children=[create_overview_panel("dark")]),
            dfl.Tab(id="theme-features", children=[create_features_panel("dark")]),
            dfl.Tab(id="theme-metrics", children=[create_metrics_panel("dark")]),
        ]
        return GLASS_CONTAINER_STYLE_DARK, tabs

Theme Options:

Custom CSS:

/* Apply custom styles to flexlayout */
:root[data-mantine-color-scheme="light"] .flexlayout__layout {
    background: rgba(255, 255, 255, 0.95);
    backdrop-filter: blur(10px);
}

:root[data-mantine-color-scheme="dark"] .flexlayout__layout {
    background: rgba(30, 30, 35, 0.95);
    backdrop-filter: blur(10px);
}

Interactive Callbacks

Use callbacks to create dynamic, interactive layouts with real-time updates.

# File: docs/flexlayout_dash/callbacks_example.py

"""
Dash Flex Layout - Interactive Callbacks Example
=================================================
Demonstrates callbacks and dynamic content updates.
"""

from dash import callback, Input, Output, dcc
import dash_mantine_components as dmc
import flexlayout_dash as dfl
import json

# Define 3-panel layout model
model = {
    "global": {
        "tabEnableClose": False,
        "tabEnableRenderOnDemand": False,  # CRITICAL for callbacks!
    },
    "layout": {
        "type": "row",
        "children": [
            {
                "type": "tabset",
                "weight": 30,
                "children": [
                    {"type": "tab", "name": "Controls", "id": "controls-panel"}
                ]
            },
            {
                "type": "tabset",
                "weight": 40,
                "children": [
                    {"type": "tab", "name": "Output", "id": "output-panel"}
                ]
            },
            {
                "type": "tabset",
                "weight": 30,
                "children": [
                    {"type": "tab", "name": "Data", "id": "data-panel"}
                ]
            }
        ]
    }
}

# Create tab components
tabs = [
    dfl.Tab(
        id="controls-panel",
        children=[
            dmc.Stack(
                p="md",
                gap="md",
                children=[
                    dmc.Title("Controls", order=4),
                    dmc.Select(
                        id="value-select",
                        label="Select a value:",
                        data=[
                            {"label": "Option 1", "value": "opt1"},
                            {"label": "Option 2", "value": "opt2"},
                            {"label": "Option 3", "value": "opt3"},
                        ],
                        value="opt1"
                    ),
                    dmc.NumberInput(
                        id="number-input",
                        label="Enter a number:",
                        value=5,
                        min=1,
                        max=10,
                    ),
                    dmc.Button(
                        "Update Output",
                        id="update-button",
                        fullWidth=True,
                        color="blue"
                    ),
                ]
            )
        ]
    ),
    dfl.Tab(
        id="output-panel",
        children=[
            dmc.Stack(
                p="md",
                gap="md",
                children=[
                    dmc.Title("Output", order=4),
                    dmc.Paper(
                        id="output-container",
                        p="md",
                        withBorder=True,
                        style={"minHeight": "200px"},
                        children=[
                            dmc.Center(
                                p="xl",
                                children=dmc.Text("Click 'Update Output' to see results here", c="dimmed")
                            )
                        ]
                    ),
                ]
            )
        ]
    ),
    dfl.Tab(
        id="data-panel",
        children=[
            dmc.Stack(
                p="md",
                gap="md",
                children=[
                    dmc.Title("Data Preview", order=4),
                    dmc.Code(
                        id="data-display",
                        block=True,
                        children="Click 'Update Output' to see data here",
                        style={
                            "fontSize": "12px",
                            "minHeight": "200px"
                        }
                    ),
                ]
            )
        ]
    ),
]


# Callback to generate data and update output
@callback(
    Output("output-container", "children"),
    Output("data-display", "children"),
    Input("update-button", "n_clicks"),
    Input("number-input", "value"),
    Input("value-select", "value"),
)
def update_output(n_clicks, number, selected_value):
    # Generate output data
    data = {
        "selected": selected_value,
        "number": number,
        "result": number * 10
    }

    # Create output display
    output = dmc.Stack(
        p="md",
        gap="sm",
        children=[
            dmc.Title(f"Result: {data['result']}", order=3, c="blue"),
            dmc.Text(f"You selected: {selected_value}"),
            dmc.Text(f"Number entered: {number}"),
            dmc.Text(f"Calculation: {number} × 10 = {data['result']}"),
        ]
    )

    # Format data display
    data_json = json.dumps(data, indent=2)

    return output, data_json


# Main component for rendering
component = dmc.Stack(
    gap="md",
    children=[
        dmc.Alert(
            color="grape",
            variant="light",
            children=[
                dmc.Text("Interactive Callbacks", fw=700, mb="xs"),
                dmc.Text("Use the controls to update the output and data preview. Callbacks work seamlessly with FlexLayout!")
            ]
        ),
        dmc.Box(
            style={"height": "500px", "position": "relative"},
            children=dfl.DashFlexLayout(
                id='flex-layout-callbacks',
                model=model,
                children=tabs,
                style={"height": "100%", "width": "100%"},
                useStateForModel=True,
                supportsPopout=False,
            )
        )
    ]
)

CRITICAL: Set tabEnableRenderOnDemand: False

model = {
    "global": {
        "tabEnableRenderOnDemand": False,  # Required for callbacks!
    },
    # ...the rest of the model (layout, borders)...
}

Without this setting, tabs are unmounted when not visible, causing callbacks to fail.

Callback Best Practices:


Model Configuration

The model prop defines the entire layout structure using a JSON-like dictionary.

Global Settings:

model = {
    "global": {
        "tabEnableClose": False,           # Allow closing tabs
        "tabEnableFloat": True,            # Allow floating tabs as windows
        "tabEnableRenderOnDemand": False,  # CRITICAL: Keep all tabs mounted for callbacks
        "tabEnableMaximize": True,         # Allow maximizing tabsets
        "tabEnableDrag": True,             # Allow dragging tabs
    },
}

Layout Structure:

model = {
    "layout": {
        "type": "row",                 # "row" (horizontal) or "column" (vertical)
        "weight": 100,                 # Relative size percentage
        "children": [...]              # Array of tabsets or nested layouts
    },
}

Tabset:

{
    "type": "tabset",
    "weight": 50,                      # 50% of parent width/height
    "selected": 0,                     # Initially selected tab index
    "children": [...]                  # Array of tab objects
}

Tab:

{
    "type": "tab",
    "name": "Tab Name",                # Display name
    "id": "unique-id",                 # Must match Tab component id
    "enableClose": True,               # Override global setting
}

Component Properties

DashFlexLayout Properties

PropertyTypeDefaultDescription
idstringRequiredUnique identifier for the component used in Dash callbacks.
modeldictRequiredLayout configuration object defining structure, global settings, and borders.
childrenlist[Tab]RequiredList of Tab components. Each Tab id must match a tab id in the model.
headersdictNoneCustom header components for tabs. Keys are tab IDs, values are Dash components.
useStateForModelboolFalseUse internal state management for model. Recommended: True to avoid excessive callbacks.
colorSchemestringAuto-detectForce color scheme: "light" or "dark". Auto-detects from MantineProvider if not set.
supportsPopoutboolTrueEnable pop-out windows for floating tabs. Set to False to disable.
popoutURLstring"/assets/popout.html"URL for pop-out window HTML template.
realtimeResizeboolFalseResize panels in real-time during drag (performance impact).
debugModeboolFalseEnable debug logging to console.
styledictNoneCSS styles for the container element.
fontstringNoneCustom font family for layout UI.
loading_stateobject(Dash Internal)Object describing the loading state of the component.

Tab Properties

PropertyTypeDefaultDescription
idstringRequiredUnique identifier that must match a tab id in the model configuration.
childrenlistRequiredDash components to render inside the tab panel.

Best Practices

For Callbacks:

For Layout Design:

For Theming:


Troubleshooting

Callbacks Not Firing:

Layout Not Filling Container:

Tabs Not Appearing:

Theme Not Applying:

Pop-out Windows Not Working:


Contributing

Contributions to flexlayout-dash are welcome! Please refer to the project's issues on GitHub for any feature requests or bug reports.

License

This project is licensed under the MIT License.

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: