Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/textual/widgets/_collapsible.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ class Collapsible(Widget):

ALLOW_MAXIMIZE = True
collapsed = reactive(True, init=False)
title = reactive("Toggle")
# The constructor publishes the supplied title through the normal watcher
# path. The default is not a separate title publication; Content's text-only
# equality must also not suppress changes to spans or action metadata.
title: reactive[ContentText] = reactive("Toggle", init=False, always_update=True)

DEFAULT_CSS = """
Collapsible {
Expand Down Expand Up @@ -177,7 +180,7 @@ class Contents(Container):
def __init__(
self,
*children: Widget,
title: str = "Toggle",
title: ContentText = "Toggle",
collapsed: bool = True,
collapsed_symbol: str = "▶",
expanded_symbol: str = "▼",
Expand Down Expand Up @@ -249,5 +252,5 @@ def compose_add_child(self, widget: Widget) -> None:
"""
self._contents_list.append(widget)

def _watch_title(self, title: str) -> None:
def _watch_title(self, title: ContentText) -> None:
self._title.label = title
36 changes: 36 additions & 0 deletions tests/test_collapsible.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,3 +271,39 @@ def compose(self) -> ComposeResult:
assert get_title(collapsible).label == "Old title"
collapsible.title = "New title"
assert get_title(collapsible).label == "New title"


async def test_parent_title_publishes_supplied_value_and_styled_changes():
class WatchedCollapsible(Collapsible):
def __init__(self, **kwargs):
self.publications = []
super().__init__(Label("arbitrary child"), **kwargs)

def watch_title(self, old, new):
self.publications.append((old, new))

original = Content.from_markup("[red]supplied[/red]")
changed = Content.from_markup("[blue]supplied[/blue]")
collapsible = WatchedCollapsible(title=original, collapsed=False)
default = WatchedCollapsible()
assert collapsible.publications == [("Toggle", original)]
assert default.publications == [("Toggle", "Toggle")]
assert collapsible._title.label.is_same(original)
app = App()
async with app.run_test() as pilot:
await app.mount(collapsible, default)
await pilot.pause()
child = get_contents(collapsible).query_one(Label)
revision = collapsible._title._layout_updates
collapsible.title = changed
assert collapsible._title.label.is_same(changed)
assert collapsible._title.content.is_same(
Content.assemble("▼", " ", changed)
)
assert collapsible._title._layout_updates == revision
assert collapsible.publications[-1] == (original, changed)
collapsible.collapsed = True
await pilot.pause()
assert not get_contents(collapsible).display
assert child.is_mounted
assert collapsible._title.content.plain == "▶ supplied"
Loading