this.infiniteScrollYears()}
ref={(ref) => (this.yearContainerRef = ref)}
>
{this.renderYears()}
+
{this.monthNames.map((month, index) => (
{
- 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
());
+
+ 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;
}
@@ -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[]) {
diff --git a/packages/core/src/components/dropdown/dropdown.tsx b/packages/core/src/components/dropdown/dropdown.tsx
index 93c90e2a82..de469c0f43 100644
--- a/packages/core/src/components/dropdown/dropdown.tsx
+++ b/packages/core/src/components/dropdown/dropdown.tsx
@@ -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
*/
@@ -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,
})
@@ -262,6 +265,10 @@ export class Dropdown implements ComponentInterface, DropdownInterface {
}
private registerKeyListener() {
+ if (!this.triggerElement) {
+ return;
+ }
+
this.disposeKeyListener = addDisposableEventListener(
this.triggerElement,
'keydown',
@@ -497,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());
diff --git a/packages/core/src/components/event-list-item/event-list-item.tsx b/packages/core/src/components/event-list-item/event-list-item.tsx
index 505e4933b3..4519e60db6 100644
--- a/packages/core/src/components/event-list-item/event-list-item.tsx
+++ b/packages/core/src/components/event-list-item/event-list-item.tsx
@@ -16,6 +16,7 @@ import {
Listen,
Prop,
} from '@stencil/core';
+import { a11yBoolean } from '../utils/a11y';
@Component({
tag: 'ix-event-list-item',
@@ -86,7 +87,8 @@ export class EventListItem {
disabled: this.disabled,
}}
>
-
)}
-
+
);
}
diff --git a/packages/core/src/components/event-list/event-list.tsx b/packages/core/src/components/event-list/event-list.tsx
index 6d3b467c79..e4a87d43c2 100644
--- a/packages/core/src/components/event-list/event-list.tsx
+++ b/packages/core/src/components/event-list/event-list.tsx
@@ -10,6 +10,7 @@
import { Component, Element, h, Host, Prop, Watch } from '@stencil/core';
import { createMutationObserver } from '../utils/mutation-observer';
import { convertToRemString } from '../utils/rwd.util';
+import anime from 'animejs';
@Component({
tag: 'ix-event-list',
@@ -102,22 +103,25 @@ export class EventList {
item.style.setProperty('--event-list-item-height', height);
}
- private triggerFadeOut(): Promise
{
- if (!this.animated) {
- return Promise.resolve();
- }
+ private triggerFadeOut(): Promise {
+ return new Promise((resolve) => {
+ if (!this.animated) {
+ resolve();
+ }
- const keyframes = [
- {
- opacity: 1,
- easing: 'ease-in',
- },
- { opacity: 0 },
- ];
- const listElement = this.hostElement.shadowRoot.querySelector('ul');
- return listElement.animate(keyframes, {
- duration: EventList.fadeOutDuration,
- }).finished;
+ const keyframes = [{ opacity: 1, easing: 'easeInSine' }, { opacity: 0 }];
+
+ const listElement = this.hostElement.shadowRoot.querySelector('ul');
+
+ anime({
+ targets: listElement,
+ opacity: keyframes,
+ duration: EventList.fadeOutDuration,
+ complete: () => {
+ resolve();
+ },
+ });
+ });
}
private triggerFadeIn() {
@@ -129,16 +133,15 @@ export class EventList {
listItems.forEach((e, i) => {
const delay = i * 80;
const offset = delay / (delay + EventList.fadeInDuration);
- const keyframes = [
- { opacity: 0 },
- { opacity: 0, easing: 'ease-out', offset },
- { opacity: 1 },
- ];
- const options = {
+ anime({
+ targets: e,
+ offset: offset,
duration: EventList.fadeInDuration + delay,
- iterations: 1,
- };
- e.animate(keyframes, options);
+ opacity: [0, 1],
+ easing: 'easeInOutSine',
+ delay: delay,
+ autoplay: true,
+ });
});
}
diff --git a/packages/core/src/components/event-list/test/event-list.ct.ts b/packages/core/src/components/event-list/test/event-list.ct.ts
new file mode 100644
index 0000000000..6c6eff8869
--- /dev/null
+++ b/packages/core/src/components/event-list/test/event-list.ct.ts
@@ -0,0 +1,70 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Siemens AG
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/*
+ * SPDX-FileCopyrightText: 2023 Siemens AG
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+import 'jest';
+import { test } from '@utils/test';
+import { expect } from '@playwright/test';
+
+test('renders', async ({ mount, page }) => {
+ await mount(`
+
+ Text 1
+ Text 2
+ Text 3
+ Text 4
+
+ `);
+
+ const eventList = page.locator('ix-event-list');
+ await expect(eventList).toHaveClass(/hydrated/);
+});
+
+test('check if items still clickable', async ({ mount, page }) => {
+ await mount(`
+
+ Text 1
+ Text 2
+ Text 3
+ Text 4
+
+ `);
+
+ await page.waitForTimeout(500);
+ const firstEventListItem = page.locator('ix-event-list-item').first();
+ const secondEventListItem = page.locator('ix-event-list-item').nth(1);
+ const thirdEventListItem = page.locator('ix-event-list-item').last();
+
+ const clickCountHandle = await page.evaluateHandle(() => {
+ return { count: 0 };
+ });
+
+ await firstEventListItem.evaluate((eventListItem, clickCountHandle) => {
+ eventListItem.addEventListener('click', () => {
+ clickCountHandle.count++;
+ });
+ }, clickCountHandle);
+
+ await firstEventListItem.click();
+ await secondEventListItem.click();
+ await thirdEventListItem.click();
+
+ //Check if still clickable
+ await firstEventListItem.click();
+ expect((await clickCountHandle.jsonValue()).count).toBe(2);
+
+ clickCountHandle.dispose();
+});
diff --git a/packages/core/src/components/event-list/test/event-list.spec.tsx b/packages/core/src/components/event-list/test/event-list.spec.tsx
index 0f03b2fd72..513c9cdc0a 100644
--- a/packages/core/src/components/event-list/test/event-list.spec.tsx
+++ b/packages/core/src/components/event-list/test/event-list.spec.tsx
@@ -72,66 +72,4 @@ describe('event-list', () => {
`);
});
-
- it('animated', async () => {
- const page = await newSpecPage({
- components: [EventList],
- html: '',
- });
-
- const eventList = page.doc.createElement('ix-event-list');
- const eventListItem = page.doc.createElement('ix-event-list-item');
-
- eventListItem.animate = jest.fn();
-
- eventList.appendChild(eventListItem);
- page.root.appendChild(eventList);
-
- await page.waitForChanges();
-
- expect(eventListItem.animate).toHaveBeenCalled();
-
- expect(page.root).toEqualHtml(`
-
-
-
-
-
-
- `);
- });
-
- it('not animated', async () => {
- const page = await newSpecPage({
- components: [EventList],
- html: '',
- });
-
- const eventList = page.doc.createElement('ix-event-list');
- eventList.animated = false;
-
- const eventListItem = page.doc.createElement('ix-event-list-item');
-
- eventListItem.animate = jest.fn();
-
- eventList.appendChild(eventListItem);
- page.root.appendChild(eventList);
-
- await page.waitForChanges();
-
- expect(eventListItem.animate).not.toHaveBeenCalled();
-
- expect(page.root).toEqualHtml(`
-
-
-
-
-
-
- `);
- });
});
diff --git a/packages/core/src/components/group-item/group-item.scss b/packages/core/src/components/group-item/group-item.scss
index 2371a8d571..ac1044815c 100644
--- a/packages/core/src/components/group-item/group-item.scss
+++ b/packages/core/src/components/group-item/group-item.scss
@@ -32,6 +32,7 @@ $focusBorderWidth: 1px;
background-color: var(--theme-group-item--background);
border: 1px solid transparent;
color: var(--theme-color-std-text);
+ cursor: pointer;
padding-left: 2.5rem;
@@ -72,6 +73,10 @@ $focusBorderWidth: 1px;
}
}
+:host(.suppress-selection) {
+ pointer-events: none;
+}
+
:host(.selected) {
border-top-width: 0.062rem !important;
background-color: var(--theme-color-ghost--selected);
@@ -81,20 +86,20 @@ $focusBorderWidth: 1px;
}
}
-:host(:not(.suppress-selection):hover) {
+:host(:hover) {
background-color: var(--theme-color-ghost--selected-hover);
border-color: var(--theme-group-item--border-color--hover);
}
-:host(:not(.suppress-selection).selected:hover) {
+:host(.selected:hover) {
background-color: var(--theme-color-ghost--selected-hover);
}
-:host(:not(.suppress-selection):active) {
+:host(:active) {
background-color: var(--theme-color-ghost--selected-active);
border-color: var(--theme-group-item--border-color--active);
}
-:host(:not(.suppress-selection).selected:active) {
+:host(.selected:active) {
background-color: var(--theme-color-ghost--selected-active);
}
diff --git a/packages/core/src/components/group/group-context-menu.scss b/packages/core/src/components/group/group-context-menu.scss
index d50a9c79a6..3213d3c250 100644
--- a/packages/core/src/components/group/group-context-menu.scss
+++ b/packages/core/src/components/group/group-context-menu.scss
@@ -20,4 +20,8 @@
.hide {
visibility: collapse;
}
+
+ ::slotted(ix-dropdown) {
+ cursor: default;
+ }
}
diff --git a/packages/core/src/components/group/group.tsx b/packages/core/src/components/group/group.tsx
index 4f3a3122ac..ee4f8e6c95 100644
--- a/packages/core/src/components/group/group.tsx
+++ b/packages/core/src/components/group/group.tsx
@@ -12,7 +12,6 @@ import {
Element,
Event,
EventEmitter,
- Fragment,
h,
Host,
Prop,
@@ -85,6 +84,8 @@ export class Group {
@State() slotSize = this.groupItems.length;
@State() footerVisible = false;
+ @State() showExpandCollapsedIcon = false;
+
private observer: MutationObserver;
get dropdownItems() {
@@ -211,8 +212,9 @@ export class Group {
>
- {!this.collapsed ? (
-
-
-
- this.onSlotChange()}
- >
-
-
- ) : null}
+
+ {
+ const slot =
+ this.hostElement.shadowRoot.querySelector('slot:not([name])');
+ this.showExpandCollapsedIcon = hasSlottedElements(slot);
+ }}
+ >
+
+ this.onSlotChange()}
+ >
+
+
);
diff --git a/packages/core/src/components/group/test/group.ct.ts b/packages/core/src/components/group/test/group.ct.ts
new file mode 100644
index 0000000000..eb799cddab
--- /dev/null
+++ b/packages/core/src/components/group/test/group.ct.ts
@@ -0,0 +1,56 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Siemens AG
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { expect } from '@playwright/test';
+import { test } from '@utils/test';
+
+test('renders', async ({ mount, page }) => {
+ await mount(`
`);
+ const group = page.locator('ix-group');
+ await expect(group).toHaveClass(/hydrated/);
+});
+
+test('hide expand icon initial', async ({ mount, page }) => {
+ await mount(`
+
+
+ `);
+ const group = page.locator('ix-group');
+ await expect(group).toHaveClass(/hydrated/);
+
+ const expandIcon = group.getByTestId('expand-collapsed-icon');
+ await expect(expandIcon).not.toBeVisible();
+
+ await group.evaluate((group) => {
+ const item = document.createElement('ix-group-item');
+ group.appendChild(item);
+ });
+
+ await expect(expandIcon).toBeVisible();
+});
+
+test('show expand icon initial', async ({ mount, page }) => {
+ await mount(`
+
+ Item 1
+
+ `);
+ const group = page.locator('ix-group');
+ await expect(group).toHaveClass(/hydrated/);
+
+ const expandIcon = group.getByTestId('expand-collapsed-icon');
+ await expect(expandIcon).toBeVisible();
+
+ await group.evaluate((group) => {
+ const item = group.querySelector('ix-group-item');
+ item.remove();
+ });
+
+ await expect(expandIcon).not.toBeVisible();
+});
diff --git a/packages/core/src/components/icon-button/icon-button-mixin.scss b/packages/core/src/components/icon-button/icon-button-mixin.scss
index 92f98fb356..5e87c89f68 100644
--- a/packages/core/src/components/icon-button/icon-button-mixin.scss
+++ b/packages/core/src/components/icon-button/icon-button-mixin.scss
@@ -26,7 +26,7 @@
@include btn;
@include ix-component;
- $button-categories: (primary, secondary);
+ $button-categories: (danger, primary, secondary);
@each $category in $button-categories {
@include btn-variant($category);
diff --git a/packages/core/src/components/icon-button/icon-button.tsx b/packages/core/src/components/icon-button/icon-button.tsx
index c34b302b6b..901684e042 100644
--- a/packages/core/src/components/icon-button/icon-button.tsx
+++ b/packages/core/src/components/icon-button/icon-button.tsx
@@ -33,6 +33,7 @@ export class IconButton {
/**
* Variant of button
+ * @since 2.3.0 - variant danger
*/
@Prop() variant: IconButtonVariant = 'secondary';
diff --git a/packages/core/src/components/menu-about/menu-about.tsx b/packages/core/src/components/menu-about/menu-about.tsx
index a62399d0cc..8cf727e52b 100644
--- a/packages/core/src/components/menu-about/menu-about.tsx
+++ b/packages/core/src/components/menu-about/menu-about.tsx
@@ -40,7 +40,7 @@ export class MenuAbout {
@Prop({ mutable: true }) activeTabLabel: string;
/**
- * Label of first tab
+ * Content of the header
*/
@Prop() label = 'About & legal information';
diff --git a/packages/core/src/components/tooltip/tooltip.tsx b/packages/core/src/components/tooltip/tooltip.tsx
index e6c41835c0..ce93a023cf 100644
--- a/packages/core/src/components/tooltip/tooltip.tsx
+++ b/packages/core/src/components/tooltip/tooltip.tsx
@@ -231,7 +231,7 @@ export class Tooltip implements IxOverlayComponent {
}
}
- private async queryAnchorElements(): Promise
> {
+ private async queryAnchorElements(): Promise | undefined> {
if (typeof this.for === 'string') {
return Promise.resolve(Array.from(document.querySelectorAll(this.for)));
}
@@ -253,6 +253,10 @@ export class Tooltip implements IxOverlayComponent {
this.disposeListener();
}
+ if (!triggerElementList) {
+ return;
+ }
+
triggerElementList.forEach((element) => {
const onMouseEnter = () => {
this.showTooltip(element);
diff --git a/packages/core/src/components/workflow-step/workflow-step.scss b/packages/core/src/components/workflow-step/workflow-step.scss
index e1adf59ae4..66a73a67bb 100644
--- a/packages/core/src/components/workflow-step/workflow-step.scss
+++ b/packages/core/src/components/workflow-step/workflow-step.scss
@@ -10,8 +10,26 @@
@import 'common-variables';
@import 'mixins/shadow-dom/component';
+:host(:not(.host-vertical)) {
+ width: 12rem;
+ height: 4rem;
+ min-width: 2rem;
+ min-height: 4rem;
+ max-width: 12rem;
+}
+
+:host(.host-vertical) {
+ width: 100%;
+ height: 4rem;
+ min-width: 4rem;
+ min-height: 2rem;
+ max-height: 12rem;
+}
+
:host {
@include ix-component;
+ display: inline-block;
+ position: relative;
.step {
display: flex;
@@ -19,10 +37,7 @@
align-items: center;
background-color: var(--theme-workflow-step--background);
border-radius: var(--theme-workflow--border-radius);
- width: auto;
padding: 1.125rem 0 $small-space 0;
- height: 4rem;
- width: 12.75rem;
.wrapper {
display: flex;
@@ -52,7 +67,7 @@
&.selected {
background-color: var(
- --theme-workflow-step-icon-default--color--selected
+ --theme-workflow-step-icon-default--color--selected
);
}
@@ -61,7 +76,7 @@
&.selected {
background-color: var(
- --theme-workflow-step-icon-done--color--selected
+ --theme-workflow-step-icon-done--color--selected
);
}
}
@@ -93,18 +108,24 @@
.text {
margin-top: $default-space;
- width: auto;
+ width: 100%;
padding: 0 $small-space;
+
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ text-align: center;
}
&.vertical {
flex-direction: row;
padding: 0;
+ height: 100%;
.wrapper {
width: auto;
padding-left: 1.125rem;
- height: 4rem;
+ height: 100%;
.line {
width: 0.125rem;
@@ -127,9 +148,9 @@
}
.text {
- margin-top: 0;
- margin-left: $default-space;
+ margin: 0 $default-space;
padding: 0;
+ width: auto;
}
}
diff --git a/packages/core/src/components/workflow-step/workflow-step.tsx b/packages/core/src/components/workflow-step/workflow-step.tsx
index 8c25ba0633..a320725f1c 100644
--- a/packages/core/src/components/workflow-step/workflow-step.tsx
+++ b/packages/core/src/components/workflow-step/workflow-step.tsx
@@ -157,7 +157,10 @@ export class WorkflowStep {
) : null;
return (
- this.onStepClick()}>
+ this.onStepClick()}
+ >
Hallo
Hallo
+ Hallo
Hallo
Hallo
+ Hallo
Hallo
Hallo
+ Hallo
Hallo
Hallo
+ Hallo
Hallo
Hallo
+ Hallo
Hallo
Hallo
+ Hallo