You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/guide/CSS.md
+25-10
Original file line number
Diff line number
Diff line change
@@ -100,25 +100,25 @@ With a header and a footer widget the DOM looks like this:
100
100
--8<-- "docs/images/dom2.excalidraw.svg"
101
101
</div>
102
102
103
-
!!! note
103
+
!!! note "What we didn't show"
104
104
105
105
We've simplified the above example somewhat. Both the Header and Footer widgets contain children of their own. When building an app with pre-built widgets you rarely need to know how they are constructed unless you plan on changing the styles of individual components.
106
106
107
107
Both Header and Footer are children of the Screen object.
108
108
109
109
To further explore the DOM, we're going to build a simple dialog with a question and two buttons. To do this we're going to import and use a few more builtin widgets:
110
110
111
-
-`textual.layout.Container` For our top-level dialog.
112
-
-`textual.layout.Horizontal` To arrange widgets left to right.
113
-
-`textual.widgets.Static` For simple content.
114
-
-`textual.widgets.Button` For a clickable button.
111
+
-[`textual.containers.Container`][textual.containers.Container] For our top-level dialog.
112
+
-[`textual.containers.Horizontal`][textual.containers.Horizontal] To arrange widgets left to right.
113
+
-[`textual.widgets.Static`][textual.widgets.Static] For simple content.
114
+
-[`textual.widgets.Button`][textual.widgets.Button] For a clickable button.
We've added a Container to our DOM which (as the name suggests) is a container for other widgets. The container has a number of other widgets passed as positional arguments which will be added as the children of the container. Not all widgets accept child widgets in this way. A Button widget doesn't require any children, for example.
121
+
We've added a Container to our DOM which (as the name suggests) contains other widgets. The container has a number of other widgets passed as positional arguments which will be added as the children of the container. Not all widgets accept child widgets in this way. A Button widget doesn't require any children, for example.
122
122
123
123
Here's the DOM created by the above code:
124
124
@@ -139,7 +139,7 @@ You may recognize some elements in the above screenshot, but it doesn't quite lo
139
139
To add a stylesheet set the `CSS_PATH` classvar to a relative path:
140
140
141
141
142
-
!!! note
142
+
!!! note "What are TCSS files?"
143
143
144
144
Textual CSS files are typically given the extension `.tcss` to differentiate them from browser CSS (`.css`).
145
145
@@ -223,7 +223,7 @@ Static {
223
223
}
224
224
```
225
225
226
-
!!! note
226
+
!!! note "This is different to browser CSS"
227
227
228
228
The fact that the type selector matches base classes is a departure from browser CSS which doesn't have the same concept.
229
229
@@ -312,6 +312,18 @@ For example, the following will draw a red outline around all widgets:
312
312
}
313
313
```
314
314
315
+
While it is rare to need to style all widgets, you can combine the universal selector with a parent, to select all children of that parent.
316
+
317
+
For instance, here's how we would make all children of a `VerticalScroll` have a red background:
318
+
319
+
```css
320
+
VerticalScroll * {
321
+
background: red;
322
+
}
323
+
```
324
+
325
+
See [Combinators](#combinators) for more details on combining selectors like this.
326
+
315
327
### Pseudo classes
316
328
317
329
Pseudo classes can be used to match widgets in a particular state. Pseudo classes are set automatically by Textual. For instance, you might want a button to have a green background when the mouse cursor moves over it. We can do this with the `:hover` pseudo selector.
@@ -403,7 +415,7 @@ It is possible that several selectors match a given widget. If the same style is
403
415
404
416
The specificity rules are usually enough to fix any conflicts in your stylesheets. There is one last way of resolving conflicting selectors which applies to individual rules. If you add the text `!important` to the end of a rule then it will "win" regardless of the specificity.
405
417
406
-
!!! warning
418
+
!!! warning "If everything is Important, nothing is Important"
407
419
408
420
Use `!important` sparingly (if at all) as it can make it difficult to modify your CSS in the future.
409
421
@@ -445,7 +457,7 @@ This will be translated into:
445
457
Variables allow us to define reusable styling in a single place.
446
458
If we decide we want to change some aspect of our design in the future, we only have to update a single variable.
447
459
448
-
!!! note
460
+
!!! note "Where can variables be used?"
449
461
450
462
Variables can only be used in the _values_ of a CSS declaration. You cannot, for example, refer to a variable inside a selector.
451
463
@@ -576,3 +588,6 @@ If we were to add other selectors for additional screens or widgets, it would be
576
588
### Why use nesting?
577
589
578
590
There is no requirement to use nested CSS, but it can help to group related rule sets together (which makes it easier to edit). Nested CSS can also help you avoid some repetition in your selectors, i.e. in the nested CSS we only need to type `#questions` once, rather than four times in the non-nested CSS.
591
+
592
+
Nesting CSS will also make rules that are *more* specific.
593
+
This is useful if you find your rules are applying to widgets that you didn't intend.
Copy file name to clipboardExpand all lines: docs/guide/app.md
+8-16
Original file line number
Diff line number
Diff line change
@@ -34,9 +34,6 @@ When you call [App.run()][textual.app.App.run] Textual puts the terminal into a
34
34
35
35
If you hit ++ctrl+q++ Textual will exit application mode and return you to the command prompt. Any content you had in the terminal prior to application mode will be restored.
36
36
37
-
!!! tip
38
-
39
-
A side effect of application mode is that you may no longer be able to select and copy text in the usual way. Terminals typically offer a way to bypass this limit with a key modifier. On iTerm you can select text if you hold the ++option++ key. See the documentation for your terminal software for how to select text in application mode.
40
37
41
38
#### Run inline
42
39
@@ -65,14 +62,10 @@ We recommend the default behavior for full-screen apps, but you may want to pres
65
62
66
63
## Events
67
64
68
-
Textual has an event system you can use to respond to key presses, mouse actions, and internal state changes. Event handlers are methods prefixed with `on_` followed by the name of the event.
65
+
Textual has an [event system](./events.md) you can use to respond to key presses, mouse actions, and internal state changes. Event handlers are methods prefixed with `on_` followed by the name of the event.
69
66
70
67
One such event is the *mount* event which is sent to an application after it enters application mode. You can respond to this event by defining a method called `on_mount`.
71
68
72
-
!!! info
73
-
74
-
You may have noticed we use the term "send" and "sent" in relation to event handler methods in preference to "calling". This is because Textual uses a message passing system where events are passed (or *sent*) between components. See [events](./events.md) for details.
75
-
76
69
Another such event is the *key* event which is sent when the user presses a key. The following example contains handlers for both those events:
77
70
78
71
```python title="event01.py"
@@ -84,13 +77,12 @@ The `on_mount` handler sets the `self.screen.styles.background` attribute to `"d
The key event handler (`on_key`) has an `event` parameter which will receive a [Key][textual.events.Key] instance. Every event has an associated event object which will be passed to the handler method if it is present in the method's parameter list.
80
+
When you press a key, the key event handler (`on_key`) which will receive a [Key][textual.events.Key] instance.
81
+
If you don't require the event in your handler, you can omit it.
88
82
89
-
!!! note
90
-
91
-
It is unusual (but not unprecedented) for a method's parameters to affect how it is called. Textual accomplishes this by inspecting the method prior to calling it.
92
-
93
-
Some events contain additional information you can inspect in the handler. The [Key][textual.events.Key] event has a `key` attribute which is the name of the key that was pressed. The `on_key` method above uses this attribute to change the background color if any of the keys from ++0++ to ++9++ are pressed.
83
+
Events may contain additional information which you can inspect in the handler.
84
+
In the case of the [Key][textual.events.Key] event, there is a `key` attribute which is the name of the key that was pressed.
85
+
The `on_key` method above uses this attribute to change the background color if any of the keys from ++0++ to ++9++ are pressed.
94
86
95
87
### Async events
96
88
@@ -224,7 +216,7 @@ You may have noticed that we subclassed `App[str]` rather than the usual `App`.
224
216
225
217
The addition of `[str]` tells mypy that `run()` is expected to return a string. It may also return `None` if [App.exit()][textual.app.App.exit] is called without a return value, so the return type of `run` will be `str | None`. Replace the `str` in `[str]` with the type of the value you intend to call the exit method with.
226
218
227
-
!!! note
219
+
!!! note "Typing in Textual"
228
220
229
221
Type annotations are entirely optional (but recommended) with Textual.
230
222
@@ -317,7 +309,7 @@ For example:
317
309
318
310
## CSS
319
311
320
-
Textual apps can reference [CSS](CSS.md) files which define how your app and widgets will look, while keeping your Python code free of display related code (which tends to be messy).
312
+
Textual apps can reference [CSS](CSS.md) files which define how your app and widgets will look, while keeping your project free of messy display related code.
Note how the text wraps in the widget, and is cropped because it doesn't fit in the space provided.
137
+
Note how the text wraps, but doesn't fit in the 10 lines provided, resulting in the last line being omitted entirely.
138
138
139
139
#### Auto dimensions
140
140
@@ -189,22 +189,26 @@ With the width set to `"50%"` and the height set to `"80%"`, the widget will kee
189
189
190
190
Percentage units can be problematic for some relative values. For instance, if we want to divide the screen into thirds, we would have to set a dimension to `33.3333333333%` which is awkward. Textual supports `fr` units which are often better than percentage-based units for these situations.
191
191
192
-
When specifying `fr` units for a given dimension, Textual will divide the available space by the sum of the `fr` units on that dimension. That space will then be divided amongst the widgets as a proportion of their individual`fr` values.
192
+
When specifying `fr` units for a given dimension, Textual will divide the available space by the sum of the `fr` units for that dimension. That space is then assigned according to each widget's`fr` values.
193
193
194
194
Let's look at an example. We will create two widgets, one with a height of `"2fr"` and one with a height of `"1fr"`.
The total `fr` units for height is 3. The first widget will have a screen height of two thirds because its height style is set to `2fr`. The second widget's height style is `1fr` so its screen height will be one third. Here's what that looks like.
200
+
The total `fr` units for height is 3.
201
+
The first widget has a height ot `2fr`, which results in the height being two thirds of the total height.
202
+
The second widget has a height of `1fr` which makes it take up the remaining third of the height.
The same units may also be used to set limits on a dimension. The following styles set minimum and maximum sizes and can accept any of the values used in width and height.
210
+
The same units may also be used to set limits on a dimension.
211
+
The following styles set minimum and maximum sizes and can accept any of the values used in width and height.
208
212
209
213
-[min-width](../styles/min_width.md) sets a minimum width.
210
214
-[max-width](../styles/max_width.md) sets a maximum width.
@@ -345,12 +349,12 @@ Notice how each widget has an additional two rows and columns around the border.
In the above example both widgets have a margin of 2, but there are only 2 lines of space between the widgets. This is because margins of consecutive widgets *overlap*. In other words when there are two widgets next to each other Textual picks the greater of the two margins.
351
355
352
356
## More styles
353
357
354
-
We've covered the most fundamental styles used by Textual apps, but there are many more which you can use to customize many aspects of how your app looks. See the [Styles reference](../styles/index.md) for a comprehensive list.
358
+
We've covered some fundamental styles used by Textual apps, but there are many more which you can use to customize all aspects of how your app looks. See the [Styles reference](../styles/index.md) for a comprehensive list.
355
359
356
360
In the next chapter we will discuss Textual CSS which is a powerful way of applying styles to widgets that keeps your code free of style attributes.
0 commit comments