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
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.12.1.9000"
shiny_html_deps = "1.13.0.9000"
bslib = "0.10.0.9000"
htmltools = "0.5.9.9000"
bootstrap = "5.3.1"
Expand Down
6 changes: 6 additions & 0 deletions shiny/express/ui/_cm_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def sidebar(
gap: Optional[CssUnit] = None,
padding: Optional[CssUnit | list[CssUnit]] = None,
fillable: bool = False,
resizable: bool = True,
**kwargs: TagAttrValue,
) -> RecallContextManager[ui.Sidebar]:
"""
Expand Down Expand Up @@ -127,6 +128,10 @@ def sidebar(
Whether or not the sidebar should be considered a fillable container.
When `True`, the sidebar and its content can use `fill` to consume
available vertical space.
resizable
Whether or not the sidebar can be resized by dragging. When `True` (the
default), a resize handle is shown at the edge of the sidebar that allows
the user to drag to resize the sidebar width.
**kwargs
Named attributes are supplied to the sidebar content container.
"""
Expand All @@ -145,6 +150,7 @@ def sidebar(
gap=gap,
padding=padding,
fillable=fillable,
resizable=resizable,
**kwargs,
),
)
Expand Down
20 changes: 20 additions & 0 deletions shiny/playwright/controller/_layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,26 @@ def expect_handle(self, exists: bool, *, timeout: Timeout = None) -> None:
"""
playwright_expect(self.loc_handle).to_have_count(int(exists), timeout=timeout)

def expect_resizable(self, value: bool, *, timeout: Timeout = None) -> None:
"""
Asserts that the sidebar is resizable or not.

Parameters
----------
value
`True` if the sidebar should be resizable, `False` otherwise.
timeout
The maximum time to wait for the expectation. Defaults to `None`.
"""
if value:
playwright_expect(self.loc).to_have_attribute(
"data-resizable", "", timeout=timeout
)
else:
playwright_expect(self.loc).not_to_have_attribute(
"data-resizable", "", timeout=timeout
)

def expect_open(self, value: bool, *, timeout: Timeout = None) -> None:
"""
Expect the sidebar to be open or closed.
Expand Down
1 change: 1 addition & 0 deletions shiny/ui/_input_code_editor_bundle.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"css",
"diff",
"docker",
"ggsql",
"ini",
"javascript",
"json",
Expand Down
17 changes: 17 additions & 0 deletions shiny/ui/_sidebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ class directly. Instead, supply the :func:`~shiny.ui.sidebar` object to
Whether or not the sidebar should be considered a fillable container.
When `True`, the sidebar and its content can use `fill` to consume
available vertical space.
resizable
Whether or not the sidebar can be resized by dragging. When `True` (the
default), a resize handle is shown at the edge of the sidebar that allows
the user to drag to resize the sidebar width.

