An open API service indexing awesome lists of open source software.

https://github.com/danieljannai/streamlit-adjustable-columns

A Streamlit custom component for creating columns with adjustable widths using draggable resize handles.
https://github.com/danieljannai/streamlit-adjustable-columns

drag-and-drop interactive-component resizable-columns streamlit streamlit-component

Last synced: 10 months ago
JSON representation

A Streamlit custom component for creating columns with adjustable widths using draggable resize handles.

Awesome Lists containing this project

README

          

# ๐ŸŽฏ Streamlit Adjustable Columns

[![PyPI version](https://badge.fury.io/py/streamlit-adjustable-columns.svg)](https://badge.fury.io/py/streamlit-adjustable-columns)

**Version:** 0.2.1

Create resizable columns in Streamlit! This component provides `st.columns` functionality with **draggable resize handles** that allow users to adjust column widths dynamically.

![Adjustable Columns Demo](https://github.com/danieljannai/streamlit-adjustable-columns/raw/main/adjustable-columns-demo.gif)

## โœจ Features

- **๐ŸŽฏ Drop-in Replacement**: Works exactly like `st.columns` with the same API
- **๐Ÿ–ฑ๏ธ Resizable Boundaries**: Drag handles between columns to adjust widths
- **๐Ÿ’พ Persistent State**: Column widths persist across app reruns
- **๐ŸŽจ Theme Integration**: Automatically matches your Streamlit theme
- **๐Ÿ“ฑ Responsive**: Works on desktop and mobile devices
- **โš™๏ธ Full Compatibility**: Supports all `st.columns` parameters (gap, alignment, border)
- **๐Ÿ”’ Minimum Width**: 6% minimum width constraint prevents unusably narrow columns
- **๐Ÿ“Š Width Tracking**: Optional `return_widths` parameter for dynamic layouts
- **๐Ÿ‘๏ธ Hide/Show Columns**: Double-click column headers to hide/show columns dynamically

## ๐Ÿš€ Quick Start

### Installation

```bash
pip install streamlit-adjustable-columns
```

**Note**: Packages installed from PyPI already include the compiled frontend so no additional tools are required. If you install from a source checkout (e.g. GitHub), Node.js and npm are needed to build the frontend assets.

### Basic Usage

```python
import streamlit as st
from streamlit_adjustable_columns import adjustable_columns

# Use exactly like st.columns - but with resize handles!
col1, col2, col3 = adjustable_columns(3, labels=["๐Ÿ“Š Charts", "๐Ÿ“‹ Data", "โš™๏ธ Settings"])

with col1:
st.metric("Sales", "$1,234", "12%")

col2.write("This column can be resized!")
col3.button("Settings")
```

### โœ… Success Indicators

You know it's working when you see:
- โœ… Column headers with drag handles between them
- โœ… Ability to drag column separators to resize
- โœ… Column widths persist when you interact with other elements
- โœ… Responsive behavior on different screen sizes

## ๐Ÿ“– API Reference

### `adjustable_columns(spec, *, gap="small", vertical_alignment="top", border=False, labels=None, return_widths=False, initial_hidden=None, key=None)`

Creates resizable columns with draggable boundaries.

#### Parameters

- **`spec`** (int or list): Number of columns or width ratios
- `3` โ†’ Three equal columns
- `[2, 1]` โ†’ Two columns with 2:1 ratio
- **`gap`** (str): Space between columns - `"small"`, `"medium"`, or `"large"`
- **`vertical_alignment`** (str): Content alignment - `"top"`, `"center"`, or `"bottom"`
- **`border`** (bool): Show borders around columns
- **`labels`** (list): Custom labels shown in resize handles
- **`return_widths`** (bool): Return width information along with columns
- **`initial_hidden`** (list of bool, optional): List of booleans indicating which columns should start hidden. Must match the number of columns. Example: `[False, True, False]` will start the second column hidden.
- **`key`** (str): Unique component key (recommended for multiple instances)

#### Returns

- **Default**: List of column containers (same as `st.columns`)
- **With `return_widths=True`**: Dict with `{'columns': [...], 'widths': [...], 'hidden': [...]}`

## ๐ŸŽฎ How to Resize & Hide Columns

1. **Look for resize handles** above each set of adjustable columns
2. **Hover over the boundaries** between column areas - you'll see resize cursors
3. **Click and drag** the handles to adjust column widths
4. **Double-click a column header** to hide/show that column
5. **Release** to apply changes - they persist across app reruns!

## ๐Ÿ“š Examples

### Dashboard Layout

```python
# Create a dashboard with resizable main content and sidebar
main, sidebar = adjustable_columns([4, 1], labels=["๐Ÿ“Š Dashboard", "โš™๏ธ Controls"])

with main:
st.subheader("Analytics Overview")
col1, col2 = st.columns(2)
col1.metric("Revenue", "$45,231", "12%")
col2.metric("Users", "1,429", "3%")
st.line_chart(data)

with sidebar:
st.selectbox("Time Period", ["1D", "1W", "1M"])
st.checkbox("Show Trends")
st.button("Refresh Data")
```

### Width Tracking

```python
# Track column widths for dynamic layouts
result = adjustable_columns([2, 1], labels=["Content", "Sidebar"], return_widths=True)
content, sidebar = result['columns']
current_widths = result['widths']

st.info(f"Current ratios: {[f'{w:.1f}' for w in current_widths]}")

with content:
st.write("Main content area")

with sidebar:
st.write("Adjustable sidebar")
```

### Multiple Column Sets

```python
# Each set of columns needs a unique key
cols1 = adjustable_columns(3, labels=["A", "B", "C"], key="top")
cols2 = adjustable_columns([1, 2], labels=["Left", "Right"], key="bottom")

# First row
cols1[0].metric("Metric 1", "100")
cols1[1].metric("Metric 2", "200")
cols1[2].metric("Metric 3", "300")

# Second row
cols2[0].button("Action")
cols2[1].write("Content area")
```

### All Parameters

```python
columns = adjustable_columns(
spec=[3, 2, 1], # Custom width ratios
gap="large", # Large spacing
vertical_alignment="center", # Center-align content
border=True, # Show column borders
labels=["๐Ÿ“Š Charts", "๐Ÿ“‹ Data", "โš™๏ธ Tools"], # Custom labels
return_widths=True, # Get width info
key="advanced_example" # Unique identifier
)

cols = columns['columns']
widths = columns['widths']
```

### Start with Some Columns Hidden

```python
# Start with the second column hidden
cols = adjustable_columns(
[1, 1, 1],
labels=["Main", "Side", "Tools"],
initial_hidden=[False, True, False],
key="hidden_example"
)

with cols[0]:
st.write("Main column is visible!")
with cols[1]:
st.write("Side column starts hidden!")
with cols[2]:
st.write("Tools column is visible!")
```

## ๐ŸŽจ Customization

### Column Labels

Customize the labels shown in resize handles:

```python
cols = adjustable_columns(
3,
labels=["๐Ÿ“ˆ Analytics", "๐Ÿ› ๏ธ Tools", "๐Ÿ“ฑ Mobile"]
)
```

### Responsive Layouts

Use width information for responsive behavior:

```python
result = adjustable_columns([2, 1], return_widths=True)
main_col, side_col = result['columns']
widths = result['widths']

# Adapt content based on current column width
if widths[0] > 3: # Main column is wide
main_col.plotly_chart(fig, use_container_width=True)
else: # Main column is narrow
main_col.write("Chart too narrow - expand column to view")
```

## ๐Ÿ”ง Development

### Prerequisites

- Python 3.9+
- Node.js 18+
- npm or yarn
- Git

### Setup

```bash
# Clone the repository
git clone https://github.com/danieljannai/streamlit-adjustable-columns
cd streamlit-adjustable-columns

# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate

# Install in development mode
make install-dev

# Or manually:
pip install -e ".[dev]"
cd streamlit_adjustable_columns/frontend
npm install
cd ../..
```

### Development Workflow

```bash
# Terminal 1: Start frontend development server
make frontend-dev # Or: cd streamlit_adjustable_columns/frontend && npm start

# Terminal 2: Run the demo (make sure venv is activated)
source venv/bin/activate
streamlit run example.py
```

### What You'll See

1. **Frontend Dev Server**: http://localhost:3001
- This serves the interactive column resizer component

2. **Streamlit App**: http://localhost:8501
- Your main app with the adjustable columns

### Testing

The project includes comprehensive tests using pytest and Playwright:

```bash
# Run all tests
make test

# Run only unit tests
make test-unit

# Run only E2E tests
make test-e2e

# Run with coverage
pytest --cov=streamlit_adjustable_columns
```

### Code Quality

```bash
# Format code
make format

# Check linting
make lint

# Run full check (format + lint + test)
make format && make lint && make test
```

### Building and Publishing

```bash
# Build the package
make build

# Upload to PyPI (requires credentials)
make upload
```

## ๐Ÿ› Troubleshooting

### Component shows "Loading..." forever
- Make sure the frontend dev server is running on port 3001
- Check that `_RELEASE = False` in `streamlit_adjustable_columns/__init__.py`

### "Module not found" error
- Make sure your virtual environment is activated: `source venv/bin/activate`
- Reinstall dependencies: `make install-dev`

### Frontend won't start
- Make sure Node.js and npm are installed
- Delete `node_modules` and run `npm install` again

### Port conflicts
- If port 3001 or 8501 are busy, kill other processes or change ports in the configuration

## ๐Ÿงช Test Coverage

The project includes comprehensive test coverage:

- **Unit Tests**: Test core functionality, parameter handling, and state management
- **Integration Tests**: Test component behavior with Streamlit integration
- **E2E Tests**: Test user interactions, resize functionality, and visual elements
- **Cross-browser Testing**: Firefox and Chromium support via Playwright

Test files are organized in the `tests/` directory:
- `tests/test_unit.py` - Unit tests for Python code
- `tests/test_integration.py` - Integration tests
- `tests/test_*.py` - E2E tests for specific features
- `tests/streamlit_apps/` - Test Streamlit applications

## ๐Ÿค Contributing

Contributions are welcome! Please feel free to submit a Pull Request. This is a brief overview of how to contribute:

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Install development dependencies (`make install-dev`)
4. Make your changes and add tests
5. Run the test suite (`make test`)
6. Format your code (`make format`)
7. Commit your changes (`git commit -m 'Add amazing feature'`)
8. Push to the branch (`git push origin feature/amazing-feature`)
9. Open a Pull Request

**For detailed contributing guidelines, development setup, testing procedures, and release processes, please see [CONTRIBUTING.md](CONTRIBUTING.md).**

## ๐Ÿ“ License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

## ๐Ÿ™ Acknowledgments

- Built with [Streamlit](https://streamlit.io/)
- Inspired by the need for flexible column layouts in Streamlit applications
- Developed with great assistance from [Cursor](https://cursor.com/) AI coding assistant

## ๐Ÿ‘จโ€๐Ÿ’ป Author

**Daniel Jannai Epstein**

- GitHub: [@danieljannai](https://github.com/danieljannai)
- Created this component to enhance Streamlit's column functionality

---

**Made with โค๏ธ for the Streamlit community**