Skip to main content

pyweft-ui

Ready-made controls for PyWeft: buttons, menus, chips, sliders, form fields with validation, autocomplete and input masks, date and date-range pickers, an event calendar, charts, cards, layout, tabs, tables, dialogs, toasts and more, styled and accessible out of the box. Build a good-looking app in Python without writing HTML or CSS.

<template>
  <ui.Theme>
    <ui.AppShell title="Orders">
      <ui.Card title="New order">
        <ui.Column>
          <ui.TextField label="Customer" @bind="customer" required="true" />
          <ui.Select label="Size" options="Small, Medium, Large" @bind="size" />
          <ui.Switch label="Express delivery" @bind="express" />
        </ui.Column>
        <Fill name="footer">
          <ui.Button variant="ghost" @click="reset">Reset</ui.Button>
          <ui.Button variant="primary" icon="send" :loading="saving" @click="submit">
            Place order
          </ui.Button>
        </Fill>
      </ui.Card>
    </ui.AppShell>
  </ui.Theme>
</template>

<code>
from pyweft_ui import ui

customer: str = ""
size: str = "Medium"
express: bool = False
saving: bool = False

def reset(self):
    self.customer, self.size, self.express = "", "Medium", False

async def submit(self):
    ...
</code>

New to the toolkit? Read the guide: page layout, forms with validation, dialogs, themes and building your own components, with complete examples. This README is the compact reference.

Install

