Skip to content

Commit 6db045f

Browse files
committed
Fix: preserve link styling during text selection
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.
1 parent a61f41e commit 6db045f

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

src/textual/visual.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,7 @@ def to_strips(
235235
selection_style,
236236
),
237237
)
238-
if (
239-
widget.auto_links
240-
and not widget.is_container
241-
and not widget.screen._selecting
242-
):
238+
if widget.auto_links and not widget.is_container:
243239
link_style = widget.link_style
244240
strips = [strip._apply_link_style(link_style) for strip in strips]
245241

tests/test_selection.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,47 @@ async def test_select_out_of_scrollable_container_on_gap():
225225
assert (
226226
f"item-{i:02d}" in selected_text
227227
), f"item-{i:02d} missing from {selected_text!r}"
228+
229+
230+
async def test_link_style_preserved_during_selection():
231+
"""Test that link style is preserved on widgets re-rendered while screen._selecting is active."""
232+
233+
class LinkApp(App[None]):
234+
CSS = "Static { link-color: cyan; link-style: underline; }"
235+
236+
def compose(self) -> ComposeResult:
237+
yield Static("See the [@click='app.bell()']docs[/] link.")
238+
239+
app = LinkApp()
240+
async with app.run_test() as pilot:
241+
await pilot.pause()
242+
static_widget = app.query_one(Static)
243+
244+
# Before selection
245+
strip_before = static_widget.render_line(0)
246+
docs_seg_before = [seg for seg in strip_before if "docs" in seg.text][0]
247+
assert docs_seg_before.style.underline is True
248+
assert docs_seg_before.style.color.name == "#00ffff"
249+
250+
# Mouse down (triggers selecting state)
251+
assert await pilot.mouse_down(offset=(0, 0))
252+
await pilot.pause()
253+
254+
assert app.screen._selecting is True
255+
static_widget.refresh()
256+
strip_selecting = static_widget.render_line(0)
257+
docs_seg_selecting = [seg for seg in strip_selecting if "docs" in seg.text][0]
258+
assert docs_seg_selecting.style.underline is True
259+
assert docs_seg_selecting.style.color.name == "#00ffff"
260+
261+
# Mouse up (selection ends at index 10, splitting 'docs' into 'doc' and 's')
262+
await pilot.mouse_up(offset=(10, 0))
263+
await pilot.pause()
264+
265+
strip_after = static_widget.render_line(0)
266+
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.")]
267+
assert len(docs_segs) > 0
268+
for seg in docs_segs:
269+
assert seg.style.underline is True
270+
assert seg.style.color.name == "#00ffff"
271+

0 commit comments

Comments
 (0)