Skip to content

Commit

Permalink
feat(sidebar): Improve collapsible sidebars on mobile (#1084)
Browse files Browse the repository at this point in the history
* fix(safari): Use `-webkit-` prefix for `backdrop-filter`

* fix: Apply main-bg color to background of layout container when sidebar is expanded on mobile

* fix: Sidebar `fg` follows main `bg` color

* feat: Sidebar toggle position on smaller screens (#1085)

* feat: Put collapse toggle in header grid row when collapsible on mobile

* feat: Remove unused sidebar toggle gutter from page-sidebar on <= lg screens

For lg or smaller screens, screen real-estate is limited and we don't need padding on both sides of the main content area, only on the side with the collapse toggle button.

* feat: Avoid main area under the collapse toggle

* feat: Also remove unused sidebar gutter for page_navbar()

* fix: Apply bslib-page-dashboard bg correctly on mobile

Need to set `--_main-bg` at the layout container and reset `background-color` rather than `--_main-bg` at the `.main` level

* chore(sidebar): remove backdrop-filter blur on mobile

* fix: bslib-page-dashboard background color
  • Loading branch information
gadenbuie authored Jul 15, 2024
1 parent b1e0656 commit cfe1ecf
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 44 deletions.
6 changes: 4 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@

* The `open` argument of `layout_sidebar()` now includes the option to place a sidebar that's always open on mobile screens _above the main content_ with `open = list(mobile = "always-above")`. (#1088)

* We've adjusted the sidebar design when collapsible on mobile screens to reduce the space used by the sidebar toggle button and to ensure that main and sidebar content do not scroll underneath the toggle button when the sidebar is collapsed. (#1084)

* The main content area of `page_sidebar()` and `page_navbar()` with a `sidebar` now have a minimum height and width to avoid squashed content in fillable layouts. The minimum height and width are controllable via Sass and CSS variables (see the pull requests for details). (#1057, #1059, #1084)

## Bug fixes

* `toggle_sidebar()` once again correctly closes a sidebar. (@fredericva, #1043)
Expand All @@ -28,8 +32,6 @@

* Improved the appearance of cards with sidebars and headers in the Shiny preset, especially when custom card color themes are used, e.g. with `text-bg-primary` or other Bootstrap utility classes. (#1056)

* The main content area of `page_sidebar()` and `page_navbar()` with a `sidebar` now have a minimum height and width to avoid squashed content in fillable layouts. The minimum height and width are controllable via Sass and CSS variables (see the pull requests for details). (#1057, #1059)

* When `card_body(fillable = FALSE)`, bslib now preserves flow-layout margin bottom settings. (#1073)

* Fixed a bug in `layout_sidebar()` that caused a spurious and confusing error message. (#1081)
Expand Down
25 changes: 18 additions & 7 deletions inst/builtin/bs5/shiny/_rules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -148,22 +148,32 @@ $bslib-checkbox-radio-margin-right: 0.35em !default;
// color of the card header, giving us the white card headers we want, without also
// blocking inheritence via `.text-bg-{theme}` classes or others.
--#{$prefix}card-cap-bg: ;
.card-header, .card-footer {

.card-header,
.card-footer {
font-size: 0.9rem;
}

.card-header {
font-weight: var(--bslib-dashboard-card-header-font-weight);
line-height: 1.375rem;
}
}

// Set the background color of page dashboard class...
.bslib-page-dashboard,
// or of global main content area in a page_navbar() with a global sidebar
.main:has(.tab-content > .bslib-page-dashboard.active) {
// Set the background color of page dashboard class with a sidebar layout...
.bslib-sidebar-layout {
&:has(> .bslib-page-dashboard),
// or of global main content area in a page_navbar() with a global sidebar
&:has(.tab-content > .bslib-page-dashboard.active) {
// or of main area of a page_sidebar()
--_main-bg: var(--bslib-dashboard-main-bg);
;
}
}

// ... or `page_navbar(nav_panel(class = "bslib-page-dashboard"), sidebar = NULL)`
.bslib-page-navbar .tab-content > .bslib-page-dashboard.active {
background-color: var(--bslib-dashboard-main-bg);
// or of main area of a page_sidebar()
--_main-bg: var(--bslib-dashboard-main-bg);
}

.bslib-page-navbar, .bslib-page-dashboard {
Expand Down Expand Up @@ -288,6 +298,7 @@ $icon-classes: ("bi", "fa", "fas", "far", "fab", "material-icons") !default;
#shiny-modal-wrapper:has( ~ .modal-backdrop) .modal {
// Blur the background when the modal has a backdrop
backdrop-filter: blur(2px);
-webkit-backdrop-filter: blur(2px);
}

// Progress Bars & Notifications
Expand Down
2 changes: 1 addition & 1 deletion inst/components/dist/components.css

Large diffs are not rendered by default.

18 changes: 0 additions & 18 deletions inst/components/scss/page_fillable.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,6 @@
> .main > .html-fill-item {
flex: 0 0 auto;
}

&:not(.sidebar-right) {
> .main {
padding-left: var(--_padding-icon);
padding-top: var(--_padding);
}
> .collapse-toggle {
left: calc(var(--_icon-size) / 2);
}
}
&.sidebar-right {
> .main {
padding-right: var(--_padding-icon);
}
> .collapse-toggle {
right: calc(var(--_icon-size) / 2);
}
}
}
}
}
Expand Down
36 changes: 32 additions & 4 deletions inst/components/scss/page_sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,40 @@ $bslib-sidebar-padding: $spacer * 1.5 !default;
margin-bottom: 0;
line-height: var(--#{$prefix}body-line-height);
}
}

@include media-breakpoint-down(lg) {
// Remove symmetrical icon gutter from page-sidebar, i.e. show the gutter on
// the sidebar side only to make room for content.
.bslib-page-sidebar,
.bslib-page-navbar>div {
>.bslib-sidebar-layout.sidebar-collapsed {
&:not(.sidebar-right)>.main {
padding-right: var(--_padding);
}

&.sidebar-right>.main {
padding-left: var(--_padding);
}
}
}
}

@include media-breakpoint-up(sm) {
.bslib-page-main {
min-width: var(--bslib-page-main-min-width, #{$bslib-page-main-min-width});
min-height: var(--bslib-page-main-min-height, #{$bslib-page-main-min-height});
}
// Ensure the page-level main area has a minimum height and width to prevent
// overly squished content in small screens, like IDE preview panels.
.bslib-sidebar-layout {
.bslib-page-main {
min-height: var(--bslib-page-main-min-height, #{$bslib-page-main-min-height});
}

// But only apply the width constraint when the sidebar expanded (i.e.
// not collapsed or in transition) to prevent overlap with toggle button.
&:not(.sidebar-collapsed),
&.transitioning {
.bslib-page-main {
min-width: var(--bslib-page-main-min-width, #{$bslib-page-main-min-width});
}
}
}
}
72 changes: 61 additions & 11 deletions inst/components/scss/sidebar.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// User-facing variables, use for theming
$bslib-sidebar-bg: rgba(var(--bs-emphasis-color-rgb, 0,0,0), 0.05) !default;
$bslib-sidebar-fg: null !default;
$bslib-sidebar-fg: var(--_main-fg) !default;
$bslib-sidebar-toggle-bg: rgba(var(--bs-emphasis-color-rgb, 0,0,0), 0.1) !default;
$bslib-sidebar-border: var(--bs-card-border-width, #{$card-border-width}) solid var(--bs-card-border-color, #{$card-border-color}) !default;

Expand Down Expand Up @@ -33,6 +33,7 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
--_toggle-position-x: calc(-2.5 * var(--_icon-size) - var(--bs-card-border-width, 1px));
--_mobile-max-height: var(--bslib-sidebar-mobile-max-height, var(--bslib-sidebar-max-height-mobile));
--_sidebar-mobile-opacity: var(--bslib-sidebar-mobile-opacity);
--_main-mobile-expanded-opacity: var(--bslib-sidebar-main-mobile-expanded-opacity, 0);
--_sidebar-mobile-max-width: var(--bslib-sidebar-mobile-max-width);
--_sidebar-mobile-box-shadow: var(--bslib-sidebar-mobile-box-shadow);
--_column-main: minmax(0, 1fr);
Expand All @@ -47,7 +48,10 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
grid-template-columns: $bslib-sidebar-column-sidebar var(--_column-main);
position: relative;

@include transition(grid-template-columns ease-in-out var(--_transition-duration));
@include transition(
grid-template-columns ease-in-out var(--_transition-duration),
background-color linear var(--_transition-duration)
);

border: var(--_border);
border-radius: var(--_border-radius);
Expand Down Expand Up @@ -89,7 +93,6 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
border-bottom-right-radius: 0;
color: var(--_sidebar-fg);
background-color: var(--_sidebar-bg);
backdrop-filter: blur(5px);

> .sidebar-content {
display: flex;
Expand All @@ -110,7 +113,7 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
margin-left: calc(-1 * var(--_padding));
margin-right: calc(-1 * var(--_padding));
&:last-child {
margin-bottom: calc(-1 * var(--_padding));
margin-bottom: calc(-1 * var(--_padding));
}
&:not(:last-child) {
margin-bottom: $spacer;
Expand Down Expand Up @@ -315,28 +318,66 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
}

&[data-collapsible-mobile="true"] {
// On mobile, when the sidebar is collapsible, we add an additional row
// for the collapse toggle. This avoid overlapping the toggle and the
// main content when the sidebar is collapsed. When the sidebar expands,
// it takes up the entire layout area.
grid-template-rows: calc(var(--_icon-button-size) + var(--_padding)) 1fr;
> .collapse-toggle {
grid-row: 1 / 2; // top row
}
> .main {
grid-row: 2 / 3; // bottom row
}
> .sidebar {
grid-row: 1 / 3; // whole layout
}
// Sidebar layer has to be lifted up to cover other (nested) sidebars
&:not(.sidebar-collapsed), &.transitioning {
> .sidebar { z-index: $zindex-offcanvas; }
> .collapse-toggle { z-index: $zindex-offcanvas; }
&:not(.sidebar-collapsed),
&.transitioning {
> .sidebar {
z-index: $zindex-offcanvas;
}
> .collapse-toggle {
z-index: $zindex-offcanvas;
}
}

> .collapse-toggle {
top: unset;
position: relative;
align-self: center;
}

// Keep toggle on sidebar side when expanded on mobile
&:not(.sidebar-right) > .collapse-toggle {
left: var(--_icon-size);
right: unset;
justify-self: left;
}

&.sidebar-right > .collapse-toggle {
right: var(--_icon-size);
left: unset;
justify-self: right;
}

> .sidebar {
opacity: var(--_sidebar-mobile-opacity, 1);
max-width: var(--_sidebar-mobile-max-width, 100%);
box-shadow: var(--_sidebar-mobile-box-shadow);
}

// Move scrollable region to .sidebar-content to avoid scrolling sidebar
// elements underneath the collapse toggle
> .sidebar {
margin: 0;
padding-top: var(--_padding-icon);
}
> .sidebar > .sidebar-content {
padding-top: 0;
height: 100%;
overflow-y: auto;
}

// When `max-width` is less than 100%, push it to the appropriate side
Expand All @@ -362,21 +403,30 @@ $bslib-sidebar-column-sidebar: Min(calc(100% - var(--_padding-icon)), var(--_sid
}
}

// Set padding on main area to account for toggle button
// Padding appears in collapse toggle grid region
> .main {
padding-top: var(--_toggle-collective-height);
padding-top: 1px;
padding-left: var(--_padding);
padding-right: var(--_padding);
}

// Soften main area when sidebar is expanded over content
// Hide (or soften) main area when sidebar is expanded over content
> .main {
opacity: 0.33;
opacity: var(--_main-mobile-expanded-opacity);
transition: opacity var(--_transition-easing-x) var(--_transition-duration);
}
&.sidebar-collapsed > .main {
opacity: 1;
}

// Move main bg to layout container so that the collapse toggle grid
// region has the same background as the main area
> .main {
background-color: none;
}
&, &.sidebar-collapsed {
background-color: var(--_main-bg);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion inst/css-precompiled/5/bootstrap.min.css

Large diffs are not rendered by default.

0 comments on commit cfe1ecf

Please sign in to comment.