{"id":33898669,"url":"https://github.com/panel-extensions/panel-splitjs","last_synced_at":"2026-04-01T23:34:11.808Z","repository":{"id":318731036,"uuid":"1075417718","full_name":"panel-extensions/panel-splitjs","owner":"panel-extensions","description":"A responsive, draggable split panel component for Panel applications, powered by split.js.","archived":false,"fork":false,"pushed_at":"2026-03-01T06:20:06.000Z","size":895,"stargazers_count":2,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-01T08:29:25.158Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/panel-extensions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-13T13:25:38.000Z","updated_at":"2026-02-05T18:05:40.000Z","dependencies_parsed_at":"2025-10-29T01:07:19.531Z","dependency_job_id":null,"html_url":"https://github.com/panel-extensions/panel-splitjs","commit_stats":null,"previous_names":["panel-extensions/panel-splitjs"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/panel-extensions/panel-splitjs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-extensions%2Fpanel-splitjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-extensions%2Fpanel-splitjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-extensions%2Fpanel-splitjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-extensions%2Fpanel-splitjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/panel-extensions","download_url":"https://codeload.github.com/panel-extensions/panel-splitjs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/panel-extensions%2Fpanel-splitjs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-11T21:02:29.756Z","updated_at":"2026-04-01T23:34:11.796Z","avatar_url":"https://github.com/panel-extensions.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# panel-splitjs\n\n[![CI](https://img.shields.io/github/actions/workflow/status/panel-extensions/panel-splitjs/test.yml?style=flat-square\u0026branch=main)](https://github.com/panel-extensions/panel-splitjs/actions/workflows/test.yml)\n[![conda-forge](https://img.shields.io/conda/vn/conda-forge/panel-splitjs?logoColor=white\u0026logo=conda-forge\u0026style=flat-square)](https://prefix.dev/channels/conda-forge/packages/panel-splitjs)\n[![pypi-version](https://img.shields.io/pypi/v/panel-splitjs.svg?logo=pypi\u0026logoColor=white\u0026style=flat-square)](https://pypi.org/project/panel-splitjs)\n[![python-version](https://img.shields.io/pypi/pyversions/panel-splitjs?logoColor=white\u0026logo=python\u0026style=flat-square)](https://pypi.org/project/panel-splitjs)\n\nA responsive, draggable split panel component for [Panel](https://panel.holoviz.org) applications, powered by [split.js](https://split.js.org/).\n\n## Features\n\n- **Draggable dividers** - Resize panels by dragging the divider between them\n- **Collapsible panels** - Collapse individual panels with toggle buttons\n- **Flexible orientation** - Support for both horizontal and vertical splits\n- **Size constraints** - Enforce minimum and maximum panel sizes\n- **Snap behavior** - Smart snapping to minimum sizes for better UX\n- **Customizable sizes** - Control initial and expanded panel sizes\n- **Multi-panel support** - Create layouts with 2+ panels using `MultiSplit`\n\n## Installation\n\nInstall via pip:\n\n```bash\npip install panel-splitjs\n```\n\nOr via conda:\n\n```bash\nconda install -c conda-forge panel-splitjs\n```\n\n## Quick Start\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\n# Create a simple split layout\nsplit = Split(\n    pn.pane.Markdown(\"## Left Panel\\nContent here\", width=150),\n    pn.pane.Markdown(\"## Right Panel\\nMore content\", width=150),\n    sizes=(50, 50),  # Equal sizing initially\n    min_size=150,     # Minimum 150px for each panel\n    sizing_mode=\"stretch_both\",\n)\n\nsplit.servable()\n```\n\n![Quick Start Example](docs/assets/images/quick-start.gif)\n\n## Usage Examples\n\n### Basic Horizontal Split\n\n```python\nimport panel as pn\nfrom panel_splitjs import HSplit\n\npn.extension(sizing_mode=\"stretch_width\")\n\nleft_panel = pn.Column(\n    \"# Main Content\",\n    pn.widgets.TextInput(name=\"Input\"),\n    pn.pane.Markdown(\"This is the main content area.\"),\n    margin=25, # To separate toggle button and column\n)\n\nright_panel = pn.Column(\n    \"# Sidebar\",\n    pn.widgets.Select(name=\"Options\", options=[\"A\", \"B\", \"C\"]),\n    margin=25, # To separate toggle button and column\n)\n\nsplit = HSplit(\n    left_panel,\n    right_panel,\n    sizes=(70, 30),  # 70% left, 30% right\n    min_size=300,    # Minimum 300px for each panel\n    sizing_mode=\"stretch_width\",\n    height=250,\n)\n\nsplit.servable()\n```\n\n![Basic Horizontal Split Example](docs/assets/images/basic-horizontal-split.png)\n\n### Vertical Split\n\n```python\nimport panel as pn\nfrom panel_splitjs import VSplit\n\npn.extension()\n\ntop_panel = pn.pane.Markdown(\"## Top Section\\nHeader content\")\nbottom_panel = pn.pane.Markdown(\"## Bottom Section\\nFooter content\")\n\nsplit = VSplit(\n    top_panel,\n    bottom_panel,\n    sizes=(70, 30),\n    min_size=200,\n    height=600,\n    sizing_mode=\"stretch_width\"\n)\n\nsplit.servable()\n```\n\n![Basic Vertical Split Example](docs/assets/images/basic-vertical-split.png)\n\n### Show Buttons\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\n# Create a simple split layout\nsplit = Split(\n    pn.pane.Markdown(\"## Left Panel\\nContent here\", width=150),\n    pn.pane.Markdown(\"## Right Panel\\nMore content\", width=150),\n    sizes=(50, 50),  # Equal sizing initially\n    min_size=150,     # Minimum 150px for each panel\n    show_buttons=True,\n    sizing_mode=\"stretch_both\",\n)\n\nsplit.servable()\n```\n\n![Show Buttons Example](docs/assets/images/show-buttons.png)\n\n### Collapsible Sidebar\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\n# Start with right panel collapsed\nbutton = pn.widgets.Button(name=\"Toggle Sidebar\")\n\nsplit = Split(\n    pn.Column(pn.pane.Markdown(\"## Main Content\"), button),\n    pn.pane.Markdown(\"## Collapsible Sidebar\", margin=(10,10,10,25)),\n    collapsed=1,  # 0 for first panel, 1 for second panel, None for not collapsed\n    expanded_sizes=(80, 20),  # When expanded, 80% main, 20% sidebar\n    sizing_mode=\"stretch_both\",\n)\n\n# Toggle collapse programmatically\n\ndef toggle(event):\n    split.collapsed = None if split.collapsed == 1 else 1\nbutton.on_click(toggle)\n\nsplit.servable()\n```\n\n![Collapsible Sidebar Example](docs/assets/images/collapsable-sidebar.gif)\n\n### Multi-Panel Split\n\n```python\nimport panel as pn\nfrom panel_splitjs import MultiSplit\n\npn.extension()\n\n# Create a layout with three panels\nmulti = MultiSplit(\n    pn.pane.Markdown(\"## Panel 1\"),\n    pn.pane.Markdown(\"## Panel 2\"),\n    pn.pane.Markdown(\"## Panel 3\"),\n    sizes=(30, 40, 30),  # Three panels with custom sizing\n    min_size=100,        # Minimum 100px for each panel\n    orientation=\"horizontal\",\n    sizing_mode=\"stretch_both\",\n)\n\nmulti.servable()\n```\n\n![MultiSplit Example](docs/assets/images/multisplit.png)\n\n## API Reference\n\n### Split\n\nThe main split panel component for creating two-panel layouts with collapsible functionality.\n\n**Parameters:**\n\n- `objects` (list): Two Panel components to display in the split panels\n- `collapsed` (int | None, default=None): Which panel is collapsed - `0` for first panel, `1` for second panel, `None` for not collapsed\n- `expanded_sizes` (tuple, default=(50, 50)): Percentage sizes when both panels are expanded\n- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to both panels, tuple for individual sizes\n- `min_size` (int | tuple, default=0): Minimum sizes in pixels - single value applies to both panels, tuple for individual sizes\n- `orientation` (str, default=\"horizontal\"): Either `\"horizontal\"` or `\"vertical\"`\n- `show_buttons` (bool, default=False): Show collapse/expand toggle buttons on the divider\n- `sizes` (tuple, default=(50, 50)): Initial percentage sizes of the panels\n- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels\n- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed\n\n### HSplit\n\nHorizontal split panel (convenience class).\n\nSame parameters as `Split` but `orientation` is locked to `\"horizontal\"`.\n\n### VSplit\n\nVertical split panel (convenience class).\n\nSame parameters as `Split` but `orientation` is locked to `\"vertical\"`.\n\n### MultiSplit\n\nMulti-panel split component for creating layouts with three or more panels.\n\n**Parameters:**\n\n- `objects` (list): List of Panel components to display (3 or more)\n- `max_size` (int | tuple, default=None): Maximum sizes in pixels - single value applies to all panels, tuple for individual sizes\n- `min_size` (int | tuple, default=100): Minimum sizes in pixels - single value applies to all panels, tuple for individual sizes\n- `orientation` (str, default=\"horizontal\"): Either `\"horizontal\"` or `\"vertical\"`\n- `sizes` (tuple, default=None): Initial percentage sizes of the panels (length must match number of objects)\n- `snap_size` (int, default=30): Snap to minimum size at this offset in pixels\n- `step_size` (int, default=1): Step size in pixels at which panel sizes can be changed\n\n## Common Use Cases\n\n### Chat Interface with Output\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\nwith pn.config.set(sizing_mode=\"stretch_width\"):\n    chat = pn.chat.ChatInterface(margin=(5,25,5,5))\n    output = pn.Column(\"# Output Area\")\n\nsplit = Split(\n    chat,\n    output,\n    collapsed=None,  # Both panels visible\n    expanded_sizes=(50, 50),\n    min_size=(600, 300),  # Minimum 600px for the first panel, 300px for the second panel\n    sizing_mode=\"stretch_both\",\n)\n\nsplit.servable()\n```\n\n![Chat Example](docs/assets/images/chat-example.png)\n\n### Dashboard with Collapsible Controls\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\nwith pn.config.set(sizing_mode=\"stretch_width\"):\n    controls = pn.Column(\n        pn.widgets.Select(name=\"Dataset\", options=[\"A\", \"B\", \"C\"]),\n        pn.widgets.IntSlider(name=\"Threshold\", start=0, end=100),\n        pn.widgets.Button(name=\"Update\"),\n        margin=(5,20,5,5),\n    )\n\n    visualization = pn.pane.Markdown(\"## Main Visualization Area\")\n\nsplit = Split(\n    controls,\n    visualization,\n    sizes=(20, 80),\n    min_size=(300, 0),\n    show_buttons=True,\n    sizing_mode=\"stretch_both\",\n)\n\nsplit.servable()\n```\n\n![Dashboard with Collapsible Controls](docs/assets/images/dashboard-with-collapsable-controls.png)\n\n### Responsive Layout with Size Constraints\n\n```python\nimport panel as pn\nfrom panel_splitjs import Split\n\npn.extension()\n\nsplit = Split(\n    pn.pane.Markdown(\"## Panel 1\\nResponsive content\", sizing_mode=\"stretch_width\", margin=(5,25,5,5)),\n    pn.pane.Markdown(\"## Panel 2\\nMore responsive content\", sizing_mode=\"stretch_width\", margin=(5,5,5,25)),\n    sizes=(50, 50),\n    min_size=200,        # Minimum 200px per panel\n    max_size=800,        # Maximum 800px per panel\n    snap_size=50,        # Snap to min size when within 50px\n    show_buttons=True,\n    sizing_mode=\"stretch_both\",\n)\n\nsplit.servable()\n```\n\n![Responsive Layout with Size Constraints](docs/assets/images/responsive-layout-with-size-constraints.png)\n\n### Complex Multi-Panel Layout\n\n```python\nimport panel as pn\nfrom panel_splitjs import MultiSplit\n\npn.extension()\n\n# Create a four-panel layout\nwith pn.config.set(sizing_mode=\"stretch_width\"):\n    sidebar = pn.Column(\"## Sidebar\", pn.widgets.Select(options=[\"A\", \"B\", \"C\"]))\n    main = pn.pane.Markdown(\"## Main Content Area\")\n    detail = pn.pane.Markdown(\"## Detail Panel\")\n    console = pn.pane.Markdown(\"## Console Output\")\n\nmulti = MultiSplit(\n    sidebar,\n    main,\n    detail,\n    console,\n    sizes=(15, 40, 25, 20),  # Custom sizing for each panel\n    min_size=(150, 300, 200, 150),  # Individual minimums\n    orientation=\"horizontal\",\n    sizing_mode=\"stretch_both\",\n)\n\nmulti.servable()\n```\n\n![Complex Multi-Panel Layout](docs/assets/images/complex-multi-panel-layout.png)\n\n### Nested Splits\n\n```python\nimport panel as pn\nfrom panel_splitjs import HSplit, VSplit\n\npn.extension()\n\n# Create a nested layout: horizontal split with vertical split on right\nleft = pn.pane.Markdown(\"## Left Panel\")\n\n# Right side has a vertical split\nwith pn.config.set(sizing_mode=\"stretch_both\"):\n    top_right = pn.pane.Markdown(\"## Top Right\")\n    bottom_right = pn.pane.Markdown(\"## Bottom Right\")\n    right = VSplit(top_right, bottom_right, sizes=(60, 40))\n\n    # Main horizontal split\n    layout = HSplit(\n        left,\n        right,\n        sizes=(30, 70),\n        min_size=200,\n        sizing_mode=\"stretch_both\",\n    )\n\nlayout.servable()\n```\n\n![Nested Splits](docs/assets/images/nested-splits.png)\n\n## Development\n\nThis project is managed by [pixi](https://pixi.sh).\n\n### Setup\n\n```bash\ngit clone https://github.com/panel-extensions/panel-splitjs\ncd panel-splitjs\n\npixi run pre-commit-install\npixi run postinstall\npixi run test\n```\n\n### Building\n\n```bash\npixi run build\n```\n\n### Testing\n\n```bash\npixi run test\n```\n\n### Pre-commit\n\nBefore committing the first time please install `pre-commit`:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nSee LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanel-extensions%2Fpanel-splitjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpanel-extensions%2Fpanel-splitjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpanel-extensions%2Fpanel-splitjs/lists"}