Nitro (N2O) is the quickest way to build web apps using Python. No front-end experience required.
Recall how simple it is to author interactive command line applications using Python's built-in input()
and print()
:
def main():
name = input('What is your name?')
feel = input(f'How do you feel today, {name}?')
print(f'What a coincidence, {name}, I feel {feel}, too!')
Output:
> What is your name?
> Boaty McBoatface
> How do you feel today, Boaty McBoatface?
> intrigued
> What a coincidence, Boaty McBoatface, I feel intrigued, too!
Nitro brings that same level of simplicity to authoring web applications:
from h2o_nitro import View, box
def main(view: View):
name = view(box('What is your name?', value='Boaty McBoatface'))
feel = view(box(f'How do you feel today, {name}?', value='intrigued'))
view(f'What a coincidence, {name}, I feel {feel}, too!')
H2O Nitro is pre-alpha software. API is subject to change.
- Write once, run anywhere. Build apps for mobile (iOS, Android), desktop (Linux, OSX, Windows) and the web from one codebase, using one language.
- Write less, do more. Code is a liability. Less code ≈ less bugs.
- No HTML/Javascript. Build sophisticated multi-page wizard-like workflows and walkthroughs using pure Python.
- Less Code. Laser-focused on keeping application code simple, concise, and clear.
- Simplicity. Page flow follows code flow.
- Conciseness. Lowest number of lines of code for expressing solutions to a given problem. bugs.
- Clarity. Write apps without jumping through callbacks, request handlers, or event handlers.
- Minimal API. Only three functions:
view()
,box()
,option()
, and optionallyrow()
andcolumn()
for layout. - Batteries-included. Huge library of sophisticated, accessibility-friendly widgets and data visualizations.
- Library. Nitro is a library, not a server. Integrates with Django , Flask, Starlette , Tornado, Uvicorn and other popular frameworks. Can be integrated into your existing applications.
- Prototyping-to-production. Carefully designed API to rapidly prototype new ideas, then progressively improve presentation and aesthetics over time without affecting initial implementation simplicity, or sacrificing control.
- Unix philosophy. Tries to do one thing and do it well: display interactive user interfaces. Bring your own web app/server of choice and follow its recommendations for hosting, deployment, security, monitoring, metrics and data management.
- Extensively documented. Run
nitro docs
to access interactive docs and 150+ live examples.
TL;DR: Use Wave for building visualization-heavy analytical dashboards. For everything else, use Nitro.
- Deployment. Nitro is a library, not a server. It's a heavily stripped-down version of Wave with a different, simpler API, designed for integration with existing frameworks, and cross-compiling for mobile and desktop apps.
- Content Management. Wave is capable of storing and broadcasting content and data, making it simple to build dashboards without having to deal with data management. Nitro has no such features.
- API. Wave's API is dashboard-oriented, and has several features that make it easy to develop and deploy real-time analytics and dashboards easily. Nitro's API is page-flow-oriented, and makes it radically simple to author sophisticated workflows and wizards without dealing with callback functions and request handlers.
Install with interactive tour and documentation:
pip3 install h2o-nitro[flask]
Or, for a minimal install:
pip3 install h2o-nitro
Nitro ships with interactive documentation and live examples:
nitro docs
Access docs at http://localhost:4999/.
Create an app named my_app
:
nitro create my_app
Launch your app inside a virtual environment:
cd my_app
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python app.py
Access your app at http://localhost:5000/.
nitro create
creates the simplest possible app by default, but you can start from other kinds of sample
apps.
Create an app that lets you apply for space flight, with multiple workflows, a menu and navbar.
nitro create my_app --template recruitment
To see a list of all available starter app templates, run:
nitro list templates
New apps created with nitro create
use Flask by default, but you can use other
frameworks, too.
Create an app using Tornado:
nitro create my_app --framework tornado
Create an app using Starlette:
nitro create my_app --framework starlette
To see a list of all available frameworks, run:
nitro list frameworks
Call view()
to show something on a page.
view('Hello World!')
Here, view()
is comparable to Python's built-in print()
function,
and prints its arguments to the web page.
Strings passed to view()
are interpreted as
Markdown
view('_Less_ `code` means _less_ **bugs**.')
Triple-quote strings to pass multiple lines of markdown.
view('''
The King said, very gravely:
- Begin at the beginning,
- And go on till you come to the end,
- Then stop.
''')
Pass multiple arguments to view()
to lay them out top to bottom.
view(
'Begin at the beginning,',
'And go on till you come to the end,',
'Then stop.',
)
Call view()
multiple times to show items one at a time.
The following example steps through three different pages.
view('Begin at the beginning,')
view('And go on till you come to the end,')
view('Then stop.')
Call box()
to create a box (an input field) and pass it to view()
.
When a view contains a box, the view()
function returns its input value.
box()
creates a textbox by default, but can also create other kinds of input fields, like checkboxes,
dropdowns, spinboxes, buttons, calendars, etc.
# Display a textbox and assign the entered value to a variable.
name = view(box('What is your name?', value='Boaty McBoatface'))
# Print the entered value.
view(f'Hello, {name}!')
Here, view()
behaves similar to Python's built-in input()
function.
Call view()
multiple times to prompt for a sequence of inputs, one at a time.
The following example steps through three different pages.
# Prompt for first name.
first_name = view(box('First name', value='Boaty'))
# Prompt for last name.
last_name = view(box('Last name', value='McBoatface'))
# Print the entered values.
view(f'Hello, {first_name} {last_name}!')
Pass multiple boxes to view()
to prompt for inputs at once.
When a view contains multiple boxes, the view()
function returns multiple values, in order.
# Prompt for first and last names.
first_name, last_name = view(
box('First name', value='Boaty'),
box('Last name', value='McBoatface'),
)
# Print the entered values
view(f'Hello, {first_name} {last_name}!')
Views can be chained together to create sophisticated workflows and wizards.
The example below shows a simple online ordering system.
Observe how it combines view()
with conditionals and loops, while keeping the code
simple, concise, and clear.
Notably, if you have built web applications before, notice the absence of callbacks, event handlers, web request handlers, routing, etc.
# Our menu.
menu = dict(
Donut=['Plain', 'Glazed', 'Chocolate'],
Coffee=['Dark-roast', 'Medium-roast', 'Decaf'],
)
# Prompt for items.
items = view(box(
'What would you like to order today?',
options=list(menu.keys()), # Menu item names.
multiple=True, # Allow multiple selections.
))
if len(items) == 0: # Nothing selected.
view(f'Nothing to order? Goodbye!')
return
# The order summary, which we'll display later.
summary = ['### Order summary:']
# Prompt for counts and flavors.
for item in items:
count = view(box(f'How many orders of {item} would you like?', value=3))
for i in range(count):
flavor = view(box(
f'Pick a flavor for {item} #{i + 1}',
options=menu[item],
))
summary.append(f'1. {flavor} {item}')
summary.append('\nThank you for your order!')
# Finally, show summary.
view('\n'.join(summary))
Building a similar multi-page interactive app with a regular web framework can be a fairly complex endeavor, weaving together requests and replies with logic spread across multiple functions , but Nitro makes all this delightfully simple!
Strings passed to view()
are interpreted as Github Flavored Markdown (GFM).
view('''
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Small print
This is a paragraph, with **bold**, *italics*
(or _italics_), ***important***, `code`
and ~~strikethrough~~ formatting.
Here's a [hyperlink](https://example.com) to https://example.com.
![An image](https://picsum.photos/200)
> This is a block quote.
- List item 1
- List item 2
- Sublist item 1
- Sublist item 2
- List item 3
1. Numbered list item 1
1. Numbered list item 2
1. Sublist item 1
1. Sublist item 2
1. Numbered list item 3
Here is a footnote[^1] and another one[^another].
[^1]: A reference.
[^another]: Another reference.
''')
Any uniform indentation is automatically ignored.
Local links in markdown content behave just like any other input.
Clicking on a local link returns the name of the link.
choice = view('''
Pick a flavor:
- [Vanilla](#vanilla)
- [Strawberry](#strawberry)
- [Chocolate](#chocolate)
Or, [surprise me](#surprise-me)!
''')
view(f'You clicked on {choice}.')
Code blocks in Markdown support syntax highlighting for 180+ languages using highlight.js.
To enable syntax highlighting, suffix the language to the opening triple-backticks.
See list of supported languages.
def markdown_syntax_highlighting(view: View):
view('''
Python:
```py
def hello():
print('Hello!')
```
Javascript:
```js
function hello() {
console.log('Hello!');
}
```
''')
By default each item passed to view()
are laid out one below the other, with a 10px gap.
view(
box(value='Top'),
box(value='Middle'),
box(value='Bottom'),
)
Use row()
to lay out multiple items horizontally, left to right.
By default, items take up equal amounts of space, with a 10px
gap between the items.
view(row(
box(value='Left'),
box(value='Center'),
box(value='Right'),
))
Setting row=True
produces the same result as wrapping items with row()
.
view(
box(value='Left'),
box(value='Center'),
box(value='Right'),
row=True,
)
Use col()
to lay out multiple items vertically, top to bottom.
The example shows one row split into three columns containing three rows each.
view(
row(
col(
box(value='North-west'),
box(value='West'),
box(value='South-west'),
),
col(
box(value='North'),
box(value='Center'),
box(value='South'),
),
col(
box(value='North-east'),
box(value='East'),
box(value='South-east'),
),
),
)
Set background=
to apply a background color.
The text color is automatically changed to a contrasting color if not specified.
A 10px
padding is automatically applied if not specified.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
view(
box(text, background='#e63946'),
box(text, background='#f1faee'),
box(text, background='#a8dadc'),
box(text, background='#457b9d'),
box(text, background='#1d3557'),
)
Set color=
to change the text color.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
view(
box(text, color='#e63946'),
box(text, color='#457b9d'),
box(text, color='#1d3557'),
)
Set border=
to add a border.
A 10px
padding is automatically applied if not specified.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
view(
box(text, border='#e63946'),
box(text, border='#457b9d'),
box(text, border='#1d3557'),
)
Set align=
to left
, right
, center
or justify
to align text.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
view(
row(
box(text, align='left'),
box(text, align='center'),
box(text, align='justify'),
box(text, align='right'),
gap=20,
)
)
Nitro provides extensive control over how items are sized and spaced, using width
, height
, margin
, padding
,
and gap
.
These parameters can be specified as either integers or strings.
- Integers are interpreted as pixels, e.g.
42
and'42px'
have the same effect. - Strings must be a number followed by one of the units listed below (e.g.
'42px'
,'42in'
,'42mm'
, etc. - Absolute units:
px
: One pixel (1/96th of an inch).cm
: One centimeter.mm
: One millimeter.in
: One inch (96px).pc
: One pica (12pt or 1/6th of an inch).pt
: One point (1/72nd of an inch).- Relative units:
%
: A percentage of the container's size.vh
: 1% of the viewport height.vw
: 1% of the viewport width.vmin
: The smaller ofvw
andvh
.vmax
: The larger ofvw
andvh
.ex
: The x-height of the font of the element.em
: The font size of the element.rem
: The font size of the page.
text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
view(
box(text, width=200, background='#eee'), # interpreted as '200px'
box(text, width='250px', background='#eee'),
box(text, width='3in', background='#eee'),
box(text, width='50%', background='#eee'),
box(text, height='1in', background='#eee'),
box(text, width='250px', height='100px', background='#eee'),
)
Set gap=
to control the spacing between items. The default gap is 10
or '10px'
.
view(
box(value='Top'),
box(value='Middle'),
box(value='Bottom'),
gap=25,
)
Set margin=
to add a margin around each item.
Top, right, bottom, left margins can be controlled independently, and are specified
as 'top right bottom left'
strings.
'x'
is shorthand for'x x x x'
.'x y'
is shorthand for'x y x y'
.'x y z'
is shorthand for'x y z y'
.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
boxes = [
# Uniform 20px margin
box(text, margin='20px', background='#eee'),
# Same as '20px'
box(text, margin=20, background='#eee'),
# 0px top and bottom, 100px right and left margin
box(text, margin='0px 100px', background='#eee'),
# 0px top, 100px right and left, 30px bottom margin
box(text, margin='0px 100px 30px', background='#eee'),
# 0px top, 100px right, 30px bottom, 200px left margin
box(text, margin='0px 100px 30px 200px', background='#eee'),
]
view(col(*[row(b, border='#000', padding=0) for b in boxes]))
Set padding=
to control the padding (inset) inside each item.
Top, right, bottom, left paddings can be controlled independently, and are specified
as 'top right bottom left'
strings.
'x'
is shorthand for'x x x x'
.'x y'
is shorthand for'x y x y'
.'x y z'
is shorthand for'x y z y'
.
text = '''
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
do eiusmod tempor incididunt ut labore et dolore magna aliqua.
'''
view(
col(
# Uniform 20px padding
box(text, padding='20px', background='#eee'),
# Same as '20px'
box(text, padding=20, background='#eee'),
# 0px top and bottom, 100px right and left padding
box(text, padding='0px 100px', background='#eee'),
# 0px top, 100px right and left, 30px bottom padding
box(text, padding='0px 100px 30px', background='#eee'),
# 0px top, 100px right, 30px bottom, 200px left padding
box(text, padding='0px 100px 30px 200px', background='#eee'),
)
)
Set tile=
to control how items inside a view, row, or column are tiled along the main axis.
- The main axis for a row is horizontal, starting at the left, and ending at the right.
- The main axis for a column is vertical, starting at the top, and ending at the bottom
tile=
can be set to start
, center
, end
, between
, around
, evenly
, 'stretch', or normal
.
boxes = [box(text=f'{i + 1}', background='#666', width=100) for i in range(3)]
row_style = dict(background='#eee')
view(
# Pack items from the start.
row(*boxes, tile='start', **row_style),
# Pack items around the center.
row(*boxes, tile='center', **row_style),
# Pack items towards the end.
row(*boxes, tile='end', **row_style),
# Distribute items evenly.
# The first item is flush with the start,
# the last is flush with the end.
row(*boxes, tile='between', **row_style),
# Distribute items evenly.
# Items have a half-size space on either side.
row(*boxes, tile='around', **row_style),
# Distribute items evenly.
# Items have equal space around them.
row(*boxes, tile='evenly', **row_style),
# Default alignment.
row(*boxes, tile='normal', **row_style),
)
Set cross_tile=
to control how items inside a view, row, or column are tiled along the cross axis.
- The cross axis for a row is vertical. starting at the top, and ending at the bottom
- The cross axis for a column is horizontal, starting at the left, and ending at the right.
cross_tile=
can be set to start
, center
, end
, stretch
, or normal
.
boxes = [box(text=f'{i + 1}', background='#666', width=100) for i in range(3)]
col_style = dict(height=100, background='#eee')
view(
# Pack items from the start.
col(row(*boxes, cross_tile='start'), **col_style),
# Pack items around the center.
col(row(*boxes, cross_tile='center'), **col_style),
# Pack items towards the end.
col(row(*boxes, cross_tile='end'), **col_style),
# Stretch items to fit.
col(row(*boxes, cross_tile='stretch'), **col_style),
# Default alignment.
col(row(*boxes, cross_tile='normal'), **col_style),
)
Set wrap=
to control how items are wrapped inside a view, row, or column.
wrap=
can be set to start
, center
, end
, between
, around
, evenly
, 'stretch', or normal
.
boxes = [box(text=f'{i + 1}', background='#666', width=150, height=50) for i in range(9)]
row_style = dict(height=300, background='#eee')
view(
# Pack items from the start.
row(*boxes, wrap='start', **row_style),
# Pack items around the center.
row(*boxes, wrap='center', **row_style),
# Pack items towards the end.
row(*boxes, wrap='end', **row_style),
# Distribute items evenly.
# The first item is flush with the start,
# the last is flush with the end.
row(*boxes, wrap='between', **row_style),
# Distribute items evenly.
# Items have a half-size space on either side.
row(*boxes, wrap='around', **row_style),
# Distribute items evenly.
# Items have equal space around them.
row(*boxes, wrap='evenly', **row_style),
# Default alignment.
row(*boxes, wrap='normal', **row_style),
)
Set grow=
or shrink=
to specify what amount of the available space the item should take up
inside a view, row, or column.
Setting grow=
expands the item. Setting shrink=
contracts the item. Both are proportions.
By default, items are grown or shrunk based on their initial size. To resize them on a different basis,
set basis=
to the value you want.
basis=0
means "distribute available space assuming that the initial size is zero".basis='20px'
means "distribute available space assuming that the initial size is 20px".- The default behavior (if
basis=
is not set) is to assume that the initial size is the size of the item's content.
box_style = dict(background='#666')
row_style = dict(background='#eee')
view(
'1:?:?',
row(
# Take up all available space.
box('a', grow=1, **box_style),
box('b', width=50, **box_style),
box('c', width=50, **box_style),
**row_style,
),
'1:1:?',
row(
# Take up one part of available space = 1 / (1 + 1).
box('a', grow=1, **box_style),
# Take up one part of available space = 1 / (1 + 1).
box('b', grow=1, **box_style),
box('c', width=50, **box_style),
**row_style,
),
'2:1:?',
row(
# Take up two parts of available space = 2 / (2 + 1).
box('a', grow=2, **box_style),
# Take up one part of available space = 1 / (2 + 1).
box('b', grow=1, **box_style),
box('c', width=50, **box_style),
**row_style,
),
'1:2:3:?',
row(
# Take up one part of available space = 1 / (1 + 2 + 3).
box('a', grow=1, **box_style),
# Take up two parts of available space = 2 / (1 + 2 + 3).
box('b', grow=2, **box_style),
# Take up three parts of available space = 3 / (1 + 2 + 3).
box('c', grow=3, **box_style),
box('d', width=50, **box_style),
**row_style,
),
'1:1:1:1',
row(
# Divide available space equally.
box('a', grow=1, **box_style),
box('b', grow=1, **box_style),
box('c', grow=1, **box_style),
box('d', grow=1, **box_style),
**row_style,
),
)
To create a form, simply lay out all the inputs you need inside a view, then destructure the return value in order.
username, password, action = view(
box('Username', value='[email protected]'),
box('Password', value='pa55w0rd', password=True),
box(['Login']),
)
view(f'You entered `{username}`/`{password}` and then clicked on {action}.')
Wrap items with row()
to lay them out left to right.
There is no change to the way the return values are destructured.
username, password, action = view(
row(
box('Username', value='[email protected]'),
box('Password', value='pa55w0rd', password=True),
box(['Login']),
)
)
view(f'You entered `{username}`/`{password}` and then clicked on {action}.')
Use row()
and col()
to mix and match how items are laid out. Destructure the return values in the same order.
first, last, addr1, addr2, city, state, zip, action = view(
row(box('First name', value=''), box('Last name', value='')),
box('Address line 1', value=''),
box('Address line 2', value=''),
row(box('City', value=''), box('State', value=''), box('Zip', value='')),
box([
option('yes', 'Sign me up!', selected=True),
option('no', 'Not now'),
])
)
view(f'''
You provided:
Address: {first} {last}, {addr1}, {addr2}, {city} {state} {zip}
Sign up: {action}
''')
Specify additional layout parameters like width=
, grow=
, etc. to get more control over
how items are laid out.
first, middle, last, addr1, addr2, city, state, zip, action = view(
row(box('First name', value=''), box('M.I.', value='', width='10%'), box('Last name', value='')),
box('Address line 1', value=''),
box('Address line 2', value=''),
row(box('City', value='', grow=5), box('State', value='', width='20%'), box('Zip', value='', grow=1)),
box([
option('yes', 'Sign me up!', caption='Terms and conditions apply', selected=True),
option('no', 'Not now', caption="I'll decide later"),
])
)
view(f'''
You provided:
Address: {first} {middle} {last}, {addr1}, {addr2}, {city} {state} {zip}
Sign up: {action}
''')
Call box()
with mode='text'
to show a textbox.
The return value is the text entered into the box.
x = view(box(mode='text'))
view(f'You entered {x}.')
Set value=
to prefill the box with a value.
mode='text'
can be elided if value=
is set.
speed = view(box(value='60 km/h'))
view(f'Your speed is {speed} km/h.')
Any text passed to box()
is used as a label.
speed = view(box('Speed', value='60'))
view(f'Your speed is {speed} km/h.')
Use placeholder=
to show placeholder text inside the box.
speed = view(box('Speed', placeholder='0 km/h'))
view(f'Your speed is {speed} km/h.')
Set required=True
to indicate that input is required.
speed = view(box('Speed (km/h)', required=True))
view(f'Your speed is {speed} km/h.')
Set mask=
to specify an input mask. An input mask is used to format the text field
for the expected entry.
For example, to accept a phone number, use an input mask containing three sets of digits.
phone = view(box('Phone', mask='(999) 999 - 9999'))
view(f'Your phone number is {phone}.')
To construct the input mask:
- Use
a
to indicate a letter. - Use
9
to indicate a number. - Use
*
to indicate a letter or number. - Use a backslash to escape any character.
Set icon=
to show an icon at the end of the box.
phrase = view(box('Filter results containing:', icon='Filter'))
view(f'You set a filter on `{phrase}`.')
Set prefix=
to show a prefix at the start of the box.
website = view(box('Website', prefix='https://', value='example.com'))
view(f'Your website is https://{website}.')
Set suffix=
to show a suffix at the end of the box.
website = view(box('Website', suffix='.com', value='example'))
view(f'Your website is {website}.com.')
A textbox can show both a prefix and a suffix at the same time.
website = view(box('Website', prefix='https://', suffix='.com', value='example'))
view(f'Your website is https://{website}.com.')
Set error=
to show an error message below the box.
speed = view(box('Speed (km/h)', error='Invalid input'))
Set password=True
when accepting passwords and other confidential inputs.
password = view(box('Password field', password=True))
view(f'Your password `{password}` is not strong enough!')
Set lines=
to show a multi-line text box (also called a text area).
bio = view(box('Bio:', lines=5))
view(f'**Bio:** {bio}')
Note that lines=
only controls the initial height of the textbox, and
multi-line textboxes can be resized by the user.
Call box()
with mode='number'
to show a box with increment/decrement buttons.
(also called a spinbox).
speed = view(box('Speed (km/h)', mode='number'))
view(f'Your speed is {speed} km/h')
Set value=
to a numeric value to prefill the box with the value.
The mode setting mode='number'
is implied, and can be elided.
speed = view(box('Speed (km/h)', value=42))
view(f'Your speed is {speed} km/h')
In other words, calling box()
with a numeric value
has the same effect
as setting mode='number'
, and is the preferred usage.
Set min=
to specify a minimum value.
speed = view(box('Speed (km/h)', min=10))
view(f'Your speed is {speed} km/h')
Set max=
to specify a maximum value.
speed = view(box('Speed (km/h)', max=100))
view(f'Your speed is {speed} km/h')
Set step=
to specify how much to increment or decrement by.
The default step is 1
.
speed = view(box('Speed (km/h)', step=5))
view(f'Your speed is {speed} km/h')
Set precision=
to specify how many decimal places the value should be rounded to.
The default is calculated based on the precision of step:
- if step = 1, precision = 0
- if step = 0.42, precision = 2
- if step = 0.0042, precision = 4
speed = view(box('Speed (m/s)', value=0.6, min=-2, max=2, step=0.2, precision=2))
view(f'Your speed is {speed} m/s')
min=
, max=
, step=
and precision=
can be combined.
speed = view(box('Speed (km/h)', min=10, max=100, step=5))
view(f'Your speed is {speed} km/h')
Set range=
to a (min, max)
tuple to restrict numeric inputs between two values.
This is a shorthand notation for setting min=
and max=
individually.
speed = view(box('Speed (km/h)', range=(10, 100)))
view(f'Your speed is {speed} km/h')
Set range=
to a (min, max, step)
tuple to increment/decrement by steps other than 1
.
This is a shorthand notation for setting min=
, max=
and step
individually.
speed = view(box('Speed (km/h)', range=(10, 100, 5)))
view(f'Your speed is {speed} km/h')
Setting range=
to a (min, max, step, precision)
tuple is a shorthand notation for setting
min=
, max=
, step
and precision
individually.
speed = view(box('Speed (m/s)', value=0.6, range=(-2, 2, 0.2, 2)))
view(f'Your speed is {speed} m/s')
Ranges can cross zero.
speed = view(box('Speed (m/s)', value=-3, range=(-5, 5)))
view(f'Your speed is {speed} m/s')
Steps can be fractional.
speed = view(box('Speed (m/s)', value=0.6, range=(-2, 2, 0.2)))
view(f'Your speed is {speed} m/s')
A picker is a box that allows the user to pick one or more options from several presented options, like buttons, checklists, dropdowns, color pickers, and so on.
Set options=
to create a picker.
choice = view(box('Choose a color', options=[
'green', 'yellow', 'orange', 'red'
]))
view(f'You chose {choice}.')
There are several ways to create options. These are explained in the next section. The simplest way is to supply a sequence (tuple, set or list) of strings.
By default, this shows buttons for up to 3 options, radio buttons for up to 7 options,
or a dropdown menu for more than 7 options.
This behavior can be controlled using mode=
, explained in later examples.
The example above has 4 options, hence radio buttons are shown.
Buttons are shown for up to 3 options.
Set mode='button'
to display buttons regardless of the number of options.
choice = view(box('Choose a color', options=[
'yellow', 'orange', 'red'
]))
view(f'You chose {choice}.')
Radio buttons is shown for 4-7 options.
Set mode='radio'
to display radio buttons regardless of the number of options.
choice = view(box('Choose a color', options=[
'green', 'yellow', 'orange', 'red'
]))
view(f'You chose {choice}.')
A dropdown menu is shown for more than 7 options.
Set mode='menu'
to display a dropdown menu regardless of the number of options.
choice = view(box('Choose a color', options=[
'violet', 'indigo', 'blue', 'green', 'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Set multiple=True
to allow choosing more than one option. The return value is a list of choices made.
By default, this displays checkboxes for up to 7 options, or a dropdown menu for more than 7 options.
Set mode='menu'
to display a dropdown menu regardless of the number of options.
choices = view(box('Choose some colors', multiple=True, options=[
'violet', 'indigo', 'blue', 'green', 'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choices}.')
A checklist is shown for up to 7 options when multiple=True
.
Set mode='check'
to display a checklist regardless of the number of options.
choices = view(box('Choose some colors', mode='check', multiple=True, options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choices}.')
Set required=True
to indicate that input is required.
choice = view(box('Choose a color', mode='menu', required=True, options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Set error=
to show an error message below the box.
choice = view(box('Choose a color', mode='menu', error='Invalid input', options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
An option
represents one of several choices to be presented to the user.
It's used by all kinds of pickers: buttons, dropdowns, checklists, color pickers, and so on.
An option has a value
and text
, created using option(value, text)
.
- The
value
is the value returned when the user picks that option. It is not user-visible. - The
text
is typically used as a label for the option.
If text
is not provided, then the value
is also used as the text
.
There are other, more concise ways to specify options, explained in later examples.
choice = view(box('Choose a color', options=[
option('green', 'Green'),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
If options
is a sequence (tuple, set or list), the elements of the sequence are used as options.
choice = view(box('Choose a color', options=[
'green', 'yellow', 'orange', 'red'
]))
view(f'You chose {choice}.')
If options=
is set to a string, each word in the string is used as an option.
choice = view(box('Choose a color', options='green yellow orange red'))
view(f'You chose {choice}.')
In other words, 'green yellow orange red'
is a shorthand notation for ['green', 'yellow', 'orange', 'red']
.
options=
can also be specified as a sequence of (value, text)
tuples.
choice = view(box('Choose a color', options=[
('green', 'Green'),
('yellow', 'Yellow'),
('orange', 'Orange'),
('red', 'Red'),
]))
view(f'You chose {choice}.')
Here, (value, text)
is a shorthand notation for option(value, text)
.
options=
can also be specified as a dict
of value: text
entries.
choice = view(box('Choose a color', options=dict(
green='Green',
yellow='Yellow',
orange='Orange',
red='Red',
)))
view(f'You chose {choice}.')
This is the most concise way to pass options where labels differ from values.
Set selected=True
to pre-select an option.
Another way to pre-select an option is to set value=
on the box, as shown in the next example.
choice = view(box('Choose a color', options=[
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Set value=
on the box to pre-select an option having that value.
Another way to pre-select an option is to set selected=True
on the option, as shown in the previous example.
choice = view(box('Choose a color', value='yellow', options=[
option('green', 'Green'),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Set mode='button'
to show buttons.
mode=
can be elided when there are 1-3 options.
choice = view(box('Choose a color', mode='button', options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Most often, it doesn't make sense to show a text prompt above a set of buttons.
In such cases, box(mode='button', options=X)
can be shortened to box(X)
.
In other words, if the first argument to box()
is a sequence of options, then mode='button'
is implied.
choice = view(box(['green', 'yellow', 'orange', 'red']))
view(f'You chose {choice}.')
This works when options
is a sequence (tuple, set, list) or dictionary too. The following forms are equivalent:
choice = view(box([
option('green', 'Green'),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
]))
# Shorter
choice = view(box([
('green', 'Green'),
('yellow', 'Yellow'),
('orange', 'Orange'),
('red', 'Red'),
]))
# Shortest
choice = view(box(dict(
green='Green',
yellow='Yellow',
orange='Orange',
red='Red',
)))
Options marked as selected
are shown in alternate colors, also called primary buttons.
This is useful when you want to emphasize certain actions over others.
choice = view(
'Updates are available!',
box([
option('now', 'Update now', selected=True),
option('tomorrow', 'Remind me tomorrow'),
option('never', 'Never update'),
])
)
view(f'You chose to update {choice}.')
Alternatively, Set value=
to mark a button as primary.
choice = view(
'Updates are available!',
box(dict(
now='Update now',
tomorrow='Remind me tomorrow',
never='Never update',
), value='now')
)
view(f'You chose to update {choice}.')
If value=
is set to a sequence, all buttons with those values are marked as primary.
choice = view(
'Sign me up!',
box(dict(
basic='Basic Plan ($9.99/month)',
pro='Pro Plan ($14.99/month)',
none='Not interested',
), value=['basic', 'pro'])
)
view(f'You chose {choice}.')
Sub-options inside options are shown as split buttons.
choice = view(
'Send fresh donuts every day?',
box([
option('yes', 'Yes!', selected=True),
option('no', 'No', options=[
option('later', 'Remind me later', icon='ChatBot'),
option('never', "Don't ask me again", icon='MuteChat'),
]),
])
)
view(f'You chose {choice}.')
Sub-options work for primary buttons, too.
choice = view(
'Send fresh donuts every day?',
box([
option('yes', 'Yes!', selected=True, options=[
option('later', 'Remind me later', icon='ChatBot'),
option('never', "Don't ask me again", icon='MuteChat'),
]),
option('no', 'No'),
])
)
view(f'You chose {choice}.')
Set caption=
to describe buttons.
choice = view(
'Send fresh donuts every day?',
box([
option('yes', 'Sign me up!', caption='Terms and conditions apply', selected=True),
option('no', 'Not now', caption='I will decide later'),
])
)
view(f'You chose {choice}.')
By default, buttons are laid out row-wise. Set row=False
to lay them column-wise.
choice = view(
'Choose a color:',
box([
option('auto', 'Automatic', selected=True),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
], row=False)
)
view(f'You chose {choice}.')
Set mode='radio'
to show radio buttons.
mode=
can be elided when there are 4-7 options.
choice = view(box('Choose a color', mode='radio', options=[
'blue', 'green', 'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Set value=
to pre-select an option having that value.
choice = view(box('Choose a color', mode='radio', value='yellow', options=[
option('green', 'Green'),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Set selected=True
to pre-select an option.
choice = view(box('Choose a color', mode='radio', options=[
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Set icon=
to show graphical options.
choice = view(box('Choose a chart type', mode='radio', options=[
option('area', 'Area', icon='AreaChart', selected=True),
option('bar', 'Bar', icon='BarChartHorizontal'),
option('column', 'Column', icon='BarChartVertical'),
option('line', 'Line', icon='LineChart'),
option('scatter', 'Scatter', icon='ScatterChart'),
option('donut', 'Donut', icon='DonutChart'),
]))
view(f'You chose {choice}.')
Set mode='menu'
to show a dropdown menu.
mode=
can be elided when there are more than 7 options.
choice = view(box('Choose a color', mode='menu', options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Set value=
to pre-select an option having that value.
choice = view(box('Choose a color', mode='menu', value='yellow', options=[
option('green', 'Green'),
option('yellow', 'Yellow'),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Set selected=True
to pre-select an option.
choice = view(box('Choose a color', mode='menu', options=[
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red'),
]))
view(f'You chose {choice}.')
Options can have sub-options. This is useful for grouping options into categories.
mode=menu
is implied if options are grouped.
choice = view(box('Choose a color', options=[
option('primary', 'Primary Colors', options=[
option('red', 'Red'),
option('blue', 'Blue'),
option('yellow', 'Yellow'),
]),
option('secondary', 'Secondary Colors', options=[
option('violet', 'Violet'),
option('green', 'Green'),
option('orange', 'Orange'),
]),
]))
view(f'You chose {choice}.')
Set editable=True
to allow arbitrary input in addition to the presented options.
mode=menu
is implied if editable=True
.
choice = view(box('Choose a color', editable=True, options=[
'yellow', 'orange', 'red', 'black'
]))
view(f'You chose {choice}.')
Set mode='menu'
with multiple=True
to show a dropdown menu that allows multiple options to be selected.
mode=
can be elided when there are more than 7 options.
choices = view(box(
'Choose some colors',
mode='menu',
multiple=True,
options=['green', 'yellow', 'orange', 'red']
))
view(f'You chose {choices}.')
Set value=
to pre-select options having those values.
choices = view(box(
'Choose some colors',
mode='menu',
multiple=True,
value=['yellow', 'red'],
options=['green', 'yellow', 'orange', 'red']
))
view(f'You chose {choices}.')
Alternatively, set selected=True
to pre-select one or more options.
choices = view(box(
'Choose some colors',
mode='menu',
multiple=True,
options=[
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red', selected=True),
]
))
view(f'You chose {choices}.')
Set mode='check'
to show a checklist
mode=
can be elided when there are 1-7 options.
choices = view(box(
'Choose some colors',
mode='check',
multiple=True,
options=['green', 'yellow', 'orange', 'red']
))
view(f'You chose {choices}.')
Set value=
to pre-select options having those values.
choices = view(box(
'Choose some colors',
mode='check',
multiple=True,
value=['yellow', 'red'],
options=['green', 'yellow', 'orange', 'red']
))
view(f'You chose {choices}.')
Alternatively, set selected=True
to pre-select one or more options.
choices = view(box(
'Choose some colors',
mode='check',
multiple=True,
options=[
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red', selected=True),
]
))
view(f'You chose {choices}.')
Set mode='range'
to show a slider.
The default range is between 0
and 10
.
speed = view(box('Speed (km/h)', mode='range'))
view(f'Your speed is {speed} km/h')
Set value=
to default the slider value.
speed = view(box('Speed (km/h)', mode='range', value=5))
view(f'Your speed is {speed} km/h')
Set min=
to specify a minimum value.
speed = view(box('Speed (km/h)', mode='range', min=3))
view(f'Your speed is {speed} km/h')
Set max=
to specify a maximum value.
speed = view(box('Speed (km/h)', mode='range', max=100))
view(f'Your speed is {speed} km/h')
Set step=
to specify how much to increment or decrement by.
The default step is 1
.
speed = view(box('Speed (km/h)', mode='range', step=2))
view(f'Your speed is {speed} km/h')
Set precision=
to specify how many decimal places the value should be rounded to.
The default is calculated based on the precision of step:
- if step = 1, precision = 0
- if step = 0.42, precision = 2
- if step = 0.0042, precision = 4
speed = view(box('Speed (m/s)', mode='range', value=0.6, min=-2, max=2, step=0.2, precision=2))
view(f'Your speed is {speed} m/s')
min=
, max=
, step=
and precision=
can be combined.
speed = view(box('Speed (km/h)', mode='range', min=10, max=100, step=5))
view(f'Your speed is {speed} km/h')
Set range=
to a (min, max)
tuple to restrict numeric inputs between two values.
This is a shorthand notation for setting min=
and max=
individually.
speed = view(box('Speed (km/h)', mode='range', range=(10, 100)))
view(f'Your speed is {speed} km/h')
Set range=
to a (min, max, step)
tuple to increment/decrement by steps other than 1
.
This is a shorthand notation for setting min=
, max=
and step
individually.
speed = view(box('Speed (km/h)', mode='range', range=(10, 100, 5)))
view(f'Your speed is {speed} km/h')
Setting range=
to a (min, max, step, precision)
tuple is a shorthand notation for setting
min=
, max=
, step
and precision
individually.
speed = view(box('Speed (m/s)', mode='range', value=0.6, range=(-2, 2, 0.2, 2)))
view(f'Your speed is {speed} m/s')
Ranges can cross zero.
speed = view(box('Speed (m/s)', mode='range', value=-3, range=(-5, 5)))
view(f'Your speed is {speed} m/s')
Steps can be fractional.
speed = view(box('Speed (m/s)', mode='range', value=0.6, range=(-2, 2, 0.2)))
view(f'Your speed is {speed} m/s')
Set value=
to a (start, end)
tuple to show a range slider.
The mode setting mode='range'
is implied, and can be elided.
start, end = view(box('Speed range (km/h)', value=(3, 7)))
view(f'Your speed ranges between {start} and {end} km/h')
Set min=
to specify a minimum value.
start, end = view(box('Speed range (km/h)', value=(3, 7), min=3))
view(f'Your speed ranges between {start} and {end} km/h')
Set max=
to specify a maximum value.
start, end = view(box('Speed range (km/h)', value=(30, 70), max=100))
view(f'Your speed ranges between {start} and {end} km/h')
Set step=
to specify how much to increment or decrement by.
The default step is 1
.
start, end = view(box('Speed range (km/h)', value=(2, 6), step=2))
view(f'Your speed ranges between {start} and {end} km/h')
Set precision=
to specify how many decimal places the value should be rounded to.
The default is calculated based on the precision of step:
- if step = 1, precision = 0
- if step = 0.42, precision = 2
- if step = 0.0042, precision = 4
start, end = view(box('Speed range (m/s)', value=(-0.4, 0.4), min=-2, max=2, step=0.2, precision=2))
view(f'Your speed ranges between {start} and {end} m/s')
min=
, max=
, step=
and precision=
can be combined.
start, end = view(box('Speed range (km/h)', value=(30, 70), min=10, max=100, step=5))
view(f'Your speed ranges between {start} and {end} km/h')
Set range=
to a (min, max)
tuple to restrict numeric inputs between two values.
This is a shorthand notation for setting min=
and max=
individually.
start, end = view(box('Speed range (km/h)', value=(30, 70), range=(10, 100)))
view(f'Your speed ranges between {start} and {end} km/h')
Set range=
to a (min, max, step)
tuple to increment/decrement by steps other than 1
.
This is a shorthand notation for setting min=
, max=
and step
individually.
start, end = view(box('Speed range (km/h)', value=(30, 70), range=(10, 100, 5)))
view(f'Your speed ranges between {start} and {end} km/h')
Set range=
to a (min, max, step)
tuple to increment/decrement by steps other than 1
.
Setting range=
to a (min, max, step, precision)
tuple is a shorthand notation for setting
min=
, max=
, step
and precision
individually.
start, end = view(box('Speed range (m/s)', value=(-0.4, 0.4), range=(-2, 2, 0.2, 2)))
view(f'Your speed ranges between {start} and {end} m/s')
Ranges can cross zero.
start, end = view(box('Speed range (m/s)', value=(-3, 3), range=(-5, 5)))
view(f'Your speed ranges between {start} and {end} m/s')
Steps can be fractional.
start, end = view(box('Speed range (m/s)', value=(-0.4, 0.4), range=(-2, 2, 0.2)))
view(f'Your speed ranges between {start} and {end} m/s')
Set mode='time'
to show a time picker.
time = view(box('Set alarm for:', mode='time', value='3:04PM'))
view(f'Alarm set for {time}.')
Include seconds in the value
to show a seconds component.
time = view(box('Set alarm for:', mode='time', value='3:04:05PM'))
view(f'Alarm set for {time}.')
Exclude minutes and seconds from the value
to show only the hour component.
time = view(box('Set alarm for:', mode='time', value='3PM'))
view(f'Alarm set for {time}.')
Exclude AM
or PM
from the value
to accept input in military time.
time = view(box('Set alarm for:', mode='time', value='15:04'))
view(f'Alarm set for {time}.')
Include seconds in the value
to show a seconds component.
time = view(box('Set alarm for:', mode='time', value='15:04:05'))
view(f'Alarm set for {time}.')
Exclude minutes and seconds from the value
to show only the hour component.
time = view(box('Set alarm for:', mode='time', value='15'))
view(f'Alarm set for {time}.')
Set mode='date'
to show a date-picker.
date = view(box('Pick a date', mode='date'))
view(f'You picked {date}.')
Set placeholder=
to show placeholder text.
date = view(box('Deliver on', mode='date', placeholder='Delivery date'))
view(f'You picked {date}.')
Set required=True
to indicate that input is required.
date = view(box('Pick a date', mode='date', required=True))
view(f'You picked {date}.')
Set value=
to pre-select a date.
Dates must be in ISO 8601 format. Date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
date = view(box('Pick a date', mode='date', value='2021-10-10'))
view(f'You picked {date}.')
Set min=
to specify a minimum date.
date = view(box('Pick a date', mode='date', value='2021-10-10', min='2019-01-01'))
view(f'You picked {date}.')
Set max=
to specify a maximum date.
date = view(box('Pick a date', mode='date', value='2021-10-10', max='2022-12-31'))
view(f'You picked {date}.')
Set both min=
and max=
to restrict selection between two dates.
date = view(box('Pick a date', mode='date', value='2021-10-10', min='2019-01-01', max='2022-12-31'))
view(f'You picked {date}.')
Set range=
to a (min, max)
tuple to restrict selection between two dates.
This is a shorthand notation for setting min=
and max=
individually.
date = view(box('Pick a date', mode='date', value='2021-10-10', range=('2019-01-01', '2022-12-31')))
view(f'You picked {date}.')
Set mode='day'
to show a calendar.
date = view(box('Pick a date', mode='day'))
view(f'You picked {date}.')
Set value=
to pre-select a date.
Dates must be in ISO 8601 format. Date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
date = view(box('Pick a date', mode='day', value='2021-10-10'))
view(f'You picked {date}.')
Set min=
to specify a minimum date.
date = view(box('Pick a date', mode='day', value='2021-10-10', min='2019-01-01'))
view(f'You picked {date}.')
Set max=
to specify a maximum date.
date = view(box('Pick a date', mode='day', value='2021-10-10', max='2022-12-31'))
view(f'You picked {date}.')
Set both min=
and max=
to restrict selection between two dates.
date = view(box('Pick a date', mode='day', value='2021-10-10', min='2019-01-01', max='2022-12-31'))
view(f'You picked {date}.')
Set range=
to a (min, max)
tuple to restrict selection between two dates.
This is a shorthand notation for setting min=
and max=
individually.
date = view(box('Pick a date', mode='day', value='2021-10-10', range=('2019-01-01', '2022-12-31')))
view(f'You picked {date}.')
Set mode='week'
to show a week picker.
week = view(box('Pick a week', mode='week'))
view(f'You picked {week}.')
Set value=
to pre-select a week.
Dates must be in ISO 8601 format. Date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
week = view(box('Pick a week', mode='week', value='2021-10-10'))
view(f'You picked {week}.')
Set min=
to specify a minimum date.
week = view(box('Pick a week', mode='week', value='2021-10-10', min='2019-01-01'))
view(f'You picked {week}.')
Set max=
to specify a maximum date.
week = view(box('Pick a week', mode='week', value='2021-10-10', max='2022-12-31'))
view(f'You picked {week}.')
Set both min=
and max=
to restrict selection between two dates.
week = view(box('Pick a week', mode='week', value='2021-10-10', min='2019-01-01', max='2022-12-31'))
view(f'You picked {week}.')
Set range=
to a (min, max)
tuple to restrict selection between two dates.
This is a shorthand notation for setting min=
and max=
individually.
week = view(box('Pick a week', mode='week', value='2021-10-10', range=('2019-01-01', '2022-12-31')))
view(f'You picked {week}.')
Set mode='month'
to show a month picker.
month = view(box('Pick a month', mode='month'))
view(f'You picked {month}.')
Set value=
to pre-select a month.
Dates must be in ISO 8601 format. Date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
month = view(box('Pick a month', mode='month', value='2021-10-10'))
view(f'You picked {month}.')
Set min=
to specify a minimum date.
month = view(box('Pick a month', mode='month', value='2021-10-10', min='2019-01-01'))
view(f'You picked {month}.')
Set max=
to specify a maximum date.
month = view(box('Pick a month', mode='month', value='2021-10-10', max='2022-12-31'))
view(f'You picked {month}.')
Set both min=
and max=
to restrict selection between two dates.
month = view(box('Pick a month', mode='month', value='2021-10-10', min='2019-01-01', max='2022-12-31'))
view(f'You picked {month}.')
Set range=
to a (min, max)
tuple to restrict selection between two dates.
This is a shorthand notation for setting min=
and max=
individually.
month = view(box('Pick a month', mode='month', value='2021-10-10', range=('2019-01-01', '2022-12-31')))
view(f'You picked {month}.')
Set mode='tag'
to display a tag picker. multiple=True
is implied.
tags = view(box(
'Choose some tags',
mode='tag',
options=['violet', 'indigo', 'blue', 'green', 'yellow', 'orange', 'red']
))
view(f'You chose {tags}.')
Set value=
to pre-select options having those values.
tags = view(box(
'Choose some tags',
mode='tag',
value=['yellow', 'red'],
options=['violet', 'indigo', 'blue', 'green', 'yellow', 'orange', 'red']
))
view(f'You chose {tags}.')
Set selected=True
to pre-select one or more options.
tags = view(box('Choose some tags', mode='tag', options=[
option('violet', 'Violet'),
option('indigo', 'Indigo'),
option('blue', 'Blue'),
option('green', 'Green'),
option('yellow', 'Yellow', selected=True),
option('orange', 'Orange'),
option('red', 'Red', selected=True),
]))
view(f'You chose {tags}.')
Set mode='color'
to show a color picker.
The return value is a (r, g, b, a)
tuple,
where r
, g
, b
are integers between 0-255,
and a
is an integer between 0-100%.
color = view(box('Choose a color', mode='color'))
r, g, b, a = color
view(f'You chose the color `rgba({r}, {g}, {b}, {a}%)`.')
Set value=
to pre-select a color.
A color value can be:
#RRGGBB
e.g.#ff0033
#RRGGBBAA
e.g.#ff003388
#RGB
e.g.#f03
(same as#ff0033
)#RGBA
e.g.#f038
(same as#ff003388
)rgb(R,G,B)
e.g.rgb(255, 0, 127)
orrgb(100%, 0%, 50%)
rgba(R,G,B,A)
e.g.rgb(255, 0, 127, 0.5)
orrgb(100%, 0%, 50%, 50%)
hsl(H,S,L)
e.g.hsl(348, 100%, 50%)
hsl(H,S,L,A)
e.g.hsl(348, 100%, 50%, 0.5)
orhsl(348, 100%, 50%, 50%)
- A named color e.g.
red
,green
,blue
, etc. transparent
(same asrgba(0,0,0,0)
)
The return value, as in the previous example, is a (r, g, b, a)
tuple.
color = view(box('Choose a color', mode='color', value='#a241e8'))
view(f'You chose {color}.')
Set options=
with mode='color'
to show a color palette.
The option's value
must be a valid color in one of the formats described in the previous example.
Unlike the Color Picker, the Color Palette returns the value
of the chosen option, and not a (r,g,b,a)
tuple.
color = view(box('Choose a color', mode='color', options=[
option('#ff0000', 'Red'),
option('#00ff00', 'Green'),
option('#0000ff', 'Blue'),
option('#ffff00', 'Yellow'),
option('#00ffff', 'Cyan'),
option('#ff00ff', 'Magenta'),
]))
view(f'You chose {color}.')
Set value=
to pre-select an option having that color value.
color = view(box('Choose a color', mode='color', value='#0000ff', options=[
option('#ff0000', 'Red'),
option('#00ff00', 'Green'),
option('#0000ff', 'Blue'),
option('#ffff00', 'Yellow'),
option('#00ffff', 'Cyan'),
option('#ff00ff', 'Magenta'),
]))
view(f'You chose {color}.')
Alternatively, set selected=True
to pre-select a color in the palette.
color = view(box('Choose a color', mode='color', options=[
option('#ff0000', 'Red'),
option('#00ff00', 'Green'),
option('#0000ff', 'Blue', selected=True),
option('#ffff00', 'Yellow'),
option('#00ffff', 'Cyan'),
option('#ff00ff', 'Magenta'),
]))
view(f'You chose {color}.')
Set mode='rating'
to accept a star-rating.
By default, five stars are displayed.
stars = view(box('Rate your experience', mode='rating'))
view(f'Your rating was {stars} stars.')
Set value=
to specify a default value.
stars = view(box('Rate your experience', mode='rating', value=3))
view(f'Your rating was {stars} stars.')
Set min=0
to allow zero stars.
stars = view(box('Rate your experience', mode='rating', min=0))
view(f'Your rating was {stars} stars.')
Set max=
to increase the number of stars displayed.
stars = view(box('Rate your experience', mode='rating', value=3, max=10))
view(f'Your rating was {stars} stars.')
min=
and max=
can be combined.
stars = view(box('Rate your experience', mode='rating', value=3, min=0, max=10))
view(f'Your rating was {stars} stars.')
Set range=
to a (min, max)
tuple to control min/max stars.
This is a shorthand notation for setting min=
and max=
individually.
stars = view(box('Rate your experience', mode='rating', value=3, range=(0, 10)))
view(f'Your rating was {stars} stars.')