mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #1408 from Textualize/review-styles-reference
Review styles reference
This commit is contained in:
@@ -396,7 +396,7 @@ Below you can see the code I wrote and a short animation of the app working.
|
|||||||
|
|
||||||
=== "CSS"
|
=== "CSS"
|
||||||
|
|
||||||
```css
|
```sass
|
||||||
Screen {
|
Screen {
|
||||||
align: center middle;
|
align: center middle;
|
||||||
}
|
}
|
||||||
|
|||||||
70
docs/css_types/_template.md
Normal file
70
docs/css_types/_template.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<!-- Template file for a Textual CSS type reference page. -->
|
||||||
|
|
||||||
|
# <type-name>
|
||||||
|
|
||||||
|
<!-- Short description of the type. -->
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
For a simple type like <integer>:
|
||||||
|
|
||||||
|
Describe the type in a short paragraph with an absolute link to the type page.
|
||||||
|
E.g., “The [`<my-type>`](/css_types/my_type) type is such and such with sprinkles on top.”
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
For a type with many different values like <color>:
|
||||||
|
|
||||||
|
Introduce the type with a link to [`<my-type>`](/css_types/my_type).
|
||||||
|
Then, a bullet list with the variants accepted:
|
||||||
|
|
||||||
|
- you can create this type with X Y Z;
|
||||||
|
- you can also do A B C; and
|
||||||
|
- also use D E F.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
For a type that accepts specific options like <border>:
|
||||||
|
|
||||||
|
Add a sentence and a table. Consider ordering values in alphabetical order if there is no other obvious ordering. See below:
|
||||||
|
|
||||||
|
The [`<my-type>`](/css_types/my_type) type can take any of the following values:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|---------------|-----------------------------------------------|
|
||||||
|
| `abc` | Describe here. |
|
||||||
|
| `other val` | Describe this one also. |
|
||||||
|
| `value three` | Please use full stops. |
|
||||||
|
| `zyx` | Describe the value without assuming any rule. |
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Include a good variety of examples.
|
||||||
|
If the type has many different syntaxes, cover all of them.
|
||||||
|
Add comments when needed/if helpful.
|
||||||
|
-->
|
||||||
|
|
||||||
|
```sass
|
||||||
|
.some-class {
|
||||||
|
rule: type-value-1;
|
||||||
|
rule: type-value-2;
|
||||||
|
rule: type-value-3;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
<!-- Same examples as above. -->
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.rule = type_value_1
|
||||||
|
widget.styles.rule = type_value_2
|
||||||
|
widget.styles.rule = type_value_3
|
||||||
|
```
|
||||||
54
docs/css_types/border.md
Normal file
54
docs/css_types/border.md
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# <border>
|
||||||
|
|
||||||
|
The `<border>` CSS type represents a border style.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
The [`<border>`](/css_types/border) type can take any of the following values:
|
||||||
|
|
||||||
|
| Border type | Description |
|
||||||
|
|-------------|----------------------------------------------------------|
|
||||||
|
| `ascii` | A border with plus, hyphen, and vertical bar characters. |
|
||||||
|
| `blank` | A blank border (reserves space for a border). |
|
||||||
|
| `dashed` | Dashed line border. |
|
||||||
|
| `double` | Double lined border. |
|
||||||
|
| `heavy` | Heavy border. |
|
||||||
|
| `hidden` | Alias for "none". |
|
||||||
|
| `hkey` | Horizontal key-line border. |
|
||||||
|
| `inner` | Thick solid border. |
|
||||||
|
| `none` | Disabled border. |
|
||||||
|
| `outer` | Solid border with additional space around content. |
|
||||||
|
| `round` | Rounded corners. |
|
||||||
|
| `solid` | Solid border. |
|
||||||
|
| `tall` | Solid border with additional space top and bottom. |
|
||||||
|
| `vkey` | Vertical key-line border. |
|
||||||
|
| `wide` | Solid border with additional space left and right. |
|
||||||
|
|
||||||
|
## Border command
|
||||||
|
|
||||||
|
The `textual` CLI has a subcommand which will let you explore the various border types interactively, when applied to the CSS rule [`border`](../styles/border.md):
|
||||||
|
|
||||||
|
```
|
||||||
|
textual borders
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
#container {
|
||||||
|
border: heavy red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#heading {
|
||||||
|
border-bottom: solid blue;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.border = ("heavy", "red")
|
||||||
|
widget.styles.border_bottom = ("solid", "blue")
|
||||||
|
```
|
||||||
138
docs/css_types/color.md
Normal file
138
docs/css_types/color.md
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
# <color>
|
||||||
|
|
||||||
|
The `<color>` CSS type represents a color.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Not to be confused with the [`color`](../styles/color.md) CSS rule to set text color.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<color>`](/css_types/color) should be in one of the formats explained in this section.
|
||||||
|
A bullet point summary of the formats available follows:
|
||||||
|
|
||||||
|
- a recognised [named color](#named-colors) (e.g., `red`);
|
||||||
|
- a 3 or 6 hexadecimal digit number representing the [RGB values](#hex-rgb-value) of the color (e.g., `#F35573`);
|
||||||
|
- a 4 or 8 hexadecimal digit number representing the [RGBA values](#hex-rgba-value) of the color (e.g., `#F35573A0`);
|
||||||
|
- a color description in the RGB system, [with](#rgba-description) or [without](#rgb-description) transparency (e.g., `rgb(23, 78, 200)`);
|
||||||
|
- a color description in the HSL system, [with](#hsla-description) or [without](#hsl-description) transparency (e.g., `hsl(290, 70%, 80%)`);
|
||||||
|
|
||||||
|
[Textual's default themes](../../guide/design#theme-reference) also provide many CSS variables with colors that can be used out of the box.
|
||||||
|
|
||||||
|
### Named colors
|
||||||
|
|
||||||
|
A named color is a [`<name>`](./name.md) that Textual recognises.
|
||||||
|
Below, you can find a (collapsed) list of all of the named colors that Textual recognises, along with their hexadecimal values, their RGB values, and a visual sample.
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>All named colors available.</summary>
|
||||||
|
|
||||||
|
```{.rich columns="80" title="colors"}
|
||||||
|
from textual._color_constants import COLOR_NAME_TO_RGB
|
||||||
|
from textual.color import Color
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.text import Text
|
||||||
|
table = Table("Name", "hex", "RGB", "Color", expand=True, highlight=True)
|
||||||
|
|
||||||
|
for name, triplet in sorted(COLOR_NAME_TO_RGB.items()):
|
||||||
|
if len(triplet) != 3:
|
||||||
|
continue
|
||||||
|
color = Color(*triplet)
|
||||||
|
r, g, b = triplet
|
||||||
|
table.add_row(
|
||||||
|
f'"{name}"',
|
||||||
|
Text(f"{color.hex}", "bold green"),
|
||||||
|
f"rgb({r}, {g}, {b})",
|
||||||
|
Text(" ", style=f"on rgb({r},{g},{b})")
|
||||||
|
)
|
||||||
|
output = table
|
||||||
|
```
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Hex RGB value
|
||||||
|
|
||||||
|
The hexadecimal RGB format starts with an octothorpe `#` and is then followed by 3 or 6 hexadecimal digits: `0123456789ABCDEF`.
|
||||||
|
Casing is ignored.
|
||||||
|
|
||||||
|
- If 6 digits are used, the format is `#RRGGBB`:
|
||||||
|
- `RR` represents the red channel;
|
||||||
|
- `GG` represents the green channel; and
|
||||||
|
- `BB` represents the blue channel.
|
||||||
|
- If 3 digits are used, the format is `#RGB`.
|
||||||
|
|
||||||
|
In a 3 digit color, each channel is represented by a single digit which is duplicated when converting to the 6 digit format.
|
||||||
|
For example, the color `#A2F` is the same as `#AA22FF`.
|
||||||
|
|
||||||
|
### Hex RGBA value
|
||||||
|
|
||||||
|
This is the same as the [hex RGB value](#hex-rgb-value), but with an extra channel for the alpha component (that sets transparency).
|
||||||
|
|
||||||
|
- If 8 digits are used, the format is `#RRGGBBAA`, equivalent to the format `#RRGGBB` with two extra digits for transparency.
|
||||||
|
- If 4 digits are used, the format is `#RGBA`, equivalent to the format `#RGB` with an extra digit for transparency.
|
||||||
|
|
||||||
|
### `rgb` description
|
||||||
|
|
||||||
|
The `rgb` format description is a functional description of a color in the RGB color space.
|
||||||
|
This description follows the format `rgb(red, green, blue)`, where `red`, `green`, and `blue` are decimal integers between 0 and 255.
|
||||||
|
They represent the value of the channel with the same name.
|
||||||
|
|
||||||
|
For example, `rgb(0, 255, 32)` is equivalent to `#00FF20`.
|
||||||
|
|
||||||
|
### `rgba` description
|
||||||
|
|
||||||
|
The `rgba` format description is the same as the `rgb` with an extra parameter for transparency, which should be a value between `0` and `1`.
|
||||||
|
|
||||||
|
For example, `rgba(0, 255, 32, 0.5)` is the color `rgb(0, 255, 32)` with 50% transparency.
|
||||||
|
|
||||||
|
### `hsl` description
|
||||||
|
|
||||||
|
The `hsl` format description is a functional description of a color in the HSL color space.
|
||||||
|
This description follows the format `hsl(hue, saturation, lightness)`, where
|
||||||
|
|
||||||
|
- `hue` is a float between 0 and 360;
|
||||||
|
- `saturation` is a percentage between `0%` and `100%`; and
|
||||||
|
- `lightness` is a percentage between `0%` and `100%`.
|
||||||
|
|
||||||
|
For example, the color `#00FF20` would be represented as `hsl(128, 100%, 50%)` in the HSL color space.
|
||||||
|
|
||||||
|
### `hsla` description
|
||||||
|
|
||||||
|
The `hsla` format description is the same as the `hsl` with an extra parameter for transparency, which should be a value between `0` and `1`.
|
||||||
|
|
||||||
|
For example, `hsla(128, 100%, 50%, 0.5)` is the color `hsl(128, 100%, 50%)` with 50% transparency.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
Header {
|
||||||
|
background: red; /* Color name */
|
||||||
|
}
|
||||||
|
|
||||||
|
.accent {
|
||||||
|
color: $accent; /* Textual variable */
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
tint: hsl(300, 20%, 70%); /* HSL description */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
In Python, rules that expect a `<color>` can also accept an instance of the type [`Color`][textual.color.Color].
|
||||||
|
|
||||||
|
```py
|
||||||
|
# Mimicking the CSS syntax
|
||||||
|
widget.styles.background = "red" # Color name
|
||||||
|
widget.styles.color = "$accent" # Textual variable
|
||||||
|
widget.styles.tint = "hsl(300, 20%, 70%)" # HSL description
|
||||||
|
|
||||||
|
from textual.color import Color
|
||||||
|
# Using a Color object directly...
|
||||||
|
color = Color(16, 200, 45)
|
||||||
|
# ... which can also parse the CSS syntax
|
||||||
|
color = Color.parse("#A8F")
|
||||||
|
```
|
||||||
29
docs/css_types/horizontal.md
Normal file
29
docs/css_types/horizontal.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# <horizontal>
|
||||||
|
|
||||||
|
The `<horizontal>` CSS type represents a position along the horizontal axis.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
The [`<horizontal>`](/css_types/horizontal) type can take any of the following values:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
| ---------------- | -------------------------------------------- |
|
||||||
|
| `center` | Aligns in the center of the horizontal axis. |
|
||||||
|
| `left` (default) | Aligns on the left of the horizontal axis. |
|
||||||
|
| `right` | Aligns on the right of the horizontal axis. |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
.container {
|
||||||
|
align-horizontal: right;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.align_horizontal = "right"
|
||||||
|
```
|
||||||
12
docs/css_types/index.md
Normal file
12
docs/css_types/index.md
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# CSS Types
|
||||||
|
|
||||||
|
CSS types define the values that Textual CSS styles accept.
|
||||||
|
|
||||||
|
CSS types will be linked from within the [styles reference](../styles/index.md) in the "Formal Syntax" section of each style.
|
||||||
|
The CSS types will be denoted by a keyword enclosed by angle brackets `<` and `>`.
|
||||||
|
|
||||||
|
For example, the style [`align-horizontal`](../styles/align.md) references the CSS type [`<horizontal>`](./horizontal.md):
|
||||||
|
|
||||||
|
--8<-- "docs/snippets/syntax_block_start.md"
|
||||||
|
align-horizontal: <a href="./horizontal.md"><horizontal></a>;
|
||||||
|
--8<-- "docs/snippets/syntax_block_end.md"
|
||||||
29
docs/css_types/integer.md
Normal file
29
docs/css_types/integer.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# <integer>
|
||||||
|
|
||||||
|
The `<integer>` CSS type represents an integer number.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
An [`<integer>`](/css_types/integer) is any valid integer number like `-10` or `42`.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
Some CSS rules may expect an `<integer>` within certain bounds. If that is the case, it will be noted in that rule.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
.classname {
|
||||||
|
offset: 10 -20
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
In Python, a rule that expects a CSS type `<integer>` will expect a value of the type `int`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.offset = (10, -20)
|
||||||
|
```
|
||||||
26
docs/css_types/name.md
Normal file
26
docs/css_types/name.md
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# <name>
|
||||||
|
|
||||||
|
The `<name>` type represents a sequence of characters that identifies something.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<name>`](/css_types/name) is any non-empty sequence of characters:
|
||||||
|
|
||||||
|
- starting with a letter `a-z`, `A-Z`, or underscore `_`; and
|
||||||
|
- followed by zero or more letters `a-zA-Z`, digits `0-9`, underscores `_`, and hiphens `-`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
Screen {
|
||||||
|
layers: onlyLetters Letters-and-hiphens _lead-under letters-1-digit;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.layers = "onlyLetters Letters-and-hiphens _lead-under letters-1-digit"
|
||||||
|
```
|
||||||
30
docs/css_types/number.md
Normal file
30
docs/css_types/number.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# <number>
|
||||||
|
|
||||||
|
The `<number>` CSS type represents a real number, which can be an integer or a number with a decimal part (akin to a `float` in Python).
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<number>`](/css_types/number) is an [`<integer>`](/css_types/integer), optionally followed by the decimal point `.` and a decimal part composed of one or more digits.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
Grid {
|
||||||
|
grid-size: 3 6 /* Integers are numbers */
|
||||||
|
}
|
||||||
|
|
||||||
|
.translucid {
|
||||||
|
opacity: 0.5 /* Numbers can have a decimal part */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
In Python, a rule that expects a CSS type `<number>` will accept an `int` or a `float`:
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.grid_size = (3, 6) # Integers are numbers
|
||||||
|
widget.styles.opacity = 0.5 # Numbers can have a decimal part
|
||||||
|
```
|
||||||
29
docs/css_types/overflow.md
Normal file
29
docs/css_types/overflow.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# <overflow>
|
||||||
|
|
||||||
|
The `<overflow>` CSS type represents overflow modes.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
The [`<overflow>`](/css_types/overflow) type can take any of the following values:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|----------|----------------------------------------|
|
||||||
|
| `auto` | Determine overflow mode automatically. |
|
||||||
|
| `hidden` | Don't overflow. |
|
||||||
|
| `scroll` | Allow overflowing. |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
#container {
|
||||||
|
overflow-y: hidden; /* Don't overflow */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.overflow_y = "hidden" # Don't overflow
|
||||||
|
```
|
||||||
37
docs/css_types/percentage.md
Normal file
37
docs/css_types/percentage.md
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# <percentage>
|
||||||
|
|
||||||
|
The `<percentage>` CSS type represents a percentage value.
|
||||||
|
It is often used to represent values that are relative to the parent's values.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Not to be confused with the [`<scalar>`](./scalar.md) type.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<percentage>`](/css_types/percentage) is a [`<number>`](/css_types/number) followed by the percent sign `%` (without spaces).
|
||||||
|
Some rules may clamp the values between `0%` and `100%`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
#footer {
|
||||||
|
/* Integer followed by % */
|
||||||
|
color: red 70%;
|
||||||
|
|
||||||
|
/* The number can be negative/decimal, although that may not make sense */
|
||||||
|
offset: -30% 12.5%;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
# Integer followed by %
|
||||||
|
widget.styles.color = "red 70%"
|
||||||
|
|
||||||
|
# The number can be negative/decimal, althought that may not make sense
|
||||||
|
widget.styles.offset = ("-30%", "12.5%")
|
||||||
|
```
|
||||||
113
docs/css_types/scalar.md
Normal file
113
docs/css_types/scalar.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
# <scalar>
|
||||||
|
|
||||||
|
The `<scalar>` CSS type represents a length.
|
||||||
|
It can be a [`<number>`](./number.md) and a unit, or the special value `auto`.
|
||||||
|
It is used to represent lengths, for example in the [`width`](../styles/width.md) and [`height`](../styles/height.md) rules.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Not to be confused with the [`<number>`](./number.md) or [`<percentage>`](./percentage.md) types.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<scalar>`](/css_types/scalar) can be any of the following:
|
||||||
|
|
||||||
|
- a fixed number of cells (e.g., `10`);
|
||||||
|
- a fractional proportion relative to the sizes of the other widgets (e.g., `1fr`);
|
||||||
|
- a percentage relative to the container widget (e.g., `50%`);
|
||||||
|
- a percentage relative to the container width/height (e.g., `25w`/`75h`);
|
||||||
|
- a percentage relative to the viewport width/height (e.g., `25vw`/`75vh`); or
|
||||||
|
- the special value `auto` to compute the optimal size to fit without scrolling.
|
||||||
|
|
||||||
|
A complete reference table and detailed explanations follow.
|
||||||
|
You can [skip to the examples](#examples).
|
||||||
|
|
||||||
|
| Unit symbol | Unit | Example | Description |
|
||||||
|
|-------------|-----------------|---------|-------------------------------------------------------------|
|
||||||
|
| `""` | Cell | `10` | Number of cells (rows or columns). |
|
||||||
|
| `"fr"` | Fraction | `1fr` | Specifies the proportion of space the widget should occupy. |
|
||||||
|
| `"%"` | Percent | `75%` | Length relative to the container widget. |
|
||||||
|
| `"w"` | Width | `25w` | Percentage relative to the width of the container widget. |
|
||||||
|
| `"h"` | Height | `75h` | Percentage relative to the height of the container widget. |
|
||||||
|
| `"vw"` | Viewport width | `25vw` | Percentage relative to the viewport width. |
|
||||||
|
| `"vh"` | Viewport height | `75vh` | Percentage relative to the viewport height. |
|
||||||
|
| - | Auto | `auto` | Tries to compute the optimal size to fit without scrolling. |
|
||||||
|
|
||||||
|
### Cell
|
||||||
|
|
||||||
|
The number of cells is the only unit for a scalar that is _absolute_.
|
||||||
|
This can be an integer or a float but floats are truncated to integers.
|
||||||
|
|
||||||
|
If used to specify a horizontal length, it corresponds to the number of columns.
|
||||||
|
For example, in `width: 15`, this sets the width of a widget to be equal to 15 cells, which translates to 15 columns.
|
||||||
|
|
||||||
|
If used to specify a vertical length, it corresponds to the number of lines.
|
||||||
|
For example, in `height: 10`, this sets the height of a widget to be equal to 10 cells, which translates to 10 lines.
|
||||||
|
|
||||||
|
### Fraction
|
||||||
|
|
||||||
|
The unit fraction is used to represent proportional sizes.
|
||||||
|
|
||||||
|
For example, if two widgets are side by side and one has `width: 1fr` and the other has `width: 3fr`, the second one will be three times as wide as the first one.
|
||||||
|
|
||||||
|
### Percent
|
||||||
|
|
||||||
|
The percent unit matches a [`<percentage>`](./percentage.md) and is used to specify a total length relative to the space made available by the container widget.
|
||||||
|
|
||||||
|
If used to specify a horizontal length, it will be relative to the width of the container.
|
||||||
|
For example, `width: 50%` sets the width of a widget to 50% of the width of its container.
|
||||||
|
|
||||||
|
If used to specify a vertical length, it will be relative to the height of the container.
|
||||||
|
For example, `height: 50%` sets the height of a widget to 50% of the height of its container.
|
||||||
|
|
||||||
|
### Width
|
||||||
|
|
||||||
|
The width unit is similar to the percent unit, except it sets the percentage to be relative to the width of the container.
|
||||||
|
|
||||||
|
For example, `width: 25w` sets the width of a widget to 25% of the width of its container and `height: 25w` sets the height of a widget to 25% of the width of its container.
|
||||||
|
So, if the container has a width of 100 cells, the width and the height of the child widget will be of 25 cells.
|
||||||
|
|
||||||
|
### Height
|
||||||
|
|
||||||
|
The height unit is similar to the percent unit, except it sets the percentage to be relative to the height of the container.
|
||||||
|
|
||||||
|
For example, `height: 75h` sets the height of a widget to 75% of the height of its container and `width: 75h` sets the width of a widget to 75% of the height of its container.
|
||||||
|
So, if the container has a height of 100 cells, the width and the height of the child widget will be of 75 cells.
|
||||||
|
|
||||||
|
### Viewport width
|
||||||
|
|
||||||
|
This is the same as the [width unit](#width), except that it is relative to the width of the viewport instead of the width of the immediate container.
|
||||||
|
The width of the viewport is the width of the terminal minus the widths of widgets that are docked left or right.
|
||||||
|
|
||||||
|
For example, `width: 25vw` will try to set the width of a widget to be 25% of the viewport width, regardless of the widths of its containers.
|
||||||
|
|
||||||
|
### Viewport height
|
||||||
|
|
||||||
|
This is the same as the [height unit](#height), except that it is relative to the height of the viewport instead of the height of the immediate container.
|
||||||
|
The height of the viewport is the height of the terminal minus the heights of widgets that are docked top or bottom.
|
||||||
|
|
||||||
|
For example, `height: 75vh` will try to set the height of a widget to be 75% of the viewport height, regardless of the height of its containers.
|
||||||
|
|
||||||
|
### Auto
|
||||||
|
|
||||||
|
This special value will try to calculate the optimal size to fit the contents of the widget without scrolling.
|
||||||
|
|
||||||
|
For example, if its container is big enough, a label with `width: auto` will be just as wide as its text.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
Horizontal {
|
||||||
|
width: 60; /* 60 cells */
|
||||||
|
height: 1fr; /* proportional size of 1 */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.width = 16 # Cell unit can be specified with an int/float
|
||||||
|
widget.styles.height = "1fr" # proportional size of 1
|
||||||
|
```
|
||||||
40
docs/css_types/text_align.md
Normal file
40
docs/css_types/text_align.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# <text-align>
|
||||||
|
|
||||||
|
The `<text-align>` CSS type represents alignments that can be applied to text.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Not to be confused with the [`text-align`](../styles/text_align.md) CSS rule that sets the alignment of text in a widget.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<text-align>`](/css_types/text_align) can be any of the following values:
|
||||||
|
|
||||||
|
| Value | Alignment type |
|
||||||
|
|-----------|--------------------------------------|
|
||||||
|
| `center` | Center alignment. |
|
||||||
|
| `end` | Alias for `right`. |
|
||||||
|
| `justify` | Text is justified inside the widget. |
|
||||||
|
| `left` | Left alignment. |
|
||||||
|
| `right` | Right alignment. |
|
||||||
|
| `start` | Alias for `left`. |
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
The meanings of `start` and `end` will likely change when RTL languages become supported by Textual.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
Label {
|
||||||
|
rule: justify;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.text_align = "justify"
|
||||||
|
```
|
||||||
46
docs/css_types/text_style.md
Normal file
46
docs/css_types/text_style.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# <text-style>
|
||||||
|
|
||||||
|
The `<text-style>` CSS type represents styles that can be applied to text.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
|
||||||
|
Not to be confused with the [`text-style`](../styles/text_style.md) CSS rule that sets the style of text in a widget.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
A [`<text-style>`](/css_types/text_style) can be any _space-separated_ combination of the following values:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
|-------------|-----------------------------------------------------------------|
|
||||||
|
| `bold` | **Bold text.** |
|
||||||
|
| `italic` | _Italic text._ |
|
||||||
|
| `none` | Plain text with no styling. |
|
||||||
|
| `reverse` | Reverse video text (foreground and background colors reversed). |
|
||||||
|
| `strike` | <s>Strikethrough text.</s> |
|
||||||
|
| `underline` | <u>Underline text.</u> |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
#label1 {
|
||||||
|
/* You can specify any value by itself. */
|
||||||
|
rule: strike;
|
||||||
|
}
|
||||||
|
|
||||||
|
#label2 {
|
||||||
|
/* You can also combine multiple values. */
|
||||||
|
rule: strike bold italic reverse;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
# You can specify any value by itself
|
||||||
|
widget.styles.text_style = "strike"
|
||||||
|
|
||||||
|
# You can also combine multiple values
|
||||||
|
widget.styles.text_style = "bold underline italic"
|
||||||
|
```
|
||||||
29
docs/css_types/vertical.md
Normal file
29
docs/css_types/vertical.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# <vertical>
|
||||||
|
|
||||||
|
The `<vertical>` CSS type represents a position along the vertical axis.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
The [`<vertical>`](/css_types/vertical) type can take any of the following values:
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
| --------------- | ------------------------------------------ |
|
||||||
|
| `bottom` | Aligns at the bottom of the vertical axis. |
|
||||||
|
| `middle` | Aligns in the middle of the vertical axis. |
|
||||||
|
| `top` (default) | Aligns at the top of the vertical axis. |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### CSS
|
||||||
|
|
||||||
|
```sass
|
||||||
|
.container {
|
||||||
|
align-vertical: top;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
```py
|
||||||
|
widget.styles.align_vertical = "top"
|
||||||
|
```
|
||||||
@@ -11,8 +11,8 @@ Static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#box1 {
|
#box1 {
|
||||||
background: darkcyan;
|
|
||||||
layer: above;
|
layer: above;
|
||||||
|
background: darkcyan;
|
||||||
}
|
}
|
||||||
|
|
||||||
#box2 {
|
#box2 {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class AlignApp(App):
|
class AlignApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("Vertical alignment with [b]Textual[/]", classes="box")
|
yield Label("Vertical alignment with [b]Textual[/]", classes="box")
|
||||||
yield Static("Take note, browsers.", classes="box")
|
yield Label("Take note, browsers.", classes="box")
|
||||||
|
|
||||||
|
|
||||||
app = AlignApp(css_path="align.css")
|
app = AlignApp(css_path="align.css")
|
||||||
|
|||||||
53
docs/examples/styles/align_all.css
Normal file
53
docs/examples/styles/align_all.css
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#left-top {
|
||||||
|
/* align: left top; this is the default value and is implied. */
|
||||||
|
}
|
||||||
|
|
||||||
|
#center-top {
|
||||||
|
align: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-top {
|
||||||
|
align: right top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-middle {
|
||||||
|
align: left middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#center-middle {
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-middle {
|
||||||
|
align: right middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-bottom {
|
||||||
|
align: left bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
#center-bottom {
|
||||||
|
align: center bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-bottom {
|
||||||
|
align: right bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen {
|
||||||
|
layout: grid;
|
||||||
|
grid-size: 3 3;
|
||||||
|
grid-gutter: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Container {
|
||||||
|
background: $boost;
|
||||||
|
border: solid gray;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: auto;
|
||||||
|
height: 1;
|
||||||
|
background: $accent;
|
||||||
|
}
|
||||||
20
docs/examples/styles/align_all.py
Normal file
20
docs/examples/styles/align_all.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.containers import Container
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class AlignAllApp(App):
|
||||||
|
"""App that illustrates all alignments."""
|
||||||
|
|
||||||
|
CSS_PATH = "align_all.css"
|
||||||
|
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Container(Label("left top"), id="left-top")
|
||||||
|
yield Container(Label("center top"), id="center-top")
|
||||||
|
yield Container(Label("right top"), id="right-top")
|
||||||
|
yield Container(Label("left middle"), id="left-middle")
|
||||||
|
yield Container(Label("center middle"), id="center-middle")
|
||||||
|
yield Container(Label("right middle"), id="right-middle")
|
||||||
|
yield Container(Label("left bottom"), id="left-bottom")
|
||||||
|
yield Container(Label("center bottom"), id="center-bottom")
|
||||||
|
yield Container(Label("right bottom"), id="right-bottom")
|
||||||
@@ -1,14 +1,18 @@
|
|||||||
Static {
|
Label {
|
||||||
|
width: 100%;
|
||||||
height: 1fr;
|
height: 1fr;
|
||||||
content-align: center middle;
|
content-align: center middle;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#static1 {
|
#static1 {
|
||||||
background: red;
|
background: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
#static2 {
|
#static2 {
|
||||||
background: rgb(0, 255, 0);
|
background: rgb(0, 255, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#static3 {
|
#static3 {
|
||||||
background: hsl(240, 100%, 50%);
|
background: hsl(240, 100%, 50%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class BackgroundApp(App):
|
class BackgroundApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("Widget 1", id="static1")
|
yield Label("Widget 1", id="static1")
|
||||||
yield Static("Widget 2", id="static2")
|
yield Label("Widget 2", id="static2")
|
||||||
yield Static("Widget 3", id="static3")
|
yield Label("Widget 3", id="static3")
|
||||||
|
|
||||||
|
|
||||||
app = BackgroundApp(css_path="background.css")
|
app = BackgroundApp(css_path="background.css")
|
||||||
|
|||||||
49
docs/examples/styles/background_transparency.css
Normal file
49
docs/examples/styles/background_transparency.css
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#t10 {
|
||||||
|
background: red 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t20 {
|
||||||
|
background: red 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t30 {
|
||||||
|
background: red 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t40 {
|
||||||
|
background: red 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t50 {
|
||||||
|
background: red 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t60 {
|
||||||
|
background: red 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t70 {
|
||||||
|
background: red 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t80 {
|
||||||
|
background: red 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t90 {
|
||||||
|
background: red 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#t100 {
|
||||||
|
background: red 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen {
|
||||||
|
layout: horizontal;
|
||||||
|
}
|
||||||
|
|
||||||
|
Static {
|
||||||
|
height: 100%;
|
||||||
|
width: 1fr;
|
||||||
|
content-align: center middle;
|
||||||
|
}
|
||||||
20
docs/examples/styles/background_transparency.py
Normal file
20
docs/examples/styles/background_transparency.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from textual.app import App, ComposeResult
|
||||||
|
from textual.widgets import Static
|
||||||
|
|
||||||
|
|
||||||
|
class BackgroundTransparencyApp(App):
|
||||||
|
"""Simple app to exemplify different transparency settings."""
|
||||||
|
def compose(self) -> ComposeResult:
|
||||||
|
yield Static("10%", id="t10")
|
||||||
|
yield Static("20%", id="t20")
|
||||||
|
yield Static("30%", id="t30")
|
||||||
|
yield Static("40%", id="t40")
|
||||||
|
yield Static("50%", id="t50")
|
||||||
|
yield Static("60%", id="t60")
|
||||||
|
yield Static("70%", id="t70")
|
||||||
|
yield Static("80%", id="t80")
|
||||||
|
yield Static("90%", id="t90")
|
||||||
|
yield Static("100%", id="t100")
|
||||||
|
|
||||||
|
|
||||||
|
app = BackgroundTransparencyApp(css_path="background_transparency.css")
|
||||||
@@ -1,25 +1,30 @@
|
|||||||
|
#label1 {
|
||||||
|
background: red 20%;
|
||||||
|
color: red;
|
||||||
|
border: solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#label2 {
|
||||||
|
background: green 20%;
|
||||||
|
color: green;
|
||||||
|
border: dashed green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#label3 {
|
||||||
|
background: blue 20%;
|
||||||
|
color: blue;
|
||||||
|
border: tall blue;
|
||||||
|
}
|
||||||
|
|
||||||
Screen {
|
Screen {
|
||||||
background: white;
|
background: white;
|
||||||
}
|
}
|
||||||
Screen > Static {
|
|
||||||
|
Screen > Label {
|
||||||
|
width: 100%;
|
||||||
height: 5;
|
height: 5;
|
||||||
content-align: center middle;
|
content-align: center middle;
|
||||||
color: white;
|
color: white;
|
||||||
margin: 1;
|
margin: 1;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
#static1 {
|
|
||||||
background: red 20%;
|
|
||||||
color: red;
|
|
||||||
border: solid red;
|
|
||||||
}
|
|
||||||
#static2 {
|
|
||||||
background: green 20%;
|
|
||||||
color: green;
|
|
||||||
border: dashed green;
|
|
||||||
}
|
|
||||||
#static3 {
|
|
||||||
background: blue 20%;
|
|
||||||
color: blue;
|
|
||||||
border: tall blue;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class BorderApp(App):
|
class BorderApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("My border is solid red", id="static1")
|
yield Label("My border is solid red", id="label1")
|
||||||
yield Static("My border is dashed green", id="static2")
|
yield Label("My border is dashed green", id="label2")
|
||||||
yield Static("My border is tall blue", id="static3")
|
yield Label("My border is tall blue", id="label3")
|
||||||
|
|
||||||
|
|
||||||
app = BorderApp(css_path="border.css")
|
app = BorderApp(css_path="border.css")
|
||||||
|
|||||||
71
docs/examples/styles/border_all.css
Normal file
71
docs/examples/styles/border_all.css
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#ascii {
|
||||||
|
border: ascii $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#blank {
|
||||||
|
border: blank $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dashed {
|
||||||
|
border: dashed $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#double {
|
||||||
|
border: double $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#heavy {
|
||||||
|
border: heavy $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hidden {
|
||||||
|
border: hidden $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hkey {
|
||||||
|
border: hkey $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner {
|
||||||
|
border: inner $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#none {
|
||||||
|
border: none $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer {
|
||||||
|
border: outer $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#round {
|
||||||
|
border: round $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#solid {
|
||||||
|
border: solid $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tall {
|
||||||
|
border: tall $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#vkey {
|
||||||
|
border: vkey $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wide {
|
||||||
|
border: wide $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 3 5;
|
||||||
|
align: center middle;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: 20;
|
||||||
|
height: 3;
|
||||||
|
content-align: center middle;
|
||||||
|
}
|
||||||
26
docs/examples/styles/border_all.py
Normal file
26
docs/examples/styles/border_all.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class AllBordersApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("ascii", id="ascii"),
|
||||||
|
Label("blank", id="blank"),
|
||||||
|
Label("dashed", id="dashed"),
|
||||||
|
Label("double", id="double"),
|
||||||
|
Label("heavy", id="heavy"),
|
||||||
|
Label("hidden/none", id="hidden"),
|
||||||
|
Label("hkey", id="hkey"),
|
||||||
|
Label("inner", id="inner"),
|
||||||
|
Label("none", id="none"),
|
||||||
|
Label("outer", id="outer"),
|
||||||
|
Label("round", id="round"),
|
||||||
|
Label("solid", id="solid"),
|
||||||
|
Label("tall", id="tall"),
|
||||||
|
Label("vkey", id="vkey"),
|
||||||
|
Label("wide", id="wide"),
|
||||||
|
)
|
||||||
|
|
||||||
|
app = AllBordersApp(css_path="border_all.css")
|
||||||
@@ -1,7 +1,16 @@
|
|||||||
|
#static1 {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#static2 {
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
Screen {
|
Screen {
|
||||||
background: white;
|
background: white;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
App Static {
|
App Static {
|
||||||
background: blue 20%;
|
background: blue 20%;
|
||||||
height: 5;
|
height: 5;
|
||||||
@@ -9,9 +18,3 @@ App Static {
|
|||||||
padding: 1;
|
padding: 1;
|
||||||
border: wide black;
|
border: wide black;
|
||||||
}
|
}
|
||||||
#static1 {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
#static2 {
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
Static {
|
Label {
|
||||||
height:1fr;
|
height: 1fr;
|
||||||
content-align: center middle;
|
content-align: center middle;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
#static1 {
|
|
||||||
|
#label1 {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
#static2 {
|
|
||||||
|
#label2 {
|
||||||
color: rgb(0, 255, 0);
|
color: rgb(0, 255, 0);
|
||||||
}
|
}
|
||||||
#static3 {
|
|
||||||
color: hsl(240, 100%, 50%)
|
#label3 {
|
||||||
|
color: hsl(240, 100%, 50%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class ColorApp(App):
|
class ColorApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("I'm red!", id="static1")
|
yield Label("I'm red!", id="label1")
|
||||||
yield Static("I'm rgb(0, 255, 0)!", id="static2")
|
yield Label("I'm rgb(0, 255, 0)!", id="label2")
|
||||||
yield Static("I'm hsl(240, 100%, 50%)!", id="static3")
|
yield Label("I'm hsl(240, 100%, 50%)!", id="label3")
|
||||||
|
|
||||||
|
|
||||||
app = ColorApp(css_path="color.css")
|
app = ColorApp(css_path="color.css")
|
||||||
|
|||||||
26
docs/examples/styles/color_auto.css
Normal file
26
docs/examples/styles/color_auto.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Label {
|
||||||
|
color: auto 80%;
|
||||||
|
content-align: center middle;
|
||||||
|
height: 1fr;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl1 {
|
||||||
|
background: red 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl2 {
|
||||||
|
background: yellow 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
background: blue 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
background: pink 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl5 {
|
||||||
|
background: green 80%;
|
||||||
|
}
|
||||||
14
docs/examples/styles/color_auto.py
Normal file
14
docs/examples/styles/color_auto.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class ColorApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label("The quick brown fox jumps over the lazy dog!", id="lbl1")
|
||||||
|
yield Label("The quick brown fox jumps over the lazy dog!", id="lbl2")
|
||||||
|
yield Label("The quick brown fox jumps over the lazy dog!", id="lbl3")
|
||||||
|
yield Label("The quick brown fox jumps over the lazy dog!", id="lbl4")
|
||||||
|
yield Label("The quick brown fox jumps over the lazy dog!", id="lbl5")
|
||||||
|
|
||||||
|
|
||||||
|
app = ColorApp(css_path="color_auto.css")
|
||||||
30
docs/examples/styles/column_span.css
Normal file
30
docs/examples/styles/column_span.css
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#p1 {
|
||||||
|
column-span: 4;
|
||||||
|
}
|
||||||
|
#p2 {
|
||||||
|
column-span: 3;
|
||||||
|
}
|
||||||
|
#p3 {
|
||||||
|
column-span: 1; /* Didn't need to be set explicitly. */
|
||||||
|
}
|
||||||
|
#p4 {
|
||||||
|
column-span: 2;
|
||||||
|
}
|
||||||
|
#p5 {
|
||||||
|
column-span: 2;
|
||||||
|
}
|
||||||
|
#p6 {
|
||||||
|
/* Default value is 1. */
|
||||||
|
}
|
||||||
|
#p7 {
|
||||||
|
column-span: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 4 4;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
19
docs/examples/styles/column_span.py
Normal file
19
docs/examples/styles/column_span.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Placeholder(id="p1"),
|
||||||
|
Placeholder(id="p2"),
|
||||||
|
Placeholder(id="p3"),
|
||||||
|
Placeholder(id="p4"),
|
||||||
|
Placeholder(id="p5"),
|
||||||
|
Placeholder(id="p6"),
|
||||||
|
Placeholder(id="p7"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="column_span.css")
|
||||||
@@ -4,7 +4,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#box2 {
|
#box2 {
|
||||||
content-align: center middle;
|
content-align-horizontal: center;
|
||||||
|
content-align-vertical: middle;
|
||||||
background: green;
|
background: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,7 +14,8 @@
|
|||||||
background: blue;
|
background: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
|
width: 100%;
|
||||||
height: 1fr;
|
height: 1fr;
|
||||||
padding: 1;
|
padding: 1;
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class ContentAlignApp(App):
|
class ContentAlignApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("With [i]content-align[/] you can...", id="box1")
|
yield Label("With [i]content-align[/] you can...", id="box1")
|
||||||
yield Static("...[b]Easily align content[/]...", id="box2")
|
yield Label("...[b]Easily align content[/]...", id="box2")
|
||||||
yield Static("...Horizontally [i]and[/] vertically!", id="box3")
|
yield Label("...Horizontally [i]and[/] vertically!", id="box3")
|
||||||
|
|
||||||
|
|
||||||
app = ContentAlignApp(css_path="content_align.css")
|
app = ContentAlignApp(css_path="content_align.css")
|
||||||
|
|||||||
39
docs/examples/styles/content_align_all.css
Normal file
39
docs/examples/styles/content_align_all.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#left-top {
|
||||||
|
/* content-align: left top; this is the default implied value. */
|
||||||
|
}
|
||||||
|
#center-top {
|
||||||
|
content-align: center top;
|
||||||
|
}
|
||||||
|
#right-top {
|
||||||
|
content-align: right top;
|
||||||
|
}
|
||||||
|
#left-middle {
|
||||||
|
content-align: left middle;
|
||||||
|
}
|
||||||
|
#center-middle {
|
||||||
|
content-align: center middle;
|
||||||
|
}
|
||||||
|
#right-middle {
|
||||||
|
content-align: right middle;
|
||||||
|
}
|
||||||
|
#left-bottom {
|
||||||
|
content-align: left bottom;
|
||||||
|
}
|
||||||
|
#center-bottom {
|
||||||
|
content-align: center bottom;
|
||||||
|
}
|
||||||
|
#right-bottom {
|
||||||
|
content-align: right bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen {
|
||||||
|
layout: grid;
|
||||||
|
grid-size: 3 3;
|
||||||
|
grid-gutter: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: $primary;
|
||||||
|
}
|
||||||
18
docs/examples/styles/content_align_all.py
Normal file
18
docs/examples/styles/content_align_all.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class AllContentAlignApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label("left top", id="left-top")
|
||||||
|
yield Label("center top", id="center-top")
|
||||||
|
yield Label("right top", id="right-top")
|
||||||
|
yield Label("left middle", id="left-middle")
|
||||||
|
yield Label("center middle", id="center-middle")
|
||||||
|
yield Label("right middle", id="right-middle")
|
||||||
|
yield Label("left bottom", id="left-bottom")
|
||||||
|
yield Label("center bottom", id="center-bottom")
|
||||||
|
yield Label("right bottom", id="right-bottom")
|
||||||
|
|
||||||
|
|
||||||
|
app = AllContentAlignApp(css_path="content_align_all.css")
|
||||||
@@ -1,12 +1,14 @@
|
|||||||
Screen {
|
Screen {
|
||||||
background: green;
|
background: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Static {
|
||||||
height: 5;
|
height: 5;
|
||||||
background: white;
|
background: white;
|
||||||
color: blue;
|
color: blue;
|
||||||
border: heavy blue;
|
border: heavy blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static.remove {
|
Static.remove {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
34
docs/examples/styles/dock_all.css
Normal file
34
docs/examples/styles/dock_all.css
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#left {
|
||||||
|
dock: left;
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
align-vertical: middle;
|
||||||
|
}
|
||||||
|
#top {
|
||||||
|
dock: top;
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
align-horizontal: center;
|
||||||
|
}
|
||||||
|
#right {
|
||||||
|
dock: right;
|
||||||
|
height: 100%;
|
||||||
|
width: auto;
|
||||||
|
align-vertical: middle;
|
||||||
|
}
|
||||||
|
#bottom {
|
||||||
|
dock: bottom;
|
||||||
|
height: auto;
|
||||||
|
width: 100%;
|
||||||
|
align-horizontal: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen {
|
||||||
|
align: center middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
#big_container {
|
||||||
|
width: 75%;
|
||||||
|
height: 75%;
|
||||||
|
border: round white;
|
||||||
|
}
|
||||||
17
docs/examples/styles/dock_all.py
Normal file
17
docs/examples/styles/dock_all.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Container
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class DockAllApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Container(
|
||||||
|
Container(Label("left"), id="left"),
|
||||||
|
Container(Label("top"), id="top"),
|
||||||
|
Container(Label("right"), id="right"),
|
||||||
|
Container(Label("bottom"), id="bottom"),
|
||||||
|
id="big_container",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = DockAllApp(css_path="dock_all.css")
|
||||||
11
docs/examples/styles/grid_columns.css
Normal file
11
docs/examples/styles/grid_columns.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Grid {
|
||||||
|
grid-size: 5 2;
|
||||||
|
grid-columns: 1fr 16 2fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
border: round white;
|
||||||
|
content-align-horizontal: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
22
docs/examples/styles/grid_columns.py
Normal file
22
docs/examples/styles/grid_columns.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("1fr"),
|
||||||
|
Label("width = 16"),
|
||||||
|
Label("2fr"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("width = 16"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("width = 16"),
|
||||||
|
Label("2fr"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("width = 16"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="grid_columns.css")
|
||||||
11
docs/examples/styles/grid_gutter.css
Normal file
11
docs/examples/styles/grid_gutter.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Grid {
|
||||||
|
grid-size: 2 4;
|
||||||
|
grid-gutter: 1 2; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
border: round white;
|
||||||
|
content-align: center middle;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
20
docs/examples/styles/grid_gutter.py
Normal file
20
docs/examples/styles/grid_gutter.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("1"),
|
||||||
|
Label("2"),
|
||||||
|
Label("3"),
|
||||||
|
Label("4"),
|
||||||
|
Label("5"),
|
||||||
|
Label("6"),
|
||||||
|
Label("7"),
|
||||||
|
Label("8"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="grid_gutter.css")
|
||||||
11
docs/examples/styles/grid_rows.css
Normal file
11
docs/examples/styles/grid_rows.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Grid {
|
||||||
|
grid-size: 2 5;
|
||||||
|
grid-rows: 1fr 6 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
border: round white;
|
||||||
|
content-align: center middle;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
22
docs/examples/styles/grid_rows.py
Normal file
22
docs/examples/styles/grid_rows.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("1fr"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("height = 6"),
|
||||||
|
Label("height = 6"),
|
||||||
|
Label("25%"),
|
||||||
|
Label("25%"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("1fr"),
|
||||||
|
Label("height = 6"),
|
||||||
|
Label("height = 6"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="grid_rows.css")
|
||||||
10
docs/examples/styles/grid_size_both.css
Normal file
10
docs/examples/styles/grid_size_both.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Grid {
|
||||||
|
grid-size: 2 4; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
border: round white;
|
||||||
|
content-align: center middle;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
17
docs/examples/styles/grid_size_both.py
Normal file
17
docs/examples/styles/grid_size_both.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("1"),
|
||||||
|
Label("2"),
|
||||||
|
Label("3"),
|
||||||
|
Label("4"),
|
||||||
|
Label("5"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="grid_size_both.css")
|
||||||
10
docs/examples/styles/grid_size_columns.css
Normal file
10
docs/examples/styles/grid_size_columns.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Grid {
|
||||||
|
grid-size: 2; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
border: round white;
|
||||||
|
content-align: center middle;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
17
docs/examples/styles/grid_size_columns.py
Normal file
17
docs/examples/styles/grid_size_columns.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("1"),
|
||||||
|
Label("2"),
|
||||||
|
Label("3"),
|
||||||
|
Label("4"),
|
||||||
|
Label("5"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="grid_size_columns.css")
|
||||||
39
docs/examples/styles/height_comparison.css
Normal file
39
docs/examples/styles/height_comparison.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#cells {
|
||||||
|
height: 2; /* (1)! */
|
||||||
|
}
|
||||||
|
#percent {
|
||||||
|
height: 12.5%; /* (2)! */
|
||||||
|
}
|
||||||
|
#w {
|
||||||
|
height: 5w; /* (3)! */
|
||||||
|
}
|
||||||
|
#h {
|
||||||
|
height: 12.5h; /* (4)! */
|
||||||
|
}
|
||||||
|
#vw {
|
||||||
|
height: 6.25vw; /* (5)! */
|
||||||
|
}
|
||||||
|
#vh {
|
||||||
|
height: 12.5vh; /* (6)! */
|
||||||
|
}
|
||||||
|
#auto {
|
||||||
|
height: auto; /* (7)! */
|
||||||
|
}
|
||||||
|
#fr1 {
|
||||||
|
height: 1fr; /* (8)! */
|
||||||
|
}
|
||||||
|
#fr2 {
|
||||||
|
height: 2fr; /* (9)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
Screen {
|
||||||
|
layers: ruler;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ruler {
|
||||||
|
layer: ruler;
|
||||||
|
dock: right;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 1;
|
||||||
|
background: $accent;
|
||||||
|
}
|
||||||
28
docs/examples/styles/height_comparison.py
Normal file
28
docs/examples/styles/height_comparison.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Vertical
|
||||||
|
from textual.widgets import Placeholder, Label, Static
|
||||||
|
|
||||||
|
|
||||||
|
class Ruler(Static):
|
||||||
|
def compose(self):
|
||||||
|
ruler_text = "·\n·\n·\n·\n•\n" * 100
|
||||||
|
yield Label(ruler_text)
|
||||||
|
|
||||||
|
|
||||||
|
class HeightComparisonApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Vertical(
|
||||||
|
Placeholder(id="cells"), # (1)!
|
||||||
|
Placeholder(id="percent"),
|
||||||
|
Placeholder(id="w"),
|
||||||
|
Placeholder(id="h"),
|
||||||
|
Placeholder(id="vw"),
|
||||||
|
Placeholder(id="vh"),
|
||||||
|
Placeholder(id="auto"),
|
||||||
|
Placeholder(id="fr1"),
|
||||||
|
Placeholder(id="fr2"),
|
||||||
|
)
|
||||||
|
yield Ruler()
|
||||||
|
|
||||||
|
|
||||||
|
app = HeightComparisonApp(css_path="height_comparison.css")
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
margin: 1;
|
margin: 1;
|
||||||
width: 12;
|
width: 12;
|
||||||
color: black;
|
color: black;
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.containers import Container
|
from textual.containers import Container
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class LayoutApp(App):
|
class LayoutApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Container(
|
yield Container(
|
||||||
Static("Layout"),
|
Label("Layout"),
|
||||||
Static("Is"),
|
Label("Is"),
|
||||||
Static("Vertical"),
|
Label("Vertical"),
|
||||||
id="vertical-layout",
|
id="vertical-layout",
|
||||||
)
|
)
|
||||||
yield Container(
|
yield Container(
|
||||||
Static("Layout"),
|
Label("Layout"),
|
||||||
Static("Is"),
|
Label("Is"),
|
||||||
Static("Horizontal"),
|
Label("Horizontal"),
|
||||||
id="horizontal-layout",
|
id="horizontal-layout",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
11
docs/examples/styles/link_background.css
Normal file
11
docs/examples/styles/link_background.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-background: red; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-background: hsl(60,100%,50%) 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
link-background: $accent;
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_background.py
Normal file
25
docs/examples/styles/link_background.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkBackgroundApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkBackgroundApp(css_path="link_background.css")
|
||||||
11
docs/examples/styles/link_color.css
Normal file
11
docs/examples/styles/link_color.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-color: red; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-color: hsl(60,100%,50%) 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
link-color: $accent;
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_color.py
Normal file
25
docs/examples/styles/link_color.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkColorApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkColorApp(css_path="link_color.css")
|
||||||
11
docs/examples/styles/link_hover_background.css
Normal file
11
docs/examples/styles/link_hover_background.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-hover-background: red; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-hover-background: hsl(60,100%,50%) 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
/* Empty to show the default hover background */ /* (2)! */
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_hover_background.py
Normal file
25
docs/examples/styles/link_hover_background.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkHoverBackgroundApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkHoverBackgroundApp(css_path="link_hover_background.css")
|
||||||
11
docs/examples/styles/link_hover_color.css
Normal file
11
docs/examples/styles/link_hover_color.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-hover-color: red; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-hover-color: hsl(60,100%,50%) 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
link-hover-color: black;
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_hover_color.py
Normal file
25
docs/examples/styles/link_hover_color.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkHoverColorApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkHoverColorApp(css_path="link_hover_color.css")
|
||||||
11
docs/examples/styles/link_hover_style.css
Normal file
11
docs/examples/styles/link_hover_style.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-hover-style: bold italic; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-hover-style: reverse strike;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
link-hover-style: bold;
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_hover_style.py
Normal file
25
docs/examples/styles/link_hover_style.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkHoverStyleApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkHoverStyleApp(css_path="link_hover_style.css")
|
||||||
11
docs/examples/styles/link_style.css
Normal file
11
docs/examples/styles/link_style.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#lbl1, #lbl2 {
|
||||||
|
link-style: bold italic; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl3 {
|
||||||
|
link-style: reverse strike;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lbl4 {
|
||||||
|
link-style: bold;
|
||||||
|
}
|
||||||
25
docs/examples/styles/link_style.py
Normal file
25
docs/examples/styles/link_style.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class LinkStyleApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(
|
||||||
|
"Visit the [link=https://textualize.io]Textualize[/link] website.",
|
||||||
|
id="lbl1", # (1)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"Click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl2", # (2)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"You can also click [@click=app.bell]here[/] for the bell sound.",
|
||||||
|
id="lbl3", # (3)!
|
||||||
|
)
|
||||||
|
yield Label(
|
||||||
|
"[@click=app.quit]Exit this application.[/]",
|
||||||
|
id="lbl4", # (4)!
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = LinkStyleApp(css_path="link_style.css")
|
||||||
@@ -3,8 +3,9 @@ Screen {
|
|||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
margin: 4 8;
|
margin: 4 8;
|
||||||
background: blue 20%;
|
background: blue 20%;
|
||||||
border: blue wide;
|
border: blue wide;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
TEXT = """I must not fear.
|
TEXT = """I must not fear.
|
||||||
Fear is the mind-killer.
|
Fear is the mind-killer.
|
||||||
@@ -12,7 +12,7 @@ Where the fear has gone there will be nothing. Only I will remain."""
|
|||||||
|
|
||||||
class MarginApp(App):
|
class MarginApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static(TEXT)
|
yield Label(TEXT)
|
||||||
|
|
||||||
|
|
||||||
app = MarginApp(css_path="margin.css")
|
app = MarginApp(css_path="margin.css")
|
||||||
|
|||||||
54
docs/examples/styles/margin_all.css
Normal file
54
docs/examples/styles/margin_all.css
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
Screen {
|
||||||
|
background: $background;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 4;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bordered {
|
||||||
|
border: white round;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
/* default is no margin */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
margin: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
margin: 1 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
margin: 1 1 2 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p5 {
|
||||||
|
margin-top: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p6 {
|
||||||
|
margin-right: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p7 {
|
||||||
|
margin-bottom: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p8 {
|
||||||
|
margin-left: 3;
|
||||||
|
}
|
||||||
20
docs/examples/styles/margin_all.py
Normal file
20
docs/examples/styles/margin_all.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Container, Grid
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MarginAllApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Container(Placeholder("no margin", id="p1"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin: 1", id="p2"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin: 1 5", id="p3"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin: 1 1 2 6", id="p4"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin-top: 4", id="p5"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin-right: 3", id="p6"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin-bottom: 4", id="p7"), classes="bordered"),
|
||||||
|
Container(Placeholder("margin-left: 3", id="p8"), classes="bordered"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MarginAllApp(css_path="margin_all.css")
|
||||||
25
docs/examples/styles/max_height.css
Normal file
25
docs/examples/styles/max_height.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Horizontal {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
height: 100%;
|
||||||
|
width: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
max-height: 10w;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
max-height: 999; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
max-height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
max-height: 10;
|
||||||
|
}
|
||||||
16
docs/examples/styles/max_height.py
Normal file
16
docs/examples/styles/max_height.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Horizontal
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MaxHeightApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Horizontal(
|
||||||
|
Placeholder("max-height: 10w", id="p1"),
|
||||||
|
Placeholder("max-height: 999", id="p2"),
|
||||||
|
Placeholder("max-height: 50%", id="p3"),
|
||||||
|
Placeholder("max-height: 10", id="p4"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MaxHeightApp(css_path="max_height.css")
|
||||||
25
docs/examples/styles/max_width.css
Normal file
25
docs/examples/styles/max_width.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Horizontal {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
width: 100%;
|
||||||
|
height: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
max-width: 50h;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
max-width: 999; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
max-width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
max-width: 30;
|
||||||
|
}
|
||||||
16
docs/examples/styles/max_width.py
Normal file
16
docs/examples/styles/max_width.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Vertical
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MaxWidthApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Vertical(
|
||||||
|
Placeholder("max-width: 50h", id="p1"),
|
||||||
|
Placeholder("max-width: 999", id="p2"),
|
||||||
|
Placeholder("max-width: 50%", id="p3"),
|
||||||
|
Placeholder("max-width: 30", id="p4"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MaxWidthApp(css_path="max_width.css")
|
||||||
26
docs/examples/styles/min_height.css
Normal file
26
docs/examples/styles/min_height.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Horizontal {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
width: 1fr;
|
||||||
|
height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
min-height: 25%; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
min-height: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
min-height: 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
min-height: 40w;
|
||||||
|
}
|
||||||
16
docs/examples/styles/min_height.py
Normal file
16
docs/examples/styles/min_height.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Horizontal
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MinHeightApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Horizontal(
|
||||||
|
Placeholder("min-height: 25%", id="p1"),
|
||||||
|
Placeholder("min-height: 75%", id="p2"),
|
||||||
|
Placeholder("min-height: 30", id="p3"),
|
||||||
|
Placeholder("min-height: 40w", id="p4"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MinHeightApp(css_path="min_height.css")
|
||||||
26
docs/examples/styles/min_width.css
Normal file
26
docs/examples/styles/min_width.css
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
Vertical {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
height: 1fr;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
min-width: 25%; /* (1)! */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
min-width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
min-width: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
min-width: 400h;
|
||||||
|
}
|
||||||
16
docs/examples/styles/min_width.py
Normal file
16
docs/examples/styles/min_width.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Vertical
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MinWidthApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Vertical(
|
||||||
|
Placeholder("min-width: 25%", id="p1"),
|
||||||
|
Placeholder("min-width: 75%", id="p2"),
|
||||||
|
Placeholder("min-width: 100", id="p3"),
|
||||||
|
Placeholder("min-width: 400h", id="p4"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MinWidthApp(css_path="min_width.css")
|
||||||
@@ -3,7 +3,7 @@ Screen {
|
|||||||
color: black;
|
color: black;
|
||||||
layout: horizontal;
|
layout: horizontal;
|
||||||
}
|
}
|
||||||
Static {
|
Label {
|
||||||
width: 20;
|
width: 20;
|
||||||
height: 10;
|
height: 10;
|
||||||
content-align: center middle;
|
content-align: center middle;
|
||||||
@@ -24,7 +24,7 @@ Static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.chani {
|
.chani {
|
||||||
offset: 0 5;
|
offset: 0 -3;
|
||||||
background: blue 20%;
|
background: blue 20%;
|
||||||
border: outer blue;
|
border: outer blue;
|
||||||
color: blue;
|
color: blue;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class OffsetApp(App):
|
class OffsetApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("Paul (offset 8 2)", classes="paul")
|
yield Label("Paul (offset 8 2)", classes="paul")
|
||||||
yield Static("Duncan (offset 4 10)", classes="duncan")
|
yield Label("Duncan (offset 4 10)", classes="duncan")
|
||||||
yield Static("Chani (offset 0 5)", classes="chani")
|
yield Label("Chani (offset 0 -3)", classes="chani")
|
||||||
|
|
||||||
|
|
||||||
app = OffsetApp(css_path="offset.css")
|
app = OffsetApp(css_path="offset.css")
|
||||||
|
|||||||
@@ -19,10 +19,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Screen {
|
Screen {
|
||||||
background: antiquewhite;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
|
width: 100%;
|
||||||
height: 1fr;
|
height: 1fr;
|
||||||
border: outer dodgerblue;
|
border: outer dodgerblue;
|
||||||
background: lightseagreen;
|
background: lightseagreen;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
class OpacityApp(App):
|
class OpacityApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static("opacity: 0%", id="zero-opacity")
|
yield Label("opacity: 0%", id="zero-opacity")
|
||||||
yield Static("opacity: 25%", id="quarter-opacity")
|
yield Label("opacity: 25%", id="quarter-opacity")
|
||||||
yield Static("opacity: 50%", id="half-opacity")
|
yield Label("opacity: 50%", id="half-opacity")
|
||||||
yield Static("opacity: 75%", id="three-quarter-opacity")
|
yield Label("opacity: 75%", id="three-quarter-opacity")
|
||||||
yield Static("opacity: 100%", id="full-opacity")
|
yield Label("opacity: 100%", id="full-opacity")
|
||||||
|
|
||||||
|
|
||||||
app = OpacityApp(css_path="opacity.css")
|
app = OpacityApp(css_path="opacity.css")
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ Screen {
|
|||||||
background: white;
|
background: white;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
Static {
|
|
||||||
|
Label {
|
||||||
margin: 4 8;
|
margin: 4 8;
|
||||||
background: green 20%;
|
background: green 20%;
|
||||||
outline: wide green;
|
outline: wide green;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
TEXT = """I must not fear.
|
TEXT = """I must not fear.
|
||||||
@@ -13,7 +13,7 @@ Where the fear has gone there will be nothing. Only I will remain."""
|
|||||||
|
|
||||||
class OutlineApp(App):
|
class OutlineApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static(TEXT)
|
yield Label(TEXT)
|
||||||
|
|
||||||
|
|
||||||
app = OutlineApp(css_path="outline.css")
|
app = OutlineApp(css_path="outline.css")
|
||||||
|
|||||||
71
docs/examples/styles/outline_all.css
Normal file
71
docs/examples/styles/outline_all.css
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#ascii {
|
||||||
|
outline: ascii $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#blank {
|
||||||
|
outline: blank $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#dashed {
|
||||||
|
outline: dashed $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#double {
|
||||||
|
outline: double $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#heavy {
|
||||||
|
outline: heavy $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hidden {
|
||||||
|
outline: hidden $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#hkey {
|
||||||
|
outline: hkey $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner {
|
||||||
|
outline: inner $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#none {
|
||||||
|
outline: none $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer {
|
||||||
|
outline: outer $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#round {
|
||||||
|
outline: round $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#solid {
|
||||||
|
outline: solid $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tall {
|
||||||
|
outline: tall $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#vkey {
|
||||||
|
outline: vkey $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wide {
|
||||||
|
outline: wide $accent;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 3 5;
|
||||||
|
align: center middle;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
width: 20;
|
||||||
|
height: 3;
|
||||||
|
content-align: center middle;
|
||||||
|
}
|
||||||
26
docs/examples/styles/outline_all.py
Normal file
26
docs/examples/styles/outline_all.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
class AllOutlinesApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Label("ascii", id="ascii"),
|
||||||
|
Label("blank", id="blank"),
|
||||||
|
Label("dashed", id="dashed"),
|
||||||
|
Label("double", id="double"),
|
||||||
|
Label("heavy", id="heavy"),
|
||||||
|
Label("hidden/none", id="hidden"),
|
||||||
|
Label("hkey", id="hkey"),
|
||||||
|
Label("inner", id="inner"),
|
||||||
|
Label("none", id="none"),
|
||||||
|
Label("outer", id="outer"),
|
||||||
|
Label("round", id="round"),
|
||||||
|
Label("solid", id="solid"),
|
||||||
|
Label("tall", id="tall"),
|
||||||
|
Label("vkey", id="vkey"),
|
||||||
|
Label("wide", id="wide"),
|
||||||
|
)
|
||||||
|
|
||||||
|
app = AllOutlinesApp(css_path="outline_all.css")
|
||||||
11
docs/examples/styles/outline_vs_border.css
Normal file
11
docs/examples/styles/outline_vs_border.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
Label {
|
||||||
|
height: 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.outline {
|
||||||
|
outline: $error round;
|
||||||
|
}
|
||||||
|
|
||||||
|
.border {
|
||||||
|
border: $success heavy;
|
||||||
|
}
|
||||||
21
docs/examples/styles/outline_vs_border.py
Normal file
21
docs/examples/styles/outline_vs_border.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
|
||||||
|
TEXT = """I must not fear.
|
||||||
|
Fear is the mind-killer.
|
||||||
|
Fear is the little-death that brings total obliteration.
|
||||||
|
I will face my fear.
|
||||||
|
I will permit it to pass over me and through me.
|
||||||
|
And when it has gone past, I will turn the inner eye to see its path.
|
||||||
|
Where the fear has gone there will be nothing. Only I will remain."""
|
||||||
|
|
||||||
|
|
||||||
|
class OutlineBorderApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(TEXT, classes="outline")
|
||||||
|
yield Label(TEXT, classes="border")
|
||||||
|
yield Label(TEXT, classes="outline border")
|
||||||
|
|
||||||
|
|
||||||
|
app = OutlineBorderApp(css_path="outline_vs_border.css")
|
||||||
@@ -3,7 +3,8 @@ Screen {
|
|||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
padding: 4 8;
|
padding: 4 8;
|
||||||
background: blue 20%;
|
background: blue 20%;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
TEXT = """I must not fear.
|
TEXT = """I must not fear.
|
||||||
Fear is the mind-killer.
|
Fear is the mind-killer.
|
||||||
@@ -12,7 +12,7 @@ Where the fear has gone there will be nothing. Only I will remain."""
|
|||||||
|
|
||||||
class PaddingApp(App):
|
class PaddingApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Static(TEXT)
|
yield Label(TEXT)
|
||||||
|
|
||||||
|
|
||||||
app = PaddingApp(css_path="padding.css")
|
app = PaddingApp(css_path="padding.css")
|
||||||
|
|||||||
45
docs/examples/styles/padding_all.css
Normal file
45
docs/examples/styles/padding_all.css
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
Screen {
|
||||||
|
background: $background;
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 4;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p1 {
|
||||||
|
/* default is no padding */
|
||||||
|
}
|
||||||
|
|
||||||
|
#p2 {
|
||||||
|
padding: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p3 {
|
||||||
|
padding: 1 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p4 {
|
||||||
|
padding: 1 1 2 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p5 {
|
||||||
|
padding-top: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p6 {
|
||||||
|
padding-right: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p7 {
|
||||||
|
padding-bottom: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
#p8 {
|
||||||
|
padding-left: 3;
|
||||||
|
}
|
||||||
20
docs/examples/styles/padding_all.py
Normal file
20
docs/examples/styles/padding_all.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Container, Grid
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class PaddingAllApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Placeholder("no padding", id="p1"),
|
||||||
|
Placeholder("padding: 1", id="p2"),
|
||||||
|
Placeholder("padding: 1 5", id="p3"),
|
||||||
|
Placeholder("padding: 1 1 2 6", id="p4"),
|
||||||
|
Placeholder("padding-top: 4", id="p5"),
|
||||||
|
Placeholder("padding-right: 3", id="p6"),
|
||||||
|
Placeholder("padding-bottom: 4", id="p7"),
|
||||||
|
Placeholder("padding-left: 3", id="p8"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = PaddingAllApp(css_path="padding_all.css")
|
||||||
30
docs/examples/styles/row_span.css
Normal file
30
docs/examples/styles/row_span.css
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#p1 {
|
||||||
|
row-span: 4;
|
||||||
|
}
|
||||||
|
#p2 {
|
||||||
|
row-span: 3;
|
||||||
|
}
|
||||||
|
#p3 {
|
||||||
|
row-span: 2;
|
||||||
|
}
|
||||||
|
#p4 {
|
||||||
|
row-span: 1; /* Didn't need to be set explicitly. */
|
||||||
|
}
|
||||||
|
#p5 {
|
||||||
|
row-span: 3;
|
||||||
|
}
|
||||||
|
#p6 {
|
||||||
|
row-span: 2;
|
||||||
|
}
|
||||||
|
#p7 {
|
||||||
|
/* Default value is 1. */
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid {
|
||||||
|
grid-size: 4 4;
|
||||||
|
grid-gutter: 1 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Placeholder {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
19
docs/examples/styles/row_span.py
Normal file
19
docs/examples/styles/row_span.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.containers import Grid
|
||||||
|
from textual.widgets import Placeholder
|
||||||
|
|
||||||
|
|
||||||
|
class MyApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Grid(
|
||||||
|
Placeholder(id="p1"),
|
||||||
|
Placeholder(id="p2"),
|
||||||
|
Placeholder(id="p3"),
|
||||||
|
Placeholder(id="p4"),
|
||||||
|
Placeholder(id="p5"),
|
||||||
|
Placeholder(id="p6"),
|
||||||
|
Placeholder(id="p7"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
app = MyApp(css_path="row_span.css")
|
||||||
4
docs/examples/styles/scrollbar_corner_color.css
Normal file
4
docs/examples/styles/scrollbar_corner_color.css
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Screen {
|
||||||
|
overflow: auto auto;
|
||||||
|
scrollbar-corner-color: white;
|
||||||
|
}
|
||||||
19
docs/examples/styles/scrollbar_corner_color.py
Normal file
19
docs/examples/styles/scrollbar_corner_color.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from textual.app import App
|
||||||
|
from textual.widgets import Label
|
||||||
|
|
||||||
|
TEXT = """I must not fear.
|
||||||
|
Fear is the mind-killer.
|
||||||
|
Fear is the little-death that brings total obliteration.
|
||||||
|
I will face my fear.
|
||||||
|
I will permit it to pass over me and through me.
|
||||||
|
And when it has gone past, I will turn the inner eye to see its path.
|
||||||
|
Where the fear has gone there will be nothing. Only I will remain.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class ScrollbarCornerColorApp(App):
|
||||||
|
def compose(self):
|
||||||
|
yield Label(TEXT.replace("\n", " ") + "\n" + TEXT * 10)
|
||||||
|
|
||||||
|
|
||||||
|
app = ScrollbarCornerColorApp(css_path="scrollbar_corner_color.css")
|
||||||
@@ -4,7 +4,7 @@ Screen {
|
|||||||
layout: horizontal;
|
layout: horizontal;
|
||||||
}
|
}
|
||||||
|
|
||||||
Static {
|
Label {
|
||||||
padding: 1 2;
|
padding: 1 2;
|
||||||
width: 200;
|
width: 200;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from textual.app import App
|
from textual.app import App
|
||||||
from textual.containers import Vertical
|
from textual.containers import Vertical
|
||||||
from textual.widgets import Static
|
from textual.widgets import Label
|
||||||
|
|
||||||
TEXT = """I must not fear.
|
TEXT = """I must not fear.
|
||||||
Fear is the mind-killer.
|
Fear is the mind-killer.
|
||||||
@@ -14,7 +14,7 @@ Where the fear has gone there will be nothing. Only I will remain.
|
|||||||
|
|
||||||
class ScrollbarApp(App):
|
class ScrollbarApp(App):
|
||||||
def compose(self):
|
def compose(self):
|
||||||
yield Vertical(Static(TEXT * 5), classes="panel")
|
yield Vertical(Label(TEXT * 5), classes="panel")
|
||||||
|
|
||||||
|
|
||||||
app = ScrollbarApp(css_path="scrollbar_size.css")
|
app = ScrollbarApp(css_path="scrollbar_size.css")
|
||||||
|
|||||||
18
docs/examples/styles/scrollbar_size2.css
Normal file
18
docs/examples/styles/scrollbar_size2.css
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Container {
|
||||||
|
width: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v1 {
|
||||||
|
scrollbar-size: 5 1;
|
||||||
|
background: red 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v2 {
|
||||||
|
scrollbar-size-vertical: 1;
|
||||||
|
background: green 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#v3 {
|
||||||
|
scrollbar-size-horizontal: 5;
|
||||||
|
background: blue 20%;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user