This commit is contained in:
Will McGugan
2024-10-17 12:05:24 +01:00
17 changed files with 874 additions and 35 deletions

View File

@@ -21,17 +21,6 @@ jobs:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
# Python 3.9 is on macos-13 but not macos-latest (macos-14-arm64)
# https://github.com/actions/setup-python/issues/696#issuecomment-1637587760
exclude:
- { python-version: "3.8", os: "macos-latest" }
- { python-version: "3.9", os: "macos-latest" }
- { python-version: "3.11", os: "macos-latest" }
include:
- { python-version: "3.8", os: "macos-13" }
- { python-version: "3.9", os: "macos-13" }
- { python-version: "3.11", os: "macos-13" }
defaults:
run:
shell: bash

View File

@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
### Changed
- Grid will now size children to the maximum height of a row
@@ -16,8 +17,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Added Link widget
- Added `open_links` to `Markdown` and `MarkdownViewer` widgets
- Added `background-tint` CSS rule https://github.com/Textualize/textual/pull/5117
- Added `App.DEFAULT_MODE`
### Fixed
- Fixed `RadioSet` not being scrollable https://github.com/Textualize/textual/issues/5100
## [0.83.0] - 2024-10-10
### Added

View File

@@ -0,0 +1,24 @@
from textual.app import App, ComposeResult
from textual.containers import Vertical
from textual.widgets import Label
class BackgroundTintApp(App):
CSS_PATH = "background_tint.tcss"
def compose(self) -> ComposeResult:
with Vertical(id="tint1"):
yield Label("0%")
with Vertical(id="tint2"):
yield Label("25%")
with Vertical(id="tint3"):
yield Label("50%")
with Vertical(id="tint4"):
yield Label("75%")
with Vertical(id="tint5"):
yield Label("100%")
if __name__ == "__main__":
app = BackgroundTintApp()
app.run()

View File

@@ -0,0 +1,9 @@
Vertical {
background: $panel;
color: auto 90%;
}
#tint1 { background-tint: $foreground 0%; }
#tint2 { background-tint: $foreground 25%; }
#tint3 { background-tint: $foreground 50%; }
#tint4 { background-tint: $foreground 75% }
#tint5 { background-tint: $foreground 100% }

View File

@@ -90,4 +90,5 @@ widget.styles.background = Color(120, 60, 100)
## See also
- [`background-tint`](./background_tint.md) to blend a color with the background.
- [`color`](./color.md) to set the color of text in a widget.

View File

@@ -0,0 +1,77 @@
# Background-tint
The `background-tint` style modifies the background color by tinting (blending) it with a new color.
This style is typically used to subtly change the background of a widget for emphasis.
For instance the following would make a focused widget have a slightly lighter background.
```css
MyWidget:focus {
background-tint: white 10%
}
```
The background tint color should typically have less than 100% alpha, in order to modify the background color.
If the alpha component is 100% then the tint color will replace the background color entirely.
## Syntax
--8<-- "docs/snippets/syntax_block_start.md"
background-tint: <a href="../../css_types/color">&lt;color&gt;</a> [<a href="../../css_types/percentage">&lt;percentage&gt;</a>];
--8<-- "docs/snippets/syntax_block_end.md"
The `background-tint` style requires a [`<color>`](../css_types/color.md) optionally followed by [`<percentage>`](../css_types/percentage.md) to specify the color's opacity (clamped between `0%` and `100%`).
## Examples
### Basic usage
This example shows background tint applied with alpha from 0 to 100%.
=== "Output"
```{.textual path="docs/examples/styles/background_tint.py"}
```
=== "background_tint.py"
```python
--8<-- "docs/examples/styles/background_tint.py"
```
=== "background.tcss"
```css hl_lines="5-9"
--8<-- "docs/examples/styles/background_tint.tcss"
```
## CSS
```css
/* 10% backgrouhnd tint */
background-tint: blue 10%;
/* 20% RGB color */
background-tint: rgb(100, 120, 200, 0.2);
```
## Python
You can use the same syntax as CSS, or explicitly set a `Color` object for finer-grained control.
```python
# Set 20% blue background tint
widget.styles.background_tint = "blue 20%"
from textual.color import Color
# Set with a color object
widget.styles.background_tint = Color(120, 60, 100, 0.5)
```
## See also
- [`background`](./background.md) to set the background color of a widget.
- [`color`](./color.md) to set the color of text in a widget.

