Skip to content
Permalink
Browse files

feat(b-nav): add card header support (#3883)

  • Loading branch information...
tmorehouse committed Aug 14, 2019
1 parent 8f8b7aa commit 4046a5307733ede9c21091600d4ba19e4bfcdf8f
@@ -495,6 +495,63 @@ assistive technologies – such as screen readers. Ensure that information denot
either obvious from the content itself (e.g. the visible text), or is included through alternative
means, such as additional text hidden with the `.sr-only` class.

## Nav integration

Integrate [`<b-nav>`](/docs/components/nav) into card headers easily.

**Using the `header` slot**:

```html
<div>
<b-card title="Card Title" body-class="text-center">
<b-nav slot="header" card-header tabs>
<b-nav-item active>Active</b-nav-item>
<b-nav-item>Inactive</b-nav-item>
<b-nav-item disabled>Disabled</b-nav-item>
</b-nav>

<b-card-text>
With supporting text below as a natural lead-in to additional content.
</b-card-text>

<b-button variant="primary">Go somewhere</b-button>
</b-card>
</div>

<!-- card-with-nav-header-slot.vue -->
```

**Using `<b-card-header>` sub-component:**

```html
<div>
<b-card no-body>
<b-card-header>
<b-nav card-header tabs>
<b-nav-item active>Active</b-nav-item>
<b-nav-item>Inactive</b-nav-item>
<b-nav-item disabled>Disabled</b-nav-item>
</b-nav>
</b-card-header>

<b-card-body class="text-center">
<b-card-title>Card Title</b-card-title>

<b-card-text>
With supporting text below as a natural lead-in to additional content.
</b-card-text>

<b-button variant="primary">Go somewhere</b-button>
</b-card-body>
</b-card>
</div>

<!-- card-with-nav-header-component.vue -->
```

For more information on using `<b-nav>` in card headers, refer to the
[Navs documentation](/docs/components/nav).

## Card groups

In addition to styling the content within cards, BootstrapVue includes a `<b-card-group>` component
@@ -170,10 +170,10 @@ Use `<b-nav-item-dropdown>` to place dropdown items within your nav.
toggle-class="nav-link-custom"
right
>
<b-dropdown-item>one</b-dropdown-item>
<b-dropdown-item>two</b-dropdown-item>
<b-dropdown-item>One</b-dropdown-item>
<b-dropdown-item>Two</b-dropdown-item>
<b-dropdown-divider></b-dropdown-divider>
<b-dropdown-item>three</b-dropdown-item>
<b-dropdown-item>Three</b-dropdown-item>
</b-nav-item-dropdown>
</b-nav>
</div>
@@ -220,6 +220,96 @@ render the menu contents only when it is shown by setting the `lazy` prop to tru
See the [`<b-tabs>`](/docs/components/tabs) component for creating tabbable panes of local content
(not suited for navigation).

## Card integration

Use a `<b-nav>` in a [`<b-card>`](/docs/components/card) header, by enabling the `card-header` prop
on `<b-nav>` and setting either the `pills` or `tabs` props:

**Tabs style:**

```html
<div>
<b-card title="Card Title" body-class="text-center">
<b-nav slot="header" card-header tabs>
<b-nav-item active>Active</b-nav-item>
<b-nav-item>Inactive</b-nav-item>
<b-nav-item disabled>Disabled</b-nav-item>
<b-nav-item-dropdown text="Dropdown" right>
<b-dropdown-item>One</b-dropdown-item>
<b-dropdown-item>Two</b-dropdown-item>
<b-dropdown-item>Three</b-dropdown-item>
</b-nav-item-dropdown>
</b-nav>

<b-card-text>
With supporting text below as a natural lead-in to additional content.
</b-card-text>

<b-button variant="primary">Go somewhere</b-button>
</b-card>
</div>

<!-- nav-card-tabs.vue -->
```

**Pill style:**

```html
<div>
<b-card title="Card Title" body-class="text-center">
<b-nav slot="header" card-header pills>
<b-nav-item active>Active</b-nav-item>
<b-nav-item>Inactive</b-nav-item>
<b-nav-item disabled>Disabled</b-nav-item>
<b-nav-item-dropdown text="Dropdown" right>
<b-dropdown-item>One</b-dropdown-item>
<b-dropdown-item>Two</b-dropdown-item>
<b-dropdown-item>Three</b-dropdown-item>
</b-nav-item-dropdown>
</b-nav>

<b-card-text>
With supporting text below as a natural lead-in to additional content.
</b-card-text>

<b-button variant="primary">Go somewhere</b-button>
</b-card>
</div>

<!-- nav-card-pills.vue -->
```

**Plain style:**

The `card-header` prop is only needed when you are applying `tabs` or `pills` style.

```html
<div>
<b-card title="Card Title" body-class="text-center">
<b-nav slot="header">
<b-nav-item active>Active</b-nav-item>
<b-nav-item>Inactive</b-nav-item>
<b-nav-item disabled>Disabled</b-nav-item>
<b-nav-item-dropdown text="Dropdown" right>
<b-dropdown-item>One</b-dropdown-item>
<b-dropdown-item>Two</b-dropdown-item>
<b-dropdown-item>Three</b-dropdown-item>
</b-nav-item-dropdown>
</b-nav>

<b-card-text>
With supporting text below as a natural lead-in to additional content.
</b-card-text>

<b-button variant="primary">Go somewhere</b-button>
</b-card>
</div>

<!-- nav-card-plain.vue -->
```

The `card-header` prop has no effect if the `<b-nav>` is `vertical`.

## Accessibility

If you're using `<b-nav>` to provide a navigation bar, be sure to add a `role="navigation"` to the
@@ -35,6 +35,11 @@ export const props = {
small: {
type: Boolean,
default: false
},
cardHeader: {
// Set to true if placing in a card header
type: Boolean,
default: false
}
}

@@ -58,7 +63,9 @@ export const BNav = /*#__PURE__*/ Vue.extend({
staticClass: 'nav',
class: {
'nav-tabs': props.tabs,
'nav-pills': props.pills,
'nav-pills': props.pills && !props.tabs,
'card-header-tabs': !props.vertical && props.cardHeader && props.tabs,
'card-header-pills': !props.vertical && props.cardHeader && props.pills && !props.tabs,
'flex-column': props.vertical,
'nav-fill': !props.vertical && props.fill,
'nav-justified': !props.vertical && props.justified,
@@ -179,4 +179,36 @@ describe('nav', () => {
expect(wrapper.classes().length).toBe(2)
expect(wrapper.text()).toBe('')
})

it('applies card-header-tabs class when tabs and card-header props set', async () => {
const wrapper = mount(BNav, {
propsData: {
tabs: true,
cardHeader: true
}
})

expect(wrapper.is('ul')).toBe(true)
expect(wrapper.classes()).toContain('nav')
expect(wrapper.classes()).toContain('nav-tabs')
expect(wrapper.classes()).toContain('card-header-tabs')
expect(wrapper.classes().length).toBe(3)
expect(wrapper.text()).toBe('')
})

it('applies card-header-pills class when pills and card-header props set', async () => {
const wrapper = mount(BNav, {
propsData: {
pills: true,
cardHeader: true
}
})

expect(wrapper.is('ul')).toBe(true)
expect(wrapper.classes()).toContain('nav')
expect(wrapper.classes()).toContain('nav-pills')
expect(wrapper.classes()).toContain('card-header-pills')
expect(wrapper.classes().length).toBe(3)
expect(wrapper.text()).toBe('')
})
})
@@ -232,17 +232,10 @@ export const BTabs = /*#__PURE__*/ Vue.extend({
// This computed prop is sniffed by the tab child
return !this.noFade
},
navStyle() {
return this.pills ? 'pills' : 'tabs'
},
localNavClass() {
const classes = []
if (this.card) {
if (this.vertical) {
classes.push('card-header', 'h-100', 'border-bottom-0', 'rounded-0')
} else {
classes.push(`card-header-${this.navStyle}`)
}
if (this.card && this.vertical) {
classes.push('card-header', 'h-100', 'border-bottom-0', 'rounded-0')
}
return [...classes, this.navClass]
}
@@ -640,7 +633,8 @@ export const BTabs = /*#__PURE__*/ Vue.extend({
tabs: !this.noNavStyle && !this.pills,
pills: !this.noNavStyle && this.pills,
vertical: this.vertical,
small: this.small
small: this.small,
cardHeader: this.card && !this.vertical
}
},
[this.normalizeSlot('tabs-start') || h(), buttons, this.normalizeSlot('tabs-end') || h()]
@@ -30,7 +30,7 @@ as well.
<template>
<div>
<b-card no-body>
<b-nav pills slot="header" v-b-scrollspy:nav-scroller>
<b-nav pills card-header slot="header" v-b-scrollspy:nav-scroller>
<b-nav-item href="#fat" @click="scrollIntoView">@fat</b-nav-item>
<b-nav-item href="#mdo" @click="scrollIntoView">@mdo</b-nav-item>
<b-nav-item-dropdown text="Dropdown 1,2,3" right-alignment>
@@ -111,15 +111,15 @@ also be active. Scroll the area next to the navbar and watch the active class ch
<b-col cols="4">
<b-navbar v-b-scrollspy:scrollspy-nested class="flex-column">
<b-navbar-brand href="#">Navbar</b-navbar-brand>
<b-nav pills class="flex-column">
<b-nav pills vertical>
<b-nav-item href="#item-1">Item 1</b-nav-item>
<b-nav pills class="flex-column">
<b-nav pills vertical>
<b-nav-item class="ml-3 my-1" href="#item-1-1">Item 1-1</b-nav-item>
<b-nav-item class="ml-3 my-1" href="#item-1-2">Item 1-2</b-nav-item>
</b-nav>
<b-nav-item href="#item-2">Item 2</b-nav-item>
<b-nav-item href="#item-3">Item 3</b-nav-item>
<b-nav pills class="flex-column">
<b-nav pills vertical>
<b-nav-item class="ml-3 my-1" href="#item-3-1">Item 3-1</b-nav-item>
<b-nav-item class="ml-3 my-1" href="#item-3-2">Item 3-2</b-nav-item>
</b-nav>

0 comments on commit 4046a53

Please sign in to comment.
You can’t perform that action at this time.