Fix/preserve link style during selection #6672 - #6695
Open
Jyotish08 wants to merge 2 commits into
Open
Conversation
Remove �nd not widget.screen._selecting condition in Visual.to_strips so link color and underline styles remain active when widgets re-render during or after text selection.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses a rendering regression where link styling (e.g., link color + underline) disappears while text drag-selection is active, by ensuring link styles are applied even when Screen._selecting is True. It also includes additional changes and tests around anchored scrolling behavior.
Changes:
- Apply link styling in
Visual.to_stripsregardless of whether screen selection is active. - Add a regression test to ensure link styling remains visible throughout mouse drag-selection.
- Add/adjust anchoring logic (and a new test) to better preserve/re-engage “anchored to bottom” scrolling during streaming content updates.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/textual/visual.py |
Removes the selection-state guard so link styles are consistently applied. |
tests/test_selection.py |
Adds a regression test for link style preservation during selection (with some brittleness to address). |
src/textual/widget.py |
Updates anchor/scroll behavior to avoid releasing/re-enable anchoring when scrolling to bottom. |
src/textual/_compositor.py |
Calls _check_anchor() during composition to help re-engage anchoring appropriately. |
tests/test_anchor.py |
Adds a test covering anchored scrolling behavior during streaming/mount updates. |
Suppressed comments (2)
tests/test_selection.py:259
- Same brittleness during the selecting-state check: matching by "docs" text and asserting color.name == "#00ffff" can break if segment boundaries or color naming differ. Use the "@click" meta to identify link segments and compare to static_widget.link_style.
strip_selecting = static_widget.render_line(0)
docs_seg_selecting = [seg for seg in strip_selecting if "docs" in seg.text][0]
assert docs_seg_selecting.style.underline is True
assert docs_seg_selecting.style.color.name == "#00ffff"
tests/test_selection.py:270
- After mouse-up, the current filter can accidentally match non-link segments (it matches any segment containing any of the letters d/o/c/s) and still asserts an exact hex string. Filtering by "@click" meta makes the test unambiguous and resilient to selection splitting.
strip_after = static_widget.render_line(0)
docs_segs = [seg for seg in strip_after if any(char in seg.text for char in "docs") and seg.text not in ("See the ", " link.")]
assert len(docs_segs) > 0
for seg in docs_segs:
assert seg.style.underline is True
assert seg.style.color.name == "#00ffff"
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
2753
to
2760
| if release_anchor: | ||
| self.release_anchor() | ||
| if y is not None and y >= self.max_scroll_y: | ||
| release_anchor = False | ||
| if self._anchored: | ||
| self._anchor_released = False | ||
| else: | ||
| self.release_anchor() | ||
| maybe_scroll_x = x is not None and (self.allow_horizontal_scroll or force) |
Comment on lines
+245
to
+248
| strip_before = static_widget.render_line(0) | ||
| docs_seg_before = [seg for seg in strip_before if "docs" in seg.text][0] | ||
| assert docs_seg_before.style.underline is True | ||
| assert docs_seg_before.style.color.name == "#00ffff" |
Comment on lines
+13
to
+15
| app = AnchorStuck() | ||
| async with app.run_test() as pilot: | ||
| v = app.query_one("#v", VerticalScroll) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #6672
When text drag-selection was initiated on a screen, link text rendered as plain unstyled text (losing custom link-color and link-style such as cyan color and underline) even though clickability survived.
Root Cause
In
src/textual/visual.py
, Visual.to_strips checked and not widget.screen._selecting before applying link styles:
python
if (
widget.auto_links
and not widget.is_container
and not widget.screen._selecting
):
link_style = widget.link_style
strips = [strip._apply_link_style(link_style) for strip in strips]
While text selection was in progress, widget.screen._selecting evaluated to True. Any widget re-rendered during drag-selection had _apply_link_style(link_style) skipped, stripping away the link styling.
Solution
Removed the selection check in Visual.to_strips: Updated
src/textual/visual.py
so link styles are applied consistently regardless of whether screen selection is active:
python
if widget.auto_links and not widget.is_container:
link_style = widget.link_style
strips = [strip._apply_link_style(link_style) for strip in strips]
Added Unit Test: Added test_link_style_preserved_during_selection to
tests/test_selection.py
to ensure link styles are preserved across mouse-down, drag, and mouse-up selection states.