diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6eed95593..8da8e3b9e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
- The styles `scrollbar-background-active` and `scrollbar-color-hover` are no longer ignored https://github.com/Textualize/textual/pull/1480
+- The widget `Placeholder` can now have its width set to `auto` https://github.com/Textualize/textual/pull/1508
## [0.9.1] - 2022-12-30
diff --git a/src/textual/widgets/_placeholder.py b/src/textual/widgets/_placeholder.py
index eabe762c9..137a0fd1c 100644
--- a/src/textual/widgets/_placeholder.py
+++ b/src/textual/widgets/_placeholder.py
@@ -3,7 +3,6 @@ from __future__ import annotations
from itertools import cycle
from .. import events
-from ..containers import Container
from ..css._error_tools import friendly_list
from ..reactive import Reactive, reactive
from ..widget import Widget, RenderResult
@@ -36,19 +35,10 @@ _LOREM_IPSUM_PLACEHOLDER_TEXT = "Lorem ipsum dolor sit amet, consectetur adipisc
class InvalidPlaceholderVariant(Exception):
- pass
+ """Raised when an invalid Placeholder variant is set."""
-class _PlaceholderLabel(Widget):
- def __init__(self, content, classes) -> None:
- super().__init__(classes=classes)
- self._content = content
-
- def render(self) -> RenderResult:
- return self._content
-
-
-class Placeholder(Container):
+class Placeholder(Widget):
"""A simple placeholder widget to use before you build your custom widgets.
This placeholder has a couple of variants that show different data.
@@ -63,44 +53,24 @@ class Placeholder(Container):
DEFAULT_CSS = """
Placeholder {
- align: center middle;
+ content-align: center middle;
overflow: hidden;
+ color: $text;
}
Placeholder.-text {
padding: 1;
}
-
- _PlaceholderLabel {
- height: auto;
- color: $text;
- }
-
- Placeholder > _PlaceholderLabel {
- content-align: center middle;
- }
-
- Placeholder.-default > _PlaceholderLabel.-size,
- Placeholder.-default > _PlaceholderLabel.-text,
- Placeholder.-size > _PlaceholderLabel.-default,
- Placeholder.-size > _PlaceholderLabel.-text,
- Placeholder.-text > _PlaceholderLabel.-default,
- Placeholder.-text > _PlaceholderLabel.-size {
- display: none;
- }
-
- Placeholder.-default > _PlaceholderLabel.-default,
- Placeholder.-size > _PlaceholderLabel.-size,
- Placeholder.-text > _PlaceholderLabel.-text {
- display: block;
- }
"""
+
# Consecutive placeholders get assigned consecutive colors.
_COLORS = cycle(_PLACEHOLDER_BACKGROUND_COLORS)
_SIZE_RENDER_TEMPLATE = "[b]{} x {}[/b]"
variant: Reactive[PlaceholderVariant] = reactive("default")
+ _renderables: dict[PlaceholderVariant, RenderResult]
+
@classmethod
def reset_color_cycle(cls) -> None:
"""Reset the placeholder background color cycle."""
@@ -128,27 +98,14 @@ class Placeholder(Container):
classes (str | None, optional): A space separated string with the CSS classes
of the placeholder, if any. Defaults to None.
"""
- # Create and cache labels for all the variants.
- self._default_label = _PlaceholderLabel(
- label if label else f"#{id}" if id else "Placeholder",
- "-default",
- )
- self._size_label = _PlaceholderLabel(
- "",
- "-size",
- )
- self._text_label = _PlaceholderLabel(
- "\n\n".join(_LOREM_IPSUM_PLACEHOLDER_TEXT for _ in range(5)),
- "-text",
- )
- super().__init__(
- self._default_label,
- self._size_label,
- self._text_label,
- name=name,
- id=id,
- classes=classes,
- )
+ # Create and cache renderables for all the variants.
+ self._renderables = {
+ "default": label if label else f"#{id}" if id else "Placeholder",
+ "size": "",
+ "text": "\n\n".join(_LOREM_IPSUM_PLACEHOLDER_TEXT for _ in range(5)),
+ }
+
+ super().__init__(name=name, id=id, classes=classes)
self.styles.background = f"{next(Placeholder._COLORS)} 50%"
@@ -158,6 +115,9 @@ class Placeholder(Container):
while next(self._variants_cycle) != self.variant:
pass
+ def render(self) -> RenderResult:
+ return self._renderables[self.variant]
+
def cycle_variant(self) -> None:
"""Get the next variant in the cycle."""
self.variant = next(self._variants_cycle)
@@ -183,6 +143,6 @@ class Placeholder(Container):
def on_resize(self, event: events.Resize) -> None:
"""Update the placeholder "size" variant with the new placeholder size."""
- self._size_label._content = self._SIZE_RENDER_TEMPLATE.format(*self.size)
+ self._renderables["size"] = self._SIZE_RENDER_TEMPLATE.format(*self.size)
if self.variant == "size":
- self._size_label.refresh(layout=True)
+ self.refresh(layout=True)
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
index 4a9464a81..d920e8d87 100644
--- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
@@ -7800,145 +7800,142 @@
font-weight: 700;
}
- .terminal-2023815619-matrix {
+ .terminal-1570661136-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
- .terminal-2023815619-title {
+ .terminal-1570661136-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
- .terminal-2023815619-r1 { fill: #e8e0e7 }
- .terminal-2023815619-r2 { fill: #c5c8c6 }
- .terminal-2023815619-r3 { fill: #eae3e5 }
- .terminal-2023815619-r4 { fill: #ede6e6 }
- .terminal-2023815619-r5 { fill: #efe9e4 }
- .terminal-2023815619-r6 { fill: #efeedf }
- .terminal-2023815619-r7 { fill: #e9eee5 }
- .terminal-2023815619-r8 { fill: #e4eee8 }
- .terminal-2023815619-r9 { fill: #dfebed }
- .terminal-2023815619-r10 { fill: #e2edeb }
- .terminal-2023815619-r11 { fill: #e4eee8;font-weight: bold }
- .terminal-2023815619-r12 { fill: #dfebed;font-weight: bold }
- .terminal-2023815619-r13 { fill: #e3e6eb }
- .terminal-2023815619-r14 { fill: #dfe9ed }
- .terminal-2023815619-r15 { fill: #e3e6eb;font-weight: bold }
- .terminal-2023815619-r16 { fill: #e6e3e9 }
+ .terminal-1570661136-r1 { fill: #c5c8c6 }
+ .terminal-1570661136-r2 { fill: #eae3e5 }
+ .terminal-1570661136-r3 { fill: #e8e0e7 }
+ .terminal-1570661136-r4 { fill: #efe9e4 }
+ .terminal-1570661136-r5 { fill: #ede6e6 }
+ .terminal-1570661136-r6 { fill: #efeedf }
+ .terminal-1570661136-r7 { fill: #e9eee5 }
+ .terminal-1570661136-r8 { fill: #e2edeb }
+ .terminal-1570661136-r9 { fill: #e4eee8;font-weight: bold }
+ .terminal-1570661136-r10 { fill: #dfebed;font-weight: bold }
+ .terminal-1570661136-r11 { fill: #dfe9ed }
+ .terminal-1570661136-r12 { fill: #e3e6eb;font-weight: bold }
+ .terminal-1570661136-r13 { fill: #e6e3e9 }
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
- PlaceholderApp
+ PlaceholderApp
-
-
-
-
- Placeholder p2 here!
- This is a custom label for p1.
- #p4
- #p3#p5Placeholde
- r
-
- Lorem ipsum dolor sit
- 26 x 6amet, consectetur 27 x 6
- adipiscing elit. Etiam
- feugiat ac elit sit amet
-
-
- Lorem ipsum dolor sit amet,
- consectetur adipiscing elit. Etiam 40 x 6
- feugiat ac elit sit amet accumsan.
- Suspendisse bibendum nec libero quis
- gravida. Phasellus id eleifend ligula.
- Nullam imperdiet sem tellus, sed
- vehicula nisl faucibus sit amet. Lorem ipsum dolor sit amet,
- Praesent iaculis tempor ultricies. Sedconsectetur adipiscing elit. Etiam
- lacinia, tellus id rutrum lacinia, feugiat ac elit sit amet accumsan.
- sapien sapien congue mauris, sit amet Suspendisse bibendum nec libero quis
+
+
+
+
+ Placeholder p2 here!
+ This is a custom label for p1.
+ #p4
+ #p3#p5Placeholde
+ r
+
+ Lorem ipsum dolor sit
+ 26 x 6amet, consectetur 27 x 6
+ adipiscing elit. Etiam
+ feugiat ac elit sit amet
+
+
+ Lorem ipsum dolor sit amet,
+ consectetur adipiscing elit. Etiam 40 x 6
+ feugiat ac elit sit amet accumsan.
+ Suspendisse bibendum nec libero quis
+ gravida. Phasellus id eleifend ligula.
+ Nullam imperdiet sem tellus, sed
+ vehicula nisl faucibus sit amet. Lorem ipsum dolor sit amet,
+ Praesent iaculis tempor ultricies. Sedconsectetur adipiscing elit. Etiam
+ lacinia, tellus id rutrum lacinia, feugiat ac elit sit amet accumsan.
+ sapien sapien congue mauris, sit amet Suspendisse bibendum nec libero quis