Skip to content

feat(b-calendar, b-form-datepicker): add prop weekday-header-format to specify weekday header length (closes #5171) #5175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions src/components/calendar/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,23 @@ Notes:
- `year`, `month` and `day` will always be shown. If you need to leave out a value, set the property
to `undefined`, although this is highly discouraged for accessibility reasons

### Weekday name header format

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

The calendar weekday name header format defaults to `'short'`, which is typically a three-character
abbreviation of the weekday, although some [locales](#internationalization) may override this. The
format can be controlled via the prop `weekday-header-format` and accepts one of three values:

- `'long'` the full weekday name (e.g. <samp>Tuesday</samp>). Handy when using a full width
calendar. Avoid using with the default calendar width.
- `'short'` typically is a 2 or 3 letter abbreviation of the weekday name, depending on the selected
locale (e.g. "Tue").
- `'narrow'` is typically a single character abbreviation (e.g., <samp>T</samp>). Two weekdays may
have the same narrow style for some locales (e.g. Tuesday and Thursday's narrow style are both
<samp>T</samp>). This can be handy for those locales that do not support the `'short'` format,
such as locales `'ar'` and `'fa'`.

### Hiding the top selected date header

By default, the current selected date will be displayed at the top of the calendar component,
Expand Down Expand Up @@ -592,6 +609,7 @@ the same locale as requested, depending on the supported locales of `Intl`).
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
},
'ar-EG': {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: 'العقد السابق',
labelPrevYear: 'العام السابق',
labelPrevMonth: 'الشهر السابق',
Expand All @@ -607,6 +625,7 @@ the same locale as requested, depending on the supported locales of `Intl`).
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
},
zh: {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: '过去十年',
labelPrevYear: '上一年',
labelPrevMonth: '上个月',
Expand Down
67 changes: 49 additions & 18 deletions src/components/calendar/calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ const NAME = 'BCalendar'
// Key Codes
const { UP, DOWN, LEFT, RIGHT, PAGEUP, PAGEDOWN, HOME, END, ENTER, SPACE } = KeyCodes

// Common calendar option value strings
export const STR_GREGORY = 'gregory'
export const STR_NUMERIC = 'numeric'
export const STR_2_DIGIT = '2-digit'
export const STR_LONG = 'long'
export const STR_SHORT = 'short'
export const STR_NARROW = 'narrow'

// --- BCalendar component ---

// @vue/component
Expand Down Expand Up @@ -224,13 +232,25 @@ export const BCalendar = Vue.extend({
},
dateFormatOptions: {
// `Intl.DateTimeFormat` object
// Note: This value is *not* to be placed in the global config
type: Object,
default: () => ({
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
year: STR_NUMERIC,
month: STR_LONG,
day: STR_NUMERIC,
weekday: STR_LONG
})
},
weekdayHeaderFormat: {
// Format of the weekday names at the top of the calendar
// Note: This value is *not* to be placed in the global config
type: String,
// `short` is typically a 3 letter abbreviation,
// `narrow` is typically a single letter
// `long` is the full week day name
// Although some locales may override this (i.e `ar`, etc)
default: STR_SHORT,
validator: value => arrayIncludes([STR_LONG, STR_SHORT, STR_NARROW], value)
}
},
data() {
Expand Down Expand Up @@ -271,18 +291,18 @@ export const BCalendar = Vue.extend({
},
computedLocale() {
// Returns the resolved locale used by the calendar
return resolveLocale(concat(this.locale).filter(identity), 'gregory')
return resolveLocale(concat(this.locale).filter(identity), STR_GREGORY)
},
calendarLocale() {
// This locale enforces the gregorian calendar (for use in formatter functions)
// Needed because IE 11 resolves `ar-IR` as islamic-civil calendar
// and IE 11 (and some other browsers) do not support the `calendar` option
// And we currently only support the gregorian calendar
const fmt = new Intl.DateTimeFormat(this.computedLocale, { calendar: 'gregory' })
const fmt = new Intl.DateTimeFormat(this.computedLocale, { calendar: STR_GREGORY })
const calendar = fmt.resolvedOptions().calendar
let locale = fmt.resolvedOptions().locale
/* istanbul ignore if: mainly for IE 11 and a few other browsers, hard to test in JSDOM */
if (calendar !== 'gregory') {
if (calendar !== STR_GREGORY) {
// Ensure the locale requests the gregorian calendar
// Mainly for IE 11, and currently we can't handle non-gregorian calendars
// TODO: Should we always return this value?
Expand Down Expand Up @@ -384,9 +404,9 @@ export const BCalendar = Vue.extend({
// Ensure we have year, month, day shown for screen readers/ARIA
// If users really want to leave one of these out, they can
// pass `undefined` for the property value
year: 'numeric',
month: '2-digit',
day: '2-digit',
year: STR_NUMERIC,
month: STR_2_DIGIT,
day: STR_2_DIGIT,
// Merge in user supplied options
...this.dateFormatOptions,
// Ensure hours/minutes/seconds are not shown
Expand All @@ -395,26 +415,37 @@ export const BCalendar = Vue.extend({
minute: undefined,
second: undefined,
// Ensure calendar is gregorian
calendar: 'gregory'
calendar: STR_GREGORY
})
},
formatYearMonth() {
// Returns a date formatter function
return createDateFormatter(this.calendarLocale, {
year: 'numeric',
month: 'long',
calendar: 'gregory'
year: STR_NUMERIC,
month: STR_LONG,
calendar: STR_GREGORY
})
},
formatWeekdayName() {
return createDateFormatter(this.calendarLocale, { weekday: 'long', calendar: 'gregory' })
// Long weekday name for weekday header aria-label
return createDateFormatter(this.calendarLocale, {
weekday: STR_LONG,
calendar: STR_GREGORY
})
},
formatWeekdayNameShort() {
// Used as the header cells
return createDateFormatter(this.calendarLocale, { weekday: 'short', calendar: 'gregory' })
// Weekday header cell format
// defaults to 'short' 3 letter days, where possible
return createDateFormatter(this.calendarLocale, {
weekday: this.weekdayHeaderFormat || STR_SHORT,
calendar: STR_GREGORY
})
},
formatDay() {
return createDateFormatter(this.calendarLocale, { day: 'numeric', calendar: 'gregory' })
return createDateFormatter(this.calendarLocale, {
day: STR_NUMERIC,
calendar: STR_GREGORY
})
},
// Disabled states for the nav buttons
prevDecadeDisabled() {
Expand Down
5 changes: 5 additions & 0 deletions src/components/calendar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@
"prop": "dateFormatOptions",
"version": "2.6.0",
"description": "Format object for displayed text string that is passed to `Intl.DateTimeFormat`"
},
{
"prop": "weekdayHeaderFormat",
"version": "2.12.0",
"description": "Format to use for the calendar weekday headings. Possible values are `long`, `short` (default), or `narrow`"
}
],
"events": [
Expand Down
19 changes: 19 additions & 0 deletions src/components/form-datepicker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,23 @@ Notes:
- `year`, `month` and `day` will always be shown. If you need to leave out a value, set the property
to `undefined`, although this is highly discouraged for accessibility reasons

### Weekday name header format

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

The calendar weekday name header format defaults to `'short'`, which is typically a three-character
abbreviation of the weekday, although some [locales](#internationalization) may override this. The
format can be controlled via the prop `weekday-header-format` and accepts one of three values:

- `'long'` the full weekday name (e.g. <samp>Tuesday</samp>). Handy when using a full width
calendar. Avoid using with the default calendar width.
- `'short'` typically is a 2 or 3 letter abbreviation of the weekday name, depending on the selected
locale (e.g. "Tue").
- `'narrow'` is typically a single character abbreviation (e.g., <samp>T</samp>). Two weekdays may
have the same narrow style for some locales (e.g. Tuesday and Thursday's narrow style are both
<samp>T</samp>). This can be handy for those locales that do not support the `'short'` format,
such as locales `'ar'` and `'fa'`.

### Date navigation button slots

<span class="badge badge-info small">2.12.0+</span>
Expand Down Expand Up @@ -551,6 +568,7 @@ Saturday.
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
},
'ar-EG': {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: 'العقد السابق',
labelPrevYear: 'العام السابق',
labelPrevMonth: 'الشهر السابق',
Expand All @@ -566,6 +584,7 @@ Saturday.
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
},
zh: {
weekdayHeaderFormat: 'narrow',
labelPrevDecade: '过去十年',
labelPrevYear: '上一年',
labelPrevMonth: '上个月',
Expand Down
26 changes: 20 additions & 6 deletions src/components/form-datepicker/form-datepicker.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import Vue from '../../utils/vue'
import { arrayIncludes } from '../../utils/array'
import { BVFormBtnLabelControl, dropdownProps } from '../../utils/bv-form-btn-label-control'
import { getComponentConfig } from '../../utils/config'
import { createDate, constrainDate, formatYMD, parseYMD } from '../../utils/date'
import { isUndefinedOrNull } from '../../utils/inspect'
import { pick } from '../../utils/object'
import idMixin from '../../mixins/id'
import { BButton } from '../button/button'
import { BCalendar } from '../calendar/calendar'
import { BCalendar, STR_LONG, STR_NARROW, STR_NUMERIC, STR_SHORT } from '../calendar/calendar'
import { BIconCalendar, BIconCalendarFill } from '../../icons/icons'

const NAME = 'BFormDatepicker'
Expand Down Expand Up @@ -240,14 +241,26 @@ const propsMixin = {
},
dateFormatOptions: {
// `Intl.DateTimeFormat` object
// Note: This value is *not* to be placed in the global config
type: Object,
default: () => ({
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
year: STR_NUMERIC,
month: STR_LONG,
day: STR_NUMERIC,
weekday: STR_LONG
})
},
weekdayHeaderFormat: {
// Format of the weekday names at the top of the calendar
// Note: This value is *not* to be placed in the global config
type: String,
// `short` is typically a 3 letter abbreviation,
// `narrow` is typically a single letter
// `long` is the full week day name
// Although some locales may override this (i.e `ar`, etc)
default: STR_SHORT,
validator: value => arrayIncludes([STR_LONG, STR_SHORT, STR_NARROW], value)
},
// Dark mode
dark: {
type: Boolean,
Expand Down Expand Up @@ -328,7 +341,8 @@ export const BFormDatepicker = /*#__PURE__*/ Vue.extend({
labelCalendar: self.labelCalendar,
labelNav: self.labelNav,
labelHelp: self.labelHelp,
dateFormatOptions: self.dateFormatOptions
dateFormatOptions: self.dateFormatOptions,
weekdayHeaderFormat: self.weekdayHeaderFormat
}
},
computedLang() {
Expand Down
5 changes: 5 additions & 0 deletions src/components/form-datepicker/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@
"prop": "dateFormatOptions",
"version": "2.6.0",
"description": "Format object for displayed text string that is passed to `Intl.DateTimeFormat`"
},
{
"prop": "weekdayHeaderFormat",
"version": "2.12.0",
"description": "Format to use for the calendar weekday headings. Possible values are `long`, `short` (default), or `narrow`"
}
],
"events": [
Expand Down