Skip to content

Commit 7919ee0

Browse files
committed
Implement widgets command
1 parent 7717c49 commit 7919ee0

File tree

15 files changed

+718
-1
lines changed

15 files changed

+718
-1
lines changed

src/textual_dev/cli.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,14 @@ def colors() -> None:
219219
ColorsApp().run()
220220

221221

222+
@run.command("widgets")
223+
def widgets() -> None:
224+
"""Explore possible widgets."""
225+
from textual_dev.previews import WidgetsApp
226+
227+
WidgetsApp().run()
228+
229+
222230
@run.command("keys")
223231
def keys() -> None:
224232
"""Show key events."""

src/textual_dev/previews/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
from .easing import EasingApp
66
from .keys import KeysApp
77

8-
__all__ = ["BorderApp", "ColorsApp", "EasingApp", "KeysApp"]
8+
__all__ = ["BorderApp", "ColorsApp", "EasingApp", "KeysApp", "WidgetsApp"]

src/textual_dev/previews/widgets.css

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
Screen {
2+
align: center middle;
3+
overflow: auto;
4+
}
5+
6+
#Button Button {
7+
margin: 1 2;
8+
}
9+
10+
#Button VerticalScroll {
11+
width: 24;
12+
}
13+
14+
#Checkbox VerticalScroll {
15+
width: auto;
16+
height: auto;
17+
background: $boost;
18+
padding: 2;
19+
}
20+
21+
#ListItem ListView {
22+
width: 34;
23+
height: auto;
24+
margin: 2 2;
25+
}
26+
27+
#ListItem Label {
28+
padding: 1 2;
29+
}
30+
31+
32+
#OptionList OptionList {
33+
width: 70%;
34+
height: 80%;
35+
}
36+
37+
38+
/*Placeholder*/
39+
40+
#top {
41+
height: 50%;
42+
width: 100%;
43+
layout: grid;
44+
grid-size: 2 2;
45+
}
46+
47+
#left {
48+
row-span: 2;
49+
}
50+
51+
#bot {
52+
height: 50%;
53+
width: 100%;
54+
layout: grid;
55+
grid-size: 8 8;
56+
}
57+
58+
#c1 {
59+
row-span: 4;
60+
column-span: 8;
61+
height: 100%;
62+
}
63+
64+
#col1, #col2, #col3 {
65+
width: 1fr;
66+
}
67+
68+
#p1 {
69+
row-span: 4;
70+
column-span: 4;
71+
}
72+
73+
#p2 {
74+
row-span: 2;
75+
column-span: 4;
76+
}
77+
78+
#p3 {
79+
row-span: 2;
80+
column-span: 2;
81+
}
82+
83+
#p4 {
84+
row-span: 1;
85+
column-span: 2;
86+
}
87+
88+
#RadioButton RadioSet {
89+
width: 50%;
90+
}
91+
92+
#RadioSet Horizontal {
93+
align: center middle;
94+
height: auto;
95+
}
96+
97+
#RadioSet RadioSet {
98+
width: 45%;
99+
}
100+
101+
#Select Select {
102+
width: 60;
103+
margin: 2;
104+
}
105+
106+
#SelectionList SelectionList {
107+
padding: 1;
108+
border: solid $accent;
109+
width: 80%;
110+
height: 80%;
111+
}
112+
113+
114+
115+
#Switch {
116+
align: center middle;
117+
}
118+
119+
#Switch .container {
120+
height: auto;
121+
width: auto;
122+
}
123+
124+
#Switch Switch {
125+
height: auto;
126+
width: auto;
127+
}
128+
129+
#Switch .label {
130+
height: 3;
131+
content-align: center middle;
132+
width: auto;
133+
}
134+
135+
#custom-design {
136+
background: darkslategrey;
137+
}
138+
139+
#custom-design > .switch--slider {
140+
color: dodgerblue;
141+
background: darkslateblue;
142+
}

