Support multiple CSS files (#1079)

* Support multiple CSS paths

* Update a type to match docstring

* Ensure the demo app still works

* Use absolute paths in tests to (hopefully) appease Windows

* Notes about CSS changes in guide/docstrings, small grammar/typos fixes

* Move snapshot apps into snapshot_tests dir, improve messaging in snapshot output, add test for multiple css files interacting with classvar CSS

* Ensure consistent snapshot naming cross-platform

* Use rpartition instead of partition in import_app

* Fix handling of import_app when colon in arg

* Support paths containing Windows drive names in import_app

* Add note on new relative paths in snap_compare

* Update docs/guide/CSS.md

Co-authored-by: Will McGugan <willmcgugan@gmail.com>

* Fix formatting

* Update CHANGELOG to mention CSS_PATH supporting a list

Co-authored-by: Will McGugan <willmcgugan@gmail.com>
This commit is contained in:
darrenburns
2022-11-01 17:13:25 +00:00
committed by GitHub
parent 0403cfdc98
commit bbd811d671
19 changed files with 425 additions and 130 deletions

View File

@@ -4,7 +4,7 @@ Textual uses CSS to apply style to widgets. If you have any exposure to web deve
## Stylesheets
CSS stands for _Cascading Stylesheets_. A stylesheet is a list of styles and rules about how those styles should be applied to a web page. In the case of Textual, the stylesheet applies [styles](./styles.md) to widgets but otherwise it is the same idea.
CSS stands for _Cascading Stylesheets_. A stylesheet is a list of styles and rules about how those styles should be applied to a web page. In the case of Textual, the stylesheet applies [styles](./styles.md) to widgets, but otherwise it is the same idea.
When Textual loads CSS it sets attributes on your widgets' `style` object. The effect is the same as if you had set attributes in Python.
@@ -48,7 +48,7 @@ Header {
}
```
The lines inside the curly braces contains CSS _rules_, which consist of a rule name and rule value separated by a colon and ending in a semi-colon. Such rules are typically written one per line, but you could add additional rules as long as they are separated by semi-colons.
The lines inside the curly braces contains CSS _rules_, which consist of a rule name and rule value separated by a colon and ending in a semicolon. Such rules are typically written one per line, but you could add additional rules as long as they are separated by semicolons.
The first rule in the above example reads `"dock: top;"`. The rule name is `dock` which tells Textual to place the widget on an edge of the screen. The text after the colon is `top` which tells Textual to dock to the _top_ of the screen. Other valid values for `dock` are "right", "bottom", or "left"; but "top" is most appropriate for a header.
@@ -93,7 +93,7 @@ This doesn't look much like a tree yet. Let's add a header and a footer to this
```{.textual path="docs/examples/guide/dom2.py"}
```
With a header and a footer widget the DOM looks the this:
With a header and a footer widget the DOM looks like this:
<div class="excalidraw">
--8<-- "docs/images/dom2.excalidraw.svg"
@@ -132,7 +132,7 @@ Here's the output from this example:
```
You may recognize some of the elements in the above screenshot, but it doesn't quite look like a dialog. This is because we haven't added a stylesheet.
You may recognize some elements in the above screenshot, but it doesn't quite look like a dialog. This is because we haven't added a stylesheet.
## CSS files
@@ -142,7 +142,8 @@ To add a stylesheet set the `CSS_PATH` classvar to a relative path:
--8<-- "docs/examples/guide/dom4.py"
```
You may have noticed that some of the constructors have additional keyword arguments: `id` and `classes`. These are used by the CSS to identify parts of the DOM. We will cover these in the next section.
You may have noticed that some constructors have additional keyword arguments: `id` and `classes`.
These are used by the CSS to identify parts of the DOM. We will cover these in the next section.
Here's the CSS file we are applying:
@@ -158,6 +159,10 @@ With the CSS in place, the output looks very different:
```
### Using multiple CSS files
You can also set the `CSS_PATH` class variable to a list of paths. Textual will combine the rules from all of the supplied paths.
### Why CSS?
It is reasonable to ask why use CSS at all? Python is a powerful and expressive language. Wouldn't it be easier to set styles in your `.py` files?
@@ -178,7 +183,7 @@ Being able to iterate on the design without restarting the application makes it
A selector is the text which precedes the curly braces in a set of rules. It tells Textual which widgets it should apply the rules to.
Selectors can target a kind of widget or a very specific widget. For instance you could have a selector that modifies all buttons, or you could target an individual button used in one dialog. This gives you a lot of flexibility in customizing your user interface.
Selectors can target a kind of widget or a very specific widget. For instance, you could have a selector that modifies all buttons, or you could target an individual button used in one dialog. This gives you a lot of flexibility in customizing your user interface.
Let's look at the selectors supported by Textual CSS.
@@ -201,7 +206,7 @@ Button {
}
```
The type selector will also match a widget's base classes. Consequently a `Static` selector will also style the button because the `Button` Python class extends `Static`.
The type selector will also match a widget's base classes. Consequently, a `Static` selector will also style the button because the `Button` Python class extends `Static`.
```sass
Static {