-
Notifications
You must be signed in to change notification settings - Fork 479
Open
Description
Problem
Currently, TextView supports .selectable(true) for intra-element text selection and copy, which works great within a single TextView. However, there is no way to select text across multiple elements — for example, selecting a Label, a TextView, and another Label together with a single mouse drag.
This is a common pattern in desktop applications. For comparison:
- egui: All text in a window is part of a unified drawing context, so cross-widget text selection works natively.
- Web browsers: Users can select text across multiple
<div>,<p>,<span>elements seamlessly. - Flutter: Initially had the same limitation (per-widget selection only). Solved in Flutter 3.3 by introducing
SelectionArea— a parent widget that enables cross-widget text selection for allSelectabledescendants.
Proposed Solution
Introduce a SelectionArea container element (similar to Flutter's approach):
// Wrap a section of UI to enable cross-element text selection
SelectionArea::new("my-selection-area", |area| {
area.child(Label::new("Title").text_lg())
.child(Label::new("Some body text"))
.child(Label::new(format!("Counter: {}", counter)))
})How it could work (referencing Flutter's architecture):
Selectabletrait: Text-bearing elements (Label,TextView, etc.) implement aSelectabletrait, registering their text content and layout bounds with the parentSelectionArea.SelectionAreacontainer: Intercepts mouse drag events, maintains a unified selection range across childSelectableelements, and renders per-element selection highlights.- Copy support: Cmd+C / Ctrl+C within the area concatenates selected text from all children in DOM order and writes to clipboard.
Key design considerations:
- Only text-bearing elements participate; buttons, inputs, sliders, etc. are skipped during selection.
- The selection area should handle scrollable content correctly.
- Nested
SelectionAreacontainers should be supported.
Current Workaround
Merge multiple text items into a single TextView::markdown(...) using \n\n for paragraph breaks:
// Instead of separate Labels:
// .child(Label::new("Line 1"))
// .child(Label::new("Line 2"))
// Merge into one selectable markdown block:
.child(TextView::markdown("id", "Line 1\n\nLine 2", window, cx).selectable(true))This works but loses individual styling control, can't span across non-text elements (like dividers or buttons), and conflates logical structure.
Environment
- gpui: 0.2.2
- gpui-component: 0.5.1
- Platform: macOS (Apple Silicon)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels