Skip to content

Commit

Permalink
feat(b-sidebar): add optional backdrop support (#5182)
Browse files Browse the repository at this point in the history
* feat(b-sidebar): add backdrop support

* Update sidebar.js

* Update sidebar.js

* Update _sidebar.scss

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update _sidebar.scss

* Update _sidebar.scss

* Update styles.scss

* Update _sidebar.scss

* Update sidebar.js

* Update sidebar.js

* Update sidebar.js

* lint

* Update sidebar.js

* Update package.json

* Update sidebar.spec.js

* Update sidebar.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update dom.js

* Update sidebar.js

* Update dom.js

* Update modal.js

* Update modal.js

* Update modal.js

* Update dom.js

* Update modal.js

* lint

* Update sidebar.js

* Update sidebar.js

* Update sidebar.js

* Update sidebar.js

* lint

* Update sidebar.js

* Update README.md

* Update README.md

* Update sidebar.js

* Update sidebar.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.spec.js

* Update sidebar.js

* Update sidebar.js

* Update sidebar.js

* Update package.json

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update sidebar.js

* Update _sidebar.scss

* Update README.md

* Update _sidebar.scss

* Update dom.js

Co-authored-by: Jacob Müller <jacob.mueller.elz@gmail.com>
  • Loading branch information
tmorehouse and jacobmllr95 authored Apr 19, 2020
1 parent 83180f1 commit c6375e5
Show file tree
Hide file tree
Showing 8 changed files with 324 additions and 78 deletions.
3 changes: 2 additions & 1 deletion docs/assets/scss/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,8 @@ table#table-transition-example {
}

// `<b-sidebar>` overrides for docs
.b-sidebar {
.b-sidebar-outer,
.b-sidebar{
z-index: 1071;
}

Expand Down
26 changes: 2 additions & 24 deletions src/components/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import identity from '../../utils/identity'
import observeDom from '../../utils/observe-dom'
import { arrayIncludes, concat } from '../../utils/array'
import { getComponentConfig } from '../../utils/config'
import { closest, contains, isVisible, requestAF, select, selectAll } from '../../utils/dom'
import { closest, contains, getTabables, isVisible, requestAF, select } from '../../utils/dom'
import { isBrowser } from '../../utils/env'
import { EVENT_OPTIONS_NO_CAPTURE, eventOn, eventOff } from '../../utils/events'
import { stripTags } from '../../utils/html'
Expand Down Expand Up @@ -37,20 +37,6 @@ const OBSERVER_CONFIG = {
attributeFilter: ['style', 'class']
}

// Query selector to find all tabbable elements
// (includes tabindex="-1", which we filter out after)
const TABABLE_SELECTOR = [
'button',
'[href]:not(.disabled)',
'input',
'select',
'textarea',
'[tabindex]',
'[contenteditable]'
]
.map(s => `${s}:not(:disabled):not([disabled])`)
.join(', ')

// --- Utility methods ---

// Attempt to focus an element, and return true if successful
Expand Down Expand Up @@ -564,14 +550,6 @@ export const BModal = /*#__PURE__*/ Vue.extend({
}
return null
},
// Private method to get a list of all tabable elements within modal content
getTabables() {
// Find all tabable elements in the modal content
// Assumes users have not used tabindex > 0 on elements!
return selectAll(TABABLE_SELECTOR, this.$refs.content)
.filter(isVisible)
.filter(i => i.tabIndex > -1 && !i.disabled)
},
// Private method to finish showing modal
doShow() {
/* istanbul ignore next: commenting out for now until we can test stacking */
Expand Down Expand Up @@ -727,7 +705,7 @@ export const BModal = /*#__PURE__*/ Vue.extend({
) {
return
}
const tabables = this.getTabables()
const tabables = getTabables(this.$refs.content)
const { bottomTrap, topTrap } = this.$refs
if (bottomTrap && target === bottomTrap) {
// If user pressed TAB out of modal into our bottom trab trap element
Expand Down
73 changes: 69 additions & 4 deletions src/components/sidebar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

> Otherwise known as off-canvas or a side drawer, BootstrapVue's custom `<b-sidebar>` component is a
> fixed-position toggleable slide out box, which can be used for navigation, menus, details, etc. It
> can be positioned on either the left (default) or right of the viewport.
> can be positioned on either the left (default) or right of the viewport, with optional backdrop
> support.
## Overview

Expand Down Expand Up @@ -118,8 +119,28 @@ for no shadow.
### Borders

By default, `<b-sidebar>` has no borders. Use
[border utility classes](/docs/reference/utility-classes) to add border(s) to `<b-sidebar>`, or use
CSS style overrides.
[border utility classes](/docs/reference/utility-classes) to add border(s) to `<b-sidebar>` (via the
`sidebar-class` prop <span class="badge badge-secondary">2.12.0+</span>), or use CSS style
overrides.

```html
<template>
<div>
<b-button v-b-toggle.sidebar-border>Toggle Sidebar</b-button>
<b-sidebar id="sidebar-border" sidebar-class="border-right border-danger">
<div class="px-3 py-2">
<p>
Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis
in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
</p>
<b-img src="https://picsum.photos/500/500/?image=54" fluid thumbnail></b-img>
</div>
</b-sidebar>
</div>
</template>

<!-- b-sidebar-border.vue -->
```

### Width

Expand All @@ -142,6 +163,9 @@ slide transition via the `no-slide` prop.
[reduced motion section of our accessibility documentation](/docs/reference/accessibility) for
additional details.

When disabling the slid transition, the fade transition of the [optional backdrop](#backdrop) will
also be disabled.

### Z-index

The sidebar has a default `z-index` defined in SCSS/CSS. In some situations you may need to use a
Expand Down Expand Up @@ -237,6 +261,43 @@ In some instances, you may not want the content rendered when the sidebar is not
the `lazy` prop on `<b-sidebar>`. When `lazy` is `true`, the body and optional footer will _not_ be
rendered (removed from DOM) whenever the sidebar is closed.

### Backdrop

<span class="badge badge-info small">2.12.0+</span>

Add a basic backdrop when the side bar is open via the `backdrop` prop. When set to `true`, the
sidebar will show an opaque backdrop. Clicking on the backdrop will close the sidebar, unless the
`no-close-on-backdrop` prop is set to `true`.

```html
<template>
<div>
<b-button v-b-toggle.sidebar-backdrop>Toggle Sidebar</b-button>
<b-sidebar
id="sidebar-backdrop"
title="Sidebar with backdrop"
backdrop
shadow
>
<div class="px-3 py-2">
<p>
Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis
in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
</p>
<b-img src="https://picsum.photos/500/500/?image=54" fluid thumbnail></b-img>
</div>
</b-sidebar>
</div>
</template>

<!-- b-sidebar-backdrop.vue -->
```

Note that when the sidebar is open, it may still be possible to scroll the body (unlike the
behaviour of modals). When the backdrop in enabled, focus constraint will attempt to keep focus
within the sidebar. Note that in rare circumstances it might be possible for users to move focus to
elements outside of the sidebar.

## Visibility control

### `v-b-toggle` directive
Expand Down Expand Up @@ -285,7 +346,11 @@ reader and keyboard-only users. When the sidebar is closed, the element that pre
before the sidebar was opened will be re-focused.

When the sidebar is open, users can press <kbd>Esc</kbd> to close the sidebar. To disable this
feature, set the `no-close-on-esc` prop to `true`.
feature, set the `no-close-on-esc` prop to `true`. with the backdrop enabled, you can use the prop
`no-close-on-backdrop` to disable the close on backdrop click feature.

When the `backdrop` prop is `true`, the sidebar will attempt to constrain focus within the sidebar,
and the sidebar will have the attribute `aria-modal="true"` set.

When you have hidden the header, or do not have a title for the sidebar, set either `aria-label` to
a string that describes the sidebar, or set `aria-labelledby` to an ID of an element that contains
Expand Down
24 changes: 22 additions & 2 deletions src/components/sidebar/_sidebar.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
.b-sidebar-outer {
position: fixed !important;
top: 0;
left: 0;
right: 0;
height: 0;
overflow: visible;
z-index: $b-sidebar-zindex;
}

.b-sidebar-backdrop {
position: fixed !important;
top: 0;
left: 0;
z-index: -1;
width: 100vw;
height: 100vh;
background-color: #000;
opacity: 0.5;
}

.b-sidebar {
display: flex;
flex-direction: column;
position: fixed !important;
top: 0;
bottom: 0;
height: 100vh;
width: $b-sidebar-width;
max-width: 100% !important;
height: 100vh !important;
margin: 0 !important;
outline: 0;
transform: translateX(0);
z-index: $b-sidebar-zindex;

&.slide {
transition: transform $b-sidebar-transition-duration ease-in-out;
Expand Down
15 changes: 15 additions & 0 deletions src/components/sidebar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@
"prop": "closeLabel",
"description": "`aria-label` to apply to the built-in close button. Defaults to 'Close'"
},
{
"prop": "sidebarClass",
"version": "2.12.0",
"description": "Class, or classes, to apply to the sidebar content wrapper"
},
{
"prop": "headerClass",
"description": "Class, or classes, to apply to the built in header. Has no effect if prop `no-header` is set"
Expand All @@ -66,6 +71,11 @@
"prop": "footerClass",
"description": "Class, or classes, to apply to the optional `footer` slot"
},
{
"prop": "backdrop",
"version": "2.12.0",
"description": "When `true`, shows a backdrop when the sidebar is open"
},
{
"prop": "lazy",
"description": "When set to `true`, the content of the sidebar will only be rendered while the sidebar is open"
Expand All @@ -82,6 +92,11 @@
"prop": "noCloseOnEsc",
"description": "When set to `true`, disables closing the sidebar when the user presses ESC"
},
{
"prop": "noCloseOnBackdrop",
"version": "2.12.0",
"description": "When set to `true`, disables closing the sidebar when the user clicks on the backdrop. Requires that the prop `backdrop` be set"
},
{
"prop": "noCloseOnRouteChange",
"description": "When set to `true`, disables closing of the sidebar on route change"
Expand Down
Loading

0 comments on commit c6375e5

Please sign in to comment.