src/textual_dev/previews/widgets.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
from textual.app import App, ComposeResult
2+
from textual.containers import Vertical
3+
from textual.widgets import Button, ContentSwitcher
4+
5+
from textual_dev.previews.widgets import (
6+
option_list_example,
7+
button_example,
8+
checkbox_example,
9+
list_item_example,
10+
data_table_example,
11+
markdown_viewer_example,
12+
placeholder_example,
13+
pretty_example,
14+
directory_tree_example,
15+
footer_example,
16+
header_example,
17+
input_example,
18+
label_example,
19+
loading_example,
20+
markdown_example,
21+
radio_button_example,
22+
radio_set_example,
23+
select_example,
24+
selection_list_example,
25+
sparkline_example,
26+
static_example,
27+
switch_example,
28+
tree_example,
29+
)
30+
31+
WIDGETS = {
32+
"Button": button_example,
33+
"Checkbox": checkbox_example,
34+
# ContentSwitcher missing
35+
"DataTable": data_table_example,
36+
"DirectoryTree": directory_tree_example,
37+
"Footer": footer_example,
38+
"Header": header_example,
39+
"Input": input_example,
40+
"Label": label_example,
41+
"ListItem": list_item_example,
42+
# ListView missing
43+
"Loading": loading_example,
44+
"MarkdownViewer": markdown_viewer_example,
45+
"Markdown": markdown_example,
46+
"OptionList": option_list_example,
47+
"Placeholder": placeholder_example,
48+
"Pretty": pretty_example,
49+
# ProgressBar missing
50+
"RadioButton": radio_button_example,
51+
"RadioSet": radio_set_example,
52+
"Select": select_example,
53+
"SelectionList": selection_list_example,
54+
"Sparkline": sparkline_example,
55+
"Static": static_example,
56+
"Switch": switch_example,
57+
# TabbedContatn missing
58+
# Tabs missing
59+
# TextLog missing
60+
"Tree": tree_example,
61+
}
62+
63+
64+
class WidgetButtons(Vertical):
65+
DEFAULT_CSS = """
66+
WidgetButtons {
67+
dock: left;
68+
width: 32;
69+
overflow-y: scroll;
70+
}
71+
72+
WidgetButtons > Button {
73+
width: 100%;
74+
}
75+
"""
76+
77+
def compose(self) -> ComposeResult:
78+
for widget in WIDGETS.keys():
79+
yield Button(widget, id=widget)
80+
81+
82+
class WidgetsApp(App[None]):
83+
"""Demonstrates widget types."""
84+
85+
CSS_PATH = "widgets.css"
86+
87+
def compose(self) -> ComposeResult:
88+
yield WidgetButtons()
89+
90+
first_button = list(WIDGETS.keys())[0]
91+
92+
with ContentSwitcher(initial=first_button):
93+
for widget_name, widget in WIDGETS.items():
94+
yield from widget(id=widget_name)
95+
96+
def on_button_pressed(self, event: Button.Pressed) -> None:
97+
self.query_one(ContentSwitcher).current = event.button.id
98+
99+
100+
if __name__ == "__main__":
101+
WidgetsApp().run()
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import random
2+
from statistics import mean
3+
4+
from textual.app import ComposeResult
5+
from textual.containers import Container
6+
from textual.widgets import (
7+
DirectoryTree,
8+
Footer,
9+
Header,
10+
Input,
11+
Label,
12+
ListView,
13+
ListItem,
14+
LoadingIndicator,
15+
Sparkline,
16+
Static,
17+
Tree,
18+
)
19+
20+
from .button import button_example
21+
from .checkbox import checkbox_example
22+
from .data_table import data_table_example
23+
from .markdown import markdown_viewer_example, markdown_example
24+
from .option_list import option_list_example
25+
from .placeholder import placeholder_example
26+
from .pretty import pretty_example
27+
from .radio import radio_button_example, radio_set_example
28+
from .select import select_example, selection_list_example
29+
from .switch import switch_example
30+
31+
32+
def directory_tree_example(id: str) -> ComposeResult:
33+
yield Container(DirectoryTree("./"), id=id)
34+
35+
36+
def footer_example(id: str) -> ComposeResult:
37+
yield Container(Footer(), id=id)
38+
39+
40+
def header_example(id: str) -> ComposeResult:
41+
yield Container(Header(), id=id)
42+
43+
44+
def input_example(id: str) -> ComposeResult:
45+
yield Container(
46+
Input(placeholder="First Name"), Input(placeholder="Last Name"), id=id
47+
)
48+
49+
50+
def label_example(id: str) -> ComposeResult:
51+
yield Container(Label("Hello, world!"), id=id)
52+
53+
54+
def list_item_example(id: str) -> ComposeResult:
55+
yield Container(
56+
ListView(
57+
ListItem(Label("One")),
58+
ListItem(Label("Two")),
59+
ListItem(Label("Three")),
60+
),
61+
id=id,
62+
)
63+
64+
yield Footer()
65+
66+
67+
def loading_example(id: str) -> ComposeResult:
68+
yield Container(LoadingIndicator(), id=id)
69+
70+
71+
def sparkline_example(id: str) -> ComposeResult:
72+
data = [random.expovariate(1 / 3) for _ in range(1000)]
73+
74+
yield Container(
75+
Sparkline(data, summary_function=max),
76+
Sparkline(data, summary_function=mean),
77+
Sparkline(data, summary_function=min),
78+
id=id,
79+
)
80+
81+
82+
def static_example(id: str) -> ComposeResult:
83+
yield Container(Static("Hello, world!"), id=id)
84+
85+
86+
def tree_example(id: str) -> ComposeResult:
87+
tree: Tree[dict] = Tree("Dune")
88+
tree.root.expand()
89+
characters = tree.root.add("Characters", expand=True)
90+
characters.add_leaf("Paul")
91+
characters.add_leaf("Jessica")
92+
characters.add_leaf("Chani")
93+
yield Container(tree, id=id)
94+
95+
96+
__all__ = [
97+
"button_example",
98+
"checkbox_example",
99+
"data_table_example",
100+
"directory_tree_example",
101+
"footer_example",
102+
"header_example",
103+
"input_example",
104+
"label_example",
105+
"list_item_example",
106+
"loading_example",
107+
"markdown_viewer_example",
108+
"markdown_example",
109+
"option_list_example",
110+
"placeholder_example",
111+
"pretty_example",
112+
"radio_button_example",
113+
"radio_set_example",
114+
"select_example",
115+
"selection_list_example",
116+
"sparkline_example",
117+
"static_example",
118+
"switch_example",
119+
"tree_example",
120+
]

0 commit comments

Comments
 (0)