## Summary
Add `color(impl Into<Hsla>)` builder method to `Switch`, allowing
callers to customize the background color when the switch is checked.
Defaults to `theme.primary` to preserve existing behavior.
```rust
Switch::new("id")
.checked(true)
.color(cx.theme().success) // green
Switch::new("id")
.checked(true)
.color(cx.theme().danger) // red
```
## Preview
<img width="676" height="104" alt="image"
src="https://github.com/user-attachments/assets/b1422295-e463-4075-b2f2-475c71ef7ac9"
/>
## Changes
- `crates/ui/src/switch.rs`: Add `color` field and builder method
- `crates/story/src/stories/switch_story.rs`: Add "Custom Color" section
- `docs/docs/components/switch.md`: Document `color` method
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Summary
Add `menu_max_h(impl Into<Length>)` builder method to `Select`, allowing
callers to customize the dropdown menu's max height. Defaults to
`rems(20.)` to preserve existing behavior.
```rust
Select::new(&state).menu_max_h(rems(10.))
Select::new(&state).menu_max_h(px(300.))
```
## Changes
- `crates/ui/src/select.rs`: Add `menu_max_h` field to `SelectOptions`
and builder method
- `crates/story/src/stories/select_story.rs`: Add "Custom Menu Max
Height" section
- `docs/docs/components/select.md`: Document `menu_max_h` under Custom
Appearance
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
## Breaking Change
`ContextMenu` must be bound to elements that implement
`InteractiveElement` to avoid duplicate ID issues.
```diff
- div().context_menu()
+ div().id("foo").context_menu()
```
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ref https://github.com/zed-industries/zed/pull/50228
## Summary
- Refactored to share Gallery component between native and web versions
- Fixed WASM compatibility issues with async/threading
- Added web version of the story gallery
## Show case
https://huacnlee.github.io/gpui-component-story-web/
## Key Changes
### 1. Shared Gallery Component
- Extracted Gallery to `crates/story/src/gallery.rs`
- Removed duplicate code (~570 lines) from `main.rs` and
`story-web/lib.rs`
- Both native and web versions now use the same Gallery implementation
### 2. WASM Async Architecture Improvements
**Problem:** WASM main thread cannot use blocking synchronization
primitives (`Mutex`, `RwLock`) that rely on `Atomics.wait`.
**Solution:** Redesigned the async architecture to avoid cross-thread
locks:
- Changed from `Arc<Mutex<ParsedContent>>` to direct storage in
`TextViewState`
- Backend tasks now use pure message-passing instead of shared locks
- All state updates happen on the main thread
**New workflow:**
1. User updates text → Send `UpdateOptions` to background task
2. Background task → Receives copy of current `ParsedContent`, parses
text, returns new `ParsedContent`
3. Main thread → Receives result, directly replaces `parsed_content`
4. Rendering → Reads `parsed_content`, no locks needed
### 3. Cross-platform Time APIs
- Replaced `std::time` with `instant` crate for cross-platform
compatibility
- Updated 11 files to use `instant::{Duration, Instant}`
- Fixed tracing-subscriber initialization for WASM (`.without_time()`)
## Technical Details
### Files Modified
- `crates/story/src/gallery.rs` - **New** shared Gallery module
- `crates/story/src/main.rs` - Simplified to use shared Gallery
- `crates/story-web/src/lib.rs` - Simplified to use shared Gallery (326
lines → 26 lines)
- `crates/ui/src/text/state.rs` - WASM async architecture improvements
- `crates/ui/src/async_util.rs` - Cross-platform async utilities
- `crates/ui/Cargo.toml` - Added `instant` and `parking_lot`
dependencies
### Key Architecture Changes
```rust
// Before: Shared mutable state with locks (blocked on WASM)
pub struct TextViewState {
parsed_content: Arc<Mutex<ParsedContent>>,
}
// After: Direct storage with message-passing (WASM-compatible)
pub struct TextViewState {
parsed_content: ParsedContent,
}
```
## Test Plan
- ✅ Native version compiles and runs
- ✅ WASM version builds successfully
- ✅ All components render correctly in both versions
- ✅ No "Atomics.wait cannot be called in this context" errors
## Benefits
- **Reduced code duplication**: Removed ~570 lines of duplicate code
- **Single source of truth**: Gallery updates only need to happen in one
place
- **WASM compatibility**: Proper async architecture that works on
single-threaded WASM
- **Cross-platform**: Native and Web use identical code paths
## TODO
- [ ] `gpui_web` not have implement the `set_menus`, app menu missing.
- [ ] `tree-sitter` can't compiled for wasm, disabled to without
highlight.
- [ ] Input can't handle any type events.
- [ ] Embed font for CJK.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
## Summary
This PR improves the Dialog component's declarative API with trigger
support and a builder pattern for content.
<img width="1103" height="776" alt="image"
src="https://github.com/user-attachments/assets/4115ffc8-0490-464b-8823-b9d8dd3b616f"
/>
<img width="1103" height="776" alt="image"
src="https://github.com/user-attachments/assets/761f4144-8fc3-4c38-8391-0e1b303b7ff5"
/>
## Changes
- **Trigger API**: Add `trigger()` method to enable declarative dialog
opening with a trigger element
- **Content Builder**: Change `content()` to accept a builder function
instead of a pre-built `DialogContent`, allowing more flexible content
construction
- **DialogProps**: Extract dialog properties (width, margins, overlay
settings, etc.) into a `DialogProps` struct for better organization
- **Styling Improvements**:
- Add proper border radius to dialog content, header, and footer
- Improve spacing and padding consistency
- Update gap values for better visual hierarchy
- **Story Updates**: Update dialog story examples to demonstrate the new
trigger and builder pattern APIs
## Breaking Changes
- `Dialog::new()` now takes only `cx` parameter (removed `window`
parameter)
- The paddings of the Dialog changed from `24px` to `16px`.
- Default Dialog width changed from `480px` to `448px`.
## Example Usage
```rust
Dialog::new(cx)
.trigger(Button::new("open-dialog").label("Open Dialog"))
.content(|content, _, cx| {
content
.child(DialogHeader::new()
.child(DialogTitle::new().child("Title"))
.child(DialogDescription::new().child("Description")))
.child(DialogFooter::new()
.child(Button::new("ok").label("OK")))
})
```
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
## Summary
Add comprehensive documentation for the new Table cell selection
feature, covering both code-level API documentation and user-facing
documentation.
## Changes
### Code Documentation
- **TableState**: Add extensive documentation explaining the three
selection modes (row, column, cell) with examples
- **cell_selectable**: Document the field and method with detailed
explanations of behavior and usage examples
- **selected_cell() / set_selected_cell()**: Add method documentation
with return value details and examples
- **TableEvent**: Document all cell-related events (SelectCell,
DoubleClickedCell, RightClickedCell) with use cases
- **Table struct**: Add feature overview highlighting cell selection
capabilities
- **Column::selectable**: Document how it affects both column and cell
selection modes
### User Documentation (docs/docs/components/table.md)
Added comprehensive sections:
1. **Key Features** - Overview of all major table capabilities
2. **Selection Modes** - Detailed explanation of row/column/cell
selection with code examples
3. **Cell Selection** - Complete guide including:
- Configuration and event subscription
- Feature list (click to select, row selector column, keyboard
navigation, etc.)
- Programmatic selection (get/set/clear methods)
- Non-selectable columns for action columns
- Custom rendering based on selection state
4. **Keyboard Shortcuts** - Separate sections for row and cell selection
modes
5. **API Reference** - Complete reference with:
- Core types (Table, TableState, TableDelegate, Column, TableEvent)
- All methods for TableState and Column
- All event types with descriptions
- Links to docs.rs for detailed API documentation
## Test Plan
- [x] Documentation follows existing patterns (button.md, accordion.md)
- [x] All code examples are syntactically correct
- [x] Links to docs.rs are properly formatted
- [x] Keyboard shortcuts are accurate and complete
- [x] API reference matches actual implementation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
## Description
This adds `.show_whitespace` and `.set_show_whitespace` to the
`InputState` to control whether or not to render spaces and tabs.
I've also updated all the themes with the new `editor.invisible` color,
this is the `comment` color with added opacity.
## Screenshot
<img width="823" height="661" alt="Screenshot From 2026-01-29 14-04-52"
src="https://github.com/user-attachments/assets/2f79f081-83bd-47ea-922c-01b9f22262cf"
/>
<img width="795" height="118" alt="Screenshot From 2026-01-29 14-05-14"
src="https://github.com/user-attachments/assets/b8e22080-a88e-44b7-abd8-4c8100b1a972"
/>
## How to Test
`cargo run --release --example editor`
Click on the "Show whitespace" button in the footer.
## Checklist
- [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and
followed the guidelines.
- [x] Reviewed the changes in this PR and confirmed AI generated code
(If any) is accurate.
- [x] Passed `cargo run` for story tests related to the changes.
- [x] Tested macOS, ~~Windows~~ and Linux platforms performance (if the
change is platform-specific)
---------
Co-authored-by: Jason Lee <huacnlee@gmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This pull request enhances the sidebar and context menu functionality
with improved right-click context menu support and better event
handling.
- Added context menu support to `SidebarMenuItem`.
- Enhanced popover overlay dismiss behavior to handle both left and
right mouse clicks.
## Preview
<img width="381" height="285" alt="image"
src="https://github.com/user-attachments/assets/f0f61465-2fcc-4f1e-9160-5af7af0884b3"
/>
This PR adds **virtual list support** to the `Sidebar` component,
significantly improving performance when rendering large numbers of menu
items. The implementation uses GPUI's `ListState` for virtualized
rendering, ensuring smooth scrolling even with hundreds of sidebar
items.
Additionally, this update refactors the `Sidebar` API to use a more
flexible builder pattern and introduces a new `SidebarItem` trait that
enables better composition of sidebar elements including `SidebarMenu`,
`SidebarMenuItem`, and `SidebarGroup`.
## Breaking changes
- An `id` is required when creating a `Sidebar`.
```diff
- Sidebar::new()
+ Sidebar::new("sidebar1")
```
- Removed the left and right methods; use side instead.
> Default is left.
```diff
- Sidebar::right()
+ Sidebar::new("sidebar1").side(Side::Right)
```
- Use the builder pattern for the `suffix` of `SidebarMenuItem`.
```diff
- this.suffix(IconName::Settings2)
+ this.suffix(|_, _| Icon::new(IconName::Settings2))
```