From 45d35a6fa2b7c0732dd25b26efeea7f52148688a Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:06:09 -0500 Subject: [PATCH 01/15] ex(page_sidebar): remove `@output` decorator --- shiny/api-examples/page_sidebar/app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/shiny/api-examples/page_sidebar/app.py b/shiny/api-examples/page_sidebar/app.py index ba84c3fe8..8ce58f8b8 100644 --- a/shiny/api-examples/page_sidebar/app.py +++ b/shiny/api-examples/page_sidebar/app.py @@ -14,7 +14,6 @@ def server(input: Inputs, output: Outputs, session: Session): - @output @render.plot(alt="A histogram") def plot() -> object: np.random.seed(19680801) From b17f0f6400b835e80e59f002e9f5da15496ff07e Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:06:42 -0500 Subject: [PATCH 02/15] expressify: api-examples/page_sidebar --- .../api-examples/page_sidebar/app-express.py | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 shiny/api-examples/page_sidebar/app-express.py diff --git a/shiny/api-examples/page_sidebar/app-express.py b/shiny/api-examples/page_sidebar/app-express.py new file mode 100644 index 000000000..54696d6fd --- /dev/null +++ b/shiny/api-examples/page_sidebar/app-express.py @@ -0,0 +1,20 @@ +import matplotlib.pyplot as plt +import numpy as np + +from shiny import render +from shiny.express import input, ui + +ui.page_opts(page_fn=page_fixed) + +with ui.sidebar(): + ui.input_slider("n", "N", min=0, max=100, value=20) + + +@render.plot(alt="A histogram") +def plot() -> object: + np.random.seed(19680801) + x = 100 + 15 * np.random.randn(437) + + fig, ax = plt.subplots() + ax.hist(x, input.n(), density=True) + return fig From 37f1fe9e561c893fe66eae9ca79a4560032b99d6 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:10:36 -0500 Subject: [PATCH 03/15] expressify: api-examples/sidebar --- shiny/api-examples/sidebar/app-express.py | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 shiny/api-examples/sidebar/app-express.py diff --git a/shiny/api-examples/sidebar/app-express.py b/shiny/api-examples/sidebar/app-express.py new file mode 100644 index 000000000..16665fd13 --- /dev/null +++ b/shiny/api-examples/sidebar/app-express.py @@ -0,0 +1,43 @@ +from shiny import render +from shiny.express import input, ui + +ui.page_opts(fillable=True) + +with ui.card(): + with ui.layout_sidebar(): + with ui.sidebar(id="sidebar_left", open="desktop"): + "Left sidebar content" + + @render.text + def state_left(): + return f"input.sidebar_left(): {input.sidebar_left()}" + + +with ui.card(): + with ui.layout_sidebar(): + with ui.sidebar(id="sidebar_right", position="right", open="desktop"): + "Right sidebar content" + + @render.text + def state_right(): + return f"input.sidebar_right(): {input.sidebar_right()}" + + +with ui.card(): + with ui.layout_sidebar(): + with ui.sidebar(id="sidebar_closed", open="closed"): + "Closed sidebar content" + + @render.text + def state_closed(): + return f"input.sidebar_closed(): {input.sidebar_closed()}" + + +with ui.card(): + with ui.layout_sidebar(): + with ui.sidebar(id="sidebar_always", open="always"): + "Always sidebar content" + + @render.text + def state_always(): + return f"input.sidebar_always(): {input.sidebar_always()}" From 5ff52bbfd34eedba34d574996c0e71971a893fad Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:38:20 -0500 Subject: [PATCH 04/15] expressify: api-examples/layout_column_wrap --- .../layout_column_wrap/app-express.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 shiny/api-examples/layout_column_wrap/app-express.py diff --git a/shiny/api-examples/layout_column_wrap/app-express.py b/shiny/api-examples/layout_column_wrap/app-express.py new file mode 100644 index 000000000..a5731350d --- /dev/null +++ b/shiny/api-examples/layout_column_wrap/app-express.py @@ -0,0 +1,18 @@ +import shiny +from shiny.express import ui + +a_card = shiny.ui.card("A simple card") + +# Always has 2 columns (on non-mobile) +with ui.layout_column_wrap(width=1 / 2): + a_card + a_card + a_card + +ui.hr() + +# Has three columns when viewport is wider than 750px +with ui.layout_column_wrap(width="250px"): + a_card + a_card + a_card From efd57b234b6a1301946de35dec30005e1c2c5a17 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:43:21 -0500 Subject: [PATCH 05/15] expressify: api-examples/layout_columns --- .../layout_columns/app-express.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 shiny/api-examples/layout_columns/app-express.py diff --git a/shiny/api-examples/layout_columns/app-express.py b/shiny/api-examples/layout_columns/app-express.py new file mode 100644 index 000000000..1362b01eb --- /dev/null +++ b/shiny/api-examples/layout_columns/app-express.py @@ -0,0 +1,35 @@ +from model_plots import * # model plots and cards + +from shiny import render +from shiny.express import input, ui + +ui.page_opts(title="Model Dashboard") + +ui.markdown("Using `ui.layout_columns()` for the layout.") + + +with ui.layout_columns( + col_widths={"sm": (5, 7, 12)}, + # row_heights=(2, 3), + # height="700px", +): + with ui.card(full_screen=True): + ui.card_header("Loss Over Time") + + @render.plot + def loss_over_time(): + return plot_loss_over_time() + + with ui.card(full_screen=True): + ui.card_header("Accuracy Over Time") + + @render.plot + def accuracy_over_time(): + return plot_accuracy_over_time() + + with ui.card(full_screen=True): + ui.card_header("Feature Importance") + + @render.plot + def feature_importance(): + return plot_feature_importance() From 6c09496f75f81b849e7df0a3eeaf29668cc6334a Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:44:39 -0500 Subject: [PATCH 06/15] expressify: api-examples/layout_sidebar --- .../api-examples/layout_sidebar/app-express.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 shiny/api-examples/layout_sidebar/app-express.py diff --git a/shiny/api-examples/layout_sidebar/app-express.py b/shiny/api-examples/layout_sidebar/app-express.py new file mode 100644 index 000000000..93e80442f --- /dev/null +++ b/shiny/api-examples/layout_sidebar/app-express.py @@ -0,0 +1,18 @@ +import matplotlib.pyplot as plt +import numpy as np + +from shiny import render +from shiny.express import input, ui + +with ui.layout_sidebar(): + with ui.sidebar(): + ui.input_slider("n", "N", min=0, max=100, value=20) + + @render.plot(alt="A histogram") + def plot() -> object: + np.random.seed(19680801) + x = 100 + 15 * np.random.randn(437) + + fig, ax = plt.subplots() + ax.hist(x, input.n(), density=True) + return fig From d941199bf4e8f716377644aa84e6bf947afc0982 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 10:45:26 -0500 Subject: [PATCH 07/15] expressify: api-examples/markdown --- shiny/api-examples/markdown/app-express.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 shiny/api-examples/markdown/app-express.py diff --git a/shiny/api-examples/markdown/app-express.py b/shiny/api-examples/markdown/app-express.py new file mode 100644 index 000000000..11cb38c87 --- /dev/null +++ b/shiny/api-examples/markdown/app-express.py @@ -0,0 +1,13 @@ +from shiny.express import input, ui + +ui.markdown( + """ + # Hello World + + This is **markdown** and here is some `code`: + + ```python + print('Hello world!') + ``` + """ +) From 930759c16480ca3c1a2bd3d69b1445f1a0fc61f7 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 12:16:43 -0500 Subject: [PATCH 08/15] expressify: api-examples/panel_absolute --- shiny/api-examples/panel_absolute/app-express.py | 8 ++++++++ shiny/api-examples/panel_absolute/app.py | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 shiny/api-examples/panel_absolute/app-express.py diff --git a/shiny/api-examples/panel_absolute/app-express.py b/shiny/api-examples/panel_absolute/app-express.py new file mode 100644 index 000000000..8cf254ecb --- /dev/null +++ b/shiny/api-examples/panel_absolute/app-express.py @@ -0,0 +1,8 @@ +from shiny.express import ui + +ui.h2("A basic absolute panel example") + +with ui.panel_absolute(draggable=True, width="300px", right="50px", top="25%"): + with ui.panel_well(): + "Drag me around!" + ui.input_slider("n", "N", min=0, max=100, value=20) diff --git a/shiny/api-examples/panel_absolute/app.py b/shiny/api-examples/panel_absolute/app.py index 10fab125e..3340e5f93 100644 --- a/shiny/api-examples/panel_absolute/app.py +++ b/shiny/api-examples/panel_absolute/app.py @@ -9,7 +9,7 @@ draggable=True, width="300px", right="50px", - top="50%", + top="25%", ), ) From 81f0314b3186609f8403123256be6e6245008d78 Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Tue, 16 Jan 2024 12:18:28 -0500 Subject: [PATCH 09/15] expressify: api-examples/panel_conditional --- shiny/api-examples/panel_conditional/app-express.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 shiny/api-examples/panel_conditional/app-express.py diff --git a/shiny/api-examples/panel_conditional/app-express.py b/shiny/api-examples/panel_conditional/app-express.py new file mode 100644 index 000000000..8c81ea531 --- /dev/null +++ b/shiny/api-examples/panel_conditional/app-express.py @@ -0,0 +1,12 @@ +from shiny.express import input, ui + +ui.input_checkbox("show", "Show radio buttons", False) + +with ui.panel_conditional("input.show"): + ui.input_radio_buttons("radio", "Choose ", ["slider", "select"]) + +with ui.panel_conditional("input.show && input.radio === 'slider'"): + ui.input_slider("slider", None, min=0, max=100, value=50) + +with ui.panel_conditional("input.show && input.radio === 'select'"): + ui.input_select("slider", None, ["A", "B", "C"]) From 40233974805715f8050d420a8f14ead299e3028a Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Wed, 24 Jan 2024 17:21:31 -0500 Subject: [PATCH 10/15] Apply suggestions from code review Co-authored-by: Carson Sievert --- shiny/api-examples/layout_column_wrap/app-express.py | 5 +++-- shiny/api-examples/layout_columns/app-express.py | 3 +-- shiny/api-examples/layout_sidebar/app-express.py | 3 +-- shiny/api-examples/markdown/app-express.py | 2 +- shiny/api-examples/page_sidebar/app-express.py | 3 +-- shiny/api-examples/sidebar/app-express.py | 3 +-- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/shiny/api-examples/layout_column_wrap/app-express.py b/shiny/api-examples/layout_column_wrap/app-express.py index a5731350d..0754d8b74 100644 --- a/shiny/api-examples/layout_column_wrap/app-express.py +++ b/shiny/api-examples/layout_column_wrap/app-express.py @@ -1,7 +1,8 @@ -import shiny from shiny.express import ui -a_card = shiny.ui.card("A simple card") +with ui.hold() as a_card: + with ui.card(): + "A simple card" # Always has 2 columns (on non-mobile) with ui.layout_column_wrap(width=1 / 2): diff --git a/shiny/api-examples/layout_columns/app-express.py b/shiny/api-examples/layout_columns/app-express.py index 1362b01eb..593ba321d 100644 --- a/shiny/api-examples/layout_columns/app-express.py +++ b/shiny/api-examples/layout_columns/app-express.py @@ -1,7 +1,6 @@ from model_plots import * # model plots and cards -from shiny import render -from shiny.express import input, ui +from shiny.express import input, render, ui ui.page_opts(title="Model Dashboard") diff --git a/shiny/api-examples/layout_sidebar/app-express.py b/shiny/api-examples/layout_sidebar/app-express.py index 93e80442f..10482a396 100644 --- a/shiny/api-examples/layout_sidebar/app-express.py +++ b/shiny/api-examples/layout_sidebar/app-express.py @@ -1,8 +1,7 @@ import matplotlib.pyplot as plt import numpy as np -from shiny import render -from shiny.express import input, ui +from shiny.express import input, render, ui with ui.layout_sidebar(): with ui.sidebar(): diff --git a/shiny/api-examples/markdown/app-express.py b/shiny/api-examples/markdown/app-express.py index 11cb38c87..f1db29501 100644 --- a/shiny/api-examples/markdown/app-express.py +++ b/shiny/api-examples/markdown/app-express.py @@ -1,4 +1,4 @@ -from shiny.express import input, ui +from shiny.express import ui ui.markdown( """ diff --git a/shiny/api-examples/page_sidebar/app-express.py b/shiny/api-examples/page_sidebar/app-express.py index 54696d6fd..1b0beab3d 100644 --- a/shiny/api-examples/page_sidebar/app-express.py +++ b/shiny/api-examples/page_sidebar/app-express.py @@ -1,8 +1,7 @@ import matplotlib.pyplot as plt import numpy as np -from shiny import render -from shiny.express import input, ui +from shiny.express import input, render, ui ui.page_opts(page_fn=page_fixed) diff --git a/shiny/api-examples/sidebar/app-express.py b/shiny/api-examples/sidebar/app-express.py index 16665fd13..17e80bb47 100644 --- a/shiny/api-examples/sidebar/app-express.py +++ b/shiny/api-examples/sidebar/app-express.py @@ -1,5 +1,4 @@ -from shiny import render -from shiny.express import input, ui +from shiny.express import input, render, ui ui.page_opts(fillable=True) From 4f602f8e24530959b2ef52c8ebf486578621aadf Mon Sep 17 00:00:00 2001 From: Garrick Aden-Buie Date: Wed, 24 Jan 2024 17:21:47 -0500 Subject: [PATCH 11/15] Update shiny/api-examples/panel_conditional/app-express.py Co-authored-by: Carson Sievert --- shiny/api-examples/panel_conditional/app-express.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shiny/api-examples/panel_conditional/app-express.py b/shiny/api-examples/panel_conditional/app-express.py index 8c81ea531..8f5fbb229 100644 --- a/shiny/api-examples/panel_conditional/app-express.py +++ b/shiny/api-examples/panel_conditional/app-express.py @@ -1,4 +1,4 @@ -from shiny.express import input, ui +from shiny.express import ui ui.input_checkbox("show", "Show radio buttons", False) From 9c5a87c76d03387d979108723b1f395af85b8a34 Mon Sep 17 00:00:00 2001 From: Gordon Shotwell Date: Thu, 25 Jan 2024 08:41:56 -0400 Subject: [PATCH 12/15] Linting --- shiny/api-examples/layout_columns/app-express.py | 8 ++++++-- shiny/api-examples/page_sidebar/app-express.py | 2 -- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/shiny/api-examples/layout_columns/app-express.py b/shiny/api-examples/layout_columns/app-express.py index 593ba321d..768056d5c 100644 --- a/shiny/api-examples/layout_columns/app-express.py +++ b/shiny/api-examples/layout_columns/app-express.py @@ -1,6 +1,10 @@ -from model_plots import * # model plots and cards +from model_plots import ( + plot_accuracy_over_time, + plot_feature_importance, + plot_loss_over_time, +) -from shiny.express import input, render, ui +from shiny.express import render, ui ui.page_opts(title="Model Dashboard") diff --git a/shiny/api-examples/page_sidebar/app-express.py b/shiny/api-examples/page_sidebar/app-express.py index 1b0beab3d..4781f851c 100644 --- a/shiny/api-examples/page_sidebar/app-express.py +++ b/shiny/api-examples/page_sidebar/app-express.py @@ -3,8 +3,6 @@ from shiny.express import input, render, ui -ui.page_opts(page_fn=page_fixed) - with ui.sidebar(): ui.input_slider("n", "N", min=0, max=100, value=20) From e24d44e60493a7923efad7a37ae265142dd1cd44 Mon Sep 17 00:00:00 2001 From: Gordon Shotwell Date: Thu, 25 Jan 2024 08:59:47 -0400 Subject: [PATCH 13/15] expressify-input-examples (#1057) --- .../input_action_link/app-express.py | 20 ++++++++ .../input_checkbox/app-express.py | 8 ++++ .../input_checkbox_group/app-express.py | 18 +++++++ shiny/api-examples/input_date/app-express.py | 24 ++++++++++ .../input_date_range/app-express.py | 27 +++++++++++ shiny/api-examples/input_file/app-express.py | 48 +++++++++++++++++++ .../api-examples/input_numeric/app-express.py | 8 ++++ .../input_password/app-express.py | 11 +++++ .../input_radio_buttons/app-express.py | 15 ++++++ .../api-examples/input_select/app-express.py | 16 +++++++ .../input_selectize/app-express.py | 45 +++++++++++++++++ shiny/api-examples/input_selectize/app.py | 4 +- .../api-examples/input_slider/app-express.py | 16 +++++++ .../api-examples/input_switch/app-express.py | 8 ++++ shiny/api-examples/input_switch/app.py | 4 +- shiny/api-examples/input_text/app-express.py | 8 ++++ .../input_text_area/app-express.py | 25 ++++++++++ 17 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 shiny/api-examples/input_action_link/app-express.py create mode 100644 shiny/api-examples/input_checkbox/app-express.py create mode 100644 shiny/api-examples/input_checkbox_group/app-express.py create mode 100644 shiny/api-examples/input_date/app-express.py create mode 100644 shiny/api-examples/input_date_range/app-express.py create mode 100644 shiny/api-examples/input_file/app-express.py create mode 100644 shiny/api-examples/input_numeric/app-express.py create mode 100644 shiny/api-examples/input_password/app-express.py create mode 100644 shiny/api-examples/input_radio_buttons/app-express.py create mode 100644 shiny/api-examples/input_select/app-express.py create mode 100644 shiny/api-examples/input_selectize/app-express.py create mode 100644 shiny/api-examples/input_slider/app-express.py create mode 100644 shiny/api-examples/input_switch/app-express.py create mode 100644 shiny/api-examples/input_text/app-express.py create mode 100644 shiny/api-examples/input_text_area/app-express.py diff --git a/shiny/api-examples/input_action_link/app-express.py b/shiny/api-examples/input_action_link/app-express.py new file mode 100644 index 000000000..39939d756 --- /dev/null +++ b/shiny/api-examples/input_action_link/app-express.py @@ -0,0 +1,20 @@ +import matplotlib.pyplot as plt +import numpy as np + +from shiny import reactive +from shiny.express import input, render, ui + +ui.input_slider("n", "Number of observations", min=0, max=1000, value=500) +ui.input_action_link("go", "Go!") + + +@render.plot(alt="A histogram") +# reactive.event() to invalidate the plot when the button is pressed but not when +# the slider is changed +@reactive.event(input.go, ignore_none=False) +def plot(): + np.random.seed(19680801) + x = 100 + 15 * np.random.randn(input.n()) + fig, ax = plt.subplots() + ax.hist(x, bins=30, density=True) + return fig diff --git a/shiny/api-examples/input_checkbox/app-express.py b/shiny/api-examples/input_checkbox/app-express.py new file mode 100644 index 000000000..1c7e87f7e --- /dev/null +++ b/shiny/api-examples/input_checkbox/app-express.py @@ -0,0 +1,8 @@ +from shiny.express import input, render, ui + +ui.input_checkbox("somevalue", "Some value", False) + + +@render.ui +def value(): + return input.somevalue() diff --git a/shiny/api-examples/input_checkbox_group/app-express.py b/shiny/api-examples/input_checkbox_group/app-express.py new file mode 100644 index 000000000..9f3b9652b --- /dev/null +++ b/shiny/api-examples/input_checkbox_group/app-express.py @@ -0,0 +1,18 @@ +from shiny import req +from shiny.express import input, render, ui + +ui.input_checkbox_group( + "colors", + "Choose color(s):", + { + "red": ui.span("Red", style="color: #FF0000;"), + "green": ui.span("Green", style="color: #00AA00;"), + "blue": ui.span("Blue", style="color: #0000AA;"), + }, +) + + +@render.ui +def val(): + req(input.colors()) + return "You chose " + ", ".join(input.colors()) diff --git a/shiny/api-examples/input_date/app-express.py b/shiny/api-examples/input_date/app-express.py new file mode 100644 index 000000000..bd696beb3 --- /dev/null +++ b/shiny/api-examples/input_date/app-express.py @@ -0,0 +1,24 @@ +from datetime import date + +from shiny.express import ui + +ui.input_date("date1", "Date:", value="2016-02-29") +# Default value is the date in client's time zone +ui.input_date("date2", "Date:") +# value is always yyyy-mm-dd, even if the display format is different +ui.input_date("date3", "Date:", value="2016-02-29", format="mm/dd/yy") +# Pass in a Date object +ui.input_date("date4", "Date:", value=date(2016, 2, 29)) +# Use different language and different first day of week +ui.input_date("date5", "Date:", language="ru", weekstart=1) +# Start with decade view instead of default month view +ui.input_date("date6", "Date:", startview="decade") +# Disable Mondays and Tuesdays. +ui.input_date("date7", "Date:", daysofweekdisabled=[1, 2]) +# Disable specific dates. +ui.input_date( + "date8", + "Date:", + value="2016-02-29", + datesdisabled=["2016-03-01", "2016-03-02"], +) diff --git a/shiny/api-examples/input_date_range/app-express.py b/shiny/api-examples/input_date_range/app-express.py new file mode 100644 index 000000000..66f79c5c4 --- /dev/null +++ b/shiny/api-examples/input_date_range/app-express.py @@ -0,0 +1,27 @@ +from datetime import date + +from shiny.express import ui + +ui.input_date_range("daterange1", "Date range:", start="2001-01-01", end="2010-12-31") +# Default start and end is the current date in the client's time zone +ui.input_date_range("daterange2", "Date range:") +# start and end are always specified in yyyy-mm-dd, even if the display +# format is different +ui.input_date_range( + "daterange3", + "Date range:", + start="2001-01-01", + end="2010-12-31", + min="2001-01-01", + max="2012-12-21", + format="mm/dd/yy", + separator=" - ", +) +# Pass in Date objects +ui.input_date_range( + "daterange4", "Date range:", start=date(2001, 1, 1), end=date(2010, 12, 31) +) +# Use different language and different first day of week +ui.input_date_range("daterange5", "Date range:", language="de", weekstart=1) +# Start with decade view instead of default month view +ui.input_date_range("daterange6", "Date range:", startview="decade") diff --git a/shiny/api-examples/input_file/app-express.py b/shiny/api-examples/input_file/app-express.py new file mode 100644 index 000000000..81222e4f7 --- /dev/null +++ b/shiny/api-examples/input_file/app-express.py @@ -0,0 +1,48 @@ +import pandas as pd + +from shiny import reactive +from shiny.express import input, render, ui +from shiny.types import FileInfo + +ui.input_file("file1", "Choose CSV File", accept=[".csv"], multiple=False) +ui.input_checkbox_group( + "stats", + "Summary Stats", + choices=["Row Count", "Column Count", "Column Names"], + selected=["Row Count", "Column Count", "Column Names"], +) + + +@reactive.Calc +def parsed_file(): + file: list[FileInfo] | None = input.file1() + if file is None: + return pd.DataFrame() + return pd.read_csv(file[0]["datapath"]) # pyright: ignore[reportUnknownMemberType] + + +@render.table +def summary(): + df = parsed_file() + + if df.empty: + return pd.DataFrame() + + # Get the row count, column count, and column names of the DataFrame + row_count = df.shape[0] + column_count = df.shape[1] + names = df.columns.tolist() + column_names = ", ".join(str(name) for name in names) + + # Create a new DataFrame to display the information + info_df = pd.DataFrame( + { + "Row Count": [row_count], + "Column Count": [column_count], + "Column Names": [column_names], + } + ) + + # input.stats() is a list of strings; subset the columns based on the selected + # checkboxes + return info_df.loc[:, input.stats()] diff --git a/shiny/api-examples/input_numeric/app-express.py b/shiny/api-examples/input_numeric/app-express.py new file mode 100644 index 000000000..7e06f1c0a --- /dev/null +++ b/shiny/api-examples/input_numeric/app-express.py @@ -0,0 +1,8 @@ +from shiny.express import input, render, ui + +ui.input_numeric("obs", "Observations:", 10, min=1, max=100) + + +@render.code +def value(): + return input.obs() diff --git a/shiny/api-examples/input_password/app-express.py b/shiny/api-examples/input_password/app-express.py new file mode 100644 index 000000000..4366c5303 --- /dev/null +++ b/shiny/api-examples/input_password/app-express.py @@ -0,0 +1,11 @@ +from shiny import reactive +from shiny.express import input, render, ui + +ui.input_password("password", "Password:") +ui.input_action_button("go", "Go") + + +@render.code +@reactive.event(input.go) +def value(): + return input.password() diff --git a/shiny/api-examples/input_radio_buttons/app-express.py b/shiny/api-examples/input_radio_buttons/app-express.py new file mode 100644 index 000000000..5354f4134 --- /dev/null +++ b/shiny/api-examples/input_radio_buttons/app-express.py @@ -0,0 +1,15 @@ +from shiny.express import input, render, ui + +ui.input_radio_buttons( + "rb", + "Choose one:", + { + "html": ui.HTML("Red Text"), + "text": "Normal text", + }, +) + + +@render.express +def val(): + "You chose " + input.rb() diff --git a/shiny/api-examples/input_select/app-express.py b/shiny/api-examples/input_select/app-express.py new file mode 100644 index 000000000..c45482f0c --- /dev/null +++ b/shiny/api-examples/input_select/app-express.py @@ -0,0 +1,16 @@ +from shiny.express import input, render, ui + +ui.input_select( + "state", + "Choose a state:", + { + "East Coast": {"NY": "New York", "NJ": "New Jersey", "CT": "Connecticut"}, + "West Coast": {"WA": "Washington", "OR": "Oregon", "CA": "California"}, + "Midwest": {"MN": "Minnesota", "WI": "Wisconsin", "IA": "Iowa"}, + }, +) + + +@render.text +def value(): + return "You choose: " + str(input.state()) diff --git a/shiny/api-examples/input_selectize/app-express.py b/shiny/api-examples/input_selectize/app-express.py new file mode 100644 index 000000000..d58e04154 --- /dev/null +++ b/shiny/api-examples/input_selectize/app-express.py @@ -0,0 +1,45 @@ +from html import escape # noqa: F401 + +from shiny.express import input, render, ui + +states = { + "East Coast": {"NY": "New York", "NJ": "New Jersey", "CT": "Connecticut"}, + "West Coast": {"WA": "Washington", "OR": "Oregon", "CA": "California"}, + "Midwest": {"MN": "Minnesota", "WI": "Wisconsin", "IA": "Iowa"}, +} + +ui.input_selectize( + "state", + "Choose a state:", + states, + multiple=True, +) + + +@render.text +def value(): + return "You choose: " + str(input.state()) + + +ui.input_selectize( + "state2", + "Selectize Options", + states, + multiple=True, + options=( + { + "placeholder": "Enter text", + "render": ui.js_eval( + '{option: function(item, escape) {return "
Select " + escape(item.label) + "
";}}' + ), + "create": True, + } + ), +) +ui.input_selectize( + "state3", + "Selectize plugins", + states, + multiple=True, + options={"plugins": ["clear_button"]}, +) diff --git a/shiny/api-examples/input_selectize/app.py b/shiny/api-examples/input_selectize/app.py index bc2dd9bd9..23a63d376 100644 --- a/shiny/api-examples/input_selectize/app.py +++ b/shiny/api-examples/input_selectize/app.py @@ -17,7 +17,7 @@ ), ui.output_text("value"), ui.input_selectize( - "state", + "state2", "Selectize Options", states, multiple=True, @@ -32,7 +32,7 @@ ), ), ui.input_selectize( - "state", + "state3", "Selectize plugins", states, multiple=True, diff --git a/shiny/api-examples/input_slider/app-express.py b/shiny/api-examples/input_slider/app-express.py new file mode 100644 index 000000000..e6e701594 --- /dev/null +++ b/shiny/api-examples/input_slider/app-express.py @@ -0,0 +1,16 @@ +import matplotlib.pyplot as plt +import numpy as np + +from shiny.express import input, render, ui + +ui.input_slider("obs", "Number of bins:", min=10, max=100, value=30) + + +@render.plot +def distPlot(): + np.random.seed(19680801) + x = 100 + 15 * np.random.randn(437) + + fig, ax = plt.subplots() + ax.hist(x, input.obs(), density=True) + return fig diff --git a/shiny/api-examples/input_switch/app-express.py b/shiny/api-examples/input_switch/app-express.py new file mode 100644 index 000000000..efd623850 --- /dev/null +++ b/shiny/api-examples/input_switch/app-express.py @@ -0,0 +1,8 @@ +from shiny.express import input, render, ui + +ui.input_switch("somevalue", "Some value", False) + + +@render.text +def value(): + return input.somevalue() diff --git a/shiny/api-examples/input_switch/app.py b/shiny/api-examples/input_switch/app.py index a438d8195..f05cba431 100644 --- a/shiny/api-examples/input_switch/app.py +++ b/shiny/api-examples/input_switch/app.py @@ -2,12 +2,12 @@ app_ui = ui.page_fluid( ui.input_switch("somevalue", "Some value", False), - ui.output_ui("value"), + ui.output_text("value"), ) def server(input: Inputs, output: Outputs, session: Session): - @render.ui + @render.text def value(): return input.somevalue() diff --git a/shiny/api-examples/input_text/app-express.py b/shiny/api-examples/input_text/app-express.py new file mode 100644 index 000000000..8c0c30d69 --- /dev/null +++ b/shiny/api-examples/input_text/app-express.py @@ -0,0 +1,8 @@ +from shiny.express import input, render, ui + +ui.input_text("caption", "Caption:", "Data summary") + + +@render.code +def value(): + return input.caption() diff --git a/shiny/api-examples/input_text_area/app-express.py b/shiny/api-examples/input_text_area/app-express.py new file mode 100644 index 000000000..4841f56ee --- /dev/null +++ b/shiny/api-examples/input_text_area/app-express.py @@ -0,0 +1,25 @@ +from shiny.express import input, render, ui + +ui.input_text_area( + "caption_regular", + "Caption:", + "Data summary\nwith\nmultiple\nlines", +) + + +@render.text +def value_regular(): + return input.caption_regular() + + +ui.input_text_area( + "caption_autoresize", + ui.markdown("Caption (w/ `autoresize=True`):"), + "Data summary\nwith\nmultiple\nlines", + autoresize=True, +) + + +@render.text +def value_autoresize(): + return input.caption_autoresize() From 42fa439fed0a12c437db3038947db98eccc2a7d1 Mon Sep 17 00:00:00 2001 From: Gordon Shotwell Date: Thu, 25 Jan 2024 15:02:25 -0400 Subject: [PATCH 14/15] Expressify navigation other cards (#1068) Co-authored-by: Carson Sievert --- shiny/api-examples/accordion/app-express.py | 30 +++++++++++++++++++ shiny/api-examples/accordion/app.py | 18 ++++++----- .../accordion_panel/app-express.py | 12 ++++++++ shiny/api-examples/card/app-express.py | 7 +++++ shiny/api-examples/card_footer/app-express.py | 7 +++++ shiny/api-examples/card_header/app-express.py | 7 +++++ .../insert_accordion_panel/app-express.py | 26 ++++++++++++++++ shiny/api-examples/nav_panel/app-express.py | 10 +++++++ .../api-examples/navset_hidden/app-express.py | 22 ++++++++++++++ .../showcase_bottom/app-express.py | 28 +++++++++++++++++ .../showcase_left_center/app-express.py | 28 +++++++++++++++++ .../showcase_top_right/app-express.py | 28 +++++++++++++++++ shiny/api-examples/value_box/app-express.py | 28 +++++++++++++++++ shiny/api-examples/value_box/app.py | 2 +- 14 files changed, 244 insertions(+), 9 deletions(-) create mode 100644 shiny/api-examples/accordion/app-express.py create mode 100644 shiny/api-examples/accordion_panel/app-express.py create mode 100644 shiny/api-examples/card/app-express.py create mode 100644 shiny/api-examples/card_footer/app-express.py create mode 100644 shiny/api-examples/card_header/app-express.py create mode 100644 shiny/api-examples/insert_accordion_panel/app-express.py create mode 100644 shiny/api-examples/nav_panel/app-express.py create mode 100644 shiny/api-examples/navset_hidden/app-express.py create mode 100644 shiny/api-examples/showcase_bottom/app-express.py create mode 100644 shiny/api-examples/showcase_left_center/app-express.py create mode 100644 shiny/api-examples/showcase_top_right/app-express.py create mode 100644 shiny/api-examples/value_box/app-express.py diff --git a/shiny/api-examples/accordion/app-express.py b/shiny/api-examples/accordion/app-express.py new file mode 100644 index 000000000..10aeb7c00 --- /dev/null +++ b/shiny/api-examples/accordion/app-express.py @@ -0,0 +1,30 @@ +from shiny.express import input, render, ui + +with ui.card(): + ui.card_header("Single selction accordion") + with ui.accordion(multiple=False, id="acc_single"): + with ui.accordion_panel("Section 1"): + "Some text for Section 1" + with ui.accordion_panel("Section 2"): + "More things on Section 2" + with ui.accordion_panel("Section 3"): + "Another great section" + + @render.text + def acc_single_val(): + return "Selected accordion: " + str(input.acc_single()) + + +with ui.card(): + ui.card_header("Multiple selction accordion") + with ui.accordion(multiple=True, id="acc_multiple"): + with ui.accordion_panel("Section 1"): + "Some text for Section 1" + with ui.accordion_panel("Section 2"): + "More things on Section 2" + with ui.accordion_panel("Section 3"): + "Another great section" + + @render.text + def acc_multiple_val(): + return "Selected accordions: " + str(input.acc_multiple()) diff --git a/shiny/api-examples/accordion/app.py b/shiny/api-examples/accordion/app.py index 5f278f6d6..6f1a95c83 100644 --- a/shiny/api-examples/accordion/app.py +++ b/shiny/api-examples/accordion/app.py @@ -22,14 +22,16 @@ def make_items(): app_ui = ui.page_fluid( - ui.markdown("#### Accordion: (`multiple=False`)"), - # Provide an id to create a shiny input binding - ui.accordion(*make_items(), id="acc_single", multiple=False), - ui.output_text_verbatim("acc_single_val", placeholder=True), - ui.tags.br(), - ui.markdown("#### Accordion: (`multiple=True`)"), - ui.accordion(*make_items(), id="acc_multiple"), - ui.output_text_verbatim("acc_multiple_val", placeholder=True), + ui.card( + ui.card_header("Single selection accordion"), + ui.accordion(*make_items(), id="acc_single", multiple=False), + ui.output_text_verbatim("acc_single_val", placeholder=True), + ), + ui.card( + ui.card_header("Multiple selection accordion"), + ui.accordion(*make_items(), id="acc_multiple"), + ui.output_text_verbatim("acc_multiple_val", placeholder=True), + ), ) diff --git a/shiny/api-examples/accordion_panel/app-express.py b/shiny/api-examples/accordion_panel/app-express.py new file mode 100644 index 000000000..c01659714 --- /dev/null +++ b/shiny/api-examples/accordion_panel/app-express.py @@ -0,0 +1,12 @@ +from shiny.express import input, render, ui + +ui.card_header("Single selection accordion") +with ui.accordion(multiple=False, id="acc"): + for letter in "ABCDE": + with ui.accordion_panel(f"Section {letter}"): + f"Some narrative for section {letter}" + + +@render.text +def acc_val(): + return "input.acc(): " + str(input.acc()) diff --git a/shiny/api-examples/card/app-express.py b/shiny/api-examples/card/app-express.py new file mode 100644 index 000000000..fb8eb3e70 --- /dev/null +++ b/shiny/api-examples/card/app-express.py @@ -0,0 +1,7 @@ +from shiny.express import ui + +with ui.card(full_screen=True): + ui.card_header("This is the header") + ui.p("This is the body") + ui.p("This is still the body.") + ui.card_footer("This is the footer") diff --git a/shiny/api-examples/card_footer/app-express.py b/shiny/api-examples/card_footer/app-express.py new file mode 100644 index 000000000..fb8eb3e70 --- /dev/null +++ b/shiny/api-examples/card_footer/app-express.py @@ -0,0 +1,7 @@ +from shiny.express import ui + +with ui.card(full_screen=True): + ui.card_header("This is the header") + ui.p("This is the body") + ui.p("This is still the body.") + ui.card_footer("This is the footer") diff --git a/shiny/api-examples/card_header/app-express.py b/shiny/api-examples/card_header/app-express.py new file mode 100644 index 000000000..fb8eb3e70 --- /dev/null +++ b/shiny/api-examples/card_header/app-express.py @@ -0,0 +1,7 @@ +from shiny.express import ui + +with ui.card(full_screen=True): + ui.card_header("This is the header") + ui.p("This is the body") + ui.p("This is still the body.") + ui.card_footer("This is the footer") diff --git a/shiny/api-examples/insert_accordion_panel/app-express.py b/shiny/api-examples/insert_accordion_panel/app-express.py new file mode 100644 index 000000000..fcad947f0 --- /dev/null +++ b/shiny/api-examples/insert_accordion_panel/app-express.py @@ -0,0 +1,26 @@ +import random + +from shiny import reactive +from shiny.express import expressify, input, ui + +with ui.sidebar(): + ui.input_action_button("add_panel", "Add random panel", class_="mt-3 mb-3") + +with ui.accordion(id="acc", multiple=True): + for letter in "ABCDE": + with ui.accordion_panel(f"Section {letter}"): + f"Some narrative for section {letter} " + "more narrative" + + +@reactive.effect +@reactive.event(input.add_panel) +@expressify +def _(): + letter = str(random.randint(0, 10000)) + with ui.hold() as panel: + with ui.accordion_panel(f"Section {letter}"): + f"Some narrative for section {letter} " + "more narrative" + + ui.insert_accordion_panel("acc", panel[0]) diff --git a/shiny/api-examples/nav_panel/app-express.py b/shiny/api-examples/nav_panel/app-express.py new file mode 100644 index 000000000..7342ff279 --- /dev/null +++ b/shiny/api-examples/nav_panel/app-express.py @@ -0,0 +1,10 @@ +from shiny.express import ui + +ui.page_opts(title="Basic Nav Examples") + + +with ui.navset_tab(): + with ui.nav_panel("One"): + "First tab content" + with ui.nav_panel("Two"): + "Second tab content" diff --git a/shiny/api-examples/navset_hidden/app-express.py b/shiny/api-examples/navset_hidden/app-express.py new file mode 100644 index 000000000..5fc22bd2a --- /dev/null +++ b/shiny/api-examples/navset_hidden/app-express.py @@ -0,0 +1,22 @@ +from shiny import reactive +from shiny.express import input, ui + +with ui.sidebar(): + ui.input_radio_buttons("controller", "Controller", ["1", "2", "3"], selected="1") + + +with ui.navset_hidden(id="hidden_tabs"): + with ui.nav_panel(None, value="panel1"): + "Panel 1 content" + with ui.nav_panel(None, value="panel2"): + "Panel 2 content" + with ui.nav_panel(None, value="panel3"): + "Panel 3 content" + with ui.nav_panel(None, value="panel4"): + "Panel 4 content" + + +@reactive.Effect +@reactive.event(input.controller) +def update_navs(): + ui.update_navs("hidden_tabs", selected="panel" + str(input.controller())) diff --git a/shiny/api-examples/showcase_bottom/app-express.py b/shiny/api-examples/showcase_bottom/app-express.py new file mode 100644 index 000000000..9b2e644bc --- /dev/null +++ b/shiny/api-examples/showcase_bottom/app-express.py @@ -0,0 +1,28 @@ +from icons import piggy_bank + +from shiny.express import ui + +with ui.layout_columns(): + with ui.value_box( + showcase=piggy_bank, theme="bg-gradient-orange-cyan", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, + theme="text-green", + showcase_layout="top right", + full_screen=True, + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, theme="purple", showcase_layout="bottom", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" diff --git a/shiny/api-examples/showcase_left_center/app-express.py b/shiny/api-examples/showcase_left_center/app-express.py new file mode 100644 index 000000000..9b2e644bc --- /dev/null +++ b/shiny/api-examples/showcase_left_center/app-express.py @@ -0,0 +1,28 @@ +from icons import piggy_bank + +from shiny.express import ui + +with ui.layout_columns(): + with ui.value_box( + showcase=piggy_bank, theme="bg-gradient-orange-cyan", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, + theme="text-green", + showcase_layout="top right", + full_screen=True, + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, theme="purple", showcase_layout="bottom", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" diff --git a/shiny/api-examples/showcase_top_right/app-express.py b/shiny/api-examples/showcase_top_right/app-express.py new file mode 100644 index 000000000..9b2e644bc --- /dev/null +++ b/shiny/api-examples/showcase_top_right/app-express.py @@ -0,0 +1,28 @@ +from icons import piggy_bank + +from shiny.express import ui + +with ui.layout_columns(): + with ui.value_box( + showcase=piggy_bank, theme="bg-gradient-orange-cyan", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, + theme="text-green", + showcase_layout="top right", + full_screen=True, + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, theme="purple", showcase_layout="bottom", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" diff --git a/shiny/api-examples/value_box/app-express.py b/shiny/api-examples/value_box/app-express.py new file mode 100644 index 000000000..9b2e644bc --- /dev/null +++ b/shiny/api-examples/value_box/app-express.py @@ -0,0 +1,28 @@ +from icons import piggy_bank + +from shiny.express import ui + +with ui.layout_columns(): + with ui.value_box( + showcase=piggy_bank, theme="bg-gradient-orange-cyan", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, + theme="text-green", + showcase_layout="top right", + full_screen=True, + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" + + with ui.value_box( + showcase=piggy_bank, theme="purple", showcase_layout="bottom", full_screen=True + ): + "KPI Title" + "$1 Billion Dollars" + "Up 30% VS PREVIOUS 30 DAYS" diff --git a/shiny/api-examples/value_box/app.py b/shiny/api-examples/value_box/app.py index 1d5416ba7..804e0f957 100644 --- a/shiny/api-examples/value_box/app.py +++ b/shiny/api-examples/value_box/app.py @@ -3,7 +3,7 @@ from shiny import App, ui app_ui = ui.page_fluid( - ui.layout_column_wrap( + ui.layout_columns( ui.value_box( "KPI Title", "$1 Billion Dollars", From 819cb7c03401603a2129bc5037e9074ce77402d6 Mon Sep 17 00:00:00 2001 From: Gordon Shotwell Date: Thu, 25 Jan 2024 15:02:51 -0400 Subject: [PATCH 15/15] Expressify update examples (#1072) --- .../update_accordion/app-express.py | 16 ++++++++ .../update_accordion_panel/app-express.py | 31 ++++++++++++++ .../update_action_button/app-express.py | 22 ++++++++++ .../api-examples/update_action_button/app.py | 18 ++++----- .../update_checkbox/app-express.py | 13 ++++++ shiny/api-examples/update_checkbox/app.py | 3 +- .../update_checkbox_group/app-express.py | 23 +++++++++++ shiny/api-examples/update_date/app-express.py | 19 +++++++++ .../update_date_range/app-express.py | 20 ++++++++++ shiny/api-examples/update_navs/app-express.py | 18 +++++++++ shiny/api-examples/update_navs/app.py | 22 ++++------ .../update_numeric/app-express.py | 20 ++++++++++ .../update_popover/app-express.py | 29 ++++++++++++++ shiny/api-examples/update_popover/app.py | 22 +++++----- .../update_radio_buttons/app-express.py | 23 +++++++++++ .../api-examples/update_select/app-express.py | 26 ++++++++++++ .../update_selectize/app-express.py | 14 +++++++ .../update_sidebar/app-express.py | 27 +++++++++++++ shiny/api-examples/update_sidebar/app.py | 8 ++-- .../api-examples/update_slider/app-express.py | 17 ++++++++ shiny/api-examples/update_slider/app.py | 13 +++--- shiny/api-examples/update_text/app-express.py | 15 +++++++ .../update_tooltip/app-express.py | 40 +++++++++++++++++++ shiny/api-examples/update_tooltip/app.py | 29 +++++++------- 24 files changed, 427 insertions(+), 61 deletions(-) create mode 100644 shiny/api-examples/update_accordion/app-express.py create mode 100644 shiny/api-examples/update_accordion_panel/app-express.py create mode 100644 shiny/api-examples/update_action_button/app-express.py create mode 100644 shiny/api-examples/update_checkbox/app-express.py create mode 100644 shiny/api-examples/update_checkbox_group/app-express.py create mode 100644 shiny/api-examples/update_date/app-express.py create mode 100644 shiny/api-examples/update_date_range/app-express.py create mode 100644 shiny/api-examples/update_navs/app-express.py create mode 100644 shiny/api-examples/update_numeric/app-express.py create mode 100644 shiny/api-examples/update_popover/app-express.py create mode 100644 shiny/api-examples/update_radio_buttons/app-express.py create mode 100644 shiny/api-examples/update_select/app-express.py create mode 100644 shiny/api-examples/update_selectize/app-express.py create mode 100644 shiny/api-examples/update_sidebar/app-express.py create mode 100644 shiny/api-examples/update_slider/app-express.py create mode 100644 shiny/api-examples/update_text/app-express.py create mode 100644 shiny/api-examples/update_tooltip/app-express.py diff --git a/shiny/api-examples/update_accordion/app-express.py b/shiny/api-examples/update_accordion/app-express.py new file mode 100644 index 000000000..17ce91787 --- /dev/null +++ b/shiny/api-examples/update_accordion/app-express.py @@ -0,0 +1,16 @@ +from shiny import reactive +from shiny.express import input, ui + +with ui.card(): + ui.input_action_button("set_acc", "Only open sections A,C,E", class_="mt-3 mb-3") + # Provide an id to create a shiny input binding + with ui.accordion(id="acc", open=["Section B", "Section D"], multiple=True): + for letter in "ABCDE": + with ui.accordion_panel(f"Section {letter}"): + f"Some narrative for section {letter}" + + +@reactive.Effect +@reactive.event(input.set_acc) +def open_panels(): + ui.update_accordion("acc", show=["Section A", "Section C", "Section E"]) diff --git a/shiny/api-examples/update_accordion_panel/app-express.py b/shiny/api-examples/update_accordion_panel/app-express.py new file mode 100644 index 000000000..15a2d47c5 --- /dev/null +++ b/shiny/api-examples/update_accordion_panel/app-express.py @@ -0,0 +1,31 @@ +from shiny import reactive +from shiny.express import input, ui + +with ui.card(): + ui.input_action_button( + "update_panel", "Only open sections A,C,E", class_="mt-3 mb-3" + ) + # Provide an id to create a shiny input binding + with ui.accordion(id="acc", open=["Section B", "Section D"], multiple=True): + for letter in "ABCDE": + with ui.accordion_panel(f"Section {letter}", value=f"sec_{letter}"): + f"Some narrative for section {letter}" + + +@reactive.Effect +@reactive.event(input.update_panel) +def _(): + txt = " (updated)" if input.update_panel() else "" + show = bool(input.update_panel() % 2 == 1) + for letter in "ABCDE": + ui.update_accordion_panel( + "acc", + f"sec_{letter}", + f"Some{txt} narrative for section {letter}", + title=f"Section {letter}{txt}", + # Open Accordion Panel to see updated contents + show=show, + ) + next_show_txt = "close" if show else "open" + + ui.update_switch("update_panel", label=f"Update (and {next_show_txt}) Sections") diff --git a/shiny/api-examples/update_action_button/app-express.py b/shiny/api-examples/update_action_button/app-express.py new file mode 100644 index 000000000..375b0d258 --- /dev/null +++ b/shiny/api-examples/update_action_button/app-express.py @@ -0,0 +1,22 @@ +from shiny import reactive, req +from shiny.express import input, ui + +with ui.sidebar(): + ui.input_action_button("update", "Update other buttons and link") + ui.input_action_button("goButton", "Go") + ui.input_action_button("goButton2", "Go 2", icon="🤩") + ui.input_action_button("goButton3", "Go 3") + ui.input_action_link("goLink", "Go Link") + + +@reactive.Effect +def update_buttons(): + req(input.update()) + # Updates goButton's label and icon + ui.update_action_button("goButton", label="New label", icon="📅") + # Leaves goButton2's label unchanged and removes its icon + ui.update_action_button("goButton2", icon=[]) + # Leaves goButton3's icon, if it exists, unchanged and changes its label + ui.update_action_button("goButton3", label="New label 3") + # Updates goLink's label and icon + ui.update_action_link("goLink", label="New link label", icon="🔗") diff --git a/shiny/api-examples/update_action_button/app.py b/shiny/api-examples/update_action_button/app.py index 0b08cc34a..c6d55da8c 100644 --- a/shiny/api-examples/update_action_button/app.py +++ b/shiny/api-examples/update_action_button/app.py @@ -1,15 +1,13 @@ from shiny import App, Inputs, Outputs, Session, reactive, req, ui -app_ui = ui.page_fluid( - ui.input_action_button("update", "Update other buttons and link"), - ui.br(), - ui.input_action_button("goButton", "Go"), - ui.br(), - ui.input_action_button("goButton2", "Go 2", icon="🤩"), - ui.br(), - ui.input_action_button("goButton3", "Go 3"), - ui.br(), - ui.input_action_link("goLink", "Go Link"), +app_ui = ui.page_sidebar( + ui.sidebar( + ui.input_action_button("update", "Update other buttons and link"), + ui.input_action_button("goButton", "Go"), + ui.input_action_button("goButton2", "Go 2", icon="🤩"), + ui.input_action_button("goButton3", "Go 3"), + ui.input_action_link("goLink", "Go Link"), + ) ) diff --git a/shiny/api-examples/update_checkbox/app-express.py b/shiny/api-examples/update_checkbox/app-express.py new file mode 100644 index 000000000..95a6b69fe --- /dev/null +++ b/shiny/api-examples/update_checkbox/app-express.py @@ -0,0 +1,13 @@ +from shiny import reactive +from shiny.express import input, ui + +"Checkbox will be checked when slider is an odd number." +ui.input_slider("controller", "Controller", min=0, max=10, value=0, step=1) +ui.input_checkbox("inCheckbox", "Input checkbox") + + +@reactive.Effect +def _(): + # True if controller is odd, False if even. + x_even = input.controller() % 2 == 1 + ui.update_checkbox("inCheckbox", value=x_even) diff --git a/shiny/api-examples/update_checkbox/app.py b/shiny/api-examples/update_checkbox/app.py index 036a4034f..5b7af883a 100644 --- a/shiny/api-examples/update_checkbox/app.py +++ b/shiny/api-examples/update_checkbox/app.py @@ -1,7 +1,8 @@ from shiny import App, Inputs, Outputs, Session, reactive, ui app_ui = ui.page_fluid( - ui.input_slider("controller", "Controller", min=0, max=1, value=0, step=1), + ui.p("Checkbox will be checked when slider is an odd number."), + ui.input_slider("controller", "Controller", min=0, max=10, value=0, step=1), ui.input_checkbox("inCheckbox", "Input checkbox"), ) diff --git a/shiny/api-examples/update_checkbox_group/app-express.py b/shiny/api-examples/update_checkbox_group/app-express.py new file mode 100644 index 000000000..f2337ece5 --- /dev/null +++ b/shiny/api-examples/update_checkbox_group/app-express.py @@ -0,0 +1,23 @@ +from shiny import reactive +from shiny.express import input, ui + +"The first checkbox group controls the second" +ui.input_checkbox_group( + "inCheckboxGroup", "Input checkbox", ["Item A", "Item B", "Item C"] +) +ui.input_checkbox_group( + "inCheckboxGroup2", "Input checkbox 2", ["Item A", "Item B", "Item C"] +) + + +@reactive.Effect +def _(): + x = input.inCheckboxGroup() + + # Can also set the label and select items + ui.update_checkbox_group( + "inCheckboxGroup2", + label="Checkboxgroup label " + str(len(x)), + choices=x, + selected=x, + ) diff --git a/shiny/api-examples/update_date/app-express.py b/shiny/api-examples/update_date/app-express.py new file mode 100644 index 000000000..88e599303 --- /dev/null +++ b/shiny/api-examples/update_date/app-express.py @@ -0,0 +1,19 @@ +from datetime import date, timedelta + +from shiny import reactive, ui +from shiny.express import input + +ui.input_slider("n", "Day of month", min=1, max=30, value=10) +ui.input_date("inDate", "Input date") + + +@reactive.Effect +def _(): + d = date(2013, 4, input.n()) + ui.update_date( + "inDate", + label="Date label " + str(input.n()), + value=d, + min=d - timedelta(days=3), + max=d + timedelta(days=3), + ) diff --git a/shiny/api-examples/update_date_range/app-express.py b/shiny/api-examples/update_date_range/app-express.py new file mode 100644 index 000000000..41defda91 --- /dev/null +++ b/shiny/api-examples/update_date_range/app-express.py @@ -0,0 +1,20 @@ +from datetime import date, timedelta + +from shiny import reactive, ui +from shiny.express import input + +ui.input_slider("n", "Day of month", min=1, max=30, value=10) +ui.input_date_range("inDateRange", "Input date") + + +@reactive.Effect +def _(): + d = date(2013, 4, input.n()) + ui.update_date_range( + "inDateRange", + label="Date range label " + str(input.n()), + start=d - timedelta(days=1), + end=d + timedelta(days=1), + min=d - timedelta(days=5), + max=d + timedelta(days=5), + ) diff --git a/shiny/api-examples/update_navs/app-express.py b/shiny/api-examples/update_navs/app-express.py new file mode 100644 index 000000000..376fa400d --- /dev/null +++ b/shiny/api-examples/update_navs/app-express.py @@ -0,0 +1,18 @@ +from shiny import reactive +from shiny.express import input, ui + +with ui.sidebar(): + ui.input_slider("controller", "Controller", min=1, max=3, value=1) + +with ui.navset_tab(id="inTabset"): + with ui.nav_panel("Panel 1", value="panel1"): + "Panel 1 content" + with ui.nav_panel("Panel 2", value="panel2"): + "Panel 2 content" + with ui.nav_panel("Panel 3", value="panel3"): + "Panel 3 content" + + +@reactive.Effect +def _(): + ui.update_navs("inTabset", selected="panel" + str(input.controller())) diff --git a/shiny/api-examples/update_navs/app.py b/shiny/api-examples/update_navs/app.py index 6a8e392a9..cec4df882 100644 --- a/shiny/api-examples/update_navs/app.py +++ b/shiny/api-examples/update_navs/app.py @@ -1,19 +1,13 @@ from shiny import App, Inputs, Outputs, Session, reactive, ui -app_ui = ui.page_fixed( - ui.layout_sidebar( - ui.panel_sidebar( - ui.input_slider("controller", "Controller", min=1, max=3, value=1) - ), - ui.panel_main( - ui.navset_card_tab( - ui.nav_panel("Panel 1", "Panel 1 content", value="panel1"), - ui.nav_panel("Panel 2", "Panel 2 content", value="panel2"), - ui.nav_panel("Panel 3", "Panel 3 content", value="panel3"), - id="inTabset", - ), - ), - ) +app_ui = ui.page_navbar( + ui.nav_panel("Panel 1", "Panel 1 content", value="panel1"), + ui.nav_panel("Panel 2", "Panel 2 content", value="panel2"), + ui.nav_panel("Panel 3", "Panel 3 content", value="panel3"), + sidebar=ui.sidebar( + ui.input_slider("controller", "Controller", min=1, max=3, value=1) + ), + id="inTabset", ) diff --git a/shiny/api-examples/update_numeric/app-express.py b/shiny/api-examples/update_numeric/app-express.py new file mode 100644 index 000000000..3f3c5a97b --- /dev/null +++ b/shiny/api-examples/update_numeric/app-express.py @@ -0,0 +1,20 @@ +from shiny import reactive, ui +from shiny.express import input + +ui.input_slider("controller", "Controller", min=0, max=20, value=10) +ui.input_numeric("inNumber", "Input number", 0) +ui.input_numeric("inNumber2", "Input number 2", 0) + + +@reactive.Effect +def _(): + x = input.controller() + ui.update_numeric("inNumber", value=x) + ui.update_numeric( + "inNumber2", + label="Number label " + str(x), + value=x, + min=x - 10, + max=x + 10, + step=5, + ) diff --git a/shiny/api-examples/update_popover/app-express.py b/shiny/api-examples/update_popover/app-express.py new file mode 100644 index 000000000..6650216b7 --- /dev/null +++ b/shiny/api-examples/update_popover/app-express.py @@ -0,0 +1,29 @@ +from shiny import reactive, req +from shiny.express import input, ui + +with ui.sidebar(): + ui.input_action_button("btn_show", "Show popover", class_="mt-3 me-3") + ui.input_action_button("btn_close", "Close popover", class_="mt-3 me-3") + with ui.popover(id="popover_id"): + ui.input_action_button("btn_w_popover", "A button w/ a popover", class_="mt-3") + "A message" + + +@reactive.Effect +def _(): + req(input.btn_show()) + + ui.update_popover("popover_id", show=True) + + +@reactive.Effect +def _(): + req(input.btn_close()) + + ui.update_popover("popover_id", show=False) + + +@reactive.Effect +def _(): + req(input.btn_w_popover()) + ui.notification_show("Button clicked!", duration=3, type="message") diff --git a/shiny/api-examples/update_popover/app.py b/shiny/api-examples/update_popover/app.py index f54f18de9..c1cb842a1 100644 --- a/shiny/api-examples/update_popover/app.py +++ b/shiny/api-examples/update_popover/app.py @@ -1,15 +1,17 @@ from shiny import App, Inputs, Outputs, Session, reactive, req, ui -app_ui = ui.page_fluid( - ui.input_action_button("btn_show", "Show popover", class_="mt-3 me-3"), - ui.input_action_button("btn_close", "Close popover", class_="mt-3 me-3"), - ui.br(), - ui.br(), - ui.popover( - ui.input_action_button("btn_w_popover", "A button w/ a popover", class_="mt-3"), - "A message", - id="popover_id", - ), +app_ui = ui.page_sidebar( + ui.sidebar( + ui.input_action_button("btn_show", "Show popover", class_="mt-3 me-3"), + ui.input_action_button("btn_close", "Close popover", class_="mt-3 me-3"), + ui.popover( + ui.input_action_button( + "btn_w_popover", "A button w/ a popover", class_="mt-3" + ), + "A message", + id="popover_id", + ), + ) ) diff --git a/shiny/api-examples/update_radio_buttons/app-express.py b/shiny/api-examples/update_radio_buttons/app-express.py new file mode 100644 index 000000000..b1f601e0b --- /dev/null +++ b/shiny/api-examples/update_radio_buttons/app-express.py @@ -0,0 +1,23 @@ +from shiny import reactive, ui +from shiny.express import input + +"The first radio button group controls the second" +ui.input_radio_buttons( + "inRadioButtons", "Input radio buttons", ["Item A", "Item B", "Item C"] +) +ui.input_radio_buttons( + "inRadioButtons2", "Input radio buttons 2", ["Item A", "Item B", "Item C"] +) + + +@reactive.Effect +def _(): + x = input.inRadioButtons() + + # Can also set the label and select items + ui.update_radio_buttons( + "inRadioButtons2", + label="Radio buttons label " + x, + choices=[x], + selected=x, + ) diff --git a/shiny/api-examples/update_select/app-express.py b/shiny/api-examples/update_select/app-express.py new file mode 100644 index 000000000..15c087989 --- /dev/null +++ b/shiny/api-examples/update_select/app-express.py @@ -0,0 +1,26 @@ +from shiny import reactive +from shiny.express import input, ui + +ui.tags.p("The checkbox group controls the select input") +ui.input_checkbox_group( + "inCheckboxGroup", "Input checkbox", ["Item A", "Item B", "Item C"] +) +ui.input_select("inSelect", "Select input", ["Item A", "Item B", "Item C"]) + + +@reactive.Effect +def _(): + x = input.inCheckboxGroup() + + # Can use [] to remove all choices + if x is None: + x = [] + elif isinstance(x, str): + x = [x] + + ui.update_select( + "inSelect", + label="Select input label " + str(len(x)), + choices=x, + selected=x[len(x) - 1] if len(x) > 0 else None, + ) diff --git a/shiny/api-examples/update_selectize/app-express.py b/shiny/api-examples/update_selectize/app-express.py new file mode 100644 index 000000000..d2a67c8c9 --- /dev/null +++ b/shiny/api-examples/update_selectize/app-express.py @@ -0,0 +1,14 @@ +from shiny import reactive +from shiny.express import ui + +ui.input_selectize("x", "Server side selectize", choices=[], multiple=True) + + +@reactive.Effect +def _(): + ui.update_selectize( + "x", + choices=[f"Foo {i}" for i in range(10000)], + selected=["Foo 0", "Foo 1"], + server=True, + ) diff --git a/shiny/api-examples/update_sidebar/app-express.py b/shiny/api-examples/update_sidebar/app-express.py new file mode 100644 index 000000000..3176c0244 --- /dev/null +++ b/shiny/api-examples/update_sidebar/app-express.py @@ -0,0 +1,27 @@ +from shiny import reactive +from shiny.express import input, render, ui + +with ui.sidebar(id="sidebar"): + "Sidebar content" + ui.input_text("foo", "Foo") + +with ui.layout_columns(): + ui.input_action_button("open_sidebar", label="Open sidebar", class_="me-3") + ui.input_action_button("close_sidebar", label="Close sidebar", class_="me-3") + + +@render.text +def state(): + return f"input.sidebar(): {input.sidebar()}" + + +@reactive.Effect +@reactive.event(input.open_sidebar) +def _(): + ui.update_sidebar("sidebar", show=True) + + +@reactive.Effect +@reactive.event(input.close_sidebar) +def _(): + ui.update_sidebar("sidebar", show=False) diff --git a/shiny/api-examples/update_sidebar/app.py b/shiny/api-examples/update_sidebar/app.py index 4c27ae57a..4fc48efb3 100644 --- a/shiny/api-examples/update_sidebar/app.py +++ b/shiny/api-examples/update_sidebar/app.py @@ -2,10 +2,10 @@ app_ui = ui.page_sidebar( ui.sidebar("Sidebar content", id="sidebar"), - ui.input_action_button("open_sidebar", label="Open sidebar", class_="me-3"), - ui.input_action_button("close_sidebar", label="Close sidebar", class_="me-3"), - ui.br(), - ui.br(), + ui.layout_columns( + ui.input_action_button("open_sidebar", label="Open sidebar", class_="me-3"), + ui.input_action_button("close_sidebar", label="Close sidebar", class_="me-3"), + ), ui.output_text_verbatim("state"), fillable=False, ) diff --git a/shiny/api-examples/update_slider/app-express.py b/shiny/api-examples/update_slider/app-express.py new file mode 100644 index 000000000..049a888d8 --- /dev/null +++ b/shiny/api-examples/update_slider/app-express.py @@ -0,0 +1,17 @@ +from shiny import reactive +from shiny.express import input, ui + +with ui.sidebar(): + ui.tags.p("The first slider controls the second") + ui.input_slider("control", "Controller:", min=0, max=20, value=10, step=1) + ui.input_slider("receive", "Receiver:", min=0, max=20, value=10, step=1) + + +@reactive.Effect +def _(): + val = input.control() + # Control the value, min, max, and step. + # Step size is 2 when input value is even; 1 when value is odd. + ui.update_slider( + "receive", value=val, min=int(val / 2), max=val + 4, step=(val + 1) % 2 + 1 + ) diff --git a/shiny/api-examples/update_slider/app.py b/shiny/api-examples/update_slider/app.py index 923d12dcc..5826f4293 100644 --- a/shiny/api-examples/update_slider/app.py +++ b/shiny/api-examples/update_slider/app.py @@ -1,13 +1,10 @@ from shiny import App, Inputs, Outputs, Session, reactive, ui -app_ui = ui.page_fixed( - ui.layout_sidebar( - ui.panel_sidebar( - ui.tags.p("The first slider controls the second"), - ui.input_slider("control", "Controller:", min=0, max=20, value=10, step=1), - ui.input_slider("receive", "Receiver:", min=0, max=20, value=10, step=1), - ), - ui.panel_main("Main app content"), +app_ui = ui.page_sidebar( + ui.sidebar( + ui.tags.p("The first slider controls the second"), + ui.input_slider("control", "Controller:", min=0, max=20, value=10, step=1), + ui.input_slider("receive", "Receiver:", min=0, max=20, value=10, step=1), ) ) diff --git a/shiny/api-examples/update_text/app-express.py b/shiny/api-examples/update_text/app-express.py new file mode 100644 index 000000000..dbd329e73 --- /dev/null +++ b/shiny/api-examples/update_text/app-express.py @@ -0,0 +1,15 @@ +from shiny import reactive +from shiny.express import input, ui + +ui.input_slider("controller", "Controller", min=0, max=20, value=10) +ui.input_text("inText", "Input text") +ui.input_text("inText2", "Input text 2") + + +@reactive.Effect +def _(): + x = str(input.controller()) + # This will change the value of input$inText, based on x + ui.update_text("inText", value="New text " + x) + # Can also set the label, this time for input$inText2 + ui.update_text("inText2", label="New label " + x, value="New text" + x) diff --git a/shiny/api-examples/update_tooltip/app-express.py b/shiny/api-examples/update_tooltip/app-express.py new file mode 100644 index 000000000..d2bf8ea44 --- /dev/null +++ b/shiny/api-examples/update_tooltip/app-express.py @@ -0,0 +1,40 @@ +from shiny import reactive, req +from shiny.express import input, ui + +with ui.sidebar(): + ui.input_action_button("btn_show", "Show tooltip", class_="mt-3 me-3") + ui.input_action_button("btn_close", "Close tooltip", class_="mt-3 me-3") + ui.input_action_button( + "btn_update", "Update tooltip phrase (and show tooltip)", class_="mt-3 me-3" + ) + with ui.tooltip(id="tooltip_id"): + ui.input_action_button("btn_w_tooltip", "A button w/ a tooltip", class_="mt-3") + "A message" + + +@reactive.Effect +def _(): + req(input.btn_show()) + + ui.update_tooltip("tooltip_id", show=True) + + +@reactive.Effect +def _(): + req(input.btn_close()) + + ui.update_tooltip("tooltip_id", show=False) + + +@reactive.Effect +@reactive.event(input.btn_update) +def _(): + content = "A " + " ".join(["NEW" for _ in range(input.btn_update())]) + " message" + + ui.update_tooltip("tooltip_id", content, show=True) + + +@reactive.Effect +def _(): + req(input.btn_w_tooltip()) + ui.notification_show("Button clicked!", duration=3, type="message") diff --git a/shiny/api-examples/update_tooltip/app.py b/shiny/api-examples/update_tooltip/app.py index aa81eee94..c3e04e3c2 100644 --- a/shiny/api-examples/update_tooltip/app.py +++ b/shiny/api-examples/update_tooltip/app.py @@ -1,19 +1,20 @@ from shiny import App, Inputs, Outputs, Session, reactive, req, ui -app_ui = ui.page_fluid( - ui.input_action_button("btn_show", "Show tooltip", class_="mt-3 me-3"), - ui.input_action_button("btn_close", "Close tooltip", class_="mt-3 me-3"), - ui.br(), - ui.input_action_button( - "btn_update", "Update tooltip phrase (and show tooltip)", class_="mt-3 me-3" - ), - ui.br(), - ui.br(), - ui.tooltip( - ui.input_action_button("btn_w_tooltip", "A button w/ a tooltip", class_="mt-3"), - "A message", - id="tooltip_id", - ), +app_ui = ui.page_sidebar( + ui.sidebar( + ui.input_action_button("btn_show", "Show tooltip", class_="mt-3 me-3"), + ui.input_action_button("btn_close", "Close tooltip", class_="mt-3 me-3"), + ui.input_action_button( + "btn_update", "Update tooltip phrase (and show tooltip)", class_="mt-3 me-3" + ), + ui.tooltip( + ui.input_action_button( + "btn_w_tooltip", "A button w/ a tooltip", class_="mt-3" + ), + "A message", + id="tooltip_id", + ), + ) )