Skip to content

Commit 8241644

Browse files
authored
feat(b-calendar, b-form-datepicker): add prop weekday-header-format to specify weekday header length (closes #5171) (#5175)
Co-authored-by: Jacob Müller
1 parent 203e669 commit 8241644

6 files changed

Lines changed: 117 additions & 24 deletions

File tree

src/components/calendar/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,23 @@ Notes:
282282
- `year`, `month` and `day` will always be shown. If you need to leave out a value, set the property
283283
to `undefined`, although this is highly discouraged for accessibility reasons
284284

285+
### Weekday name header format
286+
287+
<span class="badge badge-info small">2.12.0+</span>
288+
289+
The calendar weekday name header format defaults to `'short'`, which is typically a three-character
290+
abbreviation of the weekday, although some [locales](#internationalization) may override this. The
291+
format can be controlled via the prop `weekday-header-format` and accepts one of three values:
292+
293+
- `'long'` the full weekday name (e.g. <samp>Tuesday</samp>). Handy when using a full width
294+
calendar. Avoid using with the default calendar width.
295+
- `'short'` typically is a 2 or 3 letter abbreviation of the weekday name, depending on the selected
296+
locale (e.g. "Tue").
297+
- `'narrow'` is typically a single character abbreviation (e.g., <samp>T</samp>). Two weekdays may
298+
have the same narrow style for some locales (e.g. Tuesday and Thursday's narrow style are both
299+
<samp>T</samp>). This can be handy for those locales that do not support the `'short'` format,
300+
such as locales `'ar'` and `'fa'`.
301+
285302
### Hiding the top selected date header
286303

287304
By default, the current selected date will be displayed at the top of the calendar component,
@@ -592,6 +609,7 @@ the same locale as requested, depending on the supported locales of `Intl`).
592609
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
593610
},
594611
'ar-EG': {
612+
weekdayHeaderFormat: 'narrow',
595613
labelPrevDecade: 'العقد السابق',
596614
labelPrevYear: 'العام السابق',
597615
labelPrevMonth: 'الشهر السابق',
@@ -607,6 +625,7 @@ the same locale as requested, depending on the supported locales of `Intl`).
607625
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
608626
},
609627
zh: {
628+
weekdayHeaderFormat: 'narrow',
610629
labelPrevDecade: '过去十年',
611630
labelPrevYear: '上一年',
612631
labelPrevMonth: '上个月',

src/components/calendar/calendar.js

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ const NAME = 'BCalendar'
4242
// Key Codes
4343
const { UP, DOWN, LEFT, RIGHT, PAGEUP, PAGEDOWN, HOME, END, ENTER, SPACE } = KeyCodes
4444

45+
// Common calendar option value strings
46+
export const STR_GREGORY = 'gregory'
47+
export const STR_NUMERIC = 'numeric'
48+
export const STR_2_DIGIT = '2-digit'
49+
export const STR_LONG = 'long'
50+
export const STR_SHORT = 'short'
51+
export const STR_NARROW = 'narrow'
52+
4553
// --- BCalendar component ---
4654

4755
// @vue/component
@@ -224,13 +232,25 @@ export const BCalendar = Vue.extend({
224232
},
225233
dateFormatOptions: {
226234
// `Intl.DateTimeFormat` object
235+
// Note: This value is *not* to be placed in the global config
227236
type: Object,
228237
default: () => ({
229-
year: 'numeric',
230-
month: 'long',
231-
day: 'numeric',
232-
weekday: 'long'
238+
year: STR_NUMERIC,
239+
month: STR_LONG,
240+
day: STR_NUMERIC,
241+
weekday: STR_LONG
233242
})
243+
},
244+
weekdayHeaderFormat: {
245+
// Format of the weekday names at the top of the calendar
246+
// Note: This value is *not* to be placed in the global config
247+
type: String,
248+
// `short` is typically a 3 letter abbreviation,
249+
// `narrow` is typically a single letter
250+
// `long` is the full week day name
251+
// Although some locales may override this (i.e `ar`, etc)
252+
default: STR_SHORT,
253+
validator: value => arrayIncludes([STR_LONG, STR_SHORT, STR_NARROW], value)
234254
}
235255
},
236256
data() {
@@ -271,18 +291,18 @@ export const BCalendar = Vue.extend({
271291
},
272292
computedLocale() {
273293
// Returns the resolved locale used by the calendar
274-
return resolveLocale(concat(this.locale).filter(identity), 'gregory')
294+
return resolveLocale(concat(this.locale).filter(identity), STR_GREGORY)
275295
},
276296
calendarLocale() {
277297
// This locale enforces the gregorian calendar (for use in formatter functions)
278298
// Needed because IE 11 resolves `ar-IR` as islamic-civil calendar
279299
// and IE 11 (and some other browsers) do not support the `calendar` option
280300
// And we currently only support the gregorian calendar
281-
const fmt = new Intl.DateTimeFormat(this.computedLocale, { calendar: 'gregory' })
301+
const fmt = new Intl.DateTimeFormat(this.computedLocale, { calendar: STR_GREGORY })
282302
const calendar = fmt.resolvedOptions().calendar
283303
let locale = fmt.resolvedOptions().locale
284304
/* istanbul ignore if: mainly for IE 11 and a few other browsers, hard to test in JSDOM */
285-
if (calendar !== 'gregory') {
305+
if (calendar !== STR_GREGORY) {
286306
// Ensure the locale requests the gregorian calendar
287307
// Mainly for IE 11, and currently we can't handle non-gregorian calendars
288308
// TODO: Should we always return this value?
@@ -384,9 +404,9 @@ export const BCalendar = Vue.extend({
384404
// Ensure we have year, month, day shown for screen readers/ARIA
385405
// If users really want to leave one of these out, they can
386406
// pass `undefined` for the property value
387-
year: 'numeric',
388-
month: '2-digit',
389-
day: '2-digit',
407+
year: STR_NUMERIC,
408+
month: STR_2_DIGIT,
409+
day: STR_2_DIGIT,
390410
// Merge in user supplied options
391411
...this.dateFormatOptions,
392412
// Ensure hours/minutes/seconds are not shown
@@ -395,26 +415,37 @@ export const BCalendar = Vue.extend({
395415
minute: undefined,
396416
second: undefined,
397417
// Ensure calendar is gregorian
398-
calendar: 'gregory'
418+
calendar: STR_GREGORY
399419
})
400420
},
401421
formatYearMonth() {
402422
// Returns a date formatter function
403423
return createDateFormatter(this.calendarLocale, {
404-
year: 'numeric',
405-
month: 'long',
406-
calendar: 'gregory'
424+
year: STR_NUMERIC,
425+
month: STR_LONG,
426+
calendar: STR_GREGORY
407427
})
408428
},
409429
formatWeekdayName() {
410-
return createDateFormatter(this.calendarLocale, { weekday: 'long', calendar: 'gregory' })
430+
// Long weekday name for weekday header aria-label
431+
return createDateFormatter(this.calendarLocale, {
432+
weekday: STR_LONG,
433+
calendar: STR_GREGORY
434+
})
411435
},
412436
formatWeekdayNameShort() {
413-
// Used as the header cells
414-
return createDateFormatter(this.calendarLocale, { weekday: 'short', calendar: 'gregory' })
437+
// Weekday header cell format
438+
// defaults to 'short' 3 letter days, where possible
439+
return createDateFormatter(this.calendarLocale, {
440+
weekday: this.weekdayHeaderFormat || STR_SHORT,
441+
calendar: STR_GREGORY
442+
})
415443
},
416444
formatDay() {
417-
return createDateFormatter(this.calendarLocale, { day: 'numeric', calendar: 'gregory' })
445+
return createDateFormatter(this.calendarLocale, {
446+
day: STR_NUMERIC,
447+
calendar: STR_GREGORY
448+
})
418449
},
419450
// Disabled states for the nav buttons
420451
prevDecadeDisabled() {

src/components/calendar/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,11 @@
172172
"prop": "dateFormatOptions",
173173
"version": "2.6.0",
174174
"description": "Format object for displayed text string that is passed to `Intl.DateTimeFormat`"
175+
},
176+
{
177+
"prop": "weekdayHeaderFormat",
178+
"version": "2.12.0",
179+
"description": "Format to use for the calendar weekday headings. Possible values are `long`, `short` (default), or `narrow`"
175180
}
176181
],
177182
"events": [

src/components/form-datepicker/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,23 @@ Notes:
439439
- `year`, `month` and `day` will always be shown. If you need to leave out a value, set the property
440440
to `undefined`, although this is highly discouraged for accessibility reasons
441441

442+
### Weekday name header format
443+
444+
<span class="badge badge-info small">2.12.0+</span>
445+
446+
The calendar weekday name header format defaults to `'short'`, which is typically a three-character
447+
abbreviation of the weekday, although some [locales](#internationalization) may override this. The
448+
format can be controlled via the prop `weekday-header-format` and accepts one of three values:
449+
450+
- `'long'` the full weekday name (e.g. <samp>Tuesday</samp>). Handy when using a full width
451+
calendar. Avoid using with the default calendar width.
452+
- `'short'` typically is a 2 or 3 letter abbreviation of the weekday name, depending on the selected
453+
locale (e.g. "Tue").
454+
- `'narrow'` is typically a single character abbreviation (e.g., <samp>T</samp>). Two weekdays may
455+
have the same narrow style for some locales (e.g. Tuesday and Thursday's narrow style are both
456+
<samp>T</samp>). This can be handy for those locales that do not support the `'short'` format,
457+
such as locales `'ar'` and `'fa'`.
458+
442459
### Date navigation button slots
443460

444461
<span class="badge badge-info small">2.12.0+</span>
@@ -551,6 +568,7 @@ Saturday.
551568
labelHelp: 'Mit den Pfeiltasten durch den Kalender navigieren'
552569
},
553570
'ar-EG': {
571+
weekdayHeaderFormat: 'narrow',
554572
labelPrevDecade: 'العقد السابق',
555573
labelPrevYear: 'العام السابق',
556574
labelPrevMonth: 'الشهر السابق',
@@ -566,6 +584,7 @@ Saturday.
566584
labelHelp: 'استخدم مفاتيح المؤشر للتنقل في التواريخ'
567585
},
568586
zh: {
587+
weekdayHeaderFormat: 'narrow',
569588
labelPrevDecade: '过去十年',
570589
labelPrevYear: '上一年',
571590
labelPrevMonth: '上个月',

src/components/form-datepicker/form-datepicker.js

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import Vue from '../../utils/vue'
2+
import { arrayIncludes } from '../../utils/array'
23
import { BVFormBtnLabelControl, dropdownProps } from '../../utils/bv-form-btn-label-control'
34
import { getComponentConfig } from '../../utils/config'
45
import { createDate, constrainDate, formatYMD, parseYMD } from '../../utils/date'
56
import { isUndefinedOrNull } from '../../utils/inspect'
67
import { pick } from '../../utils/object'
78
import idMixin from '../../mixins/id'
89
import { BButton } from '../button/button'
9-
import { BCalendar } from '../calendar/calendar'
10+
import { BCalendar, STR_LONG, STR_NARROW, STR_NUMERIC, STR_SHORT } from '../calendar/calendar'
1011
import { BIconCalendar, BIconCalendarFill } from '../../icons/icons'
1112

1213
const NAME = 'BFormDatepicker'
@@ -240,14 +241,26 @@ const propsMixin = {
240241
},
241242
dateFormatOptions: {
242243
// `Intl.DateTimeFormat` object
244+
// Note: This value is *not* to be placed in the global config
243245
type: Object,
244246
default: () => ({
245-
year: 'numeric',
246-
month: 'long',
247-
day: 'numeric',
248-
weekday: 'long'
247+
year: STR_NUMERIC,
248+
month: STR_LONG,
249+
day: STR_NUMERIC,
250+
weekday: STR_LONG
249251
})
250252
},
253+
weekdayHeaderFormat: {
254+
// Format of the weekday names at the top of the calendar
255+
// Note: This value is *not* to be placed in the global config
256+
type: String,
257+
// `short` is typically a 3 letter abbreviation,
258+
// `narrow` is typically a single letter
259+
// `long` is the full week day name
260+
// Although some locales may override this (i.e `ar`, etc)
261+
default: STR_SHORT,
262+
validator: value => arrayIncludes([STR_LONG, STR_SHORT, STR_NARROW], value)
263+
},
251264
// Dark mode
252265
dark: {
253266
type: Boolean,
@@ -328,7 +341,8 @@ export const BFormDatepicker = /*#__PURE__*/ Vue.extend({
328341
labelCalendar: self.labelCalendar,
329342
labelNav: self.labelNav,
330343
labelHelp: self.labelHelp,
331-
dateFormatOptions: self.dateFormatOptions
344+
dateFormatOptions: self.dateFormatOptions,
345+
weekdayHeaderFormat: self.weekdayHeaderFormat
332346
}
333347
},
334348
computedLang() {

src/components/form-datepicker/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,11 @@
268268
"prop": "dateFormatOptions",
269269
"version": "2.6.0",
270270
"description": "Format object for displayed text string that is passed to `Intl.DateTimeFormat`"
271+
},
272+
{
273+
"prop": "weekdayHeaderFormat",
274+
"version": "2.12.0",
275+
"description": "Format to use for the calendar weekday headings. Possible values are `long`, `short` (default), or `narrow`"
271276
}
272277
],
273278
"events": [

0 commit comments

Comments
 (0)