Skip to content

Commit 5bf4da4

Browse files
committed
feat(bq-date-picker): extend component with custom calendar views
1 parent ac440fe commit 5bf4da4

File tree

7 files changed

+389
-37
lines changed

7 files changed

+389
-37
lines changed

packages/beeq/src/components.d.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -766,6 +766,8 @@ export namespace Components {
766766
* @attr {"single" | "multi" | "range"} type - It defines how the calendar will behave, allowing single date selection, range selection, or multiple date selection.
767767
* @attr {"error" | "none" | "success" | "warning"} validation-status - The validation status of the Select input.
768768
* @attr {string} value - The select input value represents the currently selected date or range and can be used to reset the field to a previous value.
769+
* @attr {boolean} allowHeaderViewToggle - Enable custom header to toggle views.
770+
* @attr {"day" | "month" | "year" | "decade" } calendarView - Panel type when the panel opens.
769771
* @method clear - Clears the selected value.
770772
* @event bqBlur - Callback handler emitted when the input loses focus.
771773
* @event bqChange - Callback handler emitted when the input value has changed and the input loses focus.
@@ -796,10 +798,19 @@ export namespace Components {
796798
* @cssprop --bq-date-picker--text-size - Date picker text size.
797799
*/
798800
interface BqDatePicker {
801+
/**
802+
* Enable custom header to toggle views
803+
* @default false
804+
*/
805+
"allowHeaderViewToggle": boolean;
799806
/**
800807
* If `true`, the Date picker input will be focused on component render
801808
*/
802809
"autofocus": boolean;
810+
/**
811+
* @default 'days'
812+
*/
813+
"calendarView": 'days' | 'months' | 'years' | 'decades';
803814
/**
804815
* Clears the selected value.
805816
* @return
@@ -3833,6 +3844,8 @@ declare global {
38333844
* @attr {"single" | "multi" | "range"} type - It defines how the calendar will behave, allowing single date selection, range selection, or multiple date selection.
38343845
* @attr {"error" | "none" | "success" | "warning"} validation-status - The validation status of the Select input.
38353846
* @attr {string} value - The select input value represents the currently selected date or range and can be used to reset the field to a previous value.
3847+
* @attr {boolean} allowHeaderViewToggle - Enable custom header to toggle views.
3848+
* @attr {"day" | "month" | "year" | "decade" } calendarView - Panel type when the panel opens.
38363849
* @method clear - Clears the selected value.
38373850
* @event bqBlur - Callback handler emitted when the input loses focus.
38383851
* @event bqChange - Callback handler emitted when the input value has changed and the input loses focus.
@@ -6160,6 +6173,8 @@ declare namespace LocalJSX {
61606173
* @attr {"single" | "multi" | "range"} type - It defines how the calendar will behave, allowing single date selection, range selection, or multiple date selection.
61616174
* @attr {"error" | "none" | "success" | "warning"} validation-status - The validation status of the Select input.
61626175
* @attr {string} value - The select input value represents the currently selected date or range and can be used to reset the field to a previous value.
6176+
* @attr {boolean} allowHeaderViewToggle - Enable custom header to toggle views.
6177+
* @attr {"day" | "month" | "year" | "decade" } calendarView - Panel type when the panel opens.
61636178
* @method clear - Clears the selected value.
61646179
* @event bqBlur - Callback handler emitted when the input loses focus.
61656180
* @event bqChange - Callback handler emitted when the input value has changed and the input loses focus.
@@ -6190,10 +6205,19 @@ declare namespace LocalJSX {
61906205
* @cssprop --bq-date-picker--text-size - Date picker text size.
61916206
*/
61926207
interface BqDatePicker {
6208+
/**
6209+
* Enable custom header to toggle views
6210+
* @default false
6211+
*/
6212+
"allowHeaderViewToggle"?: boolean;
61936213
/**
61946214
* If `true`, the Date picker input will be focused on component render
61956215
*/
61966216
"autofocus"?: boolean;
6217+
/**
6218+
* @default 'days'
6219+
*/
6220+
"calendarView"?: 'days' | 'months' | 'years' | 'decades';
61976221
/**
61986222
* The clear button aria label
61996223
* @default 'Clear value'
@@ -9211,6 +9235,8 @@ declare module "@stencil/core" {
92119235
* @attr {"single" | "multi" | "range"} type - It defines how the calendar will behave, allowing single date selection, range selection, or multiple date selection.
92129236
* @attr {"error" | "none" | "success" | "warning"} validation-status - The validation status of the Select input.
92139237
* @attr {string} value - The select input value represents the currently selected date or range and can be used to reset the field to a previous value.
9238+
* @attr {boolean} allowHeaderViewToggle - Enable custom header to toggle views.
9239+
* @attr {"day" | "month" | "year" | "decade" } calendarView - Panel type when the panel opens.
92149240
* @method clear - Clears the selected value.
92159241
* @event bqBlur - Callback handler emitted when the input loses focus.
92169242
* @event bqChange - Callback handler emitted when the input value has changed and the input loses focus.

packages/beeq/src/components/date-picker/__tests__/bq-date-picker.e2e.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,52 @@ describe('bq-date-picker', () => {
7373

7474
expect(calendarMonthElement.length).toEqual(4);
7575
});
76+
77+
it('should toggle views when heading is clicked if allow-header-view-toggle is true', async () => {
78+
const page = await newE2EPage({
79+
html: '<bq-date-picker open allow-header-view-toggle calendarView="days"></bq-date-picker>',
80+
});
81+
82+
const headingBtn = await page.find('bq-date-picker >>> .bq-date-picker__heading-btn');
83+
expect(headingBtn).not.toBeNull();
84+
// Initially: days grid exists
85+
let dayGridMonth = await page.find('bq-date-picker >>> calendar-month');
86+
expect(dayGridMonth).not.toBeNull();
87+
88+
// Click 1 → months
89+
await headingBtn.click();
90+
await page.waitForChanges();
91+
let monthsContainer = await page.find('bq-date-picker >>> .bq-date-picker_custom_container');
92+
dayGridMonth = await page.find('bq-date-picker >>> calendar-month');
93+
expect(monthsContainer).not.toBeNull();
94+
expect(dayGridMonth).toBeNull();
95+
96+
// Click 2 → years
97+
await headingBtn.click();
98+
await page.waitForChanges();
99+
const yearsContainer = await page.find('bq-date-picker >>> .bq-date-picker_custom_container');
100+
expect(yearsContainer).not.toBeNull();
101+
102+
// Click 3 → decades
103+
await headingBtn.click();
104+
await page.waitForChanges();
105+
const decadesContainer = await page.find('bq-date-picker >>> .bq-date-picker_custom_container');
106+
expect(decadesContainer).not.toBeNull();
107+
});
108+
109+
it('should not toggle views when heading is clicked if allow-header-view-toggle is false', async () => {
110+
const page = await newE2EPage({ html: '<bq-date-picker open calendarView="days"></bq-date-picker>' });
111+
112+
const headingBtn = await page.find('bq-date-picker >>> .bq-date-picker__heading-btn');
113+
expect(await headingBtn.getProperty('disabled')).toBe(true);
114+
115+
const dayGridMonth = await page.find('bq-date-picker >>> calendar-month');
116+
expect(dayGridMonth).not.toBeNull();
117+
118+
await headingBtn.click();
119+
await page.waitForChanges();
120+
121+
const stillDayGrid = await page.find('bq-date-picker >>> calendar-month');
122+
expect(stillDayGrid).not.toBeNull();
123+
});
76124
});

packages/beeq/src/components/date-picker/_storybook/bq-date-picker.stories.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ const meta: Meta = {
5353
'show-outside-days': { control: 'boolean' },
5454
skidding: { control: 'number' },
5555
strategy: { control: 'select', options: ['fixed', 'absolute'] },
56+
57+
allowHeaderViewToggle: { control: 'boolean' },
58+
calendarView: {
59+
control: 'select',
60+
options: ['days', 'months', 'years', 'decades'],
61+
},
5662
tentative: { control: 'text' },
5763
type: { control: 'select', options: [...DATE_PICKER_TYPE] },
5864
'validation-status': { control: 'select', options: [...INPUT_VALIDATION] },
@@ -96,6 +102,8 @@ const meta: Meta = {
96102
'show-outside-days': false,
97103
skidding: 0,
98104
strategy: 'absolute',
105+
allowHeaderViewToggle: true,
106+
calendarView: 'days',
99107
tentative: undefined,
100108
type: 'single',
101109
'validation-status': 'none',
@@ -179,6 +187,8 @@ const Template = (args: Args) => {
179187
?show-outside-days=${args['show-outside-days']}
180188
skidding=${ifDefined(args.skidding)}
181189
strategy=${ifDefined(args.strategy)}
190+
.allowHeaderViewToggle=${args.allowHeaderViewToggle}
191+
.calendarView=${args.calendarView}
182192
tentative=${ifDefined(args.tentative)}
183193
type=${ifDefined(args.type)}
184194
validation-status=${ifDefined(args['validation-status'])}

0 commit comments

Comments
 (0)