**Site index:** [https://2plot.dev/llms.txt](https://2plot.dev/llms.txt) — every page on this site, as Markdown.  
**Network index:** [https://2plot.ai/llms.txt](https://2plot.ai/llms.txt) — The 2plot network; start here to discover sibling sites.  
**Sibling sites:** 11 more in The 2plot network — listed in the site index above.  
**Sitemap:** https://2plot.dev/sitemap.xml  

> **Full documentation:** [https://flexlayout.2plot.dev](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](https://github.com/pip-install-python/flexlayout-dash)

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

```bash
pip install flexlayout-dash
```

**Requirements:**
- Python >= 3.7
- Dash >= 2.0
- dash-mantine-components (recommended for theming)

---

### Quick Start

Create a simple two-panel layout with resizable divider.



```python
# 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.

```python
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:**
- Weights are relative values (e.g., 70/30 creates a 70%-30% split)
- Total weights don't need to sum to 100
- Adjust weights to create custom proportions (e.g., 2:1 ratio = weights 66:33)

---

### Multiple Tabs

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



```python
# 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:**
- Set `selected: 0` in tabset to choose initially selected tab (zero-indexed)
- Enable `tabEnableFloat: True` to allow tabs to be popped out into floating windows
- Each tab needs a unique `id` that matches a Tab component

---

### Vertical Layouts

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

```python
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:**
- Dashboard with chart on top and data table below
- Editor with preview panel underneath
- Main content with footer panel

---

### Nested Layouts

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



```python
# 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:**
```python
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.

```python
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:**
- Click border button to expand/collapse
- Support left, right, and bottom positions (**Note**: top borders not supported)
- Can contain multiple tabs like regular tabsets
- Size in pixels (width for left/right, height for bottom)

---

### Theme Integration

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



```python
# 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:**
- **Automatic Detection**: Component reads theme from MantineProvider context
- **Manual Override**: Use `colorScheme="light"` or `colorScheme="dark"` prop
- **Liquid Glass Themes**: Available via custom CSS (see assets/flexlayout-dock.css)

**Custom CSS:**
```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.



```python
# 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`**

```python
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:**
- Use `useStateForModel=True` to avoid excessive callback triggers
- Define all chart/component types upfront, toggle visibility with styles
- Don't dynamically replace `children` in callbacks—update props instead
- Read layout state via `Input('layout-id', 'model')` if needed

---

### Model Configuration

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

**Global Settings:**
```python
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:**
```python
model = {
    "layout": {
        "type": "row",                 # "row" (horizontal) or "column" (vertical)
        "weight": 100,                 # Relative size percentage
        "children": [...]              # Array of tabsets or nested layouts
    },
}
```

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

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

---

### Component Properties

#### DashFlexLayout Properties

| Property | Type | Default | Description |
| :---------- | :---------- | :---------- | :---------- |
| **`id`** | `string` | **Required** | Unique identifier for the component used in Dash callbacks. |
| **`model`** | `dict` | **Required** | Layout configuration object defining structure, global settings, and borders. |
| **`children`** | `list[Tab]` | **Required** | List of Tab components. Each Tab id must match a tab id in the model. |
| `headers` | `dict` | `None` | Custom header components for tabs. Keys are tab IDs, values are Dash components. |
| `useStateForModel` | `bool` | `False` | Use internal state management for model. Recommended: `True` to avoid excessive callbacks. |
| `colorScheme` | `string` | Auto-detect | Force color scheme: `"light"` or `"dark"`. Auto-detects from MantineProvider if not set. |
| `supportsPopout` | `bool` | `True` | Enable pop-out windows for floating tabs. Set to `False` to disable. |
| `popoutURL` | `string` | `"/assets/popout.html"` | URL for pop-out window HTML template. |
| `realtimeResize` | `bool` | `False` | Resize panels in real-time during drag (performance impact). |
| `debugMode` | `bool` | `False` | Enable debug logging to console. |
| `style` | `dict` | `None` | CSS styles for the container element. |
| `font` | `string` | `None` | Custom font family for layout UI. |
| `loading_state` | `object` | (Dash Internal) | Object describing the loading state of the component. |

#### Tab Properties

| Property | Type | Default | Description |
| :---------- | :---------- | :---------- | :---------- |
| **`id`** | `string` | **Required** | Unique identifier that must match a tab id in the model configuration. |
| **`children`** | `list` | **Required** | Dash components to render inside the tab panel. |

---

### Best Practices

**For Callbacks:**
- Always set `tabEnableRenderOnDemand: False` in global config
- Use `useStateForModel=True` to avoid excessive callback triggers
- Define all chart types upfront, toggle visibility with styles
- Don't dynamically replace children in callbacks

**For Layout Design:**
- Use weight system for responsive sizing (e.g., 70/30 splits)
- Keep nested layouts shallow (max 2-3 levels deep)
- Test mobile responsiveness with smaller weights
- Use borders for collapsible sidebars

**For Theming:**
- Let component auto-detect Mantine theme when possible
- Use `colorScheme` prop only to force specific theme
- Apply custom CSS to `.flexlayout__layout` class
- Test both light and dark modes

---

### Troubleshooting

**Callbacks Not Firing:**
- Ensure `tabEnableRenderOnDemand: False` in global config
- Verify tab IDs match between model and Tab components

**Layout Not Filling Container:**
- Set explicit height on parent container
- Example: `style={"height": "100vh"}` or `h="500px"`

**Tabs Not Appearing:**
- Check that Tab component `id` matches tab `id` in model
- Verify children list includes all Tab components

**Theme Not Applying:**
- Ensure MantineProvider wraps the layout
- Check that colorScheme prop matches theme

**Pop-out Windows Not Working:**
- Verify `supportsPopout=True` (default)
- Check that popoutURL points to valid HTML file
- Ensure HTML file has proper window communication setup

---

### 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.