View File

@@ -75,6 +75,7 @@ nav:
- "styles/index.md"
- "styles/align.md"
- "styles/background.md"
- "styles/background_tint.md"
- "styles/border.md"
- "styles/border_subtitle_align.md"
- "styles/border_subtitle_background.md"

View File

@@ -202,23 +202,30 @@ def resolve_box_models(
Returns:
List of resolved box models.
"""
margin_width, margin_height = margin
fraction_width = Fraction(max(0, size.width - margin_width))
fraction_height = Fraction(max(0, size.height - margin_height))
fraction_width = Fraction(size.width)
fraction_height = Fraction(size.height)
fraction_zero = Fraction(0)
margin_size = size - margin
margins = [widget.styles.margin.totals for widget in widgets]
# Fixed box models
box_models: list[BoxModel | None] = [
(
None
if _dimension is not None and _dimension.is_fraction
else widget._get_box_model(
size, viewport_size, fraction_width, fraction_height
size,
viewport_size,
max(fraction_zero, fraction_width - margin_width),
max(fraction_zero, fraction_height - margin_height),
)
)
for (_dimension, widget) in zip(dimensions, widgets)
for (_dimension, widget, (margin_width, margin_height)) in zip(
dimensions, widgets, margins
)
]
if None not in box_models:

View File

@@ -680,6 +680,7 @@ class StylesBuilder:
process_tint = process_color
process_background = process_color
process_background_tint = process_color
process_scrollbar_color = process_color
process_scrollbar_color_hover = process_color
process_scrollbar_color_active = process_color

View File

@@ -91,6 +91,8 @@ class RulesMap(TypedDict, total=False):
background: Color
text_style: Style
background_tint: Color
opacity: float
text_opacity: float
@@ -215,6 +217,7 @@ class StylesBase:
"auto_color",
"color",
"background",
"background_tint",
"opacity",
"text_opacity",
"tint",
@@ -285,6 +288,11 @@ class StylesBase:
Supports `Color` objects but also strings e.g. "red" or "#ff0000"
You can also specify an opacity after a color e.g. "blue 10%"
"""
background_tint = ColorProperty(Color(0, 0, 0, 0))
"""Set a color to tint (blend) with the background.
Supports `Color` objects but also strings e.g. "red" or "#ff0000"
You can also specify an opacity after a color e.g. "blue 10%"
"""
text_style = StyleFlagsProperty()
"""Set the text style of the widget using Rich StyleFlags.
e.g. `"bold underline"` or `"b u strikethrough"`.
@@ -1011,6 +1019,8 @@ class Styles(StylesBase):
append_declaration("color", self.color.hex)
if "background" in rules:
append_declaration("background", self.background.hex)
if "background_tint" in rules:
append_declaration("background-tint", self.background_tint.hex)
if "text_style" in rules:
append_declaration("text-style", str(get_rule("text_style")))
if "tint" in rules:

View File

@@ -1031,8 +1031,12 @@ class DOMNode(MessagePump):
has_rule = styles.has_rule
opacity *= styles.opacity
if has_rule("background"):
text_background = background + styles.background
background += styles.background.multiply_alpha(opacity)
text_background = (
background + styles.background + styles.background_tint
)
background += (
styles.background + styles.background_tint
).multiply_alpha(opacity)
else:
text_background = background
if has_rule("color"):
@@ -1120,7 +1124,7 @@ class DOMNode(MessagePump):
for node in reversed(self.ancestors_with_self):
styles = node.styles
base_background = background
background += styles.background
background += styles.background + styles.background_tint
return (base_background, background)
@property
@@ -1136,7 +1140,9 @@ class DOMNode(MessagePump):
styles = node.styles
base_background = background
opacity *= styles.opacity
background += styles.background.multiply_alpha(opacity)
background += (styles.background + styles.background_tint).multiply_alpha(
opacity
)
return (base_background, background)
@property
@@ -1151,7 +1157,7 @@ class DOMNode(MessagePump):
for node in reversed(self.ancestors_with_self):
styles = node.styles
base_background = background
background += styles.background
background += styles.background + styles.background_tint
if styles.has_rule("color"):
base_color = color
if styles.auto_color:

View File

@@ -9,14 +9,14 @@ from rich.console import RenderableType
from textual import _widget_navigation
from textual.binding import Binding, BindingType
from textual.containers import Container
from textual.containers import VerticalScroll
from textual.events import Click, Mount
from textual.message import Message
from textual.reactive import var
from textual.widgets._radio_button import RadioButton
class RadioSet(Container, can_focus=True, can_focus_children=False):
class RadioSet(VerticalScroll, can_focus=True, can_focus_children=False):
"""Widget for grouping a collection of radio buttons into a set.
When a collection of [`RadioButton`][textual.widgets.RadioButton]s are
@@ -42,7 +42,7 @@ class RadioSet(Container, can_focus=True, can_focus_children=False):
* ToggleButton. If those styles ever get updated, these should be too.
*/
RadioSet > * {
RadioSet > RadioButton {
background: transparent;
border: none;
padding: 0 1;
@@ -188,6 +188,7 @@ class RadioSet(Container, can_focus=True, can_focus_children=False):
self.query(RadioButton).remove_class("-selected")
if self._selected is not None:
self._nodes[self._selected].add_class("-selected")
self._scroll_to_selected()
def _on_radio_button_changed(self, event: RadioButton.Changed) -> None:
"""Respond to the value of a button in the set being changed.
@@ -276,3 +277,9 @@ class RadioSet(Container, can_focus=True, can_focus_children=False):
button = self._nodes[self._selected]
assert isinstance(button, RadioButton)
button.toggle()
def _scroll_to_selected(self) -> None:
"""Ensure that the selected button is in view."""
if self._selected is not None:
button = self._nodes[self._selected]
self.call_after_refresh(self.scroll_to_widget, button, animate=False)

View File

@@ -0,0 +1,153 @@
<svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Regular"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Bold"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
font-style: bold;
font-weight: 700;
}
.terminal-2147534319-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-2147534319-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-2147534319-r1 { fill: #e2e3e3 }
.terminal-2147534319-r2 { fill: #c5c8c6 }
.terminal-2147534319-r3 { fill: #ebebec }
.terminal-2147534319-r4 { fill: #f3f3f4 }
.terminal-2147534319-r5 { fill: #fcfcfc }
</style>
<defs>
<clipPath id="terminal-2147534319-clip-terminal">
<rect x="0" y="0" width="975.0" height="584.5999999999999" />
</clipPath>
<clipPath id="terminal-2147534319-line-0">
<rect x="0" y="1.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-1">
<rect x="0" y="25.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-2">
<rect x="0" y="50.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-3">
<rect x="0" y="74.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-4">
<rect x="0" y="99.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-5">
<rect x="0" y="123.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-6">
<rect x="0" y="147.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-7">
<rect x="0" y="172.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-8">
<rect x="0" y="196.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-9">
<rect x="0" y="221.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-10">
<rect x="0" y="245.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-11">
<rect x="0" y="269.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-12">
<rect x="0" y="294.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-13">
<rect x="0" y="318.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-14">
<rect x="0" y="343.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-15">
<rect x="0" y="367.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-16">
<rect x="0" y="391.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-17">
<rect x="0" y="416.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-18">
<rect x="0" y="440.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-19">
<rect x="0" y="465.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-20">
<rect x="0" y="489.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-21">
<rect x="0" y="513.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-2147534319-line-22">
<rect x="0" y="538.3" width="976" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-2147534319-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">BackgroundTintApp</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-2147534319-clip-terminal)">
<rect fill="#24292f" x="0" y="1.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="74.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="99.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="123.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#66696d" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#a8aaac" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-2147534319-matrix">
<text class="terminal-2147534319-r1" x="0" y="20" textLength="976" clip-path="url(#terminal-2147534319-line-0)">0%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-2147534319-r2" x="976" y="20" textLength="12.2" clip-path="url(#terminal-2147534319-line-0)">
</text><text class="terminal-2147534319-r2" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-2147534319-line-1)">
</text><text class="terminal-2147534319-r2" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-2147534319-line-2)">
</text><text class="terminal-2147534319-r2" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-2147534319-line-3)">
</text><text class="terminal-2147534319-r2" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-2147534319-line-4)">
</text><text class="terminal-2147534319-r2" x="976" y="142" textLength="12.2" clip-path="url(#terminal-2147534319-line-5)">
</text><text class="terminal-2147534319-r3" x="0" y="166.4" textLength="976" clip-path="url(#terminal-2147534319-line-6)">33%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-2147534319-r2" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-2147534319-line-6)">
</text><text class="terminal-2147534319-r2" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-2147534319-line-7)">
</text><text class="terminal-2147534319-r2" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-2147534319-line-8)">
</text><text class="terminal-2147534319-r2" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-2147534319-line-9)">
</text><text class="terminal-2147534319-r2" x="976" y="264" textLength="12.2" clip-path="url(#terminal-2147534319-line-10)">
</text><text class="terminal-2147534319-r2" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-2147534319-line-11)">
</text><text class="terminal-2147534319-r4" x="0" y="312.8" textLength="976" clip-path="url(#terminal-2147534319-line-12)">66%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-2147534319-r2" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-2147534319-line-12)">
</text><text class="terminal-2147534319-r2" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-2147534319-line-13)">
</text><text class="terminal-2147534319-r2" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-2147534319-line-14)">
</text><text class="terminal-2147534319-r2" x="976" y="386" textLength="12.2" clip-path="url(#terminal-2147534319-line-15)">
</text><text class="terminal-2147534319-r2" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-2147534319-line-16)">
</text><text class="terminal-2147534319-r2" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-2147534319-line-17)">
</text><text class="terminal-2147534319-r5" x="0" y="459.2" textLength="976" clip-path="url(#terminal-2147534319-line-18)">100%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-2147534319-r2" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-2147534319-line-18)">
</text><text class="terminal-2147534319-r2" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-2147534319-line-19)">
</text><text class="terminal-2147534319-r2" x="976" y="508" textLength="12.2" clip-path="url(#terminal-2147534319-line-20)">
</text><text class="terminal-2147534319-r2" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-2147534319-line-21)">
</text><text class="terminal-2147534319-r2" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-2147534319-line-22)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,154 @@
<svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Regular"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Bold"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
font-style: bold;
font-weight: 700;
}
.terminal-3137451053-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-3137451053-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-3137451053-r1 { fill: #e9e9ea }
.terminal-3137451053-r2 { fill: #c5c8c6 }
.terminal-3137451053-r3 { fill: #eeeeee }
.terminal-3137451053-r4 { fill: #0d0d0e }
.terminal-3137451053-r5 { fill: #121212 }
.terminal-3137451053-r6 { fill: #171717 }
</style>
<defs>
<clipPath id="terminal-3137451053-clip-terminal">
<rect x="0" y="0" width="975.0" height="584.5999999999999" />
</clipPath>
<clipPath id="terminal-3137451053-line-0">
<rect x="0" y="1.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-1">
<rect x="0" y="25.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-2">
<rect x="0" y="50.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-3">
<rect x="0" y="74.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-4">
<rect x="0" y="99.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-5">
<rect x="0" y="123.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-6">
<rect x="0" y="147.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-7">
<rect x="0" y="172.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-8">
<rect x="0" y="196.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-9">
<rect x="0" y="221.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-10">
<rect x="0" y="245.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-11">
<rect x="0" y="269.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-12">
<rect x="0" y="294.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-13">
<rect x="0" y="318.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-14">
<rect x="0" y="343.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-15">
<rect x="0" y="367.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-16">
<rect x="0" y="391.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-17">
<rect x="0" y="416.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-18">
<rect x="0" y="440.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-19">
<rect x="0" y="465.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-20">
<rect x="0" y="489.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-21">
<rect x="0" y="513.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-3137451053-line-22">
<rect x="0" y="538.3" width="976" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-3137451053-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">BackgroundTintApp</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-3137451053-clip-terminal)">
<rect fill="#24292f" x="0" y="1.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#24292f" x="0" y="74.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#565a5e" x="0" y="99.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#565a5e" x="0" y="123.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#565a5e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#565a5e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#565a5e" x="0" y="196.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#888b8e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#888b8e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#888b8e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#888b8e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#888b8e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#babcbd" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#babcbd" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#babcbd" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#babcbd" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#babcbd" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#ededed" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-3137451053-matrix">
<text class="terminal-3137451053-r1" x="0" y="20" textLength="976" clip-path="url(#terminal-3137451053-line-0)">0%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3137451053-r2" x="976" y="20" textLength="12.2" clip-path="url(#terminal-3137451053-line-0)">
</text><text class="terminal-3137451053-r2" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-3137451053-line-1)">
</text><text class="terminal-3137451053-r2" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-3137451053-line-2)">
</text><text class="terminal-3137451053-r2" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-3137451053-line-3)">
</text><text class="terminal-3137451053-r3" x="0" y="117.6" textLength="976" clip-path="url(#terminal-3137451053-line-4)">25%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3137451053-r2" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-3137451053-line-4)">
</text><text class="terminal-3137451053-r2" x="976" y="142" textLength="12.2" clip-path="url(#terminal-3137451053-line-5)">
</text><text class="terminal-3137451053-r2" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-3137451053-line-6)">
</text><text class="terminal-3137451053-r2" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-3137451053-line-7)">
</text><text class="terminal-3137451053-r2" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-3137451053-line-8)">
</text><text class="terminal-3137451053-r4" x="0" y="239.6" textLength="976" clip-path="url(#terminal-3137451053-line-9)">50%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3137451053-r2" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-3137451053-line-9)">
</text><text class="terminal-3137451053-r2" x="976" y="264" textLength="12.2" clip-path="url(#terminal-3137451053-line-10)">
</text><text class="terminal-3137451053-r2" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-3137451053-line-11)">
</text><text class="terminal-3137451053-r2" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-3137451053-line-12)">
</text><text class="terminal-3137451053-r2" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-3137451053-line-13)">
</text><text class="terminal-3137451053-r5" x="0" y="361.6" textLength="976" clip-path="url(#terminal-3137451053-line-14)">75%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3137451053-r2" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-3137451053-line-14)">
</text><text class="terminal-3137451053-r2" x="976" y="386" textLength="12.2" clip-path="url(#terminal-3137451053-line-15)">
</text><text class="terminal-3137451053-r2" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-3137451053-line-16)">
</text><text class="terminal-3137451053-r2" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-3137451053-line-17)">
</text><text class="terminal-3137451053-r2" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-3137451053-line-18)">
</text><text class="terminal-3137451053-r6" x="0" y="483.6" textLength="976" clip-path="url(#terminal-3137451053-line-19)">100%&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-3137451053-r2" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-3137451053-line-19)">
</text><text class="terminal-3137451053-r2" x="976" y="508" textLength="12.2" clip-path="url(#terminal-3137451053-line-20)">
</text><text class="terminal-3137451053-r2" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-3137451053-line-21)">
</text><text class="terminal-3137451053-r2" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-3137451053-line-22)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,153 @@
<svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
<!-- Generated with Rich https://www.textualize.io -->
<style>
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Regular"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
font-style: normal;
font-weight: 400;
}
@font-face {
font-family: "Fira Code";
src: local("FiraCode-Bold"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
font-style: bold;
font-weight: 700;
}
.terminal-952358996-matrix {
font-family: Fira Code, monospace;
font-size: 20px;
line-height: 24.4px;
font-variant-east-asian: full-width;
}
.terminal-952358996-title {
font-size: 18px;
font-weight: bold;
font-family: arial;
}
.terminal-952358996-r1 { fill: #ddeedd }
.terminal-952358996-r2 { fill: #c5c8c6 }
.terminal-952358996-r3 { fill: #e1e1e1 }
.terminal-952358996-r4 { fill: #ffdddd }
.terminal-952358996-r5 { fill: #ddddff }
</style>
<defs>
<clipPath id="terminal-952358996-clip-terminal">
<rect x="0" y="0" width="975.0" height="584.5999999999999" />
</clipPath>
<clipPath id="terminal-952358996-line-0">
<rect x="0" y="1.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-1">
<rect x="0" y="25.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-2">
<rect x="0" y="50.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-3">
<rect x="0" y="74.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-4">
<rect x="0" y="99.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-5">
<rect x="0" y="123.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-6">
<rect x="0" y="147.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-7">
<rect x="0" y="172.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-8">
<rect x="0" y="196.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-9">
<rect x="0" y="221.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-10">
<rect x="0" y="245.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-11">
<rect x="0" y="269.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-12">
<rect x="0" y="294.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-13">
<rect x="0" y="318.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-14">
<rect x="0" y="343.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-15">
<rect x="0" y="367.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-16">
<rect x="0" y="391.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-17">
<rect x="0" y="416.3" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-18">
<rect x="0" y="440.7" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-19">
<rect x="0" y="465.1" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-20">
<rect x="0" y="489.5" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-21">
<rect x="0" y="513.9" width="976" height="24.65"/>
</clipPath>
<clipPath id="terminal-952358996-line-22">
<rect x="0" y="538.3" width="976" height="24.65"/>
</clipPath>
</defs>
<rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="633.6" rx="8"/><text class="terminal-952358996-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">FRApp</text>
<g transform="translate(26,22)">
<circle cx="0" cy="0" r="7" fill="#ff5f57"/>
<circle cx="22" cy="0" r="7" fill="#febc2e"/>
<circle cx="44" cy="0" r="7" fill="#28c840"/>
</g>
<g transform="translate(9, 41)" clip-path="url(#terminal-952358996-clip-terminal)">
<rect fill="#008000" x="0" y="1.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="25.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="50.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="74.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#ff0000" x="24.4" y="74.7" width="927.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="951.6" y="74.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="48.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#0000ff" x="48.8" y="196.7" width="878.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="927.2" y="196.7" width="48.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="976" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="976" height="24.65" shape-rendering="crispEdges"/>
<g class="terminal-952358996-matrix">
<text class="terminal-952358996-r1" x="0" y="20" textLength="976" clip-path="url(#terminal-952358996-line-0)">No&#160;margin&#160;-&#160;should&#160;extend&#160;to&#160;left&#160;and&#160;right&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-952358996-r2" x="976" y="20" textLength="12.2" clip-path="url(#terminal-952358996-line-0)">
</text><text class="terminal-952358996-r2" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-952358996-line-1)">
</text><text class="terminal-952358996-r2" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-952358996-line-2)">
</text><text class="terminal-952358996-r4" x="24.4" y="93.2" textLength="927.2" clip-path="url(#terminal-952358996-line-3)">A&#160;margin&#160;of&#160;2,&#160;should&#160;be&#160;2&#160;cells&#160;around&#160;the&#160;text&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-952358996-r2" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-952358996-line-3)">
</text><text class="terminal-952358996-r2" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-952358996-line-4)">
</text><text class="terminal-952358996-r2" x="976" y="142" textLength="12.2" clip-path="url(#terminal-952358996-line-5)">
</text><text class="terminal-952358996-r2" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-952358996-line-6)">
</text><text class="terminal-952358996-r2" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-952358996-line-7)">
</text><text class="terminal-952358996-r5" x="48.8" y="215.2" textLength="878.4" clip-path="url(#terminal-952358996-line-8)">A&#160;margin&#160;of&#160;4,&#160;should&#160;be&#160;4&#160;cells&#160;around&#160;the&#160;text&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text class="terminal-952358996-r2" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-952358996-line-8)">
</text><text class="terminal-952358996-r2" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-952358996-line-9)">
</text><text class="terminal-952358996-r2" x="976" y="264" textLength="12.2" clip-path="url(#terminal-952358996-line-10)">
</text><text class="terminal-952358996-r2" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-952358996-line-11)">
</text><text class="terminal-952358996-r2" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-952358996-line-12)">
</text><text class="terminal-952358996-r2" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-952358996-line-13)">
</text><text class="terminal-952358996-r2" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-952358996-line-14)">
</text><text class="terminal-952358996-r2" x="976" y="386" textLength="12.2" clip-path="url(#terminal-952358996-line-15)">
</text><text class="terminal-952358996-r2" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-952358996-line-16)">
</text><text class="terminal-952358996-r2" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-952358996-line-17)">
</text><text class="terminal-952358996-r2" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-952358996-line-18)">
</text><text class="terminal-952358996-r2" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-952358996-line-19)">
</text><text class="terminal-952358996-r2" x="976" y="508" textLength="12.2" clip-path="url(#terminal-952358996-line-20)">
</text><text class="terminal-952358996-r2" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-952358996-line-21)">
</text><text class="terminal-952358996-r2" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-952358996-line-22)">
</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -8,27 +8,28 @@ from tests.snapshot_tests.language_snippets import SNIPPETS
from textual import events, on
from textual.app import App, ComposeResult
from textual.binding import Binding, Keymap
from textual.containers import Center, Grid, Middle, Vertical
from textual.binding import Binding
from textual.containers import Vertical, VerticalScroll
from textual.containers import Center, Container, Grid, Middle, Vertical, VerticalScroll
from textual.pilot import Pilot
from textual.renderables.gradient import LinearGradient
from textual.screen import ModalScreen, Screen
from textual.widgets import (
Button,
Header,
DataTable,
Input,
RichLog,
TextArea,
Footer,
Header,
Input,
Label,
Log,
OptionList,
Placeholder,
ProgressBar,
RadioSet,
RichLog,
SelectionList,
Static,
Switch,
TextArea,
)
from textual.widgets import ProgressBar, Label, Switch
from textual.widgets import Static
from textual.widgets.text_area import BUILTIN_LANGUAGES, Selection, TextAreaTheme
# These paths should be relative to THIS directory.
@@ -331,6 +332,23 @@ def test_radio_set_example(snap_compare):
assert snap_compare(WIDGET_EXAMPLES_DIR / "radio_set.py")
def test_radio_set_is_scrollable(snap_compare):
"""Regression test for https://github.com/Textualize/textual/issues/5100"""
class RadioSetApp(App):
CSS = """
RadioSet {
height: 5;
}
"""
def compose(self) -> ComposeResult:
yield RadioSet(*[(f"This is option #{n}") for n in range(10)])
app = RadioSetApp()
assert snap_compare(app, press=["up"])
def test_content_switcher_example_initial(snap_compare):
assert snap_compare(WIDGET_EXAMPLES_DIR / "content_switcher.py")
@@ -652,7 +670,8 @@ def test_richlog_width(snap_compare):
def test_richlog_min_width(snap_compare):
"""The available space of this RichLog is less than the minimum width, so written
content should be rendered at `min_width`. This snapshot should show the renderable
clipping at the right edge, as there's not enough space to satisfy the minimum width."""
clipping at the right edge, as there's not enough space to satisfy the minimum width.
"""
class RichLogMinWidth20(App[None]):
def compose(self) -> ComposeResult:
@@ -2292,3 +2311,66 @@ def test_maximize_allow(snap_compare):
yield Footer() # Not allowed
assert snap_compare(MaximizeApp(), press=["m"])
def test_background_tint(snap_compare):
class BackgroundTintApp(App):
CSS = """
Vertical {
background: $panel;
}
#tint1 { background-tint: $foreground 0%; }
#tint2 { background-tint: $foreground 33%; }
#tint3 { background-tint: $foreground 66%; }
#tint4 { background-tint: $foreground 100% }
"""
def compose(self) -> ComposeResult:
with Vertical(id="tint1"):
yield Label("0%")
with Vertical(id="tint2"):
yield Label("33%")
with Vertical(id="tint3"):
yield Label("66%")
with Vertical(id="tint4"):
yield Label("100%")
assert snap_compare(BackgroundTintApp())
def test_fr_and_margin(snap_compare):
"""Regression test for https://github.com/Textualize/textual/issues/5116"""
# Check margins can be independently applied to widgets with fr unites
class FRApp(App):
CSS = """
#first-container {
background: green;
height: auto;
}
#second-container {
margin: 2;
background: red;
height: auto;
}
#third-container {
margin: 4;
background: blue;
height: auto;
}
"""
def compose(self) -> ComposeResult:
with Container(id="first-container"):
yield Label("No margin - should extend to left and right")
with Container(id="second-container"):
yield Label("A margin of 2, should be 2 cells around the text")
with Container(id="third-container"):
yield Label("A margin of 4, should be 4 cells around the text")
assert snap_compare(FRApp())