Skip to content
Permalink
Browse files
feat(v-b-toggle): support specifying target ID via directive argument…
…, and array of target IDs via directive value (closes #4834) (#5336)

Co-authored-by: Jacob Müller
  • Loading branch information
tmorehouse committed May 11, 2020
1 parent 562be51 commit 260ef7259e46d343823767374322db0ae3a74803
Showing 11 changed files with 515 additions and 215 deletions.
@@ -1,7 +1,8 @@
# Collapse

> Easily toggle visibility of almost any content on your pages. Includes support for making
> accordions.
> Easily toggle visibility of almost any content on your pages in a vertically collapsing container.
> Includes support for making accordions. Visibility can be easily toggled with our
> [`v-b-toggle` directive](/docs/directives/toggle), or via `v-model`.
```html
<div>
@@ -42,6 +43,9 @@ Other elements can easily toggle `<b-collapse>` components using the
<!-- b-collapse-usage.vue -->
```

See the [`v-b-toggle` directive documentation](/docs/directives/toggle) for detailed usage
information.

## Initial visibility (start expanded)

To make the `<b-collapse>` show initially, set the `visible` prop:
@@ -104,12 +108,20 @@ support.
## Trigger multiple collapse elements

You can even collapse multiple `<b-collapse>` components via a single `v-b-toggle` by providing
multiple target IDs using modifiers:
multiple target IDs using _modifiers_.

You can also pass multiple target IDs via the directive _value_ in BootstrapVue release v2.14.0+.

```html
<div>
<!-- Single button triggers two "<b-collapse>" components -->
<b-button v-b-toggle.collapse-a.collapse-b>Toggle Both Collapse A and B</b-button>
<!-- Via multiple directive modifiers -->
<b-button v-b-toggle.collapse-a.collapse-b>Toggle Collapse A and B</b-button>

<!-- Via space separated string of IDs passed to directive value -->
<b-button v-b-toggle="'collapse-a collapse-b'">Toggle Collapse A and B</b-button>

<!-- Via array of string IDs passed to directive value -->
<b-button v-b-toggle="['collapse-a', 'collapse-b']">Toggle Collapse A and B</b-button>

<!-- Elements to collapse -->
<b-collapse id="collapse-a" class="mt-2">
@@ -205,14 +217,15 @@ at a time.

When using the `v-b-toggle` directive, the class `collapsed` will automatically be placed on the
trigger element when the collapse is closed, and removed when open. You can use this class to
display or hide content within the toggle via custom CSS:
display or hide content within the toggle via custom CSS. As of BootstrapVue 2.14.0, the class
`not-collapsed` will be applied when the target(s) are not closed.

**Example HTML markup:**

```html
<div>
<b-button v-b-toggle.my-collapse>
<span class="when-opened">Close</span> <span class="when-closed">Open</span> My Collapse
<b-button v-b-toggle:my-collapse>
<span class="when-open">Close</span><span class="when-closed">Open</span> My Collapse
</b-button>
<b-collapse id="my-collapse">
<!-- Content here -->
@@ -223,8 +236,8 @@ display or hide content within the toggle via custom CSS:
**Example Custom CSS:**

```css
.collapsed > .when-opened,
:not(.collapsed) > .when-closed {
.collapsed > .when-open,
.not-collapsed > .when-closed {
display: none;
}
```
@@ -12,6 +12,11 @@
"directive": "VBModal",
"description": "Directive for opening a modal by ID",
"expression": "String",
"arg": {
"pattern": "[a-zA-Z][a-zA-Z0-9_\\-]*",
"description": "Modal ID to open",
"required": false
},
"modifiers": [
{
"name": "{modalId}",
@@ -281,6 +281,12 @@ will reverse the placement of the toggler.
See the first example on this page for reference, and also refer to
[`<b-collapse>`](/docs/components/collapse) for details on the collapse component.

Besides being used to control a collapse, the `<b-navbar-toggle>` can also be used to toggle
visibility of the [`<b-sidebar>`](/docs/components/sidebar) component. Just specify the ID of the
`<b-sidebar>` via the `target` prop.

Internally, `<b-navbar-toggle>` uses the [`v-b-toggle` directive](/docs/directives/toggle).

#### Custom navbar toggle

`<b-navbar-toggle>` renders the default Bootstrap v4 _hamburger_ (which is a background SVG image).
@@ -320,9 +326,13 @@ Navbars are hidden by default when printing. Force them to be printed by setting

## See also

- [`<b-collapse>` component](/docs/components/collapse)
- [`<b-sidebar>` component](/docs/components/sidebar)
- [`v-b-toggle` directive](/docs/directives/toggle)
- [`<b-nav>` documentation](/docs/components/nav) for additional components and sub-component
aliases

Refer to the [Router support](/docs/reference/router-links) reference page for router-link specific
props.

Also see [`<b-nav>`](/docs/components/nav) for additional components and sub-component aliases.

<!-- Component reference added automatically from component package.json -->
@@ -1,15 +1,8 @@
import Vue from '../../utils/vue'
import { getComponentConfig } from '../../utils/config'
import { toString } from '../../utils/string'
import listenOnRootMixin from '../../mixins/listen-on-root'
import normalizeSlotMixin from '../../mixins/normalize-slot'
import { EVENT_TOGGLE, EVENT_STATE, EVENT_STATE_SYNC } from '../../directives/toggle/toggle'

// TODO:
// Switch to using `VBToggle` directive, will reduce code footprint
// Although the `click` event will no longer be cancellable
// Instead add `disabled` prop, and have `VBToggle` check element
// disabled state
import { VBToggle, EVENT_STATE, EVENT_STATE_SYNC } from '../../directives/toggle/toggle'

// --- Constants ---

@@ -20,6 +13,7 @@ const CLASS_NAME = 'navbar-toggler'
// @vue/component
export const BNavbarToggle = /*#__PURE__*/ Vue.extend({
name: NAME,
directives: { BToggle: VBToggle },
mixins: [listenOnRootMixin, normalizeSlotMixin],
props: {
label: {
@@ -42,12 +36,12 @@ export const BNavbarToggle = /*#__PURE__*/ Vue.extend({
},
methods: {
onClick(evt) {
// Emit courtesy `click` event
this.$emit('click', evt)
if (!evt.defaultPrevented) {
this.emitOnRoot(EVENT_TOGGLE, this.target)
}
},
handleStateEvt(id, state) {
// We listen for state events so that we can pass the
// boolean expanded state to the default scoped slot
if (id === this.target) {
this.toggleState = state
}
@@ -59,12 +53,8 @@ export const BNavbarToggle = /*#__PURE__*/ Vue.extend({
'button',
{
staticClass: CLASS_NAME,
attrs: {
type: 'button',
'aria-label': this.label,
'aria-controls': this.target,
'aria-expanded': toString(expanded)
},
directives: [{ name: 'BToggle', value: this.target }],
attrs: { type: 'button', 'aria-label': this.label },
on: { click: this.onClick }
},
[
@@ -23,7 +23,9 @@ describe('navbar-toggle', () => {
})

expect(wrapper.classes()).toContain('navbar-toggler')
expect(wrapper.classes().length).toBe(1)
// Class added by v-b-toggle
expect(wrapper.classes()).toContain('collapsed')
expect(wrapper.classes().length).toBe(2)

wrapper.destroy()
})
@@ -12,7 +12,8 @@ You can place almost any content inside the `<b-sidebar>`
[vertical navs](/docs/components/nav#vertical-variation).

The component supports a header and built in close button, of which you can optionally disable and
provide your own header (if needed), and can be easily toggled with our `v-b-toggle` directive.
provide your own header (if needed), and can be easily toggled with our
[`v-b-toggle` directive](/docs/directives/toggle).

The component has minimal default styling, which provides you with great flexibility in laying out
the content of the sidebar.
@@ -302,9 +303,9 @@ elements outside of the sidebar.

### `v-b-toggle` directive

Using the `v-b-toggle` directive is the preferred method for _opening_ the sidebar, as it
automatically handles applying the `aria-controls` and `aria-expanded` accessibility attributes on
the trigger element.
Using the [`v-b-toggle` directive](/docs/directive/toggle) is the preferred method for _opening_ the
sidebar, as it automatically handles applying the `aria-controls` and `aria-expanded` accessibility
attributes on the trigger element.

The majority of examples on this page use the `v-b-toggle` directive.

@@ -369,5 +370,6 @@ to the [theming documentation](/docs/reference/theming) for additional details.

## See also

- [`v-b-toggle` directive](/docs/directives/toggle)
- [`<b-collapse>` component](/docs/components/collapse)
- [`<b-button-close>` component](/docs/components/button#comp-ref-b-button-close)
@@ -1,7 +1,7 @@
# Toggle

> `v-b-toggle` is a light-weight directive for toggling the visibility of collapses and sidebars,
> and includes automated accessibility handling.
> and includes automated [WAI-ARIA accessibility](/docs/reference/accessibility) attribute handling.
## Overview

@@ -12,18 +12,27 @@ visibility state of the [`<b-collapse>`](/docs/components/collapse) and
Besides toggling the visibility of the target component, the directive automatically updates ARIA
accessibility attributes on the element it is applied to so that they reflect the visibility state
of the target component. Refer to the [Accessibility section](#accessibility) below for additional
details.
details and caveats.

## Directive syntax and usage

The directive is applied to the element or component that triggers the visibility of hte target. The
target component can be specified (via ID) as either a directive modifier(s) or as a string passed
to as the directive value:

- `v-b-toggle.my-collapse` - the directive modifier (multiple targets allowed)
- `v-b-toggle="'my-collapse'"` - the directive value (as a String, single target only)

Modifiers and the value can be used at the same time.
target component can be specified (via its ID) as either a directive modifier(s), the directive
argument, or as a string/array passed to as the directive value:

- `v-b-toggle.my-collapse` - the directive modifier (multiple targets allowed, each modifier is a
target ID)
- `v-b-toggle:my-collapse` - the directive argument
([Vue dynamic argument](https://vuejs.org/v2/guide/syntax.html#Dynamic-Arguments) is supported)
<span class="badge badge-info small" aria-label="Available in BootstrapVue v2.14.0+">v2.14.0+</span>
- `v-b-toggle="'my-collapse'"` - the directive value as a string ID
- `v-b-toggle="'my-collapse1 my-collapse2'"` - the directive value as a space separated string of
IDs
<span class="badge badge-info small" aria-label="Available in BootstrapVue v2.14.0+">v2.14.0+</span>
- `v-b-toggle="['my-collapse1', 'my-collapse2']"` - the directive value as an array of string IDs
<span class="badge badge-info small" aria-label="Available in BootstrapVue v2.14.0+">v2.14.0+</span>

Modifiers, argument, and the value can be used at the same time when targeting multiple components.

### Example usage

@@ -53,26 +62,59 @@ Modifiers and the value can be used at the same time.
<!-- v-b-toggle-directive.vue -->
```

## Hiding and showing content in the toggle trigger element

When using the `v-b-toggle` directive, the class `collapsed` will automatically be placed on the
trigger element when the target component is closed, and removed when open. As of BootstrapVue
`2.14.0`, the class `not-collapsed` will be applied when the target is _not_ closed.

**Example HTML markup:**

```html
<div>
<b-button v-b-toggle:my-collapse>
<span class="when-open">Close</span><span class="when-closed">Open</span> My Collapse
</b-button>
<b-collapse id="my-collapse">
<!-- Content here -->
</b-collapse>
</div>
```

**Example Custom CSS:**

```css
.collapsed > .when-open,
.not-collapsed > .when-closed {
display: none;
}
```

## Accessibility

The directive, for accessibility reasons, should be placed on an clickable interactive element such
as a `<button>` or `<b-button>`, which can easily be accessed by keyboard-only users and screen
reader users. Elements that do not natively have an accessibility role of `button` will have the
attributes `role="button"` and `tabindex="0"` applied, and will have the appropriate click and
keyboard handlers instantiated. Therefore it is _highly recommended_ to _not_ place the directive on
form controls other than buttons.
reader users. Elements that do not natively have an accessibility role of `button` (or `link`) will
have the attributes `role="button"` and `tabindex="0"` applied, and will have the appropriate click
handler instantiated. Therefore it is _highly recommended_ to _not_ place the directive on form
controls other than buttons.

The directive applies, and dynamically updates, the following ARIA attributes on the trigger
element:

- `aria-controls` - the ID of the collapse or sidebar component(s) being toggled
- `aria-expanded` - the visibility state of the collapse or sidebar
- `aria-controls` - the ID(s) of the collapse or sidebar component(s) being toggled
- `aria-expanded` - the visibility state of the collapse or sidebar (see the
[caveats section](#caveats-with-multiple-targets) below)

### Caveats with multiple targets

When the target component is _not_ expanded, the trigger element will have the class `collapsed`
applied. When the target component is expanded, the `collapsed` class will be removed from the
trigger element.
When multiple targets are specified, the value of the `aria-expanded` attribute may not be correct
if the individual target components can have their collapsed state controlled independently (either
via `v-model`, other controls with `v-b-toggle` directive, or CSS visibility).

## See also

- [`<b-collapse>`](/docs/components/collapse) Collapsible content with accordion support
- [`<b-sidebar>`](/docs/components/sidebar) Off-canvas sidebar
- [`<b-navbar-toggle>`](/docs/components/navbar#b-navbar-toggle-and-b-collapse-is-nav) Navbar
hamburger toggle button (based on `v-b-toggle` directive)
@@ -5,7 +5,16 @@
"title": "Toggle",
"description": "A light-weight directive for toggling visibility state for collapses and sidebars by ID. It automatically handles the accessibility attributes on the trigger element.",
"directive": "VBToggle",
"expression": "String",
"expression": [
"String",
"Array"
],
"arg": {
"version": "2.14.0",
"pattern": "[a-zA-Z][a-zA-Z0-9_\\-]*",
"description": "ID of component to toggle",
"required": false
},
"modifiers": [
{
"name": "{componentId}",

0 comments on commit 260ef72

Please sign in to comment.