mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
more docs and diagrams
This commit is contained in:
@@ -16,21 +16,40 @@ App > Screen {
|
||||
|
||||
background: $surface;
|
||||
color: $text-surface;
|
||||
layers: sidebar;
|
||||
layers: base sidebar;
|
||||
|
||||
color: $text-background;
|
||||
background: $background;
|
||||
layout: vertical;
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
}
|
||||
|
||||
#tree-container {
|
||||
overflow-y: auto;
|
||||
height: 20;
|
||||
margin: 1 2;
|
||||
background: $panel;
|
||||
padding: 1 2;
|
||||
}
|
||||
|
||||
DirectoryTree {
|
||||
padding: 0 1;
|
||||
height: auto;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
DataTable {
|
||||
/*border:heavy red;*/
|
||||
/* tint: 10% green; */
|
||||
/* opacity: 50%; */
|
||||
padding: 1;
|
||||
margin: 1 2;
|
||||
height: 12;
|
||||
height: 24;
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
@@ -38,6 +57,7 @@ DataTable {
|
||||
background: $panel;
|
||||
dock: left;
|
||||
width: 30;
|
||||
margin-bottom: 1;
|
||||
offset-x: -100%;
|
||||
|
||||
transition: offset 500ms in_out_cubic;
|
||||
@@ -71,14 +91,7 @@ DataTable {
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
#header {
|
||||
color: $text-secondary-background;
|
||||
background: $secondary-background;
|
||||
height: 1;
|
||||
content-align: center middle;
|
||||
|
||||
dock: top;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Tweet {
|
||||
@@ -103,7 +116,7 @@ Tweet {
|
||||
overflow-x: auto;
|
||||
overflow-y: scroll;
|
||||
margin: 1 2;
|
||||
height: 20;
|
||||
height: 24;
|
||||
align-horizontal: center;
|
||||
layout: vertical;
|
||||
}
|
||||
@@ -6,7 +6,8 @@ from rich.text import Text
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.reactive import Reactive
|
||||
from textual.widget import Widget
|
||||
from textual.widgets import Static, DataTable
|
||||
from textual.widgets import Static, DataTable, DirectoryTree, Header, Footer
|
||||
from textual.layout import Container
|
||||
|
||||
CODE = '''
|
||||
from __future__ import annotations
|
||||
@@ -103,24 +104,23 @@ class Success(Widget):
|
||||
return Text("This is a success message", justify="center")
|
||||
|
||||
|
||||
class BasicApp(App, css_path="demo.css"):
|
||||
class BasicApp(App, css_path="basic.css"):
|
||||
"""A basic app demonstrating CSS"""
|
||||
|
||||
def on_load(self):
|
||||
"""Bind keys here."""
|
||||
self.bind("s", "toggle_class('#sidebar', '-active')")
|
||||
self.bind("s", "toggle_class('#sidebar', '-active')", description="Sidebar")
|
||||
self.bind("d", "toggle_dark", description="Dark mode")
|
||||
self.bind("q", "quit", description="Quit")
|
||||
self.bind("f", "query_test", description="Query test")
|
||||
|
||||
def compose(self):
|
||||
yield Header()
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
table = DataTable()
|
||||
self.scroll_to_target = Tweet(TweetBody())
|
||||
|
||||
yield Static(
|
||||
Text.from_markup(
|
||||
"[b]This is a [u]Textual[/u] app, running in the terminal"
|
||||
),
|
||||
id="header",
|
||||
)
|
||||
yield from (
|
||||
yield Container(
|
||||
Tweet(TweetBody()),
|
||||
Widget(
|
||||
Static(
|
||||
@@ -130,6 +130,7 @@ class BasicApp(App, css_path="demo.css"):
|
||||
classes="scrollable",
|
||||
),
|
||||
table,
|
||||
Widget(DirectoryTree("~/projects/textual"), id="tree-container"),
|
||||
Error(),
|
||||
Tweet(TweetBody(), classes="scrollbar-size-custom"),
|
||||
Warning(),
|
||||
@@ -141,7 +142,6 @@ class BasicApp(App, css_path="demo.css"):
|
||||
Tweet(TweetBody(), classes="scroll-horizontal"),
|
||||
Tweet(TweetBody(), classes="scroll-horizontal"),
|
||||
)
|
||||
yield Widget(id="footer")
|
||||
yield Widget(
|
||||
Widget(classes="title"),
|
||||
Widget(classes="user"),
|
||||
@@ -151,6 +151,7 @@ class BasicApp(App, css_path="demo.css"):
|
||||
Widget(classes="content"),
|
||||
id="sidebar",
|
||||
)
|
||||
yield Footer()
|
||||
|
||||
table.add_column("Foo", width=20)
|
||||
table.add_column("Bar", width=20)
|
||||
@@ -162,12 +163,32 @@ class BasicApp(App, css_path="demo.css"):
|
||||
for n in range(100):
|
||||
table.add_row(*[f"Cell ([b]{n}[/b], {col})" for col in range(6)])
|
||||
|
||||
def on_mount(self):
|
||||
self.sub_title = "Widget demo"
|
||||
|
||||
async def on_key(self, event) -> None:
|
||||
await self.dispatch_key(event)
|
||||
|
||||
def key_d(self):
|
||||
def action_toggle_dark(self):
|
||||
self.dark = not self.dark
|
||||
|
||||
def action_query_test(self):
|
||||
query = self.query("Tweet")
|
||||
self.log(query)
|
||||
self.log(query.nodes)
|
||||
self.log(query)
|
||||
self.log(query.nodes)
|
||||
|
||||
query.set_styles("outline: outer red;")
|
||||
|
||||
query = query.exclude(".scroll-horizontal")
|
||||
self.log(query)
|
||||
self.log(query.nodes)
|
||||
|
||||
# query = query.filter(".rubbish")
|
||||
# self.log(query)
|
||||
# self.log(query.first())
|
||||
|
||||
async def key_q(self):
|
||||
await self.shutdown()
|
||||
|
||||
|
||||
8
docs/examples/guide/dom1.py
Normal file
8
docs/examples/guide/dom1.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from textual.app import App
|
||||
|
||||
|
||||
class ExampleApp(App):
|
||||
pass
|
||||
|
||||
|
||||
app = ExampleApp()
|
||||
11
docs/examples/guide/dom2.py
Normal file
11
docs/examples/guide/dom2.py
Normal file
@@ -0,0 +1,11 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.widgets import Header, Footer
|
||||
|
||||
|
||||
class ExampleApp(App):
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header()
|
||||
yield Footer()
|
||||
|
||||
|
||||
app = ExampleApp()
|
||||
17
docs/examples/guide/dom3.py
Normal file
17
docs/examples/guide/dom3.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.layout import Container
|
||||
from textual.widgets import Header, Footer, Static
|
||||
|
||||
|
||||
class ExampleApp(App):
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header()
|
||||
yield Footer()
|
||||
yield Container(
|
||||
Static(id="widget1"),
|
||||
Static(id="widget2"),
|
||||
Static(id="widget3"),
|
||||
)
|
||||
|
||||
|
||||
app = ExampleApp()
|
||||
0
docs/examples/guide/dom4.css
Normal file
0
docs/examples/guide/dom4.css
Normal file
18
docs/examples/guide/dom4.py
Normal file
18
docs/examples/guide/dom4.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.layout import Container
|
||||
from textual.widget import Widget
|
||||
from textual.widgets import Header, Footer
|
||||
|
||||
|
||||
class ExampleApp(App):
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header()
|
||||
yield Footer()
|
||||
yield Container(
|
||||
Widget(id="widget1"),
|
||||
Widget(id="widget2"),
|
||||
Widget(id="widget3"),
|
||||
)
|
||||
|
||||
|
||||
app = ExampleApp()
|
||||
14
docs/examples/styles/background.css
Normal file
14
docs/examples/styles/background.css
Normal file
@@ -0,0 +1,14 @@
|
||||
Static {
|
||||
height: 1fr;
|
||||
content-align: center middle;
|
||||
color: white;
|
||||
}
|
||||
#static1 {
|
||||
background: red;
|
||||
}
|
||||
#static2 {
|
||||
background: rgb(0, 255, 0);
|
||||
}
|
||||
#static3 {
|
||||
background: hsl(240, 100%, 50%);
|
||||
}
|
||||
@@ -3,27 +3,10 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class BackgroundApp(App):
|
||||
CSS = """
|
||||
Static {
|
||||
height: 1fr;
|
||||
content-align: center middle;
|
||||
color: white;
|
||||
}
|
||||
#static1 {
|
||||
background: red;
|
||||
}
|
||||
#static2 {
|
||||
background: rgb(0, 255, 0);
|
||||
}
|
||||
#static3 {
|
||||
background: hsl(240, 100%, 50%);
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("Widget 1", id="static1")
|
||||
yield Static("Widget 2", id="static2")
|
||||
yield Static("Widget 3", id="static3")
|
||||
|
||||
|
||||
app = BackgroundApp()
|
||||
app = BackgroundApp(css_path="background.css")
|
||||
|
||||
25
docs/examples/styles/border.css
Normal file
25
docs/examples/styles/border.css
Normal file
@@ -0,0 +1,25 @@
|
||||
Screen {
|
||||
background: white;
|
||||
}
|
||||
Screen > Static {
|
||||
height: 5;
|
||||
content-align: center middle;
|
||||
color: white;
|
||||
margin: 1;
|
||||
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;
|
||||
}
|
||||
@@ -3,38 +3,10 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class BorderApp(App):
|
||||
CSS = """
|
||||
Screen {
|
||||
background: white;
|
||||
}
|
||||
Screen > Static {
|
||||
height: 5;
|
||||
content-align: center middle;
|
||||
color: white;
|
||||
margin: 1;
|
||||
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;
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("My border is solid red", id="static1")
|
||||
yield Static("My border is dashed green", id="static2")
|
||||
yield Static("My border is tall blue", id="static3")
|
||||
|
||||
|
||||
app = BorderApp()
|
||||
app = BorderApp(css_path="border.css")
|
||||
|
||||
17
docs/examples/styles/box_sizing.css
Normal file
17
docs/examples/styles/box_sizing.css
Normal file
@@ -0,0 +1,17 @@
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
App Static {
|
||||
background: blue 20%;
|
||||
height: 5;
|
||||
margin: 2;
|
||||
padding: 1;
|
||||
border: wide black;
|
||||
}
|
||||
#static1 {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#static2 {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
@@ -3,30 +3,9 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class BoxSizingApp(App):
|
||||
CSS = """
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
Static {
|
||||
background: blue 20%;
|
||||
height: 5;
|
||||
margin: 2;
|
||||
padding: 1;
|
||||
border: wide black;
|
||||
}
|
||||
#static1 {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#static2 {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("I'm using border-box!", id="static1")
|
||||
yield Static("I'm using content-box!", id="static2")
|
||||
|
||||
|
||||
app = BoxSizingApp()
|
||||
app = BoxSizingApp(css_path="box_sizing.css")
|
||||
|
||||
13
docs/examples/styles/color.css
Normal file
13
docs/examples/styles/color.css
Normal file
@@ -0,0 +1,13 @@
|
||||
Static {
|
||||
height:1fr;
|
||||
content-align: center middle;
|
||||
}
|
||||
#static1 {
|
||||
color: red;
|
||||
}
|
||||
#static2 {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
#static3 {
|
||||
color: hsl(240, 100%, 50%)
|
||||
}
|
||||
@@ -3,26 +3,10 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class ColorApp(App):
|
||||
CSS = """
|
||||
Static {
|
||||
height:1fr;
|
||||
content-align: center middle;
|
||||
}
|
||||
#static1 {
|
||||
color: red;
|
||||
}
|
||||
#static2 {
|
||||
color: rgb(0, 255, 0);
|
||||
}
|
||||
#static3 {
|
||||
color: hsl(240, 100%, 50%)
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("I'm red!", id="static1")
|
||||
yield Static("I'm rgb(0, 255, 0)!", id="static2")
|
||||
yield Static("I'm hsl(240, 100%, 50%)!", id="static3")
|
||||
|
||||
|
||||
app = ColorApp()
|
||||
app = ColorApp(css_path="color.css")
|
||||
|
||||
12
docs/examples/styles/display.css
Normal file
12
docs/examples/styles/display.css
Normal file
@@ -0,0 +1,12 @@
|
||||
Screen {
|
||||
background: green;
|
||||
}
|
||||
Static {
|
||||
height: 5;
|
||||
background: white;
|
||||
color: blue;
|
||||
border: heavy blue;
|
||||
}
|
||||
Static.remove {
|
||||
display: none;
|
||||
}
|
||||
@@ -3,25 +3,10 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class DisplayApp(App):
|
||||
CSS = """
|
||||
Screen {
|
||||
background: green;
|
||||
}
|
||||
Static {
|
||||
height: 5;
|
||||
background: white;
|
||||
color: blue;
|
||||
border: heavy blue;
|
||||
}
|
||||
Static.remove {
|
||||
display: none;
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("Widget 1")
|
||||
yield Static("Widget 2", classes="remove")
|
||||
yield Static("Widget 3")
|
||||
|
||||
|
||||
app = DisplayApp()
|
||||
app = DisplayApp(css_path="display.css")
|
||||
|
||||
5
docs/examples/styles/height.css
Normal file
5
docs/examples/styles/height.css
Normal file
@@ -0,0 +1,5 @@
|
||||
Screen > Widget {
|
||||
background: green;
|
||||
height: 50%;
|
||||
color: white;
|
||||
}
|
||||
@@ -3,16 +3,8 @@ from textual.widget import Widget
|
||||
|
||||
|
||||
class HeightApp(App):
|
||||
CSS = """
|
||||
Screen > Widget {
|
||||
background: green;
|
||||
height: 50%;
|
||||
color: white;
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Widget()
|
||||
|
||||
|
||||
app = HeightApp()
|
||||
app = HeightApp(css_path="height.css")
|
||||
|
||||
10
docs/examples/styles/margin.css
Normal file
10
docs/examples/styles/margin.css
Normal file
@@ -0,0 +1,10 @@
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
Static {
|
||||
margin: 4 8;
|
||||
background: blue 20%;
|
||||
border: blue wide;
|
||||
}
|
||||
@@ -11,23 +11,8 @@ Where the fear has gone there will be nothing. Only I will remain."""
|
||||
|
||||
|
||||
class MarginApp(App):
|
||||
CSS = """
|
||||
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
Static {
|
||||
margin: 4 8;
|
||||
background: blue 20%;
|
||||
border: blue wide;
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static(TEXT)
|
||||
|
||||
|
||||
app = MarginApp()
|
||||
app = MarginApp(css_path="margin.css")
|
||||
|
||||
31
docs/examples/styles/offset.css
Normal file
31
docs/examples/styles/offset.css
Normal file
@@ -0,0 +1,31 @@
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
layout: horizontal;
|
||||
}
|
||||
Static {
|
||||
width: 20;
|
||||
height: 10;
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
.paul {
|
||||
offset: 8 2;
|
||||
background: red 20%;
|
||||
border: outer red;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.duncan {
|
||||
offset: 4 10;
|
||||
background: green 20%;
|
||||
border: outer green;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.chani {
|
||||
offset: 0 5;
|
||||
background: blue 20%;
|
||||
border: outer blue;
|
||||
color: blue;
|
||||
}
|
||||
@@ -3,44 +3,10 @@ from textual.widgets import Static
|
||||
|
||||
|
||||
class OffsetApp(App):
|
||||
CSS = """
|
||||
Screen {
|
||||
background: white;
|
||||
color: black;
|
||||
layout: horizontal;
|
||||
}
|
||||
Static {
|
||||
width: 20;
|
||||
height: 10;
|
||||
content-align: center middle;
|
||||
}
|
||||
|
||||
.paul {
|
||||
offset: 8 2;
|
||||
background: red 20%;
|
||||
border: outer red;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.duncan {
|
||||
offset: 4 10;
|
||||
background: green 20%;
|
||||
border: outer green;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.chani {
|
||||
offset: 0 5;
|
||||
background: blue 20%;
|
||||
border: outer blue;
|
||||
color: blue;
|
||||
}
|
||||
"""
|
||||
|
||||
def compose(self):
|
||||
yield Static("Paul (offset 8 2)", classes="paul")
|
||||
yield Static("Duncan (offset 4 10)", classes="duncan")
|
||||
yield Static("Chani (offset 0 5)", classes="chani")
|
||||
|
||||
|
||||
app = OffsetApp()
|
||||
app = OffsetApp(css_path="offset.css")
|
||||
|
||||
Reference in New Issue
Block a user