Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3a97253
feat(b-calendar, b-form-datepicker): add optional decade navigation b…
tmorehouse Apr 6, 2020
8c00ff9
Update date.spec.js
tmorehouse Apr 6, 2020
a9a7eac
lint
tmorehouse Apr 6, 2020
f41ce8b
Update config-defaults.js
tmorehouse Apr 6, 2020
5ba9436
Update calendar.js
tmorehouse Apr 6, 2020
3efa175
Update config-defaults.js
tmorehouse Apr 6, 2020
d4f6c16
Update calendar.spec.js
tmorehouse Apr 6, 2020
922f032
Update calendar.spec.js
tmorehouse Apr 6, 2020
217aa6a
Update calendar.spec.js
tmorehouse Apr 6, 2020
6eaa3f3
Update form-datepicker.js
tmorehouse Apr 6, 2020
e7ad427
Update calendar.js
tmorehouse Apr 6, 2020
893deaa
Update package.json
tmorehouse Apr 6, 2020
4a67035
Update package.json
tmorehouse Apr 6, 2020
a257a17
Update README.md
tmorehouse Apr 7, 2020
113ea40
Update README.md
tmorehouse Apr 7, 2020
a665e92
Update README.md
tmorehouse Apr 7, 2020
53ae87c
Update README.md
tmorehouse Apr 7, 2020
e0f7efd
Update README.md
tmorehouse Apr 7, 2020
152c75b
Merge branch 'dev' into calendar-decade
tmorehouse Apr 7, 2020
baa953a
Update date.js
tmorehouse Apr 7, 2020
3f405d7
Update README.md
tmorehouse Apr 7, 2020
baa7a96
Update README.md
tmorehouse Apr 7, 2020
a11cf19
Update calendar.js
tmorehouse Apr 7, 2020
f00712d
Update README.md
tmorehouse Apr 7, 2020
2096f74
lint
tmorehouse Apr 7, 2020
37e9217
lint
tmorehouse Apr 7, 2020
e6e50ef
Update README.md
tmorehouse Apr 7, 2020
f80f522
Update README.md
tmorehouse Apr 7, 2020
ebcc5e8
Update calendar.js
jacobmllr95 Apr 7, 2020
787e693
Prettify
jacobmllr95 Apr 7, 2020
039a6c6
Update README.md
jacobmllr95 Apr 7, 2020
ca26b84
Unify key name spacing
jacobmllr95 Apr 7, 2020
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 src/components/avatar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,4 +330,4 @@ Avatars are based upon `<b-badge>` and `<b-button>` components, and as such, rel
`badge-*` and `btn-*` variant classes, as well as the `rounded-*`
[utility classes](/docs/reference/utility-classes).

`<b-avatar>` also requires BootstrapVue's custom CSS for proper styling.
`<b-avatar>` also requires BootstrapVue's custom CSS for proper styling.
12 changes: 6 additions & 6 deletions src/components/button-toolbar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,12 @@ Enable optional keyboard navigation by setting the prop `key-nav`.

| Keypress | Action |
| --------------------------------------------------------------------- | ----------------------------------------------------- |
| <kbd>LEFT</kbd> or <kbd>UP</kbd> | Move to the previous non-disabled item in the toolbar |
| <kbd>RIGHT</kbd> or <kbd>DOWN</kbd> | Move to the next non-disabled item in the toolbar |
| <kbd>SHIFT</kbd>+<kbd>LEFT</kbd> or <kbd>SHIFT</kbd>+<kbd>UP</kbd> | Move to the first non-disabled item in the toolbar |
| <kbd>SHIFT</kbd>+<kbd>RIGHT</kbd> or <kbd>SHIFT</kbd>+<kbd>DOWN</kbd> | Move to the last non-disabled item in the toolbar |
| <kbd>TAB</kbd> | Move to the next control on the page |
| <kbd>SHIFT</kbd>+<kbd>TAB</kbd> | Move to the previous control on the page |
| <kbd>Left</kbd> or <kbd>Up</kbd> | Move to the previous non-disabled item in the toolbar |
| <kbd>Right</kbd> or <kbd>Down</kbd> | Move to the next non-disabled item in the toolbar |
| <kbd>Shift</kbd>+<kbd>Left</kbd> or <kbd>Shift</kbd>+<kbd>Up</kbd> | Move to the first non-disabled item in the toolbar |
| <kbd>Shift</kbd>+<kbd>Right</kbd> or <kbd>Shift</kbd>+<kbd>Down</kbd> | Move to the last non-disabled item in the toolbar |
| <kbd>Tab</kbd> | Move to the next control on the page |
| <kbd>Shift</kbd>+<kbd>Tab</kbd> | Move to the previous control on the page |

**Caution:** If you have text or text-like inputs in your toolbar, leave keyboard navigation off, as
it is not possible to use key presses to jump out of a text (or test-like) inputs.
Expand Down
2 changes: 1 addition & 1 deletion src/components/button/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

## Overview

BootstrapVue's `<b-button>` component generates either a `<button>` element, `<a>` element, or
BootstrapVue's `<b-button>` component generates either a `<button>` element, `<a>` element, or
`<router-link>` component with the styling of a button.

```html
Expand Down
34 changes: 33 additions & 1 deletion src/components/calendar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,18 @@ formatted in the locale's language.
You can hide this header via the `hide-header` prop. Note this only _visually hides_ the selected
date, while keeping it available to screen reader users as an `aria-live` region.

For example usage, refer to the [Internationalization section](#internationalization) below.

### Optional decade navigation buttons

Set the prop `show-decade-nav` to enable the previous and next decade buttons in the calendar's date
navigation toolbar.

The props `label-prev-decade` and `label-next-decade` props can be used to provide custom label text
for the decade buttons.

For example usage, refer to the [Internationalization section](#internationalization) below.

### Border and padding

Fancy a calendar with a border with padding? Use Bootstrap's
Expand Down Expand Up @@ -489,15 +501,23 @@ the same locale as requested, depending on the supported locales of `Intl`).
<b-col cols="12" class="mb-3">
<label for="example-locales">Locale:</label>
<b-form-select id="example-locales" v-model="locale" :options="locales"></b-form-select>
<label for="example-weekdays">Start weekday:</label>
<label for="example-weekdays" class="mt-2">Start weekday:</label>
<b-form-select id="example-weekdays" v-model="weekday" :options="weekdays"></b-form-select>
<b-form-checkbox v-model="showDecadeNav" switch inline class="my-2">
Show decade navigation buttons
</b-form-checkbox>
<b-form-checkbox v-model="hideHeader" switch inline class="my-2">
Hide the date header
</b-form-checkbox>
</b-col>
<b-col md="auto">
<b-calendar
v-model="value"
v-bind="labels[locale] || {}"
:locale="locale"
:start-weekday="weekday"
:hide-header="hideHeader"
:show-decade-nav="showDecadeNav"
@context="onContext"
></b-calendar>
</b-col>
Expand All @@ -515,6 +535,8 @@ the same locale as requested, depending on the supported locales of `Intl`).
return {
value: '',
context: null,
showDecadeNav: false,
hideHeader: false,
locale: 'en-US',
locales: [
{ value: 'en-US', text: 'English US (en-US)' },
Expand All @@ -530,11 +552,13 @@ the same locale as requested, depending on the supported locales of `Intl`).
],
labels: {
de: {
labelPrevDecade: 'Vorheriges Jahrzehnt',
labelPrevYear: 'Vorheriges Jahr',
labelPrevMonth: 'Vorheriger Monat',
labelCurrentMonth: 'Aktueller Monat',
labelNextMonth: 'Nächster Monat',
labelNextYear: 'Nächstes Jahr',
labelNextDecade: 'Nächstes Jahrzehnt',
labelToday: 'Heute',
labelSelected: 'Ausgewähltes Datum',
labelNoDateSelected: 'Kein Datum gewählt',
Expand All @@ -543,11 +567,13 @@ the same locale as requested, depending on the supported locales of `Intl`).
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
},
'ar-EG': {
labelPrevDecade: 'العقد السابق',
labelPrevYear: 'العام السابق',
labelPrevMonth: 'الشهر السابق',
labelCurrentMonth: 'الشهر الحالي',
labelNextMonth: 'الشهر المقبل',
labelNextYear: 'العام المقبل',
labelNextDecade: 'العقد القادم',
labelToday: 'اليوم',
labelSelected: 'التاريخ المحدد',
labelNoDateSelected: 'لم يتم اختيار تاريخ',
Expand All @@ -556,11 +582,13 @@ the same locale as requested, depending on the supported locales of `Intl`).
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
},
zh: {
labelPrevDecade: '过去十年',
labelPrevYear: '上一年',
labelPrevMonth: '上个月',
labelCurrentMonth: '当前月份',
labelNextMonth: '下个月',
labelNextYear: '明年',
labelNextDecade: '下一个十年',
labelToday: '今天',
labelSelected: '选定日期',
labelNoDateSelected: '未选择日期',
Expand Down Expand Up @@ -610,6 +638,10 @@ Keyboard navigation:
- <kbd>PageDown</kbd> moves to the same day in the next month
- <kbd>Alt</kbd>+<kbd>PageUp</kbd> moves to the same day and month in the previous year
- <kbd>Alt</kbd>+<kbd>PageDown</kbd> moves to the same day and month in the next year
- <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>PageUp</kbd> moves to the same day and month in the previous
decade
- <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>PageDown</kbd> moves to the same day and month in the next
decade
- <kbd>Home</kbd> moves to today's date
- <kbd>End</kbd> moves to the current selected date, or today if no selected date
- <kbd>Enter</kbd> or <kbd>Space</kbd> selects the currently highlighted (focused) day
Expand Down
70 changes: 63 additions & 7 deletions src/components/calendar/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
oneMonthAhead,
oneYearAgo,
oneYearAhead,
oneDecadeAgo,
oneDecadeAhead,
parseYMD,
resolveLocale
} from '../../utils/date'
Expand All @@ -26,7 +28,12 @@ import { toInteger } from '../../utils/number'
import { toString } from '../../utils/string'
import idMixin from '../../mixins/id'
import normalizeSlotMixin from '../../mixins/normalize-slot'
import { BIconChevronLeft, BIconChevronDoubleLeft, BIconCircleFill } from '../../icons/icons'
import {
BIconChevronLeft,
BIconChevronDoubleLeft,
BIconChevronBarLeft,
BIconCircleFill
} from '../../icons/icons'

// --- Constants ---

Expand Down Expand Up @@ -141,6 +148,11 @@ export const BCalendar = Vue.extend({
type: Boolean,
default: false
},
showDecadeNav: {
// When `true` enables the decade navigation buttons
type: Boolean,
default: false
},
hidden: {
// When `true`, renders a comment node, but keeps the component instance active
// Mainly for <b-form-date>, so that we can get the component's value and locale
Expand All @@ -158,6 +170,10 @@ export const BCalendar = Vue.extend({
// default: null
},
// Labels for buttons and keyboard shortcuts
labelPrevDecade: {
type: String,
default: () => getComponentConfig(NAME, 'labelPrevDecade')
},
labelPrevYear: {
type: String,
default: () => getComponentConfig(NAME, 'labelPrevYear')
Expand All @@ -178,6 +194,10 @@ export const BCalendar = Vue.extend({
type: String,
default: () => getComponentConfig(NAME, 'labelNextYear')
},
labelNextDecade: {
type: String,
default: () => getComponentConfig(NAME, 'labelNextDecade')
},
labelToday: {
type: String,
default: () => getComponentConfig(NAME, 'labelToday')
Expand Down Expand Up @@ -397,6 +417,10 @@ export const BCalendar = Vue.extend({
return createDateFormatter(this.calendarLocale, { day: 'numeric', calendar: 'gregory' })
},
// Disabled states for the nav buttons
prevDecadeDisabled() {
const min = this.computedMin
return this.disabled || (min && lastDateOfMonth(oneDecadeAgo(this.activeDate)) < min)
},
prevYearDisabled() {
const min = this.computedMin
return this.disabled || (min && lastDateOfMonth(oneYearAgo(this.activeDate)) < min)
Expand All @@ -417,7 +441,11 @@ export const BCalendar = Vue.extend({
const max = this.computedMax
return this.disabled || (max && firstDateOfMonth(oneYearAhead(this.activeDate)) > max)
},
// Calendar generation
nextDecadeDisabled() {
const max = this.computedMax
return this.disabled || (max && firstDateOfMonth(oneDecadeAhead(this.activeDate)) > max)
},
// Calendar dates generation
calendar() {
const matrix = []
const firstDay = this.calendarFirstDay
Expand Down Expand Up @@ -571,8 +599,7 @@ export const BCalendar = Vue.extend({
// Calendar keyboard navigation
// Handles PAGEUP/PAGEDOWN/END/HOME/LEFT/UP/RIGHT/DOWN
// Focuses grid after updating
const keyCode = evt.keyCode
const altKey = evt.altKey
const { altKey, ctrlKey, keyCode } = evt
if (!arrayIncludes([PAGEUP, PAGEDOWN, END, HOME, LEFT, UP, RIGHT, DOWN], keyCode)) {
/* istanbul ignore next */
return
Expand All @@ -586,13 +613,15 @@ export const BCalendar = Vue.extend({
const isRTL = this.isRTL
if (keyCode === PAGEUP) {
// PAGEUP - Previous month/year
activeDate = (altKey ? oneYearAgo : oneMonthAgo)(activeDate)
activeDate = (altKey ? (ctrlKey ? oneDecadeAgo : oneYearAgo) : oneMonthAgo)(activeDate)
// We check the first day of month to be in rage
checkDate = createDate(activeDate)
checkDate.setDate(1)
} else if (keyCode === PAGEDOWN) {
// PAGEDOWN - Next month/year
activeDate = (altKey ? oneYearAhead : oneMonthAhead)(activeDate)
activeDate = (altKey ? (ctrlKey ? oneDecadeAhead : oneYearAhead) : oneMonthAhead)(
activeDate
)
// We check the last day of month to be in rage
checkDate = createDate(activeDate)
checkDate.setMonth(checkDate.getMonth() + 1)
Expand Down Expand Up @@ -670,6 +699,9 @@ export const BCalendar = Vue.extend({
this.focus()
}
},
gotoPrevDecade() {
this.activeYMD = formatYMD(this.constrainDate(oneDecadeAgo(this.activeDate)))
},
gotoPrevYear() {
this.activeYMD = formatYMD(this.constrainDate(oneYearAgo(this.activeDate)))
},
Expand All @@ -686,6 +718,9 @@ export const BCalendar = Vue.extend({
gotoNextYear() {
this.activeYMD = formatYMD(this.constrainDate(oneYearAhead(this.activeDate)))
},
gotoNextDecade() {
this.activeYMD = formatYMD(this.constrainDate(oneDecadeAhead(this.activeDate)))
},
onHeaderClick() {
if (!this.disabled) {
this.activeYMD = this.selectedYMD || formatYMD(this.getToday())
Expand All @@ -700,6 +735,7 @@ export const BCalendar = Vue.extend({
}

const isRTL = this.isRTL
const hideDecadeNav = !this.showDecadeNav
const todayYMD = formatYMD(this.getToday())
const selectedYMD = this.selectedYMD
const activeYMD = this.activeYMD
Expand Down Expand Up @@ -762,11 +798,13 @@ export const BCalendar = Vue.extend({
)

// Content for the date navigation buttons
const $prevDecadeIcon = h(BIconChevronBarLeft, { props: { shiftV: 0.5, flipH: isRTL } })
const $prevYearIcon = h(BIconChevronDoubleLeft, { props: { shiftV: 0.5, flipH: isRTL } })
const $prevMonthIcon = h(BIconChevronLeft, { props: { shiftV: 0.5, flipH: isRTL } })
const $thisMonthIcon = h(BIconCircleFill, { props: { shiftV: 0.5 } })
const $nextMonthIcon = h(BIconChevronLeft, { props: { shiftV: 0.5, flipH: !isRTL } })
const $nextYearIcon = h(BIconChevronDoubleLeft, { props: { shiftV: 0.5, flipH: !isRTL } })
const $nextDecadeIcon = h(BIconChevronBarLeft, { props: { shiftV: 0.5, flipH: !isRTL } })

// Utility to create the date navigation buttons
const makeNavBtn = (content, label, handler, btnDisabled, shortcut) => {
Expand Down Expand Up @@ -802,6 +840,15 @@ export const BCalendar = Vue.extend({
}
},
[
hideDecadeNav
? h()
: makeNavBtn(
$prevDecadeIcon,
this.labelPrevDecade,
this.gotoPrevDecade,
this.prevDecadeDisabled,
'Ctrl+Alt+PageDown'
),
makeNavBtn(
$prevYearIcon,
this.labelPrevYear,
Expand Down Expand Up @@ -836,7 +883,16 @@ export const BCalendar = Vue.extend({
this.gotoNextYear,
this.nextYearDisabled,
'Alt+PageUp'
)
),
hideDecadeNav
? h()
: makeNavBtn(
$nextDecadeIcon,
this.labelNextDecade,
this.gotoNextDecade,
this.nextDecadeDisabled,
'Ctrl+Alt+PageUp'
)
]
)

Expand Down
25 changes: 19 additions & 6 deletions src/components/calendar/calendar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ describe('calendar', () => {
const wrapper = mount(BCalendar, {
attachToDocument: true,
propsData: {
showDecadeNav: true,
value: '2020-02-15' // Leap year
}
})
Expand All @@ -139,28 +140,40 @@ describe('calendar', () => {
expect($grid.attributes('data-month')).toBe('2020-02')

const $navBtns = wrapper.findAll('.b-calendar-nav button')
expect($navBtns.length).toBe(5)
expect($navBtns.length).toBe(7)

// Prev Month
$navBtns.at(1).trigger('click')
$navBtns.at(2).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2020-01')

// Next Month
$navBtns.at(3).trigger('click')
$navBtns.at(4).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2020-02')

// Prev Year
$navBtns.at(0).trigger('click')
$navBtns.at(1).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2019-02')

// Next Year
$navBtns.at(4).trigger('click')
$navBtns.at(5).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2020-02')

// Prev Decade
$navBtns.at(0).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2010-02')

// Next Decade
$navBtns.at(6).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
expect($grid.attributes('data-month')).toBe('2020-02')
Expand All @@ -169,7 +182,7 @@ describe('calendar', () => {
// Handle the rare case this test is run right at midnight where
// the current month rolled over at midnight when clicked
const thisMonth1 = formatYMD(new Date()).slice(0, -3)
$navBtns.at(2).trigger('click')
$navBtns.at(3).trigger('click')
await waitNT(wrapper.vm)
await waitRAF()
const thisMonth2 = formatYMD(new Date()).slice(0, -3)
Expand Down
Loading