Merge pull request #606 from Textualize/render-enhancements

Render enhancements
This commit is contained in:
Will McGugan
2022-07-12 10:44:57 +01:00
committed by GitHub
19 changed files with 146 additions and 232 deletions

35
poetry.lock generated
View File

@@ -52,7 +52,7 @@ python-versions = ">=3.5"
[[package]]
name = "atomicwrites"
version = "1.4.0"
version = "1.4.1"
description = "Atomic file writes."
category = "dev"
optional = false
@@ -208,7 +208,7 @@ dev = ["twine", "markdown", "flake8", "wheel"]
[[package]]
name = "griffe"
version = "0.21.0"
version = "0.22.0"
description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
category = "dev"
optional = false
@@ -345,7 +345,7 @@ mkdocs = ">=1.1"
[[package]]
name = "mkdocs-material"
version = "8.3.8"
version = "8.3.9"
description = "Documentation that simply works"
category = "dev"
optional = false
@@ -713,7 +713,7 @@ python-versions = ">=3.6"
[[package]]
name = "typing-extensions"
version = "4.2.0"
version = "4.3.0"
description = "Backported and Experimental Type Hints for Python 3.7+"
category = "main"
optional = false
@@ -721,7 +721,7 @@ python-versions = ">=3.7"
[[package]]
name = "virtualenv"
version = "20.15.0"
version = "20.15.1"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
@@ -869,10 +869,7 @@ asynctest = [
{file = "asynctest-0.13.0-py3-none-any.whl", hash = "sha256:5da6118a7e6d6b54d83a8f7197769d046922a44d2a99c21382f0a6e4fadae676"},
{file = "asynctest-0.13.0.tar.gz", hash = "sha256:c27862842d15d83e6a34eb0b2866c323880eb3a75e4485b079ea11748fd77fac"},
]
atomicwrites = [
{file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
{file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
]
atomicwrites = []
attrs = [
{file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
@@ -1042,10 +1039,7 @@ ghp-import = [
{file = "ghp-import-2.1.0.tar.gz", hash = "sha256:9c535c4c61193c2df8871222567d7fd7e5014d835f97dc7b7439069e2413d343"},
{file = "ghp_import-2.1.0-py3-none-any.whl", hash = "sha256:8337dd7b50877f163d4c0289bc1f1c7f127550241988d568c1db512c4324a619"},
]
griffe = [
{file = "griffe-0.21.0-py3-none-any.whl", hash = "sha256:e9fb5eeb7c721e1d84804452bdc742bd57b120b13aba663157668ae2d217088a"},
{file = "griffe-0.21.0.tar.gz", hash = "sha256:61ab3bc02b09afeb489f1aef44c646a09f1837d9cdf15943ac6021903a4d3984"},
]
griffe = []
identify = [
{file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"},
{file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"},
@@ -1124,10 +1118,7 @@ mkdocs-autorefs = [
{file = "mkdocs-autorefs-0.4.1.tar.gz", hash = "sha256:70748a7bd025f9ecd6d6feeba8ba63f8e891a1af55f48e366d6d6e78493aba84"},
{file = "mkdocs_autorefs-0.4.1-py3-none-any.whl", hash = "sha256:a2248a9501b29dc0cc8ba4c09f4f47ff121945f6ce33d760f145d6f89d313f5b"},
]
mkdocs-material = [
{file = "mkdocs-material-8.3.8.tar.gz", hash = "sha256:b9cd305c3c29ef758931dae06e4aea0ca9f8bcc8ac6b2d45f10f932a015d6b83"},
{file = "mkdocs_material-8.3.8-py2.py3-none-any.whl", hash = "sha256:949c75fa934d4b9ecc7b519964e58f0c9fc29f2ceb04736c85809cdbc403dfb5"},
]
mkdocs-material = []
mkdocs-material-extensions = [
{file = "mkdocs-material-extensions-1.0.3.tar.gz", hash = "sha256:bfd24dfdef7b41c312ede42648f9eb83476ea168ec163b613f9abd12bbfddba2"},
{file = "mkdocs_material_extensions-1.0.3-py3-none-any.whl", hash = "sha256:a82b70e533ce060b2a5d9eb2bc2e1be201cf61f901f93704b4acf6e3d5983a44"},
@@ -1468,14 +1459,8 @@ typed-ast = [
{file = "typed_ast-1.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:0fdbcf2fef0ca421a3f5912555804296f0b0960f0418c440f5d6d3abb549f3e1"},
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
]
typing-extensions = [
{file = "typing_extensions-4.2.0-py3-none-any.whl", hash = "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708"},
{file = "typing_extensions-4.2.0.tar.gz", hash = "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"},
]
virtualenv = [
{file = "virtualenv-20.15.0-py2.py3-none-any.whl", hash = "sha256:804cce4de5b8a322f099897e308eecc8f6e2951f1a8e7e2b3598dff865f01336"},
{file = "virtualenv-20.15.0.tar.gz", hash = "sha256:4c44b1d77ca81f8368e2d7414f9b20c428ad16b343ac6d226206c5b84e2b4fcc"},
]
typing-extensions = []
virtualenv = []
watchdog = [
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a735a990a1095f75ca4f36ea2ef2752c99e6ee997c46b0de507ba40a09bf7330"},
{file = "watchdog-2.1.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b17d302850c8d412784d9246cfe8d7e3af6bcd45f958abb2d08a6f8bedf695d"},

BIN
reference/box.monopic Normal file

Binary file not shown.

View File

@@ -1,4 +1,6 @@
Button {
padding-left: 1;
padding-right: 1;
box-sizing: border-box;
margin: 1;
width: 100%;
}

View File

@@ -6,14 +6,6 @@
transition: color 300ms linear, background 300ms linear;
}
* {
scrollbar-background: $panel-darken-2;
scrollbar-background-hover: $panel-darken-3;
scrollbar-color: $system;
scrollbar-color-active: $accent-darken-1;
scrollbar-size-horizontal: 1;
scrollbar-size-vertical: 2;
}
*:hover {
/* tint: 30% red;
@@ -74,8 +66,8 @@ DataTable {
}
#header {
color: $text-primary-darken-1;
background: $primary-darken-1;
color: $text-primary-background-darken-1;
background: $primary-background-darken-1;
height: 3;
content-align: center middle;
}
@@ -92,7 +84,7 @@ Tweet {
height:12;
width: 100%;
margin: 1 3;
background: $panel;
color: $text-panel;
layout: vertical;
@@ -117,7 +109,6 @@ Tweet {
.code {
height: auto;
}
@@ -172,7 +163,7 @@ Tweet.scroll-horizontal TweetBody {
color: $text-accent;
background: $accent;
height: 1;
border-top: hkey $accent-darken-2;
content-align: center middle;
}
@@ -191,12 +182,12 @@ OptionItem {
OptionItem:hover {
height: 3;
color: $accent;
color: $secondary;
background: $primary-background-darken-1;
/* border-top: hkey $accent2-darken-3;
border-bottom: hkey $accent2-darken-3; */
text-style: bold;
border-left: outer $accent-darken-2;
border-left: outer $secondary-darken-2;
}
Error {
@@ -204,10 +195,10 @@ Error {
height:3;
background: $error;
color: $text-error;
border-top: hkey $error-darken-2;
border-bottom: hkey $error-darken-2;
margin: 1 3;
border-top: wide $error-darken-1;
border-bottom: wide $error-darken-1;
padding: 0;
text-style: bold;
align-horizontal: center;
}
@@ -217,9 +208,9 @@ Warning {
height:3;
background: $warning;
color: $text-warning-fade-1;
border-top: hkey $warning-darken-2;
border-bottom: hkey $warning-darken-2;
margin: 1 2;
border-top: wide $warning-darken-1;
border-bottom: wide $warning-darken-1;
text-style: bold;
align-horizontal: center;
}
@@ -229,13 +220,14 @@ Success {
width:90%;
height:auto;
box-sizing: border-box;
background: $success-lighten-3;
color: $text-success-lighten-3-fade-1;
background: $success;
color: $text-success;
border-top: hkey $success;
border-bottom: hkey $success;
border-top: hkey $success-darken-1;
border-bottom: hkey $success-darken-1;
text-style: bold underline;
text-style: bold;
align-horizontal: center;
}

View File

@@ -88,7 +88,7 @@ class Warning(Widget):
class Success(Widget):
def render(self) -> Text:
return Text("This\nis\na\nsuccess\n message", justify="center")
return Text("This is a success message", justify="center")
class BasicApp(App, css_path="basic.css"):

View File

@@ -225,8 +225,7 @@ class StylesCache:
from_color = Style.from_color
rich_style = styles.rich_style
inner = from_color(bgcolor=background.rich_color) + rich_style
inner = from_color(bgcolor=(base_background + background).rich_color)
outer = from_color(bgcolor=base_background.rich_color)
def post(segments: Iterable[Segment]) -> list[Segment]:
@@ -265,9 +264,7 @@ class StylesCache:
elif (pad_top and y < gutter.top) or (
pad_bottom and y >= height - gutter.bottom
):
background_style = from_color(
color=rich_style.color, bgcolor=background.rich_color
)
background_style = from_color(bgcolor=background.rich_color)
left_style = from_color(color=border_left_color.rich_color)
left = get_box(border_left, inner, outer, left_style)[1][0]
right_style = from_color(color=border_right_color.rich_color)

View File

@@ -85,12 +85,13 @@ DEFAULT_COLORS = ColorSystem(
secondary="#ffa62b",
warning="#ffa62b",
error="#ba3c5b",
success="#6d9f71",
accent="#ffa62b",
success="#4EBF71",
accent="#1A75B4",
system="#5a4599",
dark_surface="#292929",
)
ComposeResult = Iterable[Widget]

View File

@@ -62,7 +62,7 @@ def get_box_model(
else:
# An explicit width
content_width = styles.width.resolve_dimension(
sizing_container, viewport, fraction_unit
sizing_container - styles.margin.totals, viewport, fraction_unit
)
if is_border_box:
content_width -= gutter.width

View File

@@ -834,10 +834,10 @@ class ColorProperty:
_rich_traceback_omit = True
if color is None:
if obj.clear_rule(self.name):
obj.refresh()
obj.refresh(children=True)
elif isinstance(color, Color):
if obj.set_rule(self.name, color):
obj.refresh()
obj.refresh(children=True)
elif isinstance(color, str):
try:
parsed_color = Color.parse(color)
@@ -849,7 +849,7 @@ class ColorProperty:
),
)
if obj.set_rule(self.name, parsed_color):
obj.refresh()
obj.refresh(children=True)
else:
raise StyleValueError(f"Invalid color value {color}")

View File

@@ -43,6 +43,7 @@ VALID_STYLE_FLAGS: Final = {
"none",
"not",
"bold",
"blink",
"italic",
"underline",
"overline",
@@ -50,7 +51,9 @@ VALID_STYLE_FLAGS: Final = {
"b",
"i",
"u",
"uu",
"o",
"reverse",
}
NULL_SPACING: Final = Spacing.all(0)

View File

@@ -178,6 +178,8 @@ class StylesBase(ABC):
"scrollbar_background_active",
}
node: DOMNode | None = None
display = StringEnumProperty(VALID_DISPLAY, "block", layout=True)
visibility = StringEnumProperty(VALID_VISIBILITY, "visible")
layout = LayoutProperty()
@@ -325,11 +327,12 @@ class StylesBase(ABC):
"""
@abstractmethod
def refresh(self, *, layout: bool = False) -> None:
def refresh(self, *, layout: bool = False, children: bool = False) -> None:
"""Mark the styles as requiring a refresh.
Args:
layout (bool, optional): Also require a layout. Defaults to False.
children (bool, opional): Also refresh children. Defaults to False.
"""
@abstractmethod
@@ -439,7 +442,6 @@ class StylesBase(ABC):
class Styles(StylesBase):
node: DOMNode | None = None
_rules: RulesMap = field(default_factory=dict)
important: set[str] = field(default_factory=set)
@@ -486,9 +488,12 @@ class Styles(StylesBase):
def get_rule(self, rule: str, default: object = None) -> object:
return self._rules.get(rule, default)
def refresh(self, *, layout: bool = False) -> None:
def refresh(self, *, layout: bool = False, children: bool = False) -> None:
if self.node is not None:
self.node.refresh(layout=layout)
if children:
for child in self.node.walk_children(with_self=False):
child.refresh(layout=layout)
def reset(self) -> None:
"""Reset the rules to initial state."""
@@ -783,8 +788,8 @@ class RenderStyles(StylesBase):
if self.has_rule(rule_name):
yield rule_name, getattr(self, rule_name)
def refresh(self, *, layout: bool = False) -> None:
self._inline_styles.refresh(layout=layout)
def refresh(self, *, layout: bool = False, children: bool = False) -> None:
self._inline_styles.refresh(layout=layout, children=children)
def merge(self, other: Styles) -> None:
"""Merge values from another Styles.

View File

@@ -143,7 +143,7 @@ class Token(NamedTuple):
yield "name", self.name
yield "value", self.value
yield "path", self.path
yield "code", self.code
yield "code", self.code if len(self.code) < 40 else self.code[:40] + "..."
yield "location", self.location
yield "referenced_by", self.referenced_by, None

View File

@@ -7,6 +7,7 @@ class Vertical(Widget):
CSS = """
Vertical {
layout: vertical;
overflow: auto;
}
"""
@@ -17,5 +18,6 @@ class Horizontal(Widget):
CSS = """
Horizontal {
layout: horizontal;
overflow: auto;
}
"""

View File

@@ -212,18 +212,16 @@ class ScrollBar(Widget):
def render(self) -> RenderableType:
styles = self.parent.styles
scrollbar_style = Style(
bgcolor=(
styles.scrollbar_background_hover.rich_color
if self.mouse_over
else styles.scrollbar_background.rich_color
),
color=(
styles.scrollbar_color_active.rich_color
if self.grabbed
else styles.scrollbar_color.rich_color
),
background = (
styles.scrollbar_background_hover
if self.mouse_over
else styles.scrollbar_background
)
color = (
styles.scrollbar_color_active if self.grabbed else styles.scrollbar_color
)
color = background + color
scrollbar_style = Style.from_color(color.rich_color, background.rich_color)
return ScrollBarRender(
virtual_size=self.window_virtual_size,
window_size=self.window_size,

View File

@@ -16,9 +16,11 @@ import rich.repr
from rich.align import Align
from rich.console import Console, RenderableType
from rich.measure import Measurement
from rich.padding import Padding
from rich.segment import Segment
from rich.style import Style
from rich.styled import Styled
from rich.text import Text
from . import errors, events, messages
from ._animator import BoundAnimator
@@ -72,10 +74,9 @@ class Widget(DOMNode):
scrollbar-background: $panel-darken-2;
scrollbar-background-hover: $panel-darken-3;
scrollbar-color: $system;
scrollbar-color-active: $secondary-darken-1;
scrollbar-color-active: $warning-darken-1;
scrollbar-size-vertical: 2;
scrollbar-size-horizontal: 1;
}
"""
@@ -879,54 +880,7 @@ class Widget(DOMNode):
def watch(self, attribute_name, callback: Callable[[Any], Awaitable[None]]) -> None:
watch(self, attribute_name, callback)
def _style_renderable(self, renderable: RenderableType) -> RenderableType:
"""Applies CSS styles to a renderable by wrapping it in another renderable.
Args:
renderable (RenderableType): Renderable to apply styles to.
Returns:
RenderableType: An updated renderable.
"""
(base_background, base_color), (background, color) = self.colors
styles = self.styles
content_align = (styles.content_align_horizontal, styles.content_align_vertical)
if content_align != ("left", "top"):
horizontal, vertical = content_align
renderable = Align(renderable, horizontal, vertical=vertical)
renderable = Padding(
renderable,
styles.padding,
style=Style.from_color(color.rich_color, background.rich_color),
)
if styles.border:
renderable = Border(
renderable,
styles.border,
inner_color=background,
outer_color=base_background,
)
if styles.outline:
renderable = Border(
renderable,
styles.outline,
inner_color=styles.background,
outer_color=base_background,
outline=True,
)
if styles.tint.a != 0:
renderable = Tint(renderable, styles.tint)
if styles.opacity != 1.0:
renderable = Opacity(renderable, opacity=styles.opacity)
return renderable
def render_styled(self) -> RenderableType:
def _render_styled(self) -> RenderableType:
"""Applies style attributes to the default renderable.
Returns:
@@ -934,8 +888,21 @@ class Widget(DOMNode):
"""
renderable = self.render()
if isinstance(renderable, str):
renderable = Text.from_markup(renderable)
rich_style = self.rich_style
if isinstance(renderable, Text):
renderable.stylize(rich_style)
else:
renderable = Styled(renderable, rich_style)
styles = self.styles
content_align = (styles.content_align_horizontal, styles.content_align_vertical)
content_align = (
styles.content_align_horizontal,
styles.content_align_vertical,
)
if content_align != ("left", "top"):
horizontal, vertical = content_align
renderable = Align(renderable, horizontal, vertical=vertical)
@@ -977,11 +944,11 @@ class Widget(DOMNode):
def _render_content(self) -> None:
"""Render all lines."""
width, height = self.size
renderable = self.render_styled()
renderable = self._render_styled()
options = self.console.options.update_dimensions(width, height).update(
highlight=False
)
lines = self.console.render_lines(renderable, options, style=self.rich_style)
lines = self.console.render_lines(renderable, options)
self._render_cache = RenderCache(self.size, lines)
self._dirty_regions.clear()

View File

@@ -33,145 +33,96 @@ class Button(Widget, can_focus=True):
Button {
width: auto;
height: 3;
background: $primary;
color: $text-primary;
border: tall $primary-lighten-3;
color: $text-primary;
border: none;
border-top: tall $primary-lighten-2;
border-bottom: tall $primary-darken-3;
content-align: center middle;
text-style: bold;
}
content-align: center middle;
margin: 1 0;
align: center middle;
text-style: bold;
transition: background 0.1;/* for "active" effect */
Button:focus {
text-style: bold underline;
}
Button:hover {
border-top: tall $primary-lighten-1;
background: $primary-darken-2;
color: $text-primary-darken-2;
border: tall $primary-lighten-1;
color: $text-primary-darken-2;
}
Button.-active {
background: $primary-lighten-1;
background: $primary;
border-bottom: tall $primary-lighten-2;
border-top: tall $primary-darken-2;
}
.-dark-mode Button {
background: $background;
color: $primary-lighten-2;
border: tall white $primary-lighten-2;
}
.-dark-mode Button:hover {
background: $surface;
}
.-dark-mode Button.-active {
background: $background-lighten-3;
}
/* Success variant */
Button.-success {
background: $success;
color: $text-success;
border: tall $success-lighten-3;
border-top: tall $success-lighten-2;
border-bottom: tall $success-darken-3;
}
Button.-success:hover {
background: $success-darken-1;
color: $text-success-darken-1;
border: tall $success-lighten-2;
background: $success-darken-2;
color: $text-success-darken-2;
}
Button.-success.-active {
background: $success-lighten-1;
}
.-dark-mode Button.-success {
background: $success;
color: $text-success;
border: tall $success-lighten-3;
}
.-dark-mode Button.-success:hover {
background: $success-darken-1;
color: $text-success-darken-1;
border: tall $success-lighten-3;
}
.-dark-mode Button.-success.-active {
background: $success-lighten-1;
border-bottom: tall $success-lighten-2;
border-top: tall $success-darken-2;
}
/* Warning variant */
Button.-warning {
background: $warning;
color: $text-warning;
border: tall $warning-lighten-3;
color: $text-warning;
border-top: tall $warning-lighten-2;
border-bottom: tall $warning-darken-3;
}
Button.-warning:hover {
background: $warning-darken-1;
background: $warning-darken-2;
color: $text-warning-darken-1;
border: tall $warning-lighten-3;
}
Button.-warning.-active {
background: $warning;
border-bottom: tall $warning-lighten-2;
border-top: tall $warning-darken-2;
}
.-dark-mode Button.-warning {
background: $warning;
color: $text-warning;
border: tall $warning-lighten-3;
}
.-dark-mode Button.-warning:hover {
background: $warning-darken-1;
color: $text-warning-darken-1;
border: tall $warning-lighten-3;
}
.-dark-mode Button.-warning.-active {
background: $warning-lighten-1;
}
/* Error variant */
Button.-error {
background: $error;
color: $text-error;
border: tall $error-lighten-3;
border-top: tall $error-lighten-2;
border-bottom: tall $error-darken-3;
}
Button.-error:hover {
background: $error-darken-1;
color: $text-error-darken-1;
border: tall $error-lighten-3;
color: $text-error-darken-2;
}
Button.-error.-active {
background: $error;
border-bottom: tall $error-lighten-2;
border-top: tall $error-darken-2;
}
.-dark-mode Button.-error {
background: $error;
color: $text-error;
border: tall $error-lighten-3;
}
.-dark-mode Button.-error:hover {
background: $error-darken-1;
color: $text-error-darken-1;
border: tall $error-lighten-3;
}
.-dark-mode Button.-error.-active {
background: $error;
}
App.-show-focus Button:focus {
tint: $accent 20%;
}
"""
ACTIVE_EFFECT_DURATION = 0.3

View File

@@ -113,8 +113,8 @@ class DataTable(ScrollView, Generic[CellType]):
}
DataTable > .datatable--header {
text-style: bold;
background: $primary;
color: $text-primary;
background: $primary-darken-1;
color: $text-primary-darken-1;
}
DataTable > .datatable--fixed {
text-style: bold;

View File

@@ -49,7 +49,7 @@ def test_width():
def get_auto_width(container: Size, parent: Size) -> int:
return 10
def get_auto_height(container: Size, parent: Size) -> int:
def get_auto_height(container: Size, parent: Size, width: int) -> int:
return 10
box_model = get_box_model(
@@ -88,7 +88,7 @@ def test_width():
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
)
assert box_model == BoxModel(Fraction(60), Fraction(16), Spacing(1, 2, 3, 4))
assert box_model == BoxModel(Fraction(54), Fraction(16), Spacing(1, 2, 3, 4))
styles.width = "100vw"
styles.max_width = "50%"
@@ -107,7 +107,7 @@ def test_height():
def get_auto_width(container: Size, parent: Size) -> int:
return 10
def get_auto_height(container: Size, parent: Size) -> int:
def get_auto_height(container: Size, parent: Size, width: int) -> int:
return 10
box_model = get_box_model(
@@ -139,6 +139,15 @@ def test_height():
)
assert box_model == BoxModel(Fraction(54), Fraction(20), Spacing(1, 2, 3, 4))
styles.height = "auto"
styles.margin = 2
box_model = get_box_model(
styles, Size(60, 20), Size(80, 24), one, get_auto_width, get_auto_height
)
assert box_model == BoxModel(Fraction(56), Fraction(10), Spacing(2, 2, 2, 2))
styles.margin = 1, 2, 3, 4
styles.height = "100vh"
styles.max_height = "50%"

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
from rich.segment import Segment
from rich.style import Style
from textual.color import Color
from textual.geometry import Region, Size
@@ -41,10 +42,11 @@ def test_no_styles():
content.__getitem__,
content_size=Size(3, 3),
)
style = Style.from_color(bgcolor=Color.parse("green").rich_color)
expected = [
[Segment("foo", styles.rich_style)],
[Segment("bar", styles.rich_style)],
[Segment("baz", styles.rich_style)],
[Segment("foo", style)],
[Segment("bar", style)],
[Segment("baz", style)],
]
assert lines == expected