Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [UNRELEASED]

### New features

* Added `shiny.render.renderer_components` decorator to help create new output renderers (#621).
* Added `shiny.experimental.ui.popover()`, `update_popover()`, and `toggle_popover()` for easy creation (and server-side updating) of [Bootstrap popovers](https://getbootstrap.com/docs/5.2/components/popovers/). Popovers are similar to tooltips, but are more persistent, and should primarily be used with button-like UI elements (e.g. `input_action_button()` or icons) (#680).
* Added `shiny.experimental.ui.toggle_switch()` (#680).
* Added CSS classes to UI input methods (#680) .
* `Session` objects can now accept an asynchronous (or synchronous) function for `.on_flush(fn=)`, `.on_flushed(fn=)`, and `.on_ended(fn=)` (#686).

### API changes

* Renamed `shiny.ui.navset_pill_card` to `shiny.ui.navset_card_pill`. `shiny.ui.navset_pill_card` will throw a deprecated warning (#492).
* Renamed `shiny.ui.navset_tab_card` to `shiny.ui.navset_card_tab`. `shiny.ui.navset_tab_card` will throw a deprecated warning (#492).

#### Experimental API changes

* Renamed `shiny.experimental.ui.navset_pill_card` to `shiny.experimental.ui.navset_card_pill` (#492).
* Renamed `shiny.experimental.ui.navset_tab_card` to `shiny.experimental.ui.navset_card_tab` (#492).
* Renamed `shiny.experimental.ui.sidebar_toggle()` to `shiny.experimental.ui.toggle_sidebar()` (#680).
* Renamed `shiny.experimental.ui.tooltip_toggle()` to `shiny.experimental.ui.toggle_tooltip()` (#680).
* Renamed `shiny.experimental.ui.tooltip_update()` to `shiny.experimental.ui.update_tooltip()` (#680).

### New features

* Added `shiny.render.renderer_components` decorator to help create new output renderers. (#621)
* `Session` objects can now accept an asynchronous (or synchronous) function for `.on_flush(fn=)`, `.on_flushed(fn=)`, and `.on_ended(fn=)` (#686).

### Bug fixes

Expand Down
15 changes: 13 additions & 2 deletions docs/_quartodoc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ quartodoc:
- experimental.ui.navset_bar
- experimental.ui.navset_card_tab
- experimental.ui.navset_card_pill
- experimental.ui.sidebar_toggle
- experimental.ui.toggle_sidebar
- experimental.ui.toggle_switch
- experimental.ui.panel_main
- experimental.ui.panel_sidebar
- experimental.ui.Sidebar
Expand Down Expand Up @@ -306,8 +307,18 @@ quartodoc:
flatten: true
contents:
- experimental.ui.tooltip
- experimental.ui.tooltip_toggle
- experimental.ui.toggle_tooltip
- experimental.ui.update_tooltip
- kind: page
path: ExPopover
summary:
name: "Popovers"
desc: "Display additional information when clicking on a UI element (typically a button)."
flatten: true
contents:
- experimental.ui.popover
- experimental.ui.toggle_popover
- experimental.ui.update_popover
- kind: page
path: ExFillingLayout
summary:
Expand Down
2 changes: 1 addition & 1 deletion scripts/htmlDependencies.R
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ fs::dir_copy(x_www_htmltools_fill, main_x_htmltools_fill)
fs::file_delete(
fs::dir_ls(
fs::path(main_x_bslib_components, "components"),
regexp="(_version|sidebar|nav_spacer)",
regexp="(_version|sidebar|nav_spacer|bslibShiny)",
invert = TRUE
)
)
Expand Down
2 changes: 1 addition & 1 deletion shiny/_versions.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
shiny_html_deps = "1.7.4.9002"
shiny_html_deps = "1.7.4.9003"
bslib = "0.5.0.9000"
htmltools = "0.5.5.9000"
bootstrap = "5.2.2"
Expand Down
46 changes: 46 additions & 0 deletions shiny/experimental/api-examples/popover/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

import shiny.experimental as x
from shiny import App, Inputs, Outputs, Session, render, ui

# https://icons.getbootstrap.com/icons/gear-fill/
gear_fill = ui.HTML(
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-gear-fill" viewBox="0 0 16 16"><path d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z"/></svg>'
)

app_ui = ui.page_fluid(
x.ui.popover(
ui.input_action_button("btn", "A button", class_="mt-3"),
"A popover with more context and information than should be used in a tooltip.",
"You can even have multiple DOM elements in a popover!",
id="btn_popover",
),
ui.hr(),
x.ui.card(
x.ui.card_header(
"Plot title (Click the gear to change variables)",
x.ui.popover(
ui.span(
gear_fill,
style="position:absolute; top: 5px; right: 7px;",
),
"Put dropdowns here to alter your plot!",
ui.input_selectize("x", "X", ["x1", "x2", "x3"]),
ui.input_selectize("y", "Y", ["y1", "y2", "y3"]),
placement="right",
id="card_popover",
),
),
ui.output_text_verbatim("plot_txt", placeholder=True),
),
)


def server(input: Inputs, output: Outputs, session: Session):
@output
@render.text
def plot_txt():
return f"<Making plot using x: {input.x()} and y: {input.y()}>"


app = App(app_ui, server=server)
46 changes: 46 additions & 0 deletions shiny/experimental/api-examples/toggle_popover/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from __future__ import annotations

import shiny.experimental as x
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.input_action_button("btn_toggle", "Toggle popover", class_="mt-3 me-3"),
ui.br(),
ui.br(),
x.ui.popover(
ui.input_action_button("btn_w_popover", "A button w/ a popover", class_="mt-3"),
"A message",
id="popover_id",
),
)


def server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
def _():
req(input.btn_show())

x.ui.toggle_popover("popover_id", show=True)

@reactive.Effect
def _():
req(input.btn_close())

x.ui.toggle_popover("popover_id", show=False)

@reactive.Effect
def _():
req(input.btn_toggle())

x.ui.toggle_popover("popover_id")

@reactive.Effect
def _():
req(input.btn_w_popover())
ui.notification_show("Button clicked!", duration=3, type="message")


app = App(app_ui, server=server)
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
app_ui = x.ui.page_sidebar(
x.ui.sidebar("Sidebar content", id="sidebar"),
ui.input_action_button(
"sidebar_toggle",
"toggle_sidebar",
label="Toggle sidebar",
width="fit-content",
),
Expand All @@ -16,9 +16,9 @@

def server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
@reactive.event(input.sidebar_toggle)
@reactive.event(input.toggle_sidebar)
def _():
x.ui.sidebar_toggle("sidebar")
x.ui.toggle_sidebar("sidebar")

@output
@render.text
Expand Down
29 changes: 29 additions & 0 deletions shiny/experimental/api-examples/toggle_switch/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from __future__ import annotations

import shiny.experimental as x
from shiny import App, Inputs, Outputs, Session, reactive, render, ui

app_ui = ui.page_fluid(
ui.input_switch("switch_value", label="Switch"),
ui.input_action_button(
"toggle_btn",
label="Toggle the switch",
width="fit-content",
),
ui.output_text_verbatim("state"),
)


def server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
@reactive.event(input.toggle_btn)
def _():
x.ui.toggle_switch("switch_value")

@output
@render.text
def state():
return f"input.switch(): {input.switch_value()}"


app = App(app_ui, server=server)
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ def server(input: Inputs, output: Outputs, session: Session):
def _():
req(input.btn_show())

x.ui.tooltip_toggle("tooltip_id", show=True)
x.ui.toggle_tooltip("tooltip_id", show=True)

@reactive.Effect
def _():
req(input.btn_close())

x.ui.tooltip_toggle("tooltip_id", show=False)
x.ui.toggle_tooltip("tooltip_id", show=False)

@reactive.Effect
def _():
req(input.btn_toggle())

x.ui.tooltip_toggle("tooltip_id")
x.ui.toggle_tooltip("tooltip_id")

@reactive.Effect
def _():
Expand Down
41 changes: 41 additions & 0 deletions shiny/experimental/api-examples/update_popover/app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from __future__ import annotations

import shiny.experimental as x
from shiny import App, Inputs, Outputs, Session, reactive, req, ui

app_ui = ui.page_fluid(
ui.input_action_button("btn_update", "Update popover phrase", class_="mt-3 me-3"),
ui.br(),
ui.br(),
x.ui.popover(
ui.input_action_button("btn_w_popover", "A button w/ a popover", class_="mt-3"),
"A message",
id="popover_id",
title="To start",
),
)


def server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
def _():
# Immediately display popover
x.ui.toggle_popover("popover_id", show=True)

@reactive.Effect
@reactive.event(input.btn_update)
def _():
content = (
"A " + " ".join(["NEW" for _ in range(input.btn_update())]) + " message"
)

x.ui.update_popover("popover_id", content)
# x.ui.toggle_popover("popover_id", show=True)

@reactive.Effect
def _():
req(input.btn_w_popover())
ui.notification_show("Button clicked!", duration=3, type="message")


app = App(app_ui, server=server)
11 changes: 5 additions & 6 deletions shiny/experimental/api-examples/update_tooltip/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import shiny.experimental as x
from shiny import App, Inputs, Outputs, Session, reactive, req, ui
from shiny import App, Inputs, Outputs, Session, reactive, ui

app_ui = ui.page_fluid(
ui.input_action_button("btn_update", "Update tooltip phrase", class_="mt-3 me-3"),
Expand All @@ -19,22 +19,21 @@ def server(input: Inputs, output: Outputs, session: Session):
@reactive.Effect
def _():
# Immediately display tooltip
x.ui.tooltip_toggle("tooltip_id", show=True)
x.ui.toggle_tooltip("tooltip_id", show=True)

@reactive.Effect
@reactive.event(input.btn_update)
def _():
req(input.btn_update())

content = (
"A " + " ".join(["NEW" for _ in range(input.btn_update())]) + " message"
)

x.ui.update_tooltip("tooltip_id", content)
x.ui.tooltip_toggle("tooltip_id", show=True)
x.ui.toggle_tooltip("tooltip_id", show=True)

@reactive.Effect
@reactive.event(input.btn_w_tooltip)
def _():
req(input.btn_w_tooltip())
ui.notification_show("Button clicked!", duration=3, type="message")


Expand Down
12 changes: 6 additions & 6 deletions shiny/experimental/e2e/sidebar/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,24 @@ def ui_content():
@reactive.Effect
@reactive.event(input.open_all)
def _():
x.ui.sidebar_toggle("sidebar_inner", open=True)
x.ui.sidebar_toggle("sidebar_outer", open=True)
x.ui.toggle_sidebar("sidebar_inner", open=True)
x.ui.toggle_sidebar("sidebar_outer", open=True)

@reactive.Effect
@reactive.event(input.close_all)
def _():
x.ui.sidebar_toggle("sidebar_inner", open=False)
x.ui.sidebar_toggle("sidebar_outer", open=False)
x.ui.toggle_sidebar("sidebar_inner", open=False)
x.ui.toggle_sidebar("sidebar_outer", open=False)

@reactive.Effect
@reactive.event(input.toggle_inner)
def _():
x.ui.sidebar_toggle("sidebar_inner")
x.ui.toggle_sidebar("sidebar_inner")

@reactive.Effect
@reactive.event(input.toggle_outer)
def _():
x.ui.sidebar_toggle("sidebar_outer")
x.ui.toggle_sidebar("sidebar_outer")


app = App(app_ui, server)
Loading