pyweft-ui 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyweft_ui-0.1.0/.gitignore +10 -0
- pyweft_ui-0.1.0/CHANGELOG.md +23 -0
- pyweft_ui-0.1.0/LICENSE +21 -0
- pyweft_ui-0.1.0/PKG-INFO +184 -0
- pyweft_ui-0.1.0/README.md +165 -0
- pyweft_ui-0.1.0/docs/guide.md +929 -0
- pyweft_ui-0.1.0/gallery/app.weft +289 -0
- pyweft_ui-0.1.0/gallery/pyproject.toml +4 -0
- pyweft_ui-0.1.0/gallery/styles.css +4 -0
- pyweft_ui-0.1.0/pyproject.toml +41 -0
- pyweft_ui-0.1.0/src/pyweft_ui/__init__.py +23 -0
- pyweft_ui-0.1.0/src/pyweft_ui/alert.weft +48 -0
- pyweft_ui-0.1.0/src/pyweft_ui/app_shell.weft +47 -0
- pyweft_ui-0.1.0/src/pyweft_ui/badge.weft +25 -0
- pyweft_ui-0.1.0/src/pyweft_ui/button.weft +64 -0
- pyweft_ui-0.1.0/src/pyweft_ui/card.weft +45 -0
- pyweft_ui-0.1.0/src/pyweft_ui/checkbox.weft +26 -0
- pyweft_ui-0.1.0/src/pyweft_ui/column.weft +23 -0
- pyweft_ui-0.1.0/src/pyweft_ui/dialog.weft +91 -0
- pyweft_ui-0.1.0/src/pyweft_ui/grid.weft +25 -0
- pyweft_ui-0.1.0/src/pyweft_ui/icon.weft +50 -0
- pyweft_ui-0.1.0/src/pyweft_ui/number_field.weft +69 -0
- pyweft_ui-0.1.0/src/pyweft_ui/radio_group.weft +60 -0
- pyweft_ui-0.1.0/src/pyweft_ui/row.weft +28 -0
- pyweft_ui-0.1.0/src/pyweft_ui/select.weft +81 -0
- pyweft_ui-0.1.0/src/pyweft_ui/spinner.weft +21 -0
- pyweft_ui-0.1.0/src/pyweft_ui/switch.weft +39 -0
- pyweft_ui-0.1.0/src/pyweft_ui/table.weft +223 -0
- pyweft_ui-0.1.0/src/pyweft_ui/tabs.weft +122 -0
- pyweft_ui-0.1.0/src/pyweft_ui/text_area.weft +48 -0
- pyweft_ui-0.1.0/src/pyweft_ui/text_field.weft +51 -0
- pyweft_ui-0.1.0/src/pyweft_ui/theme.weft +81 -0
- pyweft_ui-0.1.0/src/pyweft_ui/toaster.weft +117 -0
- pyweft_ui-0.1.0/src/pyweft_ui/toasts.py +73 -0
- pyweft_ui-0.1.0/tests/conftest.py +14 -0
- pyweft_ui-0.1.0/tests/test_controls.py +555 -0
- pyweft_ui-0.1.0/tests/test_guide_examples.py +194 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
What changed in each release of `pyweft-ui`. Newest first.
|
|
4
|
+
|
|
5
|
+
Add a line under **Unreleased** with each change worth knowing about;
|
|
6
|
+
releasing moves them under the new version (see
|
|
7
|
+
[RELEASING.md](../../RELEASING.md)).
|
|
8
|
+
|
|
9
|
+
## Unreleased
|
|
10
|
+
|
|
11
|
+
## 0.1.0
|
|
12
|
+
|
|
13
|
+
The first release, for `pyweft` 0.2.
|
|
14
|
+
|
|
15
|
+
- **22 controls**: `Theme`, `AppShell`, `Row`, `Column`, `Grid`, `Card`,
|
|
16
|
+
`Button`, `Icon`, `TextField`, `TextArea`, `NumberField`, `Select`,
|
|
17
|
+
`RadioGroup`, `Checkbox`, `Switch`, `Alert`, `Badge`, `Spinner`,
|
|
18
|
+
`Dialog`, `Tabs`, `Table` and `Toaster` with `toast()`.
|
|
19
|
+
- Light, dark and system themes, every colour a `--ui-*` CSS variable.
|
|
20
|
+
- Keyboard and screen reader support: labelled fields, focus kept inside
|
|
21
|
+
dialogs and returned on close, arrow keys between tabs, sortable table
|
|
22
|
+
headings announced.
|
|
23
|
+
- A gallery app and a guide with tested examples.
|
pyweft_ui-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Prassanth Nicholas
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
pyweft_ui-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pyweft-ui
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Ready-made controls for PyWeft: buttons, fields, cards, layout, dialogs. No HTML or CSS required.
|
|
5
|
+
Project-URL: Homepage, https://github.com/prassanthn/PyWeft
|
|
6
|
+
Project-URL: Documentation, https://github.com/prassanthn/PyWeft/blob/main/packages/pyweft-ui/docs/guide.md
|
|
7
|
+
Project-URL: Issues, https://github.com/prassanthn/PyWeft/issues
|
|
8
|
+
Author: Prassanth Nicholas
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: components,controls,pyodide,pyweft,ui
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: pyweft<0.3,>=0.2
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# pyweft-ui
|
|
21
|
+
|
|
22
|
+
Ready-made controls for [PyWeft](https://github.com/prassanthn/PyWeft):
|
|
23
|
+
buttons, form fields, cards, layout, tabs, tables, dialogs, toasts and more,
|
|
24
|
+
styled and accessible out of the box. Build a good-looking app in Python without writing HTML or
|
|
25
|
+
CSS.
|
|
26
|
+
|
|
27
|
+
```xml
|
|
28
|
+
<template>
|
|
29
|
+
<ui.Theme>
|
|
30
|
+
<ui.AppShell title="Orders">
|
|
31
|
+
<ui.Card title="New order">
|
|
32
|
+
<ui.Column>
|
|
33
|
+
<ui.TextField label="Customer" @bind="customer" required="true" />
|
|
34
|
+
<ui.Select label="Size" options="Small, Medium, Large" @bind="size" />
|
|
35
|
+
<ui.Switch label="Express delivery" @bind="express" />
|
|
36
|
+
</ui.Column>
|
|
37
|
+
<Fill name="footer">
|
|
38
|
+
<ui.Button variant="ghost" @click="reset">Reset</ui.Button>
|
|
39
|
+
<ui.Button variant="primary" icon="send" :loading="saving" @click="submit">
|
|
40
|
+
Place order
|
|
41
|
+
</ui.Button>
|
|
42
|
+
</Fill>
|
|
43
|
+
</ui.Card>
|
|
44
|
+
</ui.AppShell>
|
|
45
|
+
</ui.Theme>
|
|
46
|
+
</template>
|
|
47
|
+
|
|
48
|
+
<code>
|
|
49
|
+
from pyweft_ui import ui
|
|
50
|
+
|
|
51
|
+
customer: str = ""
|
|
52
|
+
size: str = "Medium"
|
|
53
|
+
express: bool = False
|
|
54
|
+
saving: bool = False
|
|
55
|
+
|
|
56
|
+
def reset(self):
|
|
57
|
+
self.customer, self.size, self.express = "", "Medium", False
|
|
58
|
+
|
|
59
|
+
async def submit(self):
|
|
60
|
+
...
|
|
61
|
+
</code>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**New to the toolkit? Read the [guide](docs/guide.md)**: page layout, forms
|
|
65
|
+
with validation, dialogs, themes and building your own components, with
|
|
66
|
+
complete examples. This README is the compact reference.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
It isn't on PyPI yet, so install it from GitHub, into the same environment
|
|
71
|
+
as PyWeft itself (see PyWeft's [quick start](../../README.md#quick-start)):
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv add "pyweft-ui @ git+https://github.com/prassanthn/PyWeft.git#subdirectory=packages/pyweft-ui"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
With pip:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install "git+https://github.com/prassanthn/PyWeft.git#subdirectory=packages/pyweft-ui"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Then add `"pyweft-ui"` to the `dependencies` list in your app's own
|
|
84
|
+
`pyproject.toml` (`myapp/pyproject.toml`), import it in a component's code
|
|
85
|
+
block with `from pyweft_ui import ui`, and use the controls as `<ui.Name>`.
|
|
86
|
+
`pyweft run` and `pyweft build` see that it is installed locally and send it
|
|
87
|
+
to the browser for you.
|
|
88
|
+
|
|
89
|
+
## Controls
|
|
90
|
+
|
|
91
|
+
Every control is a PyWeft component: attributes set its fields, `@bind`
|
|
92
|
+
connects it to a field of yours, and attributes it doesn't have, such as
|
|
93
|
+
`class`, `style`, `id` and `aria-*`, go onto its outer element. Plain
|
|
94
|
+
attribute values are converted to each field's type, so `cols="3"` is the
|
|
95
|
+
number 3 and `disabled="true"` is `True`.
|
|
96
|
+
|
|
97
|
+
### Layout
|
|
98
|
+
|
|
99
|
+
| Control | Fields | Notes |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `Theme` | `mode` (light, dark, auto), `primary`, `radius`, `font` | Wrap your app in it to set colours and corners for everything inside. Optional. |
|
|
102
|
+
| `AppShell` | `title`, `width` (narrow, normal, wide, full) | Header, optional sidebar and content. Fills: `brand`, `actions`, `nav`. |
|
|
103
|
+
| `Row` | `gap`, `align`, `justify` (start, center, end, between), `wrap` | Children side by side. |
|
|
104
|
+
| `Column` | `gap`, `align` | Children stacked. |
|
|
105
|
+
| `Grid` | `cols`, `min_width`, `gap` | Fixed columns, or as many as fit. |
|
|
106
|
+
| `Card` | `title`, `subtitle` | Fills: `title`, `actions`, `footer`. |
|
|
107
|
+
|
|
108
|
+
Gaps take `none`, `xs`, `sm`, `md`, `lg`, `xl`, or any CSS length.
|
|
109
|
+
|
|
110
|
+
### Form fields
|
|
111
|
+
|
|
112
|
+
All have `label`, `hint`, `error`, `required`, `disabled`, `name`, and take
|
|
113
|
+
`@bind`.
|
|
114
|
+
|
|
115
|
+
| Control | Binds | Extra fields |
|
|
116
|
+
|---|---|---|
|
|
117
|
+
| `TextField` | `str` | `type` (text, email, password, search, url, tel, date, time), `placeholder`, `autocomplete`; emits `enter` on Enter |
|
|
118
|
+
| `TextArea` | `str` | `rows`, `placeholder` |
|
|
119
|
+
| `NumberField` | `int` or `float` | `min`, `max`, `step`, `placeholder` |
|
|
120
|
+
| `Select` | the chosen option's value | `options`, `placeholder` |
|
|
121
|
+
| `RadioGroup` | the chosen option's value | `options`, `inline` |
|
|
122
|
+
| `Checkbox` | `bool` | |
|
|
123
|
+
| `Switch` | `bool` | |
|
|
124
|
+
|
|
125
|
+
`options` can be a comma-separated string (`"Small, Medium, Large"`), a list
|
|
126
|
+
of values, a list of `(value, label)` pairs or a list of
|
|
127
|
+
`{"value": ..., "label": ...}` dicts. The bound field gets the value itself,
|
|
128
|
+
so `[(1, "One"), (2, "Two")]` binds an `int`.
|
|
129
|
+
|
|
130
|
+
### Data and navigation
|
|
131
|
+
|
|
132
|
+
| Control | Fields | Notes |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `Tabs` | `options`, `label`, `variant` (line, pills) | `@bind` to the chosen option's value. The content between the tags is the panel; `tab` inside it is the chosen value. Arrow keys, Home and End move between tabs. |
|
|
135
|
+
| `Table` | `rows`, `columns`, `row_key`, `sortable`, `sort`, `striped`, `dense`, `caption`, `empty` | `rows` are dicts or objects. Emits `select` with the clicked row. Fills: `cell` (with `row`, `column`, `value`, `text`), `empty`. |
|
|
136
|
+
|
|
137
|
+
`Table` columns are field names (`"id, customer"`), `(field, heading)` pairs,
|
|
138
|
+
or dicts with `key` and optionally `label`, `format` (`",.2f"` or a
|
|
139
|
+
function), `align` and `sortable`. Left out, they come from the first row.
|
|
140
|
+
`sort="-total"` starts sorted by `total`, largest first.
|
|
141
|
+
|
|
142
|
+
### Actions and feedback
|
|
143
|
+
|
|
144
|
+
| Control | Fields | Notes |
|
|
145
|
+
|---|---|---|
|
|
146
|
+
| `Button` | `variant` (primary, secondary, ghost, danger), `size` (sm, md, lg), `icon`, `loading`, `disabled`, `block`, `type` | Emits `click`. |
|
|
147
|
+
| `Dialog` | `title`, `width`, `dismissible` | `@bind` to a `bool`: open while it is `True`. Esc, a click outside or the X close it. Keeps Tab inside while open and gives focus back when closed. Fill: `footer`. |
|
|
148
|
+
| `Toaster` | `position` (bottom-right, bottom-left, bottom-center, top-left, top-center, top-right), `limit` | Put one on the page; it shows what `toast()` raises. |
|
|
149
|
+
| `Alert` | `kind` (info, success, warning, danger), `title`, `dismissible` | Emits `close`. |
|
|
150
|
+
| `Badge` | `kind` (neutral, primary, info, success, warning, danger) | |
|
|
151
|
+
| `Spinner` | `size`, `label` | |
|
|
152
|
+
| `Icon` | `name`, `size` | check, x, plus, minus, search, info, alert, chevron-up/down/left/right, menu, trash, edit, send, user, home, star, heart, download, upload, external, copy, settings, sun, moon |
|
|
153
|
+
|
|
154
|
+
## Toasts
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from pyweft_ui import toast, clear_toasts
|
|
158
|
+
|
|
159
|
+
toast("Saved") # info, closes after 4 s
|
|
160
|
+
toast("Payment failed", "danger", title="Oops") # kind: info, success, warning, danger
|
|
161
|
+
toast("Archived", action="Undo", on_action=undo) # a button that calls undo()
|
|
162
|
+
note = toast("Uploading…", duration=None) # stays until note.close()
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Call it from any handler or task; the page's `<ui.Toaster />` shows it.
|
|
166
|
+
|
|
167
|
+
## Theming
|
|
168
|
+
|
|
169
|
+
```xml
|
|
170
|
+
<ui.Theme mode="auto" primary="#0f766e" radius="12px">
|
|
171
|
+
...
|
|
172
|
+
</ui.Theme>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Every colour is a CSS variable (`--ui-primary`, `--ui-text`, `--ui-surface`,
|
|
176
|
+
`--ui-border`, `--ui-danger` ...), so you can also set them in your own CSS.
|
|
177
|
+
|
|
178
|
+
## The gallery
|
|
179
|
+
|
|
180
|
+
`gallery/` is a PyWeft app showing every control. From the PyWeft repository:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
uv run pyweft run packages/pyweft-ui/gallery
|
|
184
|
+
```
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# pyweft-ui
|
|
2
|
+
|
|
3
|
+
Ready-made controls for [PyWeft](https://github.com/prassanthn/PyWeft):
|
|
4
|
+
buttons, form fields, cards, layout, tabs, tables, dialogs, toasts and more,
|
|
5
|
+
styled and accessible out of the box. Build a good-looking app in Python without writing HTML or
|
|
6
|
+
CSS.
|
|
7
|
+
|
|
8
|
+
```xml
|
|
9
|
+
<template>
|
|
10
|
+
<ui.Theme>
|
|
11
|
+
<ui.AppShell title="Orders">
|
|
12
|
+
<ui.Card title="New order">
|
|
13
|
+
<ui.Column>
|
|
14
|
+
<ui.TextField label="Customer" @bind="customer" required="true" />
|
|
15
|
+
<ui.Select label="Size" options="Small, Medium, Large" @bind="size" />
|
|
16
|
+
<ui.Switch label="Express delivery" @bind="express" />
|
|
17
|
+
</ui.Column>
|
|
18
|
+
<Fill name="footer">
|
|
19
|
+
<ui.Button variant="ghost" @click="reset">Reset</ui.Button>
|
|
20
|
+
<ui.Button variant="primary" icon="send" :loading="saving" @click="submit">
|
|
21
|
+
Place order
|
|
22
|
+
</ui.Button>
|
|
23
|
+
</Fill>
|
|
24
|
+
</ui.Card>
|
|
25
|
+
</ui.AppShell>
|
|
26
|
+
</ui.Theme>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<code>
|
|
30
|
+
from pyweft_ui import ui
|
|
31
|
+
|
|
32
|
+
customer: str = ""
|
|
33
|
+
size: str = "Medium"
|
|
34
|
+
express: bool = False
|
|
35
|
+
saving: bool = False
|
|
36
|
+
|
|
37
|
+
def reset(self):
|
|
38
|
+
self.customer, self.size, self.express = "", "Medium", False
|
|
39
|
+
|
|
40
|
+
async def submit(self):
|
|
41
|
+
...
|
|
42
|
+
</code>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**New to the toolkit? Read the [guide](docs/guide.md)**: page layout, forms
|
|
46
|
+
with validation, dialogs, themes and building your own components, with
|
|
47
|
+
complete examples. This README is the compact reference.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
|
|
51
|
+
It isn't on PyPI yet, so install it from GitHub, into the same environment
|
|
52
|
+
as PyWeft itself (see PyWeft's [quick start](../../README.md#quick-start)):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
uv add "pyweft-ui @ git+https://github.com/prassanthn/PyWeft.git#subdirectory=packages/pyweft-ui"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
With pip:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install "git+https://github.com/prassanthn/PyWeft.git#subdirectory=packages/pyweft-ui"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then add `"pyweft-ui"` to the `dependencies` list in your app's own
|
|
65
|
+
`pyproject.toml` (`myapp/pyproject.toml`), import it in a component's code
|
|
66
|
+
block with `from pyweft_ui import ui`, and use the controls as `<ui.Name>`.
|
|
67
|
+
`pyweft run` and `pyweft build` see that it is installed locally and send it
|
|
68
|
+
to the browser for you.
|
|
69
|
+
|
|
70
|
+
## Controls
|
|
71
|
+
|
|
72
|
+
Every control is a PyWeft component: attributes set its fields, `@bind`
|
|
73
|
+
connects it to a field of yours, and attributes it doesn't have, such as
|
|
74
|
+
`class`, `style`, `id` and `aria-*`, go onto its outer element. Plain
|
|
75
|
+
attribute values are converted to each field's type, so `cols="3"` is the
|
|
76
|
+
number 3 and `disabled="true"` is `True`.
|
|
77
|
+
|
|
78
|
+
### Layout
|
|
79
|
+
|
|
80
|
+
| Control | Fields | Notes |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| `Theme` | `mode` (light, dark, auto), `primary`, `radius`, `font` | Wrap your app in it to set colours and corners for everything inside. Optional. |
|
|
83
|
+
| `AppShell` | `title`, `width` (narrow, normal, wide, full) | Header, optional sidebar and content. Fills: `brand`, `actions`, `nav`. |
|
|
84
|
+
| `Row` | `gap`, `align`, `justify` (start, center, end, between), `wrap` | Children side by side. |
|
|
85
|
+
| `Column` | `gap`, `align` | Children stacked. |
|
|
86
|
+
| `Grid` | `cols`, `min_width`, `gap` | Fixed columns, or as many as fit. |
|
|
87
|
+
| `Card` | `title`, `subtitle` | Fills: `title`, `actions`, `footer`. |
|
|
88
|
+
|
|
89
|
+
Gaps take `none`, `xs`, `sm`, `md`, `lg`, `xl`, or any CSS length.
|
|
90
|
+
|
|
91
|
+
### Form fields
|
|
92
|
+
|
|
93
|
+
All have `label`, `hint`, `error`, `required`, `disabled`, `name`, and take
|
|
94
|
+
`@bind`.
|
|
95
|
+
|
|
96
|
+
| Control | Binds | Extra fields |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `TextField` | `str` | `type` (text, email, password, search, url, tel, date, time), `placeholder`, `autocomplete`; emits `enter` on Enter |
|
|
99
|
+
| `TextArea` | `str` | `rows`, `placeholder` |
|
|
100
|
+
| `NumberField` | `int` or `float` | `min`, `max`, `step`, `placeholder` |
|
|
101
|
+
| `Select` | the chosen option's value | `options`, `placeholder` |
|
|
102
|
+
| `RadioGroup` | the chosen option's value | `options`, `inline` |
|
|
103
|
+
| `Checkbox` | `bool` | |
|
|
104
|
+
| `Switch` | `bool` | |
|
|
105
|
+
|
|
106
|
+
`options` can be a comma-separated string (`"Small, Medium, Large"`), a list
|
|
107
|
+
of values, a list of `(value, label)` pairs or a list of
|
|
108
|
+
`{"value": ..., "label": ...}` dicts. The bound field gets the value itself,
|
|
109
|
+
so `[(1, "One"), (2, "Two")]` binds an `int`.
|
|
110
|
+
|
|
111
|
+
### Data and navigation
|
|
112
|
+
|
|
113
|
+
| Control | Fields | Notes |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `Tabs` | `options`, `label`, `variant` (line, pills) | `@bind` to the chosen option's value. The content between the tags is the panel; `tab` inside it is the chosen value. Arrow keys, Home and End move between tabs. |
|
|
116
|
+
| `Table` | `rows`, `columns`, `row_key`, `sortable`, `sort`, `striped`, `dense`, `caption`, `empty` | `rows` are dicts or objects. Emits `select` with the clicked row. Fills: `cell` (with `row`, `column`, `value`, `text`), `empty`. |
|
|
117
|
+
|
|
118
|
+
`Table` columns are field names (`"id, customer"`), `(field, heading)` pairs,
|
|
119
|
+
or dicts with `key` and optionally `label`, `format` (`",.2f"` or a
|
|
120
|
+
function), `align` and `sortable`. Left out, they come from the first row.
|
|
121
|
+
`sort="-total"` starts sorted by `total`, largest first.
|
|
122
|
+
|
|
123
|
+
### Actions and feedback
|
|
124
|
+
|
|
125
|
+
| Control | Fields | Notes |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| `Button` | `variant` (primary, secondary, ghost, danger), `size` (sm, md, lg), `icon`, `loading`, `disabled`, `block`, `type` | Emits `click`. |
|
|
128
|
+
| `Dialog` | `title`, `width`, `dismissible` | `@bind` to a `bool`: open while it is `True`. Esc, a click outside or the X close it. Keeps Tab inside while open and gives focus back when closed. Fill: `footer`. |
|
|
129
|
+
| `Toaster` | `position` (bottom-right, bottom-left, bottom-center, top-left, top-center, top-right), `limit` | Put one on the page; it shows what `toast()` raises. |
|
|
130
|
+
| `Alert` | `kind` (info, success, warning, danger), `title`, `dismissible` | Emits `close`. |
|
|
131
|
+
| `Badge` | `kind` (neutral, primary, info, success, warning, danger) | |
|
|
132
|
+
| `Spinner` | `size`, `label` | |
|
|
133
|
+
| `Icon` | `name`, `size` | check, x, plus, minus, search, info, alert, chevron-up/down/left/right, menu, trash, edit, send, user, home, star, heart, download, upload, external, copy, settings, sun, moon |
|
|
134
|
+
|
|
135
|
+
## Toasts
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from pyweft_ui import toast, clear_toasts
|
|
139
|
+
|
|
140
|
+
toast("Saved") # info, closes after 4 s
|
|
141
|
+
toast("Payment failed", "danger", title="Oops") # kind: info, success, warning, danger
|
|
142
|
+
toast("Archived", action="Undo", on_action=undo) # a button that calls undo()
|
|
143
|
+
note = toast("Uploading…", duration=None) # stays until note.close()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Call it from any handler or task; the page's `<ui.Toaster />` shows it.
|
|
147
|
+
|
|
148
|
+
## Theming
|
|
149
|
+
|
|
150
|
+
```xml
|
|
151
|
+
<ui.Theme mode="auto" primary="#0f766e" radius="12px">
|
|
152
|
+
...
|
|
153
|
+
</ui.Theme>
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Every colour is a CSS variable (`--ui-primary`, `--ui-text`, `--ui-surface`,
|
|
157
|
+
`--ui-border`, `--ui-danger` ...), so you can also set them in your own CSS.
|
|
158
|
+
|
|
159
|
+
## The gallery
|
|
160
|
+
|
|
161
|
+
`gallery/` is a PyWeft app showing every control. From the PyWeft repository:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
uv run pyweft run packages/pyweft-ui/gallery
|
|
165
|
+
```
|