Install it into the same environment as PyWeft itself (see PyWeft's quick start):

uv add pyweft-ui

With pip:

pip install pyweft-ui

Then add "pyweft-ui" to the dependencies list in your app's own pyproject.toml (myapp/pyproject.toml), import it in a component's code block with from pyweft_ui import ui, and use the controls as <ui.Name>. pyweft run and pyweft build see that it is installed locally and send it to the browser for you.

Controls

Every control is a PyWeft component: attributes set its fields, @bind connects it to a field of yours, and attributes it doesn't have, such as class, style, id and aria-*, go onto its outer element. Plain attribute values are converted to each field's type, so cols="3" is the number 3 and disabled="true" is True.

Layout

Control Fields Notes
Theme mode (light, dark, auto), primary, radius, font Wrap your app in it to set colours and corners for everything inside. Optional.
AppShell title, width (narrow, normal, wide, full), sticky_nav Header, optional sidebar and content; the sidebar stays in view while the page scrolls. Fills: brand, actions, nav.
Row gap, align, justify (start, center, end, between), wrap Children side by side.
Column gap, align Children stacked.
Grid cols, min_width, gap Fixed columns, or as many as fit.
Card title, subtitle Fills: title, actions, footer.
Carousel items, label, per_view, gap, loop, autoplay (seconds), arrows, indicators (dots, none) Slides moved by arrows, dots, swipe or drag; @bind to the first shown slide's index; emits change. Fill: slide (with slide, index, active).
Divider label, align (center, start, end), vertical, inset ("true" or a length), spacing (none, sm, md, lg) A thin line; with label, text on the line; vertical between items in a Row.
Expansion title, description, icon, open, disabled, toggle (after, before, none), level, lazy @bind to a bool; emits open, close. Fills: header, actions.
Accordion options (dicts may add description, icon, disabled), multiple, disabled, toggle, level, lazy @bind to the open panel's value (multiple: a list). The content between the tags is each panel's body; panel inside it is that panel's value. Up/Down, Home/End move between headers.

Gaps take none, xs, sm, md, lg, xl, or any CSS length.

Form fields

All have label, hint, error, required, disabled, name, and take @bind.

Control Binds Extra fields
TextField str type (text, email, password, search, url, tel, date, time), placeholder, autocomplete, mask ("(999) 999-9999": 9 digit, a letter, * either), readonly; emits enter on Enter
TextArea str rows, placeholder, readonly
NumberField int or float min, max, step, placeholder, readonly
Select the chosen option's value options, placeholder
RadioGroup the chosen option's value options, inline
Checkbox bool
Switch bool
Autocomplete the chosen option's value (free="true": the typed text) options, match (contains, starts, none), max_results, min_chars, free, loading, empty, placeholder, align; emits search (the text, each keystroke), select (the whole option), enter. Fills: option (with option, active, query), empty
CascadeSelect the chosen option's value nested options (value, label, children; children: None loads on demand via load), any_level, show_path, separator, clearable, placeholder, name; emits select (the path), load, blur. Fill: option (with option, chosen)
ButtonToggle the chosen value; multiple="true": a list options (dicts may add icon, icon_only, disabled), multiple, allow_none, check, size (sm, md, lg), full_width, orientation, aria_label, name
Chips the chosen value; multiple="true": a list options (dicts may add icon, disabled), multiple, required, removable (emits remove), selectable. Fill: option (with option, selected)
ChipInput a list options (suggestions), free, separators, max, add_on_blur, match, placeholder, name; emits add, remove. Fills: chip (with chip), option
Slider an int or float; range="true": (low, high) min, max, step, range, value_label (drag/always/side/none), format, ticks, marks, lazy, name; emits change, blur
DateRangePicker (start, end) dates or None min, max, min_days, max_days, months, placeholder, format, week_start, align; name sends <name>_start and <name>_end
Calendar datetime.date, or with range="true" (start, end) always open on the page: range, months, min, max, min_days, max_days, week_start
DatePicker datetime.date or None min, max (a date or "YYYY-MM-DD"), placeholder, format (strftime), week_start (monday, sunday), align

options can be a comma-separated string ("Small, Medium, Large"), a list of values, a list of (value, label) pairs or a list of {"value": ..., "label": ...} dicts. The bound field gets the value itself, so [(1, "One"), (2, "Two")] binds an int.

TextField, TextArea, NumberField, Select and DatePicker emit blur when the user leaves them, which is when a form starts showing that field's message.

Data and navigation

Control Fields Notes
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.
Stepper steps (dicts may add description, optional, error, done, disabled), linear, orientation (horizontal, vertical), label_position (end, bottom), label, back_label, next_label, finish_label @bind to the current step's value; the content between the tags is its body (step, index). @next runs before moving on (returning False stays); emits finish, back. Fill: actions (with go_next(), go_back(), first, last).
Tree nodes (dicts with value, label, icon, children (None: load on open), disabled), checkable, expanded, expand_all, filter, lines, label, empty, no_matches @bind to the selected node's value (checkable: the list of checked leaves). Emits activate, toggle, load. Fill: node (with node, level, expanded, selected). Arrow keys, Home/End, *, type-ahead.
Breadcrumbs items, auto, home, home_icon, separator (chevron, slash, text), max, label The trail to the current page; links go through the router. auto="true": built from the URL and each page's crumb. With @select, items are buttons. Fill: item (with item, current).
EventCalendar events, view (month, week, agenda), months, date, week_start, day_start, day_end, max_per_day, time_format, switcher, label Events (dicts or objects with title, start, end, color) by month, week or day; a date start is all day. Emits select (your event), day (the date or hour clicked), navigate ((first, last) showing).
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.

Table columns are field names ("id, customer"), (field, heading) pairs, or dicts with key and optionally label, format (",.2f" or a function), align and sortable. Left out, they come from the first row. sort="-total" starts sorted by total, largest first.

Charts

Control Fields Notes
BarChart data, x, y, series, horizontal, stacked (true, percent), labels, y_min, y_max, y2_label Grouped, stacked or 100% bars, across or up; with series of type line or area, a combo chart, and axis="right", a second scale.
LineChart data, x, y, series, curve (linear, smooth, step, step-before, step-after), fill, stacked, points, connect_gaps, labels Lines, or areas with fill="true"; series can be dashed (dash), on a second scale or bars.
PieChart data, label, value, donut, hole, half, labels (percent, value, label, none), center, center_label Pie, doughnut or half circle; center="total" writes the sum in the hole.
PolarAreaChart data, label, value Equal angles, each slice as long as its value.
RadarChart data, x, y, series, points One shape per series over three or more spokes.
ScatterChart data, x, y, group, size, label, trend, radius, x_min, x_max, y_min, y_max, x_format, x_tick_format, size_label Points by two numbers; size makes bubbles (area shows the value); trend="true" adds least-squares lines with R².
Sparkline data (numbers or rows), x, y, kind (line, area, bar), points (last, minmax, all, none), color, height, name A small chart with no axes, for stat cards and table cells.
Gauge value, min, max, label, format, bands, color, half, needle, show_range A 270° dial or half circle, coloured by bands ("60:success, 85:warning, 100:danger"); a meter for screen readers.
FunnelChart data, label, value, shape (bars, funnel), color, colors, height Stages with their share of the first; tooltips add the step's conversion and how many were lost.
WaterfallChart data, label, value, total, totals, labels, up_color, down_color, total_color Each bar starts where the last ended; totals stand on zero.
Histogram data, y, group, bins, density, cumulative, curve, show_mean Counts in round bins; overlapping groups; a density curve (KDE).
BoxPlot data, y, group, violin, points (outliers, all, none), horizontal, show_mean Quartiles, whiskers and outliers, or violins.
Heatmap data, x, y, value, x_labels, y_labels, labels, color, low_color, diverging, center, min_value, max_value, show_scale Cells coloured by value, with a colour scale.
CorrelationMatrix data, fields, method (pearson, spearman), triangle (full, lower) Correlations between number fields, -1 to 1.
CandlestickChart data, date, open, high, low, close, volume, averages, style (candle, hollow, ohlc), show_volume Prices per period with volume and moving averages.
Treemap data, label, value, path, children, depth Nested rectangles sized by value.
SankeyChart data, source, target, value, align (left, justify), node_width Flows between nodes.
CalendarHeatmap data, date, value, start, end, week_start, color A year of days shaded by value.

The charts (all but Gauge and Sparkline) take title, subtitle, height, legend (auto, top, bottom, right, none), format, tick_format, x_label, y_label, colors, aria_label and empty, and emit select with what was clicked. data is rows (dicts or objects), a dict of columns, a pandas or polars DataFrame, a {label: value} dict or Chart.js's {"labels", "datasets"}. Bar and line series also take lower/upper (a band), error (error bars) and trend (a least-squares line). Charts are SVG drawn in Python: themed, sized to their container, with tooltips, a legend that hides series, arrow-key reading and a data table for screen readers.

Actions and feedback

Control Fields Notes
Button variant (primary, secondary, ghost, danger), size (sm, md, lg), icon, loading, disabled, block, type Emits click.
Menu label, items, icon, icon_only, variant, align (start, end), position (below, above), caret, disabled A button that opens a list of actions; emits select with the chosen item's value. items: text, (value, label) pairs, or dicts with value, label, icon, description, hint, danger, disabled and items (a submenu); "-" is a divider, {"heading": ...} a group heading. Fills: trigger (your own button content), item (with item).
ContextMenu items, label, disabled Wraps content; right-click (or the Menu key, Shift+F10) opens items at the pointer. Emits select, open. Fill: item.
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.
BottomSheet title, items (dicts may add icon, description, danger, disabled), max_width, dismissible, aria_label @bind to a bool. Slides up from the bottom; choosing an item emits select and closes it. Esc, a tap outside or a swipe down close it; emits close with how. Fill: actions.
Popover label, icon, icon_only, variant (primary, secondary, ghost, link), caret, title, open_on (click, hover), position (below, above, start, end), align (start, center, end), arrow, width, disabled A button opening a panel of your content beside it. Click mode: @bind a bool, emits open/close; click outside or Esc closes. Hover mode: a preview card shown by CSS. Fill: trigger.
Tooltip text, position (above, below, start, end), tip_id, disabled Wraps a control; shows text on hover or keyboard focus (CSS only). Pair tip_id with the control's aria-describedby.
Toaster look (toast, snackbar), position (bottom-right, bottom-left, bottom-center, top-left, top-center, top-right), limit, dismissible Put one on the page; it shows what toast() raises. look="snackbar": a compact dark bar, bottom centre, one at a time.
Alert kind (info, success, warning, danger), title, dismissible Emits close.
Badge kind (neutral, primary, info, success, warning, danger)
Spinner size, label
Progress value (none: indeterminate), max, buffer, label, aria_label, show_value, format, shape (bar, circle), kind, size (sm, md, lg), striped How far along something is; a bar, or a ring with the value inside.
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, calendar, more, bold, italic, underline, align-left/center/right, list, grid, folder, folder-open, file

Checking forms

from pyweft_ui import Form, rules

form = Form(
    email=[rules.required(), rules.email()],
    password=[rules.required(), rules.min_length(8)],
    agreed=rules.accepted("Agree to the terms to continue"),
)

async def submit(self):
    if not self.form.check():     # shows every message, focuses the first field to fix
        return
    ...
<ui.TextField ref="email" label="Email" @bind="email"
              :error="form.error('email')" @blur="form.touch('email')" />

A field's message shows once the user has left it or tried to submit, then follows what they type. Rules: required, accepted, email, url, min_length, max_length, min_value, max_value, pattern, one_of, same_as and check, or any function of the value that returns a message. form.valid, form.errors and form.reset() do what they say. The guide has the details.

Toasts

from pyweft_ui import toast, clear_toasts

toast("Saved")                                   # info, closes after 4 s
toast("Payment failed", "danger", title="Oops")  # kind: info, success, warning, danger
toast("Archived", action="Undo", on_action=undo) # a button that calls undo()
note = toast("Uploading…", duration=None)        # stays until note.close()

Call it from any handler or task; the page's <ui.Toaster /> shows it.

Theming

<ui.Theme mode="auto" primary="#0f766e" radius="12px">
  ...
</ui.Theme>

Every colour is a CSS variable (--ui-primary, --ui-text, --ui-surface, --ui-border, --ui-danger ...), so you can also set them in your own CSS.

gallery/ is a PyWeft app showing every control. From the PyWeft repository:

uv run pyweft run packages/pyweft-ui/gallery

Metadata

Release files for pyweft-ui 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyweft-ui 0.5.0
File Size Uploaded Provenance Actions
pyweft_ui-0.5.0.tar.gz 255.4 kB With provenance Details for pyweft_ui-0.5.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pyweft-ui 0.5.0
File Interpreter ABI Platform Actions
pyweft_ui-0.5.0-py3-none-any.whl Python 3 none any Details for pyweft_ui-0.5.0-py3-none-any.whl

Total release size: 452.8 kB

Release files / pyweft_ui-0.5.0.tar.gz

Download URL pyweft_ui-0.5.0.tar.gz
Size 255.4 kB
Tags Source
SHA-256 checksum
How to use checksums
c0c240c923e7f0d97f0d888c5c9211248f007149d004c399b08c556d6d038eac
BLAKE2b-256 checksum
How to use checksums
fdc7d898088243de62de6c7069df6c8a531da01de875d5fc3785c9d668f6726f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Release files / pyweft_ui-0.5.0-py3-none-any.whl

Download URL pyweft_ui-0.5.0-py3-none-any.whl
Size 197.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f18e822e64947428ebd4977d8547d477e7685386f2df7bb9ce15b691dc514ba
BLAKE2b-256 checksum
How to use checksums
a65060ea0f3b21cbc7afded7444894f9c31a9118dae232cae1a14695757c919a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

Security for pyweft-ui 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pyweft_ui-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page