Skip to content

Commit

Permalink
fix(core/date-dropdown): show year and month dropdown (#1261)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielleroux authored May 8, 2024
1 parent 76dd067 commit c025a49
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 15 deletions.
6 changes: 6 additions & 0 deletions .changeset/clean-walls-bake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@siemens/ix": patch
"@siemens/ix-vue": patch
---

fix(core/date-dropdown): show year and month dropdown
2 changes: 2 additions & 0 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ export namespace Components {
* An optional header shown at the top of the dropdown
*/
"header"?: string;
"ignoreRelatedSubmenu": boolean;
/**
* Move dropdown along main axis of alignment
*/
Expand Down Expand Up @@ -4905,6 +4906,7 @@ declare namespace LocalJSX {
* An optional header shown at the top of the dropdown
*/
"header"?: string;
"ignoreRelatedSubmenu"?: boolean;
/**
* Move dropdown along main axis of alignment
*/
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/components/date-dropdown/date-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ export class DateDropdown {
return (
<Host>
<ix-button
data-testid="date-dropdown-trigger"
data-date-dropdown-trigger
variant="primary"
icon="history"
Expand All @@ -307,10 +308,11 @@ export class DateDropdown {
{this.getButtonLabel()}
</ix-button>
<ix-dropdown
data-testid="date-dropdown"
data-date-dropdown
class="min-width max-height"
trigger={this.triggerRef}
close-behavior="outside"
closeBehavior="outside"
placement="bottom-start"
onShowChanged={({ detail: show }) => {
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,41 @@ test('set date from a button', async ({ mount, page }) => {
await expect(button).toHaveText(/2024\/02\/17 \- 2024\/02\/27/);
});

test('select different year', async ({ mount, page }) => {
await mount(`<ix-date-dropdown from="2024/02/16"></ix-date-dropdown>`);
const dateDropdown = page.locator(DATE_DROPDOWN_SELECTOR);

await expect(dateDropdown).toHaveClass(/hydrated/);
await expect(dateDropdown).toBeVisible();

const dateDropdownTrigger = dateDropdown.getByTestId('date-dropdown-trigger');
await dateDropdownTrigger.click();
await expect(dateDropdownTrigger).toBeVisible();

const datePickerDropdown = dateDropdown.getByTestId('date-dropdown');
await expect(datePickerDropdown).toBeVisible();

const datepicker = datePickerDropdown.locator('ix-date-picker');
const yearMonthButton = datepicker.getByTestId('year-month-button');
await yearMonthButton.click();

const yearMonthDropdown = datepicker.getByTestId('year-month-dropdown');
await expect(yearMonthDropdown).toBeVisible();

const yearContainer = yearMonthDropdown.getByTestId('year-container');
const year2020 = yearContainer.getByText('2020');

await year2020.click();

const monthContainer = yearMonthDropdown.getByTestId('month-container');
const march2020 = monthContainer.getByText('March 2020');

await march2020.click();

await expect(yearMonthDropdown).not.toBeVisible();
await expect(yearMonthButton).toHaveText('March 2020');
});

test('disable', async ({ mount, page }) => {
await mount(`<ix-date-dropdown disabled></ix-date-dropdown>`);
const dateDropdown = page.locator('ix-date-dropdown');
Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/components/date-picker/date-picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -689,25 +689,32 @@ export class DatePicker {
class="arrows"
></ix-icon-button>
<div class="selector">
<ix-button ghost ref={(ref) => (this.dropdownButtonRef = ref)}>
<ix-button
ghost
ref={(ref) => (this.dropdownButtonRef = ref)}
data-testid="year-month-button"
>
<span class="fontSize capitalize">
{this.monthNames[this.selectedMonth]} {this.selectedYear}
</span>
</ix-button>
<ix-dropdown
data-testid="year-month-dropdown"
class="dropdown"
trigger={this.dropdownButtonRef}
ignoreRelatedSubmenu
placement="bottom-start"
>
<div class="wrapper">
<div
data-testid="year-container"
class="overflow"
onScroll={() => this.infiniteScrollYears()}
ref={(ref) => (this.yearContainerRef = ref)}
>
{this.renderYears()}
</div>
<div class="overflow">
<div class="overflow" data-testid="month-container">
{this.monthNames.map((month, index) => (
<div
key={month}
Expand Down
36 changes: 28 additions & 8 deletions packages/core/src/components/dropdown/dropdown-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,33 @@ class DropdownController {
}
}

dismissAll(ignoreBehaviorForIds: string[] = []) {
dismissAll(
ignoreBehaviorForIds: string[] = [],
ignoreRelatedDropdowns = false
) {
this.dropdowns.forEach((dropdown) => {
if (
!ignoreBehaviorForIds.includes(dropdown.getId()) &&
(dropdown.closeBehavior === 'inside' ||
dropdown.closeBehavior === false)
) {
const preventClosing =
dropdown.closeBehavior === 'inside' || dropdown.closeBehavior === false;

const shouldIgnore = ignoreBehaviorForIds.includes(dropdown.getId());
const path = this.buildComposedPath(dropdown.getId(), new Set<string>());

if (ignoreBehaviorForIds.length > 0 && ignoreRelatedDropdowns) {
let skipRelatedDropdown = false;

ignoreBehaviorForIds.forEach((id) => {
if (path.has(id)) {
skipRelatedDropdown = true;
return;
}
});

if (!skipRelatedDropdown) {
return;
}
}

if (!shouldIgnore && preventClosing) {
return;
}

Expand All @@ -128,12 +148,12 @@ class DropdownController {
for (let eventTarget of eventTargets) {
if (eventTarget instanceof HTMLElement) {
if (eventTarget.hasAttribute('data-ix-dropdown-trigger')) {
return true;
return eventTarget;
}
}
}

return false;
return;
}

private pathIncludesDropdown(eventTargets: EventTarget[]) {
Expand Down
13 changes: 9 additions & 4 deletions packages/core/src/components/dropdown/dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ export class Dropdown implements ComponentInterface, DropdownInterface {
*/
@Prop() discoverAllSubmenus = false;

/** @internal */
@Prop() ignoreRelatedSubmenu = false;

/**
* Fire event after visibility of dropdown has changed
*/
Expand Down Expand Up @@ -254,7 +257,7 @@ export class Dropdown implements ComponentInterface, DropdownInterface {
this.triggerElement?.dispatchEvent(
new CustomEvent('ix-assign-sub-menu', {
bubbles: true,
composed: false,
composed: true,
cancelable: true,
detail: this.localUId,
})
Expand Down Expand Up @@ -501,16 +504,18 @@ export class Dropdown implements ComponentInterface, DropdownInterface {
}

private onDropdownClick(event: PointerEvent) {
if (dropdownController.pathIncludesTrigger(event.composedPath())) {
const target = dropdownController.pathIncludesTrigger(event.composedPath());
if (target) {
event.preventDefault();

if (this.isTriggerElement(event.target as HTMLElement)) {
if (this.isTriggerElement(target)) {
return;
}
}

if (this.closeBehavior === 'inside' || this.closeBehavior === 'both') {
dropdownController.dismissAll([this.getId()]);
dropdownController.dismissAll([this.getId()], this.ignoreRelatedSubmenu);
return;
}

dropdownController.dismissOthers(this.getId());
Expand Down
1 change: 1 addition & 0 deletions packages/vue/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ export const IxDropdown = /*@__PURE__*/ defineContainer<JSX.IxDropdown>('ix-drop
'offset',
'overwriteDropdownStyle',
'discoverAllSubmenus',
'ignoreRelatedSubmenu',
'showChanged'
]);

Expand Down

0 comments on commit c025a49

Please sign in to comment.