Add weekNumbers option to Datepicker (#3245)

This commit is contained in:
Paweł Kuna authored and Bartek committed 2026-10-02 11:32:45 +02:00
1 parent ed41f049a7
commit 725e45d456
7 files changed
+113

No files matched your search

+7
View File
@@ -0,0 +1,7 @@
---
"@tabler/core": minor
"@tabler/preview": patch
"@tabler/docs": patch
---
Added the `weekNumbers` option to `Datepicker` to show the week number in front of each row.
+5
View File
@@ -100,6 +100,8 @@ type ComponentConfig = {
selectedDates: string[] selectedDates: string[]
selectionMode: DateMode selectionMode: DateMode
placement: PositionToInput placement: PositionToInput
/** show the ISO week number in front of each row */
weekNumbers: boolean
/** pass-through for any Vanilla Calendar Pro option */ /** pass-through for any Vanilla Calendar Pro option */
vcpOptions: object vcpOptions: object
} }
@@ -122,6 +124,7 @@ const Default: ComponentConfig = {
selectedDates: [], selectedDates: [],
selectionMode: 'single', selectionMode: 'single',
placement: 'left', placement: 'left',
weekNumbers: false,
vcpOptions: {}, vcpOptions: {},
} }
@@ -139,6 +142,7 @@ const DefaultType: Record<keyof ComponentConfig, string> = {
selectedDates: 'array', selectedDates: 'array',
selectionMode: 'string', selectionMode: 'string',
placement: 'string', placement: 'string',
weekNumbers: 'boolean',
vcpOptions: 'object', vcpOptions: 'object',
} }
@@ -605,6 +609,7 @@ class Datepicker extends BaseComponent {
selectionDatesMode: this._config.selectionMode, selectionDatesMode: this._config.selectionMode,
selectedDates: this._config.selectedDates, selectedDates: this._config.selectedDates,
displayMonthsCount: this._config.displayMonthsCount, displayMonthsCount: this._config.displayMonthsCount,
enableWeekNumbers: this._config.weekNumbers || Boolean(vcpOptions.enableWeekNumbers),
type: this._config.displayMonthsCount > 1 ? 'multiple' : 'default', type: this._config.displayMonthsCount > 1 ? 'multiple' : 'default',
selectedTheme: vcpTheme, selectedTheme: vcpTheme,
themeAttrDetect: '[data-bs-theme]', themeAttrDetect: '[data-bs-theme]',
+18
View File
@@ -115,6 +115,24 @@ describe('Datepicker', () => {
expect(instance._config.firstWeekday).toBe(0) expect(instance._config.firstWeekday).toBe(0)
}) })
it('should turn week numbers on from a data attribute', () => {
fixtureEl.innerHTML = '<input type="text" data-bs-toggle="datepicker" data-bs-week-numbers="true">'
const instance = new Datepicker(input())
expect(Datepicker.Default.weekNumbers).toBe(false)
expect(instance._config.weekNumbers).toBe(true)
expect(instance._buildCalendarOptions().enableWeekNumbers).toBe(true)
})
it('should keep week numbers enabled through vcpOptions', () => {
fixtureEl.innerHTML = '<input type="text" data-bs-toggle="datepicker">'
const instance = new Datepicker(input(), { vcpOptions: { enableWeekNumbers: true } })
expect(instance._buildCalendarOptions().enableWeekNumbers).toBe(true)
})
it('should let a passed config win over data attributes', () => { it('should let a passed config win over data attributes', () => {
fixtureEl.innerHTML = '<input type="text" data-bs-toggle="datepicker" data-bs-first-weekday="0">' fixtureEl.innerHTML = '<input type="text" data-bs-toggle="datepicker" data-bs-first-weekday="0">'
+48
View File
@@ -19,6 +19,8 @@
--calendar-font-size: #{$datepicker-calendar-font-size}; --calendar-font-size: #{$datepicker-calendar-font-size};
--calendar-header-font-weight: #{$datepicker-calendar-header-font-weight}; --calendar-header-font-weight: #{$datepicker-calendar-header-font-weight};
--calendar-weekday-color: var(--secondary); --calendar-weekday-color: var(--secondary);
--calendar-week-number-color: var(--secondary);
--calendar-week-number-border-color: var(--border-color);
--calendar-day-hover-bg: var(--hover-bg); --calendar-day-hover-bg: var(--hover-bg);
--calendar-day-selected-bg: var(--primary); --calendar-day-selected-bg: var(--primary);
--calendar-day-selected-color: var(--primary-fg); --calendar-day-selected-color: var(--primary-fg);
@@ -151,6 +153,12 @@
} }
} }
// Holds the week numbers column, when enabled, next to the month
[data-vc='wrapper'] {
display: flex;
flex-grow: 1;
}
[data-vc='content'] { [data-vc='content'] {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
@@ -252,6 +260,46 @@ button[data-vc-week-day] {
cursor: pointer; cursor: pointer;
} }
// Week numbers: a column in front of the month, with a title that lines up
// with the weekday header and one number for each row of dates.
[data-vc-week='numbers'] {
display: flex;
flex-direction: column;
padding-inline-end: 0.5rem;
margin-inline-end: 0.5rem;
border-inline-end: var(--border-width) solid var(--calendar-week-number-border-color);
}
[data-vc-week-numbers='title'] {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 0.5rem;
font-size: var(--calendar-day-font-size);
font-weight: var(--calendar-header-font-weight);
line-height: 1rem;
color: var(--calendar-week-number-color);
}
[data-vc-week-numbers='content'] {
display: grid;
grid-auto-rows: calc(var(--calendar-day-size) + 0.25rem);
align-items: center;
justify-items: center;
}
[data-vc-week-number] {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-width: var(--calendar-day-size);
font-size: var(--calendar-day-font-size);
font-weight: $font-weight-normal;
line-height: 1rem;
color: var(--calendar-week-number-color);
}
// Dates grid // Dates grid
[data-vc='dates'] { [data-vc='dates'] {
pointer-events: none; pointer-events: none;
+10
View File
@@ -131,6 +131,15 @@ The week starts on Monday. Set `data-bs-first-weekday="0"` to start it on Sunday
<input type="text" class="form-control" id="datepicker-sunday" data-bs-toggle="datepicker" autocomplete="off" data-bs-first-weekday="0" placeholder="Select a date" /> <input type="text" class="form-control" id="datepicker-sunday" data-bs-toggle="datepicker" autocomplete="off" data-bs-first-weekday="0" placeholder="Select a date" />
</Example> </Example>
### Week numbers
Add `data-bs-week-numbers="true"` to show the week number in front of each row. Use it where people plan by week, for example delivery dates or sprints.
<Example>
<label class="form-label" for="datepicker-week-numbers">Delivery date</label>
<input type="text" class="form-control" id="datepicker-week-numbers" data-bs-toggle="datepicker" autocomplete="off" data-bs-week-numbers="true" placeholder="Select a date" />
</Example>
### Placement ### Placement
The popup lines up with the left edge of the field. Set `data-bs-placement` to `center`, `right` or `auto` to change that. The popup lines up with the left edge of the field. Set `data-bs-placement` to `center`, `right` or `auto` to change that.
@@ -224,6 +233,7 @@ const datepicker = new tabler.Datepicker(document.getElementById('my-date'), {
| `selectedDates` | array | `[]` | Preselected dates as `YYYY-MM-DD`. | | `selectedDates` | array | `[]` | Preselected dates as `YYYY-MM-DD`. |
| `selectionMode` | string | `'single'` | `'single'`, `'multiple'` or `'multiple-ranged'`. | | `selectionMode` | string | `'single'` | `'single'`, `'multiple'` or `'multiple-ranged'`. |
| `placement` | string | `'left'` | Where the popup lines up with the field: `'left'`, `'center'`, `'right'` or `'auto'`. | | `placement` | string | `'left'` | Where the popup lines up with the field: `'left'`, `'center'`, `'right'` or `'auto'`. |
| `weekNumbers` | boolean | `false` | Show the week number in front of each row. |
| `datepickerTheme` | string | `null` | Force the popup's theme to `'light'`, `'dark'` or `'auto'`. By default it follows the nearest `[data-bs-theme]`. | | `datepickerTheme` | string | `null` | Force the popup's theme to `'light'`, `'dark'` or `'auto'`. By default it follows the nearest `[data-bs-theme]`. |
| `vcpOptions` | object | `{}` | Any [Vanilla Calendar Pro option](https://vanilla-calendar.pro/docs/reference/settings), passed straight through. | | `vcpOptions` | object | `{}` | Any [Vanilla Calendar Pro option](https://vanilla-calendar.pro/docs/reference/settings), passed straight through. |
+21
View File
@@ -108,6 +108,17 @@ const rangeEnd = `${year}-06-18`
</Card> </Card>
</div> </div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Week numbers</CardTitle>
<CardSubtitle>Add <code>data-bs-week-numbers="true"</code> to show the week number in front of each row.</CardSubtitle>
<label class="form-label" for="datepicker-week-numbers">Delivery date</label>
<Datepicker id="week-numbers" weekNumbers />
</CardBody>
</Card>
</div>
<div class="col-md-6 col-lg-4"> <div class="col-md-6 col-lg-4">
<Card> <Card>
<CardBody> <CardBody>
@@ -187,6 +198,16 @@ const rangeEnd = `${year}-06-18`
</Card> </Card>
</div> </div>
<div class="col-md-6 col-lg-4">
<Card>
<CardBody>
<CardTitle>Inline with week numbers</CardTitle>
<CardSubtitle>Week numbers work in an inline calendar too, and with every selection mode.</CardSubtitle>
<Datepicker id="inline-week-numbers" inline weekNumbers selectionMode="multiple-ranged" selectedDates={[rangeStart, rangeEnd]} />
</CardBody>
</Card>
</div>
<div class="col-md-12 col-lg-8"> <div class="col-md-12 col-lg-8">
<Card> <Card>
<CardBody> <CardBody>
+4
View File
@@ -25,6 +25,8 @@ interface Props {
/** 0 = Sunday, 1 = Monday */ /** 0 = Sunday, 1 = Monday */
firstWeekday?: 0 | 1 | 2 | 3 | 4 | 5 | 6 firstWeekday?: 0 | 1 | 2 | 3 | 4 | 5 | 6
placement?: 'left' | 'center' | 'right' | 'auto' placement?: 'left' | 'center' | 'right' | 'auto'
/** show the week number in front of each row */
weekNumbers?: boolean
/** name of the hidden input an inline calendar submits with a form */ /** name of the hidden input an inline calendar submits with a form */
name?: string name?: string
} }
@@ -43,6 +45,7 @@ const {
dateMax, dateMax,
firstWeekday, firstWeekday,
placement, placement,
weekNumbers = false,
name, name,
} = Astro.props } = Astro.props
@@ -58,6 +61,7 @@ const dataAttributes = {
'data-bs-date-max': dateMax, 'data-bs-date-max': dateMax,
'data-bs-first-weekday': firstWeekday, 'data-bs-first-weekday': firstWeekday,
'data-bs-placement': placement, 'data-bs-placement': placement,
'data-bs-week-numbers': weekNumbers ? 'true' : undefined,
} }
--- ---