Parameters
----------
Expand Down Expand Up @@ -269,6 +273,10 @@ class directly. Instead, supply the :func:`~shiny.ui.sidebar` object to
and right, and the third will be bottom.
* If four, then the values will be interpreted as top, right, bottom, and left
respectively.
resizable
Whether or not the sidebar can be resized by dragging. When `True` (the
default), a resize handle is shown at the edge of the sidebar that allows
the user to drag to resize the sidebar width.
"""

def __init__(
Expand All @@ -288,6 +296,7 @@ def __init__(
gap: Optional[CssUnit] = None,
padding: Optional[CssUnit | list[CssUnit]] = None,
fillable: bool = False,
resizable: bool = True,
):
if isinstance(title, (str, int, float)):
title = tags.header(str(title), class_="sidebar-title")
Expand All @@ -298,6 +307,7 @@ def __init__(
self.gap = as_css_unit(gap)
self.padding = as_css_padding(padding)
self.fillable = fillable
self.resizable = resizable
# User-provided initial open state
self._open: SidebarOpen | None = self._as_open(open)
# Shiny or consumer-provided default open state, change with `_set_default_open()`
Expand Down Expand Up @@ -434,6 +444,7 @@ def _sidebar_tag(self, id: str | None) -> Tag:
"id": id,
"class": "sidebar",
"hidden": "true" if is_hidden_initially else None,
"data-resizable": "" if self.resizable else None,
},
# If the user provided an id, we make the sidebar an input to report state
{"class": "bslib-sidebar-input"} if self.id is not None else None,
Expand Down Expand Up @@ -468,6 +479,7 @@ def sidebar(
gap: Optional[CssUnit] = None,
padding: Optional[CssUnit | list[CssUnit]] = None,
fillable: bool = False,
resizable: bool = True,
**kwargs: TagAttrValue,
) -> Sidebar:
# See [this article](https://rstudio.github.io/bslib/articles/sidebars.html)
Expand Down Expand Up @@ -547,6 +559,10 @@ def sidebar(
Whether or not the sidebar should be considered a fillable container.
When `True`, the sidebar and its content can use `fill` to consume
available vertical space.
resizable
Whether or not the sidebar can be resized by dragging. When `True` (the
default), a resize handle is shown at the edge of the sidebar that allows
the user to drag to resize the sidebar width.
**kwargs
Named attributes are supplied to the sidebar content container.

Expand Down Expand Up @@ -594,6 +610,7 @@ def sidebar(
gap=gap,
padding=padding,
fillable=fillable,
resizable=resizable,
)


Expand Down
2 changes: 1 addition & 1 deletion shiny/www/shared/_version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"package": "shiny",
"version": "1.12.1.9000 (rstudio/shiny@e161f2e4a866c3b3ac1f7d669661786a814641c1)"
"version": "1.13.0.9000 (rstudio/shiny@75a63716e578976965daeadde81af7166a50faac)"
}
4 changes: 2 additions & 2 deletions shiny/www/shared/bootstrap/_version.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"shiny_version": "1.12.1.9000 (rstudio/shiny@e161f2e4a866c3b3ac1f7d669661786a814641c1)",
"bslib_version": "0.10.0.9000 (rstudio/bslib@9bd1a8997e2136a8eed79fe32854f764d54d5cde)",
"shiny_version": "1.13.0.9000 (rstudio/shiny@75a63716e578976965daeadde81af7166a50faac)",
"bslib_version": "0.10.0.9000 (rstudio/bslib@d9b20fee14650e88931161ce7f1f70832d4a850e)",
"htmltools_version": "0.5.9.9000 (rstudio/htmltools@94c450e2798fcb7e5460dd997691a7185b6d7e74)",
"bootstrap_version": "5.3.1"
}
2 changes: 1 addition & 1 deletion shiny/www/shared/bootstrap/bootstrap.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/_version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"package": "bslib",
"version": "0.10.0.9000 (rstudio/bslib@9bd1a8997e2136a8eed79fe32854f764d54d5cde)"
"version": "0.10.0.9000 (rstudio/bslib@d9b20fee14650e88931161ce7f1f70832d4a850e)"
}
2 changes: 1 addition & 1 deletion shiny/www/shared/bslib/components/components.css

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions shiny/www/shared/bslib/components/components.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions shiny/www/shared/bslib/components/components.min.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shiny/www/shared/busy-indicators/busy-indicators.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shiny/www/shared/prism-code-editor/_version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"note!": "Generated by scripts/htmlDependencies.R: do not edit by hand",
"package": "bslib",
"version": "0.10.0.9000 (rstudio/bslib@9bd1a8997e2136a8eed79fe32854f764d54d5cde)"
"version": "0.10.0.9000 (rstudio/bslib@d9b20fee14650e88931161ce7f1f70832d4a850e)"
}
85 changes: 85 additions & 0 deletions shiny/www/shared/prism-code-editor/prism/languages/ggsql.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// ggsql.js — ggsql language for prism-code-editor
//
// AUTO-GENERATED by tools/build_ggsql_grammar.R from the TextMate grammar at:
// https://github.com/posit-dev/ggsql/blob/main/ggsql-vscode/syntaxes/ggsql.tmLanguage.json
// Do not edit by hand.
//
// NOTE: The import path below is a content-hashed internal module of
// prism-code-editor. If bslib updates prism-code-editor, this hash may change.
// Re-run this script to regenerate.

import "./sql.js";
import { l as languages } from "../../index-C1_GGQ8y.js";

var sql = languages.sql;
var ggsql = {};

// Copy SQL tokens
Object.keys(sql).forEach(function(k) { ggsql[k] = sql[k]; });

// ggsql clause keywords
ggsql["ggsql-keyword"] = {
pattern: /\b(?:VISUALISE|VISUALIZE|DRAW|PLACE|SCALE|FACET|PROJECT|LABEL|MAPPING|REMAPPING|SETTING|FILTER|FROM|ORDER|BY|PARTITION|RENAMING|AS|TO|VIA)\b/i,
alias: "keyword",
};

// Geom types
ggsql["ggsql-geom"] = {
pattern: /\b(?:point|line|path|bar|col|area|tile|polygon|ribbon|histogram|density|smooth|boxplot|violin|text|label|segment|arrow|rule|errorbar|rect)\b/,
alias: "builtin",
};

// Scale type modifiers
ggsql["ggsql-scale-type"] = {
pattern: /\b(?:CONTINUOUS|DISCRETE|BINNED|ORDINAL|IDENTITY)\b/i,
alias: "builtin",
};

// Scale type values
ggsql["ggsql-scale-value"] = {
pattern: /\b(?:linear|log|log10|log2|sqrt|reverse|date|datetime|time|viridis|plasma|magma|inferno|cividis|diverging|sequential|identity)\b/,
alias: "string",
};

// Aesthetic names
ggsql["ggsql-aesthetic"] = {
pattern: /\b(?:x|y|xmin|xmax|ymin|ymax|xend|yend|theta|radius|thetamin|thetamax|radiusmin|radiusmax|thetaend|radiusend|color|colour|fill|stroke|opacity|size|shape|linetype|linewidth|width|height|label|family|fontface|hjust|vjust|weight|coef|intercept|offset|density|count|intensity|panel|row|column)\b/,
alias: "attr-name",
};

// Property names
ggsql["ggsql-property"] = {
pattern: /\b(?:type|limits|breaks|labels|expand|direction|na_value|palette|domain|range|free|ncol|missing|xlim|ylim|ratio|angle|clip|start|title|subtitle|x|y|caption|tag|color|colour|fill|size|shape|linetype)\b/,
alias: "property",
};

// Project types
ggsql["ggsql-project"] = {
pattern: /\b(?:cartesian|polar)\b/,
alias: "class-name",
};

// Fat arrow operator
ggsql["ggsql-arrow"] = {
pattern: /=>/,
alias: "operator",
};

// SQL functions (aggregate, window, datetime, string, math, conversion, conditional, JSON, list)
ggsql["function"] = /\b(?:count|sum|avg|min|max|stddev|variance|array_agg|string_agg|group_concat|row_number|rank|dense_rank|ntile|lag|lead|first_value|last_value|nth_value|cume_dist|percent_rank|date_trunc|date_part|datepart|datename|dateadd|datediff|extract|now|current_date|current_time|current_timestamp|getdate|getutcdate|strftime|strptime|make_date|make_time|make_timestamp|concat|substring|substr|left|right|length|len|char_length|lower|upper|trim|ltrim|rtrim|replace|reverse|repeat|lpad|rpad|split_part|string_split|format|printf|regexp_replace|regexp_extract|regexp_matches|abs|ceil|ceiling|floor|round|trunc|truncate|mod|power|sqrt|exp|ln|log|log10|log2|sign|sin|cos|tan|asin|acos|atan|atan2|pi|degrees|radians|random|rand|cast|convert|coalesce|nullif|ifnull|isnull|nvl|try_cast|typeof|if|iff|iif|greatest|least|decode|json|json_extract|json_extract_path|json_extract_string|json_value|json_query|json_object|json_array|json_array_length|to_json|from_json|list|list_value|list_aggregate|array_length|unnest|generate_series|range)(?=\s*\()/i;

// Reorder: ggsql tokens before generic SQL keyword/boolean
var ordered = {};
["comment", "variable", "string", "identifier"].forEach(function(k) {
if (k in ggsql) ordered[k] = ggsql[k];
});
["ggsql-keyword", "ggsql-geom", "ggsql-scale-type", "ggsql-scale-value",
"ggsql-aesthetic", "ggsql-property", "ggsql-project", "ggsql-arrow"].forEach(function(k) {
if (k in ggsql) ordered[k] = ggsql[k];
});
Object.keys(ggsql).forEach(function(k) {
if (!(k in ordered)) ordered[k] = ggsql[k];
});

languages.ggsql = ordered;

62 changes: 53 additions & 9 deletions shiny/www/shared/sass/bslib/components/scss/sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
--_toggle-collective-height: calc(calc(var(--_icon-button-size) + 0.5em) * var(--_js-toggle-count-max-side, 1));

// Resize handle variables
--_resize-handle-width: var(--bslib-sidebar-resize-handle-width, 12px);
--_resize-handle-width: var(--bslib-sidebar-resize-handle-width, 8px);

@media (any-pointer: coarse) {
--_resize-handle-width: var(--bslib-sidebar-resize-handle-width, 26px);
}
--_resize-indicator-color: var(--_sidebar-fg, var(--bs-emphasis-color, black));
--_resize-indicator-color-active: var(--bslib-sidebar-resize-indicator-color-active, var(--bs-primary, #0d6efd));

Expand Down Expand Up @@ -309,20 +313,45 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
width: var(--_resize-handle-width);
left: calc(calc(-1 * var(--_resize-handle-width)) - 2px);
grid-column: 2;
cursor: ew-resize;
pointer-events: none;
user-select: none;
z-index: calc(#{$zindex-dropdown} + 1); // Above toggle button

// Make the handle easier to grab
// Trip area: a narrow strip at the sidebar outer edge that detects the
// mouse crossing the sidebar boundary. Positioned past the handle so
// it doesn't overlap the sidebar scrollbar beneath the handle.
// Expands when .handle-active is added to prevent accidental deactivation.
&::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
// Invisible expanded hit area
left: 0;
right: calc(-1 * var(--_resize-handle-width) - 2px);
z-index: calc(#{$zindex-dropdown} + 1); // Above toggle button
left: 100%;
width: 5px;
pointer-events: auto;
}

// When the mouse crosses the sidebar edge, JS adds .handle-active
// to show the resize cursor and expand the trip area.
&.handle-active {
cursor: ew-resize;

&::before {
left: calc(100% - 10px);
width: 24px;
}
}

// Touch users get the full handle + extended hit area
@media (any-pointer: coarse) {
pointer-events: auto;
cursor: ew-resize;

&::before {
left: 0;
width: auto;
right: calc(-1 * var(--_resize-handle-width) - 2px);
}
}

.resize-indicator {
Expand All @@ -338,14 +367,15 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
transition: all 0.15s ease;
}

&:hover, &:focus, &:active, &:focus {
&:hover, &:focus, &:active, &.handle-active {
.resize-indicator {
opacity: 1;
}
}

&:hover .resize-indicator,
&:focus .resize-indicator {
&:focus .resize-indicator,
&.handle-active .resize-indicator {
width: 3px;
height: 40px;
}
Expand All @@ -370,6 +400,20 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
// Right sidebar resize handle positioning
&.sidebar-right > .bslib-sidebar-resize-handle {
left: 2px;

&::before {
left: auto;
right: 100%;
}

&.handle-active::before {
right: calc(100% - 10px);
}
}

// Hide resize handle when sidebar is not resizable
> .sidebar:not([data-resizable]) ~ .bslib-sidebar-resize-handle {
display: none;
}

// Hide resize handle during transitions and when collapsed
Expand Down
14 changes: 14 additions & 0 deletions shiny/www/shared/sass/bslib/components/scss/toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
justify-content: center;
line-height: 1; // Override Bootstrap's line-height to avoid too much vertical space
height: var(--_toolbar-btn-size); // Keep square icon and label + icon button heights consistent
display: flex; // Prevent Shiny from overwriting flex centering

// Remove margins from action button elements
.action-icon,
.action-label {
margin: 0;
}

&.btn-default:not(.btn-primary):not(.btn-secondary):not(.btn-success):not(.btn-danger):not(.btn-warning):not(.btn-info):not(.btn-light):not(.btn-dark) {
background-color: transparent !important;
Expand Down Expand Up @@ -67,6 +74,13 @@
}
}

// Add spacing between icon and label in buttons with both
.bslib-toolbar-input-button[data-type="both"] {
.action-icon {
margin-right: 0.35rem;
}
}

// Square icon-only buttons
.bslib-toolbar-input-button[data-type="icon"] {
aspect-ratio: 1;
Expand Down
2 changes: 1 addition & 1 deletion shiny/www/shared/sass/preset/bootstrap/bootstrap.min.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion shiny/www/shared/sass/preset/shiny/bootstrap.min.css

Large diffs are not rendered by default.

Loading
Loading