Skip to content

Commit 02945c7

Browse files
schloerkecpsievertwch
authored
Port more bslib methods: accordion, sidebar, navset, and fill methods (#481)
Co-authored-by: Carson Sievert <[email protected]> Co-authored-by: Winston Chang <[email protected]>
1 parent b874f0f commit 02945c7

File tree

65 files changed

+2897
-459
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+2897
-459
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212

1313
* Added `include_js()` and `include_css()`, for easily including JS and CSS files in an application. (#127)
1414

15+
* Added sidebar, card, value box, and accordion methods into `shiny.experimental.ui`. (#481)
16+
17+
* Added `fill` and `fillable` methods into `shiny.experimental.ui`. If `fill` is `True`, then the UI component is allowed to expand into the parent container. If `fillable` is `True`, then the UI component will allow its content to expand. Both `fill` on the child component and `fillable` on the parent component must be `True` for the child component to expand. (#481)
18+
19+
* Added sidebar methods into `shiny.experimental.ui`. `shiny.experimental.ui.layout_sidebar()` does not require `ui.panel_main()` and `ui.panel_sidebar()`. These two methods have been deprecated. `x.ui.page_navbar()`, `x.ui.navset_bar()`, `x.navset_tab_card()`, and `x.navset.pill_card()` added `sidebar=` support. (#481)
20+
21+
1522
### Bug fixes
1623

1724
### Other changes

examples/cpuinfo/app.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
import numpy as np
1414
import pandas as pd
1515

16-
from shiny import App, Inputs, Outputs, Session, reactive, render, ui
16+
from shiny import App, Inputs, Outputs, Session
17+
from shiny import experimental as x
18+
from shiny import reactive, render, ui
1719

1820
# The agg matplotlib backend seems to be a little more efficient than the default when
1921
# running on macOS, and also gives more consistent results across operating systems
@@ -53,8 +55,8 @@
5355
% f"{ncpu*4}em"
5456
),
5557
ui.h3("CPU Usage %", class_="mt-2"),
56-
ui.layout_sidebar(
57-
ui.panel_sidebar(
58+
x.ui.layout_sidebar(
59+
x.ui.sidebar(
5860
ui.input_select(
5961
"cmap",
6062
"Colormap",
@@ -69,33 +71,31 @@
6971
ui.input_switch("hold", "Freeze output", value=False),
7072
class_="mb-3",
7173
),
72-
ui.panel_main(
74+
ui.div(
75+
{"class": "card mb-3"},
7376
ui.div(
74-
{"class": "card mb-3"},
75-
ui.div(
76-
{"class": "card-body"},
77-
ui.h5({"class": "card-title mt-0"}, "Graphs"),
78-
ui.output_plot("plot", height=f"{ncpu * 40}px"),
79-
),
80-
ui.div(
81-
{"class": "card-footer"},
82-
ui.input_numeric("sample_count", "Number of samples per graph", 50),
83-
),
77+
{"class": "card-body"},
78+
ui.h5({"class": "card-title mt-0"}, "Graphs"),
79+
ui.output_plot("plot", height=f"{ncpu * 40}px"),
8480
),
8581
ui.div(
86-
{"class": "card"},
87-
ui.div(
88-
{"class": "card-body"},
89-
ui.h5({"class": "card-title m-0"}, "Heatmap"),
90-
),
91-
ui.div(
92-
{"class": "card-body overflow-auto pt-0"},
93-
ui.output_table("table"),
94-
),
95-
ui.div(
96-
{"class": "card-footer"},
97-
ui.input_numeric("table_rows", "Rows to display", 5),
98-
),
82+
{"class": "card-footer"},
83+
ui.input_numeric("sample_count", "Number of samples per graph", 50),
84+
),
85+
),
86+
ui.div(
87+
{"class": "card"},
88+
ui.div(
89+
{"class": "card-body"},
90+
ui.h5({"class": "card-title m-0"}, "Heatmap"),
91+
),
92+
ui.div(
93+
{"class": "card-body overflow-auto pt-0"},
94+
ui.output_table("table"),
95+
),
96+
ui.div(
97+
{"class": "card-footer"},
98+
ui.input_numeric("table_rows", "Rows to display", 5),
9999
),
100100
),
101101
),

examples/penguins/app.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,9 @@ def penguin_value_box(title: str, count: int, bgcol: str, showcase_img: str):
9494
return x.ui.value_box(
9595
title,
9696
count,
97-
{"class_": "pt-1 pb-0"},
98-
showcase=x.ui.bind_fill_role(
99-
ui.tags.img({"style": "object-fit:contain;"}, src=showcase_img),
100-
item=True,
97+
{"class": "pt-1 pb-0"},
98+
showcase=x.ui.as_fill_item(
99+
ui.tags.img({"style": "object-fit:contain;"}, src=showcase_img)
101100
),
102101
theme_color=None,
103102
style=f"background-color: {bgcol};",

scripts/htmlDependencies.R

Lines changed: 86 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,70 +2,133 @@
22

33
versions <- list()
44

5-
pak::pkg_install("rstudio/bslib")
6-
# pak::pkg_install("cran::bslib")
5+
# Use local lib path for installing packages so we don't pollute the user's library
6+
withr::local_temp_libpaths()
7+
8+
pak::pkg_install(c("rstudio/bslib@main", "rstudio/shiny@main", "rstudio/htmltools@main"))
9+
# pak::pkg_install(c("cran::bslib", "cran::shiny"))
710

811
versions["shiny_html_deps"] <- as.character(packageVersion("shiny"))
912
versions["bslib"] <- as.character(packageVersion("bslib"))
13+
versions["htmltools"] <- as.character(packageVersion("htmltools"))
14+
15+
pkg_source_version <- function(pkg_name) {
16+
pkg_info <- sessioninfo::package_info(pkg_name)
17+
pkg_info_list <- pkg_info[pkg_info$package == pkg_name, , drop = TRUE]
18+
pkg_info_list$source
19+
}
20+
write_json <- function(file, x, ..., pretty = TRUE, auto_unbox = TRUE) {
21+
jsonlite::write_json(
22+
c(
23+
list("note!" = "This file is auto-generated by scripts/htmlDependencies.R"),
24+
x
25+
),
26+
file,
27+
...,
28+
pretty = pretty, auto_unbox = auto_unbox
29+
)
30+
31+
}
1032

11-
bslib_info <- sessioninfo::package_info("bslib")
12-
bslib_info_list <- bslib_info[bslib_info$package == "bslib", , drop = TRUE]
33+
bslib_version <- pkg_source_version("bslib")
34+
shiny_version <- pkg_source_version("shiny")
35+
htmltools_version <- pkg_source_version("htmltools")
1336

1437
library(htmltools)
1538
library(bslib)
1639

1740
shiny_path <- fs::path(getwd(), "shiny")
1841
www <- fs::path(shiny_path, "www")
19-
if (fs::dir_exists(www)) fs::dir_delete(www)
20-
fs::dir_create(www)
42+
www_shared <- fs::path(www, "shared")
43+
x_www <- fs::path(shiny_path, "experimental", "www")
44+
x_www_components <- fs::path(x_www, "bslib", "components")
2145

2246
# Copy over shiny's www/shared directory
23-
withr::with_tempdir({
24-
cmd <- paste("git clone --depth 1 --branch main https://github.com/rstudio/shiny")
25-
system(cmd)
47+
copy_from_pkg <- function(pkg_name, pkg_dir, local_dir) {
48+
if (fs::dir_exists(local_dir)) fs::dir_delete(local_dir)
49+
fs::dir_create(local_dir)
50+
51+
stopifnot(local_dir != ".")
52+
53+
# Copy other folder into local parent folder
2654
fs::dir_copy(
27-
"shiny/inst/www/shared",
28-
www
55+
system.file(pkg_dir, package = pkg_name),
56+
dirname(local_dir)
2957
)
30-
})
58+
# Rename folder to local folder name
59+
if (basename(local_dir) != basename(pkg_dir)) {
60+
file.rename(
61+
fs::path(dirname(local_dir), basename(pkg_dir)),
62+
local_dir
63+
)
64+
}
65+
# Save pkg version info
66+
write_json(
67+
fs::path(local_dir, "_versions.json"),
68+
list(
69+
package = pkg_name,
70+
version = pkg_source_version(pkg_name)
71+
)
72+
)
73+
}
74+
75+
76+
# Copy over bslib's components directory
77+
copy_from_pkg("bslib", "components", x_www_components)
78+
# Remove unused Sass files
79+
fs::file_delete(
80+
fs::dir_ls(x_www_components, type = "file", regexp = "\\.scss$")
81+
)
82+
# Remove unused tag require
83+
fs::file_delete(fs::path(x_www_components, "tag-require.js"))
84+
85+
# Copy over htmltools's fill directory
86+
copy_from_pkg("htmltools", "fill", fs::path(x_www, "htmltools", "fill"))
87+
88+
89+
90+
91+
# Copy over shiny's www/shared directory
92+
copy_from_pkg("shiny", "www/shared", www_shared)
3193

3294
# Don't need legacy (hopefully)
33-
fs::dir_delete(fs::path(www, "shared", "legacy"))
95+
fs::dir_delete(fs::path(www_shared, "legacy"))
3496
# Don't need dataTables (hopefully)
35-
fs::dir_delete(fs::path(www, "shared", "datatables"))
97+
fs::dir_delete(fs::path(www_shared, "datatables"))
3698

3799
# jQuery will come in via bslib (below)
38100
fs::file_delete(
39-
fs::dir_ls(fs::path(www, "shared"), type = "file", regexp = "jquery")
101+
fs::dir_ls(www_shared, type = "file", regexp = "jquery")
40102
)
41103

42104
# Upgrade to Bootstrap 5 by default
43105
deps <- bs_theme_dependencies(bs_theme(version = 5))
44106
withr::with_options(
45107
list(htmltools.dir.version = FALSE),
46-
ignore <- lapply(deps, copyDependencyToDir, "shiny/www/shared")
108+
ignore <- lapply(deps, copyDependencyToDir, www_shared)
47109
)
48110
bs_ver <- names(bslib::versions())[bslib::versions() == "5"]
49111
versions["bootstrap"] <- bs_ver
50-
jsonlite::write_json(
112+
write_json(
113+
"shiny/www/shared/bootstrap/_version.json",
51114
list(
52-
bslib_version = bslib_info_list$source,
115+
shiny_version = shiny_version,
116+
bslib_version = bslib_version,
117+
htmltools_version = htmltools_version,
53118
bootstrap_version = bs_ver
54-
),
55-
"shiny/www/shared/bootstrap/version.json",
56-
pretty = TRUE, auto_unbox = TRUE
119+
)
57120
)
58121

59122
# This additional bs3compat HTMLDependency() only holds
60123
# the JS shim for tab panel logic, which we don't need
61124
# since we're generating BS5+ tab markup. Note, however,
62125
# we still do have bs3compat's CSS on the page, which
63126
# comes in via the bootstrap HTMLDependency()
64-
fs::dir_delete(fs::path(www, "shared", "bs3compat"))
127+
fs::dir_delete(fs::path(www_shared, "bs3compat"))
65128

66129
requirejs_version <- "2.3.6"
67130
versions["requirejs"] <- requirejs_version
68-
requirejs <- fs::path(www, "shared", "requirejs")
131+
requirejs <- fs::path(www_shared, "requirejs")
69132
fs::dir_create(requirejs)
70133
download.file(
71134
paste0("https://cdnjs.cloudflare.com/ajax/libs/require.js/", requirejs_version, "/require.min.js"),
@@ -94,6 +157,5 @@ cat(
94157
version_vars,
95158
"\n",
96159
version_all,
97-
# paste0("versions = ", versions_txt),
98160
sep = ""
99161
)

setup.cfg

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ dev =
7777
flake8>=6.0.0;python_version>"3.7"
7878
flake8-bugbear>=23.2.13
7979
isort>=5.10.1
80-
pyright>=1.1.305
80+
# pyright produces break changes rapidly. Fix to a particular version
81+
pyright==1.1.308
8182
pre-commit>=2.15.0
8283
wheel
8384
matplotlib

shiny/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""A package for building reactive web applications."""
22

3-
__version__ = "0.3.3.9000"
3+
__version__ = "0.3.3.9001"
44

55
from ._shinyenv import is_pyodide as _is_pyodide
66

shiny/_versions.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
shiny_html_deps = "1.7.4"
1+
shiny_html_deps = "1.7.4.9002"
22
bslib = "0.4.2.9000"
3+
htmltools = "0.5.5.9000"
34
bootstrap = "5.2.2"
45
requirejs = "2.3.6"
56

67
__all__ = (
78
"shiny_html_deps",
89
"bslib",
10+
"htmltools",
911
"bootstrap",
1012
"requirejs",
1113
)

shiny/examples/input_file/app.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import pandas as pd
22

33
from shiny import *
4+
from shiny import experimental as x
45
from shiny.types import FileInfo
56

67
app_ui = ui.page_fluid(
7-
ui.layout_sidebar(
8-
ui.panel_sidebar(
8+
x.ui.layout_sidebar(
9+
x.ui.sidebar(
910
ui.input_file("file1", "Choose CSV File", accept=[".csv"], multiple=False),
1011
ui.input_checkbox("header", "Header", True),
1112
),
12-
ui.panel_main(ui.output_ui("contents")),
13+
ui.output_ui("contents"),
1314
)
1415
)
1516

shiny/examples/layout_sidebar/app.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
import numpy as np
33

44
from shiny import *
5+
from shiny import experimental as x
56

67
app_ui = ui.page_fluid(
7-
ui.layout_sidebar(
8-
ui.panel_sidebar(ui.input_slider("n", "N", min=0, max=100, value=20)),
9-
ui.panel_main(ui.output_plot("plot")),
8+
x.ui.layout_sidebar(
9+
x.ui.sidebar(ui.input_slider("n", "N", min=0, max=100, value=20)),
10+
ui.output_plot("plot"),
1011
),
1112
)
1213

shiny/examples/navset_hidden/app.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
from shiny import *
2+
from shiny import experimental as x
23

34
app_ui = ui.page_fluid(
4-
ui.layout_sidebar(
5-
ui.panel_sidebar(
5+
x.ui.layout_sidebar(
6+
x.ui.sidebar(
67
ui.input_radio_buttons(
78
"controller", "Controller", ["1", "2", "3"], selected="1"
89
)
910
),
10-
ui.panel_main(
11-
ui.navset_hidden(
12-
ui.nav(None, "Panel 1 content", value="panel1"),
13-
ui.nav(None, "Panel 2 content", value="panel2"),
14-
ui.nav(None, "Panel 3 content", value="panel3"),
15-
id="hidden_tabs",
16-
)
11+
ui.navset_hidden(
12+
ui.nav(None, "Panel 1 content", value="panel1"),
13+
ui.nav(None, "Panel 2 content", value="panel2"),
14+
ui.nav(None, "Panel 3 content", value="panel3"),
15+
id="hidden_tabs",
1716
),
1817
)
1918
)

0 commit comments

Comments
 (0)