PasswordField#

Masked text input for password entry with an optional visibility toggle.

PasswordField demo — light theme PasswordField demo — dark theme

Usage#

Read or set the secret through field.value — always the unmasked string — or bind it with textsignal=. Users can briefly reveal the input by holding the eye toggle, and you can drive masking from code with reveal() / hide(). Validation runs against the typed value, exactly like a plain text field.

Basic#

bs.PasswordField(placeholder="Enter password…")

Label and message#

Use label= for a field title and message= for helper text below.

bs.PasswordField(
    label="Password",
    placeholder="Enter password…",
    message="Must be at least 8 characters.",
)

Required#

Set required=True to mark the field visually and prevent empty submission.

bs.PasswordField(label="Password", required=True)

Visibility toggle#

The eye-icon button is shown by default and reveals the password while held. Disable it with show_visibility_toggle=False.

bs.PasswordField(label="With toggle", value="secret123")
bs.PasswordField(label="No toggle",   value="secret123", show_visibility_toggle=False)
PasswordField visibility toggle — light theme PasswordField visibility toggle — dark theme

The toggle stays usable on a read-only field — revealing only unmasks the text, it never changes the value (handy for a generated secret shown for the user to peek at and copy). A fully disabled field dims it along with everything else.

Programmatic reveal / hide#

Call reveal() and hide() to control masking in code — useful for a “show password” checkbox pattern.

field = bs.PasswordField(label="Password", show_visibility_toggle=False)

def _toggle_reveal(e):
    if checkbox.value:
        field.reveal()
    else:
        field.hide()

checkbox = bs.Checkbox("Show password", on_change=_toggle_reveal)

Custom mask character#

The default mask is '•'. Supply any single character via mask=.

bs.PasswordField(mask="*")

States#

bs.PasswordField(value="secret123", label="Normal")
bs.PasswordField(value="secret123", label="Read only", read_only=True)
bs.PasswordField(value="secret123", label="Disabled",  disabled=True)
PasswordField states — light theme PasswordField states — dark theme

Reactive binding#

Bind a Signal[str] with textsignal=. The field and signal stay in sync automatically — typing updates the signal, setting the signal updates the field.

password = bs.Signal("")
bs.PasswordField(label="Password", textsignal=password)
password.subscribe(lambda v: validate_strength(v))

Submit on Enter#

field = bs.PasswordField(placeholder="Password…")
field.on_submit(lambda e: attempt_login(field.value))

Validation#

Attach rules with add_validation_rule(). Rules run on the configured trigger ('blur', 'key', or 'manual').

field = bs.PasswordField(label="Password")
field.add_validation_rule(
    "stringLength",
    message="Password must be at least 8 characters.",
    min=8,
    trigger="blur",
)

# Explicit validation check
is_valid = field.validate()
PasswordField validation — light theme PasswordField validation — dark theme

Validity is reactive state. field.valid is a Signal[bool] and field.error a Signal[str] (the current message, "" when valid) — bind the error to a label and it keeps itself in sync, or gate the submit button off field.valid:

bs.Label(textsignal=field.error, accent="danger")   # shows and clears itself

Note

The full rule taxonomy (stringLength, pattern, custom, …) and aggregating a whole form’s validity live in the Validation guide.

Widget sizing#

All widgets accept self-placement kwargs via **kwargs. The parent container determines which options apply — Column / Row parents use the layout kwargs below, grid-based parents use grid kwargs.

Column (vertical layout)

Used inside a Column, App, or any other container with a column layout. Children are arranged top-to-bottom, so horizontal aligns each child across the width and grow shares the vertical space. (vertical does not apply — the order of the children sets their top-to-bottom position.)

horizontal

Cross-axis placement of the widget: 'left', 'center', 'right', or 'stretch' to fill the available width.

grow

Claim and fill a share of the leftover vertical space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Row (horizontal layout)

Used inside a Row or any other container with a row layout. Children are arranged left-to-right, so vertical aligns each child across the height and grow shares the horizontal space. (horizontal does not apply — the order of the children sets their left-to-right position.)

vertical

Cross-axis placement of the widget: 'top', 'center', 'bottom', or 'stretch' to fill the available height.

grow

Claim and fill a share of the leftover horizontal space (the layout direction). True or False.

margin

External spacing in pixels. Accepts an integer (equal on all sides), a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing (left and right). Accepts an integer or a 2-tuple (left, right) for asymmetric spacing. Overrides the horizontal component of margin=.

margin_y

Vertical external spacing (top and bottom). Accepts an integer or a 2-tuple (top, bottom) for asymmetric spacing. Overrides the vertical component of margin=.

Grid

Used inside a Grid container.

row / column

Zero-based row and column indices.

rowspan / columnspan

Number of rows or columns to span.

horizontal

Horizontal placement within the grid cell: 'left', 'center', 'right', or 'stretch' to fill the cell width.

vertical

Vertical placement within the grid cell: 'top', 'center', 'bottom', or 'stretch' to fill the cell height.

margin

External spacing in pixels. Accepts an integer, a 2-tuple (horizontal, vertical), or a 4-tuple (left, top, right, bottom).

margin_x

Horizontal external spacing. Accepts an integer or (left, right).

margin_y

Vertical external spacing. Accepts an integer or (top, bottom).

See also#

  • TextField — plain text input

  • NumberField — numeric input with optional range constraints

  • Validation — the full rule set and form-level validity

  • Customizing Fields — add buttons or icons inside a field, and reusable field types

  • Signals — the reactive binding behind textsignal=

API#

The complete reference for PasswordField lives on the Widgets API page. At a glance:

PasswordField

A masked text field for password input with an optional visibility toggle.

Full Example#

 1
 2with bs.App(title="PasswordField Demo", padding=20, gap=16) as app:
 3
 4    # Basic
 5    bs.Label("Basic", font="heading-sm")
 6    bs.PasswordField(placeholder="Enter password…", horizontal="stretch")
 7
 8    # Label, message, required
 9    bs.Label("Label, Message, Required", font="heading-sm")
10    bs.PasswordField(
11        label="Password",
12        placeholder="Enter password…",
13        message="Must be at least 8 characters.",
14        required=True,
15        horizontal="stretch",
16    )
17
18    # Visibility toggle
19    bs.Label("Visibility Toggle", font="heading-sm")
20    with bs.Row(gap=8, horizontal="stretch", grow_items=True):
21        bs.PasswordField(label="With toggle", value="secret123")
22        bs.PasswordField(label="No toggle",   value="secret123", show_visibility_toggle=False)
23
24    # Custom mask character
25    bs.Label("Custom Mask Character", font="heading-sm")
26    with bs.Row(gap=8, horizontal="stretch", grow_items=True):
27        bs.PasswordField(value="secret", label="Default (•)")
28        bs.PasswordField(value="secret", label="Asterisk (*)", mask="*")
29
30    # States
31    bs.Label("States", font="heading-sm")
32    with bs.Row(gap=8, horizontal="stretch", grow_items=True):
33        bs.PasswordField(value="secret123", label="Normal")
34        bs.PasswordField(value="secret123", label="Read only", read_only=True)
35        bs.PasswordField(value="secret123", label="Disabled",  disabled=True)
36
37app.run()