diff --git a/.changeset/clever-rings-sneeze.md b/.changeset/clever-rings-sneeze.md new file mode 100644 index 00000000000..2da4c88a555 --- /dev/null +++ b/.changeset/clever-rings-sneeze.md @@ -0,0 +1,5 @@ +--- +'@siemens/ix': patch +--- + +fix(core/modal): figma - code mismatch diff --git a/.changeset/eight-windows-shout.md b/.changeset/eight-windows-shout.md new file mode 100644 index 00000000000..5849541ebac --- /dev/null +++ b/.changeset/eight-windows-shout.md @@ -0,0 +1,7 @@ +--- +"@siemens/ix-angular": minor +"@siemens/ix": minor +"@siemens/ix-vue": minor +--- + +feat(core): improve component a11y diff --git a/.changeset/eighty-clocks-bake.md b/.changeset/eighty-clocks-bake.md new file mode 100644 index 00000000000..3a82b265133 --- /dev/null +++ b/.changeset/eighty-clocks-bake.md @@ -0,0 +1,5 @@ +--- +'@siemens/ix': patch +--- + +fix(core/content-header): adapt spacing diff --git a/.changeset/few-eels-smell.md b/.changeset/few-eels-smell.md new file mode 100644 index 00000000000..a7da8bf7746 --- /dev/null +++ b/.changeset/few-eels-smell.md @@ -0,0 +1,5 @@ +--- +'@siemens/ix': patch +--- + +fix(core/checkbox): page jumps on checkbox click in scrollable ix-content diff --git a/.changeset/nasty-mangos-love.md b/.changeset/nasty-mangos-love.md new file mode 100644 index 00000000000..f8632ceafac --- /dev/null +++ b/.changeset/nasty-mangos-love.md @@ -0,0 +1,5 @@ +--- +'@siemens/ix': patch +--- + +fix(core/button): fix keyboard navigation & accessibility diff --git a/.changeset/small-meals-think.md b/.changeset/small-meals-think.md new file mode 100644 index 00000000000..f4378c8426a --- /dev/null +++ b/.changeset/small-meals-think.md @@ -0,0 +1,5 @@ +--- +'@siemens/ix': patch +--- + +fix(core/card-list): adapt title margin to figma diff --git a/packages/angular/src/components.ts b/packages/angular/src/components.ts index 9eb6d100afe..2bf486f7404 100644 --- a/packages/angular/src/components.ts +++ b/packages/angular/src/components.ts @@ -350,14 +350,14 @@ export declare interface IxCardTitle extends Components.IxCardTitle {} @ProxyCmp({ - inputs: ['categories', 'disabled', 'filterState', 'hideIcon', 'i18nPlainText', 'icon', 'labelCategories', 'nonSelectableCategories', 'placeholder', 'readonly', 'repeatCategories', 'staticOperator', 'suggestions'] + inputs: ['ariaLabel', 'categories', 'disabled', 'filterState', 'hideIcon', 'i18nPlainText', 'icon', 'labelCategories', 'nonSelectableCategories', 'placeholder', 'readonly', 'repeatCategories', 'staticOperator', 'suggestions'] }) @Component({ selector: 'ix-category-filter', changeDetection: ChangeDetectionStrategy.OnPush, template: '', // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property - inputs: ['categories', 'disabled', 'filterState', 'hideIcon', 'i18nPlainText', 'icon', 'labelCategories', 'nonSelectableCategories', 'placeholder', 'readonly', 'repeatCategories', 'staticOperator', 'suggestions'], + inputs: ['ariaLabel', 'categories', 'disabled', 'filterState', 'hideIcon', 'i18nPlainText', 'icon', 'labelCategories', 'nonSelectableCategories', 'placeholder', 'readonly', 'repeatCategories', 'staticOperator', 'suggestions'], }) export class IxCategoryFilter { protected el: HTMLElement; diff --git a/packages/core/component-doc.json b/packages/core/component-doc.json index 87cd7b7865b..87755143ae3 100644 --- a/packages/core/component-doc.json +++ b/packages/core/component-doc.json @@ -583,7 +583,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -604,7 +604,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -625,7 +625,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -651,7 +651,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false } ], @@ -1533,7 +1533,13 @@ "styles": [], "slots": [], "parts": [], - "listeners": [] + "listeners": [ + { + "event": "click", + "capture": true, + "passive": false + } + ] }, { "dirPath": "src/components/card", @@ -1936,7 +1942,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -1970,7 +1976,7 @@ "name": "showAllCount", "type": "number", "complexType": { - "original": "number | undefined", + "original": "number", "resolved": "number", "references": {} }, @@ -1984,7 +1990,7 @@ "type": "number" } ], - "optional": false, + "optional": true, "required": false }, { @@ -2154,6 +2160,33 @@ ] }, "props": [ + { + "name": "ariaLabel", + "type": "string", + "complexType": { + "original": "string", + "resolved": "string", + "references": {} + }, + "mutable": false, + "attr": "aria-label", + "reflectToAttr": false, + "docs": "Aria label for the filter input field", + "docsTags": [ + { + "name": "since", + "text": "2.6.0" + } + ], + "default": "'Filter'", + "values": [ + { + "type": "string" + } + ], + "optional": false, + "required": false + }, { "name": "categories", "type": "{ [id: string]: { label: string; options: string[]; }; }", @@ -6302,6 +6335,7 @@ "reflectToAttr": false, "docs": "Display a chevron icon in list items. Defaults to 'false'", "docsTags": [], + "default": "false", "values": [ { "type": "boolean" @@ -6399,6 +6433,7 @@ "reflectToAttr": false, "docs": "Show chevron on right side of the event list item", "docsTags": [], + "default": "false", "values": [ { "type": "boolean" @@ -6435,7 +6470,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -6451,6 +6486,7 @@ "reflectToAttr": false, "docs": "Disable event list item", "docsTags": [], + "default": "false", "values": [ { "type": "boolean" @@ -6482,7 +6518,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -6498,6 +6534,7 @@ "reflectToAttr": false, "docs": "Show event list item as selected", "docsTags": [], + "default": "false", "values": [ { "type": "boolean" @@ -9281,7 +9318,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -11736,7 +11773,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -11757,7 +11794,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false } ], @@ -12186,7 +12223,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { @@ -12229,7 +12266,7 @@ "type": "string" } ], - "optional": false, + "optional": true, "required": false }, { diff --git a/packages/core/scss/components/_checkboxes.scss b/packages/core/scss/components/_checkboxes.scss index d984f2f7176..c477e8d7d68 100755 --- a/packages/core/scss/components/_checkboxes.scss +++ b/packages/core/scss/components/_checkboxes.scss @@ -13,18 +13,11 @@ /* Base for label styling */ [type='checkbox']:not(:checked), [type='checkbox']:checked { - clip: rect(0 0 0 0); - clip-path: inset(50%); - height: 1px; - width: 1px; - max-height: 1px; - max-width: 1px; - min-height: 0px; - min-width: 0px; - overflow: hidden; position: absolute; - white-space: nowrap; - appearance: none; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; } [type='checkbox']:not(:checked) + label, diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index d0f874aa83c..c25aad2d9eb 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -163,20 +163,20 @@ export namespace Components { * Optional description text that will be displayed underneath the username. Note: Only working if avatar is part of the ix-application-header * @since 2.1.0 */ - "extra": string; + "extra"?: string; /** * Display an avatar image */ - "image": string; + "image"?: string; /** * Display the initials of the user. Will be overwritten by image */ - "initials": string; + "initials"?: string; /** * If set an info card displaying the username will be placed inside the dropdown. Note: Only working if avatar is part of the ix-application-header * @since 2.1.0 */ - "username": string; + "username"?: string; } interface IxBasicNavigation { /** @@ -342,7 +342,7 @@ export namespace Components { /** * Name the card list */ - "label": string; + "label"?: string; /** * List style */ @@ -354,7 +354,7 @@ export namespace Components { /** * Overwrite the default show all count. */ - "showAllCount": number | undefined; + "showAllCount"?: number; /** * Suppress the overflow handling of child elements */ @@ -366,6 +366,11 @@ export namespace Components { interface IxCardTitle { } interface IxCategoryFilter { + /** + * Aria label for the filter input field + * @since 2.6.0 + */ + "ariaLabel": string; /** * Configuration object hash used to populate the dropdown menu for type-ahead and quick selection functionality. Each ID maps to an object with a label and an array of options to select from. */ @@ -987,7 +992,7 @@ export namespace Components { * @link https://ix.siemens.io/docs/theming/colors/ * @deprecated since 2.1.0 use `item-color` */ - "color": string; + "color"?: string; /** * Disable event list item */ @@ -996,7 +1001,7 @@ export namespace Components { * Color of the status indicator. You can find a list of all available colors in our documentation. Example values are `--theme-color-alarm` or `color-alarm` * @link https://ix.siemens.io/docs/theming/colors/ */ - "itemColor": string; + "itemColor"?: string; /** * Show event list item as selected */ @@ -1348,7 +1353,7 @@ export namespace Components { /** * Should only be set if you use ix-menu standalone */ - "applicationName": string; + "applicationName"?: string; /** * Internal */ @@ -1676,11 +1681,11 @@ export namespace Components { /** * Icon of the Header */ - "icon": string; + "icon"?: string; /** * Icon color */ - "iconColor": string; + "iconColor"?: string; } interface IxModalLoading { } @@ -1740,7 +1745,7 @@ export namespace Components { /** * Title of the side panel */ - "heading": string; + "heading"?: string; /** * Define if the pane should have a collapsed state */ @@ -1748,7 +1753,7 @@ export namespace Components { /** * Name of the icon */ - "icon": string; + "icon"?: string; "ignoreLayoutSettings": boolean; "isMobile": boolean; /** @@ -4430,7 +4435,7 @@ declare namespace LocalJSX { /** * Overwrite the default show all count. */ - "showAllCount"?: number | undefined; + "showAllCount"?: number; /** * Suppress the overflow handling of child elements */ @@ -4442,6 +4447,11 @@ declare namespace LocalJSX { interface IxCardTitle { } interface IxCategoryFilter { + /** + * Aria label for the filter input field + * @since 2.6.0 + */ + "ariaLabel"?: string; /** * Configuration object hash used to populate the dropdown menu for type-ahead and quick selection functionality. Each ID maps to an object with a label and an array of options to select from. */ diff --git a/packages/core/src/components/avatar/avatar.scss b/packages/core/src/components/avatar/avatar.scss index 5a69d88c526..d1f668bea67 100644 --- a/packages/core/src/components/avatar/avatar.scss +++ b/packages/core/src/components/avatar/avatar.scss @@ -106,7 +106,7 @@ @include btn-base-variant('invisible-primary', false); - li { + .avatar { transform: scale(0.8); } } diff --git a/packages/core/src/components/avatar/avatar.tsx b/packages/core/src/components/avatar/avatar.tsx index 04b1f4f2b5e..1e6cbfc55c6 100644 --- a/packages/core/src/components/avatar/avatar.tsx +++ b/packages/core/src/components/avatar/avatar.tsx @@ -53,23 +53,23 @@ function DefaultAvatar(props: { initials?: string }) { ); } -function AvatarImage(props: { image: string; initials: string }) { +function AvatarImage(props: { image?: string; initials?: string }) { return ( -
  • +
    {props.image ? ( ) : ( )} -
  • + ); } function UserInfo(props: { - image: string; - initials: string; + image?: string; + initials?: string; userName: string; - extra: string; + extra?: string; }) { return ( @@ -97,19 +97,19 @@ function UserInfo(props: { shadow: true, }) export class Avatar { - @Element() hostElement: HTMLIxAvatarElement; + @Element() hostElement!: HTMLIxAvatarElement; /** * Display an avatar image * */ - @Prop() image: string; + @Prop() image?: string; /** * Display the initials of the user. Will be overwritten by image * */ - @Prop() initials: string; + @Prop() initials?: string; /** * If set an info card displaying the username will be placed inside the dropdown. @@ -117,7 +117,7 @@ export class Avatar { * * @since 2.1.0 */ - @Prop() username: string; + @Prop() username?: string; /** * Optional description text that will be displayed underneath the username. @@ -125,13 +125,13 @@ export class Avatar { * * @since 2.1.0 */ - @Prop() extra: string; + @Prop() extra?: string; @State() isClosestApplicationHeader = false; @State() hasSlottedElements = false; - private slotElement: HTMLSlotElement; - private dropdownElement: HTMLIxDropdownElement; + private slotElement?: HTMLSlotElement; + private dropdownElement?: HTMLIxDropdownElement; componentWillLoad() { const closest = closestElement('ix-application-header', this.hostElement); @@ -143,10 +143,15 @@ export class Avatar { } private resolveAvatarTrigger() { - return new Promise((resolve) => { - readTask(() => - resolve(this.hostElement.shadowRoot.querySelector('button')) - ); + return new Promise((resolve, reject) => { + readTask(() => { + const button = this.hostElement.shadowRoot!.querySelector('button'); + if (button) { + resolve(button); + } else { + reject(new Error('ix-avatar - trigger element not found')); + } + }); }); } diff --git a/packages/core/src/components/button/button.tsx b/packages/core/src/components/button/button.tsx index 3e78601326f..005c91e53e4 100644 --- a/packages/core/src/components/button/button.tsx +++ b/packages/core/src/components/button/button.tsx @@ -7,7 +7,7 @@ * LICENSE file in the root directory of this source tree. */ -import { Component, Element, h, Host, Prop } from '@stencil/core'; +import { Component, Element, h, Host, Listen, Prop } from '@stencil/core'; import { BaseButton, BaseButtonProps } from './base-button'; export type ButtonVariant = 'danger' | 'primary' | 'secondary'; @@ -69,6 +69,14 @@ export class Button { */ submitButtonElement?: HTMLButtonElement; + @Listen('click', { capture: true }) + handleClick(event: Event) { + if (this.disabled || this.loading) { + event.stopPropagation(); + event.preventDefault(); + } + } + componentDidLoad() { if (this.type === 'submit') { const submitButton = document.createElement('button'); @@ -82,7 +90,12 @@ export class Button { } dispatchFormEvents() { - if (this.type === 'submit' && this.submitButtonElement) { + if ( + this.type === 'submit' && + this.submitButtonElement && + !this.disabled && + !this.loading + ) { this.submitButtonElement.click(); } } diff --git a/packages/core/src/components/card-list/card-list.scss b/packages/core/src/components/card-list/card-list.scss index dfa50b70c00..75177d35976 100644 --- a/packages/core/src/components/card-list/card-list.scss +++ b/packages/core/src/components/card-list/card-list.scss @@ -25,7 +25,7 @@ $CardList__Title__Height: 1.5rem; height: $CardList__Title__Height; align-items: center; width: 100%; - margin-bottom: 0.5rem; + margin-bottom: 1rem; &__Label { overflow: hidden; diff --git a/packages/core/src/components/card-list/card-list.tsx b/packages/core/src/components/card-list/card-list.tsx index 0d07809e3fb..b2130de913f 100644 --- a/packages/core/src/components/card-list/card-list.tsx +++ b/packages/core/src/components/card-list/card-list.tsx @@ -12,7 +12,7 @@ import { import { createMutationObserver } from '../utils/mutation-observer'; function CardListTitle(props: { - label: string; + label?: string; isCollapsed: boolean; onClick: (e: MouseEvent) => void; onShowAllClick: (e: MouseEvent) => void; @@ -20,7 +20,7 @@ function CardListTitle(props: { showAllCounter: number; hideShowAll: boolean; }) { - if (props.label === '') { + if (!props.label) { return null; } @@ -67,7 +67,7 @@ export class CardList { /** * Name the card list */ - @Prop() label: string; + @Prop() label?: string; /** * Collapse the list @@ -89,7 +89,7 @@ export class CardList { /** * Overwrite the default show all count. * */ - @Prop() showAllCount: number | undefined; + @Prop() showAllCount?: number; /** * Suppress the overflow handling of child elements @@ -116,23 +116,23 @@ export class CardList { /** * Fire event when the collapse state is changed by the user */ - @Event() collapseChanged: EventEmitter; + @Event() collapseChanged!: EventEmitter; /** * Fire event when the collapse state is changed by the user */ - @Event() showAllClick: EventEmitter<{ + @Event() showAllClick!: EventEmitter<{ nativeEvent: MouseEvent; }>; /** * Fire event when the show more card is clicked. */ - @Event() showMoreCardClick: EventEmitter<{ + @Event() showMoreCardClick!: EventEmitter<{ nativeEvent: MouseEvent; }>; - @Element() hostElement: HTMLIxCardListElement; + @Element() hostElement!: HTMLIxCardListElement; @State() private hasOverflowingElements = false; @State() private numberOfOverflowingElements = 0; @@ -140,7 +140,7 @@ export class CardList { @State() private leftScrollDistance = 0; @State() private rightScrollDistance = 0; - private observer: MutationObserver; + private observer?: MutationObserver; private onCardListVisibilityToggle() { this.collapse = !this.collapse; @@ -154,7 +154,7 @@ export class CardList { } private getListChildren() { - const slot = this.hostElement.shadowRoot.querySelector( + const slot = this.hostElement.shadowRoot!.querySelector( '.CardList__Content > slot' ) as HTMLSlotElement; return slot.assignedElements({ flatten: true }); @@ -185,7 +185,7 @@ export class CardList { }); this.observer.observe( - this.hostElement.shadowRoot.querySelector('.CardList__Content'), + this.hostElement.shadowRoot!.querySelector('.CardList__Content')!, { childList: true, subtree: true, @@ -207,7 +207,7 @@ export class CardList { } private get listElement() { - return this.hostElement.shadowRoot.querySelector('.CardList__Content'); + return this.hostElement.shadowRoot!.querySelector('.CardList__Content'); } private onCardListScroll() { @@ -260,6 +260,9 @@ export class CardList { @Listen('resize', { target: 'window' }) private detectOverflow() { + if (!this.listElement) { + return; + } const { clientWidth, scrollWidth, scrollLeft } = this.listElement; this.leftScrollDistance = scrollLeft; diff --git a/packages/core/src/components/category-filter/category-filter.scss b/packages/core/src/components/category-filter/category-filter.scss index 61b2fa31a97..7cecadf8d92 100644 --- a/packages/core/src/components/category-filter/category-filter.scss +++ b/packages/core/src/components/category-filter/category-filter.scss @@ -95,9 +95,7 @@ .list-unstyled { display: flex; flex-wrap: wrap; - list-style: none; - padding: 0; - margin: 0; + height: 100%; overflow-y: auto; } @@ -126,7 +124,7 @@ height: 100%; } - ul > li, + .list-unstyled > span:not(.category-preview), input { padding-inline-start: 0; padding-top: 2px; diff --git a/packages/core/src/components/category-filter/category-filter.tsx b/packages/core/src/components/category-filter/category-filter.tsx index 6a572a05459..105f54c94ad 100644 --- a/packages/core/src/components/category-filter/category-filter.tsx +++ b/packages/core/src/components/category-filter/category-filter.tsx @@ -138,6 +138,13 @@ export class CategoryFilter { */ @Prop() i18nPlainText = 'Filter by text'; + /** + * Aria label for the filter input field + * + * @since 2.6.0 + */ + @Prop() ariaLabel = 'Filter'; + /** * Event dispatched whenever a category gets selected in the dropdown */ @@ -710,9 +717,9 @@ export class CategoryFilter { size="16" >
    -
      +
      {this.filterTokens.map((value, index) => ( -
    • {this.getFilterChipLabel(value)} -
    • + ))} {this.categories === undefined ? ( '' ) : ( -
    • {this.categories[this.category]?.label} -
    • + )} (this.textInput = el)} type="text" placeholder={this.placeholder} + aria-label={this.ariaLabel} > -
    +
    {!this.readonly && !this.disabled && this.getResetButton()} diff --git a/packages/core/src/components/content-header/content-header.scss b/packages/core/src/components/content-header/content-header.scss index 84ac84b54dd..c9cce370699 100644 --- a/packages/core/src/components/content-header/content-header.scss +++ b/packages/core/src/components/content-header/content-header.scss @@ -11,16 +11,20 @@ display: flex; flex-direction: row; align-items: flex-start; - padding: 0px; + padding: 0; .titleGroup { display: flex; flex-direction: column; - flex: 1 1 0%; + flex: 1 1 0; + + .secondary { + padding: 0.25rem 0; + } } .subtitle { - margin-top: 0.5rem; + margin-top: -0.125rem; } .backButton { diff --git a/packages/core/src/components/content-header/content-header.tsx b/packages/core/src/components/content-header/content-header.tsx index 927b1ae5b94..6ad134af1e3 100644 --- a/packages/core/src/components/content-header/content-header.tsx +++ b/packages/core/src/components/content-header/content-header.tsx @@ -56,14 +56,21 @@ export class ContentHeader { ) : null}
    - + {this.headerTitle} - {this.headerSubtitle !== undefined ? ( - + {!!this.headerSubtitle && ( + {this.headerSubtitle} - ) : null} + )}
    diff --git a/packages/core/src/components/content/content.scss b/packages/core/src/components/content/content.scss index 7008702ae71..da0330faee0 100644 --- a/packages/core/src/components/content/content.scss +++ b/packages/core/src/components/content/content.scss @@ -24,6 +24,7 @@ flex-grow: 1; overflow: auto; padding-right: 1.5rem; + position: relative; } .content-header.slotted { diff --git a/packages/core/src/components/content/content.tsx b/packages/core/src/components/content/content.tsx index 15a4f46fa7e..11d42a15c36 100644 --- a/packages/core/src/components/content/content.tsx +++ b/packages/core/src/components/content/content.tsx @@ -25,7 +25,7 @@ export class Content { @State() isContentHeaderSlotted = false; get contentHeaderSlot() { - return this.hostElement.shadowRoot.querySelector( + return this.hostElement.shadowRoot!.querySelector( '.content-header slot' ) as HTMLSlotElement; } diff --git a/packages/core/src/components/date-picker/date-picker.tsx b/packages/core/src/components/date-picker/date-picker.tsx index 74933790d14..24c145d8144 100644 --- a/packages/core/src/components/date-picker/date-picker.tsx +++ b/packages/core/src/components/date-picker/date-picker.tsx @@ -147,6 +147,7 @@ export class DatePicker { * @since 2.1.0 */ @Prop() locale: string = undefined; + @Watch('locale') onLocaleChange() { this.setTranslations(); @@ -518,7 +519,11 @@ export class DatePicker { } } - private selectDay(selectedDay: number) { + private selectDay(selectedDay: number, target: Element) { + if (target.classList.contains('disabled')) { + return; + } + const date = DateTime.fromJSDate( new Date(this.selectedYear, this.selectedMonth, selectedDay) ); @@ -781,8 +786,16 @@ export class DatePicker { id={`day-cell-${day}`} date-calender-day class={this.getDayClasses(day)} - onClick={() => this.selectDay(day)} - onKeyUp={(e) => e.key === 'Enter' && this.selectDay(day)} + onClick={(e) => { + const target = e.currentTarget as HTMLElement; + this.selectDay(day, target); + }} + onKeyUp={(e) => { + const target = e.currentTarget as HTMLElement; + if (e.key === 'Enter') { + this.selectDay(day, target); + } + }} tabIndex={day === this.focusedDay ? 0 : -1} onFocus={() => this.onDayFocus()} onBlur={() => this.onDayBlur()} diff --git a/packages/core/src/components/date-picker/test/date-picker.ct.ts b/packages/core/src/components/date-picker/test/date-picker.ct.ts index 95f359bef7e..31e6315d83b 100644 --- a/packages/core/src/components/date-picker/test/date-picker.ct.ts +++ b/packages/core/src/components/date-picker/test/date-picker.ct.ts @@ -36,6 +36,37 @@ test('translation', async ({ mount, page }) => { await expect(header).toHaveCount(1); }); +test.describe('date picker tests single', () => { + test.beforeEach(async ({ mount }) => { + await mount( + `` + ); + }); + + test('select disabled date with enter', async ({ page }) => { + await page.waitForSelector('ix-date-time-card'); + + await page.getByText(/^9$/).focus(); + await page.keyboard.press('Enter'); + + expect((await getDateObj(page))[0]).toEqual({ + from: '2024/10/10', + to: undefined, + }); + }); + + test('select disabled date with click', async ({ page }) => { + await page.waitForSelector('ix-date-time-card'); + + await page.getByText(/^9$/).click({ force: true }); + + expect((await getDateObj(page))[0]).toEqual({ + from: '2024/10/10', + to: undefined, + }); + }); +}); + test.describe('date picker tests single', () => { test.beforeEach(async ({ mount }) => { await mount( 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 4519e60db6b..d86eddd65f5 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 @@ -34,7 +34,7 @@ export class EventListItem { * @deprecated since 2.1.0 use `item-color` */ // eslint-disable-next-line @stencil-community/reserved-member-names - @Prop() color: string; + @Prop() color?: string; /** * Color of the status indicator. @@ -43,27 +43,27 @@ export class EventListItem { * * @link https://ix.siemens.io/docs/theming/colors/ */ - @Prop() itemColor: string; + @Prop() itemColor?: string; /** * Show event list item as selected */ - @Prop() selected: boolean; + @Prop() selected = false; /** * Disable event list item */ - @Prop() disabled: boolean; + @Prop() disabled = false; /** * Show chevron on right side of the event list item */ - @Prop() chevron: boolean; + @Prop() chevron = false; /** * Event list item click */ - @Event() itemClick: EventEmitter; + @Event() itemClick!: EventEmitter; @Listen('click', { passive: true }) handleItemClick() { @@ -87,7 +87,8 @@ export class EventListItem { disabled: this.disabled, }} > -
  • )}
  • - + ); } diff --git a/packages/core/src/components/event-list/event-list.scss b/packages/core/src/components/event-list/event-list.scss index f88c0acd2a6..3210978083a 100644 --- a/packages/core/src/components/event-list/event-list.scss +++ b/packages/core/src/components/event-list/event-list.scss @@ -14,13 +14,6 @@ display: block; position: relative; - - ul { - list-style: none; - padding: 0; - margin-top: 0; - margin-bottom: 0; - } } :host(.item-size-l) { diff --git a/packages/core/src/components/event-list/event-list.tsx b/packages/core/src/components/event-list/event-list.tsx index e4a87d43c29..115e9923faf 100644 --- a/packages/core/src/components/event-list/event-list.tsx +++ b/packages/core/src/components/event-list/event-list.tsx @@ -48,7 +48,7 @@ export class EventList { /** * Display a chevron icon in list items. Defaults to 'false' */ - @Prop() chevron: boolean; + @Prop() chevron = false; @Watch('chevron') watchChevron(chevron: boolean | undefined) { @@ -111,7 +111,7 @@ export class EventList { const keyframes = [{ opacity: 1, easing: 'easeInSine' }, { opacity: 0 }]; - const listElement = this.hostElement.shadowRoot.querySelector('ul'); + const listElement = this.hostElement.shadowRoot!.querySelector('ul'); anime({ targets: listElement, @@ -166,9 +166,9 @@ export class EventList { compact: this.compact, }} > -
      +
      -
    + ); } 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 deleted file mode 100644 index 513c9cdc0ad..00000000000 --- a/packages/core/src/components/event-list/test/event-list.spec.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 { newSpecPage } from '@stencil/core/testing'; -//@ts-ignore -import { createMutationObserver } from '../../utils/mutation-observer'; -import { EventList } from '../event-list'; - -jest.mock('../../utils/mutation-observer'); - -describe('event-list', () => { - beforeEach(() => { - //@ts-ignore - createMutationObserver = jest.fn(() => ({ - observe: jest.fn(), - })); - }); - - it('renders', async () => { - const page = await newSpecPage({ - components: [EventList], - html: ` - - - - `, - }); - expect(page.root).toEqualHtml(` - - -
      - -
    -
    - -
    - `); - }); - - it('compact', async () => { - const page = await newSpecPage({ - components: [EventList], - html: ` - - - - `, - }); - - const eventList = page.doc.querySelector( - 'ix-event-list' - ) as HTMLIxEventListElement; - - eventList.compact = true; - - await page.waitForChanges(); - - expect(page.root).toEqualHtml(` - - -
      - -
    -
    - -
    - `); - }); -}); diff --git a/packages/core/src/components/menu-item/menu-item.tsx b/packages/core/src/components/menu-item/menu-item.tsx index e5c3573a880..328bcc5575c 100644 --- a/packages/core/src/components/menu-item/menu-item.tsx +++ b/packages/core/src/components/menu-item/menu-item.tsx @@ -76,11 +76,11 @@ export class MenuItem { @State() tooltip?: string; @State() menuExpanded: boolean = false; - private buttonRef = makeRef(); + private readonly buttonRef = makeRef(); private isHostedInsideCategory = false; - private menuExpandedDisposer: Disposable; + private menuExpandedDisposer?: Disposable; - private observer: MutationObserver = createMutationObserver(() => { + private readonly observer: MutationObserver = createMutationObserver(() => { this.setTooltip(); }); @@ -91,7 +91,7 @@ export class MenuItem { this.onIconChange(); this.onTabIconChange(); - this.menuExpanded = menuController.nativeElement.expand; + this.menuExpanded = menuController.nativeElement?.expand || false; this.menuExpandedDisposer = menuController.expandChange.on( (expand) => (this.menuExpanded = expand) ); @@ -102,7 +102,7 @@ export class MenuItem { } setTooltip() { - this.tooltip = this.label ?? this.hostElement.textContent; + this.tooltip = this.label ?? this.hostElement.textContent ?? undefined; } connectedCallback() { @@ -172,7 +172,6 @@ export class MenuItem {