From e8d4d0f7852763b8988c2f85c3ae0b4d1086e9ad Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Thu, 9 Jul 2026 12:46:39 +0300 Subject: [PATCH 01/12] feat(badge): add badge component IX-3943 --- .changeset/ix-3943-badge.md | 8 + .../src/app/app.routes.ts | 10 + .../src/preview-examples/badge-counter.css | 19 + .../src/preview-examples/badge-counter.ts | 62 ++ .../src/preview-examples/badge-dot.css | 19 + .../src/preview-examples/badge-dot.ts | 62 ++ .../src/preview-examples/badge-label.css | 18 + .../src/preview-examples/badge-label.ts | 58 ++ .../preview-examples/badge-status-icon.css | 19 + .../src/preview-examples/badge-status-icon.ts | 52 ++ .../src/preview-examples/badge.css | 28 + .../src/preview-examples/badge.ts | 55 ++ .../src/app/app-routing.module.ts | 25 + .../angular-test-app/src/app/app.module.ts | 10 + .../src/preview-examples/badge-counter.css | 19 + .../src/preview-examples/badge-counter.html | 42 + .../src/preview-examples/badge-counter.ts | 18 + .../src/preview-examples/badge-dot.css | 19 + .../src/preview-examples/badge-dot.html | 42 + .../src/preview-examples/badge-dot.ts | 18 + .../src/preview-examples/badge-label.css | 18 + .../src/preview-examples/badge-label.html | 34 + .../src/preview-examples/badge-label.ts | 22 + .../preview-examples/badge-status-icon.css | 19 + .../preview-examples/badge-status-icon.html | 32 + .../src/preview-examples/badge-status-icon.ts | 18 + .../src/preview-examples/badge.css | 28 + .../src/preview-examples/badge.html | 31 + .../src/preview-examples/badge.ts | 22 + packages/angular/src/components.ts | 23 + packages/angular/src/declare-components.ts | 1 + packages/angular/standalone/src/components.ts | 24 + packages/core/src/components.d.ts | 242 ++++++ packages/core/src/components/badge/badge.scss | 427 ++++++++++ .../src/components/badge/badge.status-icon.ts | 119 +++ packages/core/src/components/badge/badge.tsx | 646 ++++++++++++++++ .../core/src/components/badge/badge.types.ts | 50 ++ .../core/src/components/badge/badge.utils.ts | 77 ++ .../src/components/badge/test/badge.ct.ts | 728 ++++++++++++++++++ .../src/components/badge/test/badge.page.ts | 274 +++++++ .../src/components/badge/test/badge.spec.ts | 160 ++++ .../menu-category/test/menu-category.ct.ts | 4 +- .../src/preview-examples/badge-counter.css | 19 + .../src/preview-examples/badge-counter.html | 63 ++ .../src/preview-examples/badge-dot.css | 19 + .../src/preview-examples/badge-dot.html | 63 ++ .../src/preview-examples/badge-label.css | 18 + .../src/preview-examples/badge-label.html | 60 ++ .../preview-examples/badge-status-icon.css | 19 + .../preview-examples/badge-status-icon.html | 53 ++ .../src/preview-examples/badge.css | 28 + .../src/preview-examples/badge.html | 57 ++ packages/react-test-app/src/main.tsx | 20 +- .../preview-examples/badge-counter.scoped.css | 19 + .../src/preview-examples/badge-counter.tsx | 167 ++++ .../src/preview-examples/badge-dot.scoped.css | 19 + .../src/preview-examples/badge-dot.tsx | 262 +++++++ .../preview-examples/badge-label.scoped.css | 18 + .../src/preview-examples/badge-label.tsx | 263 +++++++ .../badge-status-icon.scoped.css | 19 + .../preview-examples/badge-status-icon.tsx | 192 +++++ .../src/preview-examples/badge.scoped.css | 28 + .../src/preview-examples/badge.tsx | 137 ++++ .../react/src/components/components.server.ts | 27 + packages/react/src/components/components.ts | 12 + .../.storybook/define-custom-elements.ts | 2 + .../badge/accessibility/a11y-badge.stories.ts | 120 +++ .../src/stories/badge/badge-preview.css | 193 +++++ .../src/stories/badge/badge-preview.shared.ts | 342 ++++++++ .../src/stories/badge/counter.stories.ts | 432 +++++++++++ .../src/stories/badge/dot.stories.ts | 239 ++++++ .../src/stories/badge/label.stories.ts | 291 +++++++ .../src/stories/badge/status-icon.stories.ts | 249 ++++++ packages/vue-test-app/src/Root.vue | 10 + .../src/preview-examples/badge-counter.css | 19 + .../src/preview-examples/badge-counter.vue | 59 ++ .../src/preview-examples/badge-dot.css | 19 + .../src/preview-examples/badge-dot.vue | 59 ++ .../src/preview-examples/badge-label.css | 18 + .../src/preview-examples/badge-label.vue | 52 ++ .../preview-examples/badge-status-icon.css | 19 + .../preview-examples/badge-status-icon.vue | 49 ++ .../src/preview-examples/badge.css | 28 + .../src/preview-examples/badge.vue | 49 ++ packages/vue/src/components/components.ts | 1 + packages/vue/src/components/ix-badge.ts | 25 + .../__snapshots__/badge-aria-snapshot.yaml | 14 + .../badge-counter-aria-snapshot.yaml | 1 + .../badge-dot-aria-snapshot.yaml | 33 + .../badge-label-aria-snapshot.yaml | 1 + .../badge-status-icon-aria-snapshot.yaml | 25 + .../framework-tests/tests/generated/axe.ts | 5 + .../tests/generated/badge-axe.spec.ts | 26 + .../tests/generated/badge-counter-axe.spec.ts | 26 + .../tests/generated/badge-counter.spec.ts | 26 + .../tests/generated/badge-dot-axe.spec.ts | 26 + .../tests/generated/badge-dot.spec.ts | 26 + .../tests/generated/badge-label-axe.spec.ts | 26 + .../tests/generated/badge-label.spec.ts | 26 + .../generated/badge-status-icon-axe.spec.ts | 26 + .../tests/generated/badge-status-icon.spec.ts | 26 + .../tests/generated/badge.spec.ts | 26 + .../framework-tests/tests/generated/index.ts | 10 + .../tests/generated/test-ids.autogenerated.ts | 5 + .../tests/working-with-axe.spec.ts | 7 + testing/framework-tests/tests/working.spec.ts | 7 + ...ounter-1-chromium---classic-dark-linux.png | Bin 0 -> 59910 bytes ...unter-1-chromium---classic-light-linux.png | Bin 0 -> 60359 bytes ...ge-dot-1-chromium---classic-dark-linux.png | Bin 0 -> 37593 bytes ...e-dot-1-chromium---classic-light-linux.png | Bin 0 -> 38288 bytes ...-label-1-chromium---classic-dark-linux.png | Bin 0 -> 81751 bytes ...label-1-chromium---classic-light-linux.png | Bin 0 -> 82934 bytes ...s-icon-1-chromium---classic-dark-linux.png | Bin 0 -> 35185 bytes ...-icon-1-chromium---classic-light-linux.png | Bin 0 -> 35291 bytes .../visual-testing/tests/badge/badge.e2e.ts | 41 + .../visual-testing/tests/badge/badge.page.ts | 56 ++ .../tests/badge/counter/index.html | 189 +++++ .../visual-testing/tests/badge/dot/index.html | 163 ++++ .../tests/badge/label/index.html | 210 +++++ .../tests/badge/status-icon/index.html | 160 ++++ 120 files changed, 8640 insertions(+), 6 deletions(-) create mode 100644 .changeset/ix-3943-badge.md create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-counter.css create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-dot.css create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-label.css create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-label.ts create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.css create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge.css create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge.ts create mode 100644 packages/angular-test-app/src/preview-examples/badge-counter.css create mode 100644 packages/angular-test-app/src/preview-examples/badge-counter.html create mode 100644 packages/angular-test-app/src/preview-examples/badge-counter.ts create mode 100644 packages/angular-test-app/src/preview-examples/badge-dot.css create mode 100644 packages/angular-test-app/src/preview-examples/badge-dot.html create mode 100644 packages/angular-test-app/src/preview-examples/badge-dot.ts create mode 100644 packages/angular-test-app/src/preview-examples/badge-label.css create mode 100644 packages/angular-test-app/src/preview-examples/badge-label.html create mode 100644 packages/angular-test-app/src/preview-examples/badge-label.ts create mode 100644 packages/angular-test-app/src/preview-examples/badge-status-icon.css create mode 100644 packages/angular-test-app/src/preview-examples/badge-status-icon.html create mode 100644 packages/angular-test-app/src/preview-examples/badge-status-icon.ts create mode 100644 packages/angular-test-app/src/preview-examples/badge.css create mode 100644 packages/angular-test-app/src/preview-examples/badge.html create mode 100644 packages/angular-test-app/src/preview-examples/badge.ts create mode 100644 packages/core/src/components/badge/badge.scss create mode 100644 packages/core/src/components/badge/badge.status-icon.ts create mode 100644 packages/core/src/components/badge/badge.tsx create mode 100644 packages/core/src/components/badge/badge.types.ts create mode 100644 packages/core/src/components/badge/badge.utils.ts create mode 100644 packages/core/src/components/badge/test/badge.ct.ts create mode 100644 packages/core/src/components/badge/test/badge.page.ts create mode 100644 packages/core/src/components/badge/test/badge.spec.ts create mode 100644 packages/html-test-app/src/preview-examples/badge-counter.css create mode 100644 packages/html-test-app/src/preview-examples/badge-counter.html create mode 100644 packages/html-test-app/src/preview-examples/badge-dot.css create mode 100644 packages/html-test-app/src/preview-examples/badge-dot.html create mode 100644 packages/html-test-app/src/preview-examples/badge-label.css create mode 100644 packages/html-test-app/src/preview-examples/badge-label.html create mode 100644 packages/html-test-app/src/preview-examples/badge-status-icon.css create mode 100644 packages/html-test-app/src/preview-examples/badge-status-icon.html create mode 100644 packages/html-test-app/src/preview-examples/badge.css create mode 100644 packages/html-test-app/src/preview-examples/badge.html create mode 100644 packages/react-test-app/src/preview-examples/badge-counter.scoped.css create mode 100644 packages/react-test-app/src/preview-examples/badge-counter.tsx create mode 100644 packages/react-test-app/src/preview-examples/badge-dot.scoped.css create mode 100644 packages/react-test-app/src/preview-examples/badge-dot.tsx create mode 100644 packages/react-test-app/src/preview-examples/badge-label.scoped.css create mode 100644 packages/react-test-app/src/preview-examples/badge-label.tsx create mode 100644 packages/react-test-app/src/preview-examples/badge-status-icon.scoped.css create mode 100644 packages/react-test-app/src/preview-examples/badge-status-icon.tsx create mode 100644 packages/react-test-app/src/preview-examples/badge.scoped.css create mode 100644 packages/react-test-app/src/preview-examples/badge.tsx create mode 100644 packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts create mode 100644 packages/storybook-docs/src/stories/badge/badge-preview.css create mode 100644 packages/storybook-docs/src/stories/badge/badge-preview.shared.ts create mode 100644 packages/storybook-docs/src/stories/badge/counter.stories.ts create mode 100644 packages/storybook-docs/src/stories/badge/dot.stories.ts create mode 100644 packages/storybook-docs/src/stories/badge/label.stories.ts create mode 100644 packages/storybook-docs/src/stories/badge/status-icon.stories.ts create mode 100644 packages/vue-test-app/src/preview-examples/badge-counter.css create mode 100644 packages/vue-test-app/src/preview-examples/badge-counter.vue create mode 100644 packages/vue-test-app/src/preview-examples/badge-dot.css create mode 100644 packages/vue-test-app/src/preview-examples/badge-dot.vue create mode 100644 packages/vue-test-app/src/preview-examples/badge-label.css create mode 100644 packages/vue-test-app/src/preview-examples/badge-label.vue create mode 100644 packages/vue-test-app/src/preview-examples/badge-status-icon.css create mode 100644 packages/vue-test-app/src/preview-examples/badge-status-icon.vue create mode 100644 packages/vue-test-app/src/preview-examples/badge.css create mode 100644 packages/vue-test-app/src/preview-examples/badge.vue create mode 100644 packages/vue/src/components/ix-badge.ts create mode 100644 testing/framework-tests/__snapshots__/badge-aria-snapshot.yaml create mode 100644 testing/framework-tests/__snapshots__/badge-counter-aria-snapshot.yaml create mode 100644 testing/framework-tests/__snapshots__/badge-dot-aria-snapshot.yaml create mode 100644 testing/framework-tests/__snapshots__/badge-label-aria-snapshot.yaml create mode 100644 testing/framework-tests/__snapshots__/badge-status-icon-aria-snapshot.yaml create mode 100644 testing/framework-tests/tests/generated/badge-axe.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-counter-axe.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-counter.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-dot-axe.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-dot.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-label-axe.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-label.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-status-icon-axe.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge-status-icon.spec.ts create mode 100644 testing/framework-tests/tests/generated/badge.spec.ts create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-dark-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-light-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-dot-1-chromium---classic-dark-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-dot-1-chromium---classic-light-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-label-1-chromium---classic-dark-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-label-1-chromium---classic-light-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-status-icon-1-chromium---classic-dark-linux.png create mode 100644 testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-status-icon-1-chromium---classic-light-linux.png create mode 100644 testing/visual-testing/tests/badge/badge.e2e.ts create mode 100644 testing/visual-testing/tests/badge/badge.page.ts create mode 100644 testing/visual-testing/tests/badge/counter/index.html create mode 100644 testing/visual-testing/tests/badge/dot/index.html create mode 100644 testing/visual-testing/tests/badge/label/index.html create mode 100644 testing/visual-testing/tests/badge/status-icon/index.html diff --git a/.changeset/ix-3943-badge.md b/.changeset/ix-3943-badge.md new file mode 100644 index 00000000000..4d32c4e6e7f --- /dev/null +++ b/.changeset/ix-3943-badge.md @@ -0,0 +1,8 @@ +--- +'@siemens/ix': minor +'@siemens/ix-angular': minor +'@siemens/ix-react': minor +'@siemens/ix-vue': minor +--- + +Introduces `ix-badge` for overlay count and status indicators on anchors or as standalone badges, with semantic variants, outline mode, position/offset, optional attention animation, and standalone `tooltipText` support. diff --git a/packages/angular-standalone-test-app/src/app/app.routes.ts b/packages/angular-standalone-test-app/src/app/app.routes.ts index d73a9d7b173..8e4893a92a7 100644 --- a/packages/angular-standalone-test-app/src/app/app.routes.ts +++ b/packages/angular-standalone-test-app/src/app/app.routes.ts @@ -52,6 +52,16 @@ export const routePaths: IxPreviewRoutes = { import('../preview-examples/avatar-image').then((m) => m.default), 'preview/avatar-initials': () => import('../preview-examples/avatar-initials').then((m) => m.default), + 'preview/badge': () => + import('../preview-examples/badge').then((m) => m.default), + 'preview/badge-counter': () => + import('../preview-examples/badge-counter').then((m) => m.default), + 'preview/badge-dot': () => + import('../preview-examples/badge-dot').then((m) => m.default), + 'preview/badge-label': () => + import('../preview-examples/badge-label').then((m) => m.default), + 'preview/badge-status-icon': () => + import('../preview-examples/badge-status-icon').then((m) => m.default), 'preview/blind': () => import('../preview-examples/blind').then((m) => m.default), 'preview/blind-header-actions': () => diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-counter.css b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts new file mode 100644 index 00000000000..5b3873fc590 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { IxBadge } from '@siemens/ix-angular/standalone'; + +@Component({ + selector: 'app-example', + imports: [IxBadge], + styleUrls: ['./badge-counter.css'], + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ `, +}) +export default class BadgeCounter {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-dot.css b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts new file mode 100644 index 00000000000..b338105838b --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { IxBadge } from '@siemens/ix-angular/standalone'; + +@Component({ + selector: 'app-example', + imports: [IxBadge], + styleUrls: ['./badge-dot.css'], + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ `, +}) +export default class BadgeDot {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-label.css b/packages/angular-standalone-test-app/src/preview-examples/badge-label.css new file mode 100644 index 00000000000..e8543b9428b --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-label.css @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts new file mode 100644 index 00000000000..75572a6582f --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { addIcons } from '@siemens/ix-icons'; +import { iconInfo } from '@siemens/ix-icons/icons'; +import { IxBadge } from '@siemens/ix-angular/standalone'; + +addIcons({ iconInfo }); + +@Component({ + selector: 'app-example', + imports: [IxBadge], + styleUrls: ['./badge-label.css'], + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ `, +}) +export default class BadgeLabel {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.css b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts new file mode 100644 index 00000000000..2e48ac92442 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { IxBadge } from '@siemens/ix-angular/standalone'; + +@Component({ + selector: 'app-example', + imports: [IxBadge], + styleUrls: ['./badge-status-icon.css'], + template: ` +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ `, +}) +export default class BadgeStatusIcon {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.css b/packages/angular-standalone-test-app/src/preview-examples/badge.css new file mode 100644 index 00000000000..875f0b6238a --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.css @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + margin-bottom: 1.5rem; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1.5rem; +} + +.styled { + width: 7rem; + --ix-badge-max-width: 7rem; +} + +.styled-ellipsis-4 { + width: 4rem; + --ix-badge-max-width: 4rem; +} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.ts b/packages/angular-standalone-test-app/src/preview-examples/badge.ts new file mode 100644 index 00000000000..9bbd289cfe8 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.ts @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { addIcons } from '@siemens/ix-icons'; +import { iconInfo, iconStar } from '@siemens/ix-icons/icons'; +import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-angular/standalone'; + +addIcons({ iconInfo, iconStar }); + +@Component({ + selector: 'app-example', + imports: [IxBadge, IxButton, IxIconButton], + styleUrls: ['./badge.css'], + template: ` +
+ Review + + Bottom after + Messages + Device +
+ +
+ + + + + + + + + + +
+ +
+ + + + + + + + +
+ `, +}) +export default class Badge {} diff --git a/packages/angular-test-app/src/app/app-routing.module.ts b/packages/angular-test-app/src/app/app-routing.module.ts index e75fa426e54..b3de23a66cd 100644 --- a/packages/angular-test-app/src/app/app-routing.module.ts +++ b/packages/angular-test-app/src/app/app-routing.module.ts @@ -21,6 +21,11 @@ import ApplicationAppSwitchExample from '../preview-examples/application-app-swi import ApplicationBreakpointExample from '../preview-examples/application-breakpoints'; import ApplicationHeaderExample from '../preview-examples/application-header'; import Avatar from '../preview-examples/avatar'; +import Badge from '../preview-examples/badge'; +import BadgeCounter from '../preview-examples/badge-counter'; +import BadgeDot from '../preview-examples/badge-dot'; +import BadgeLabel from '../preview-examples/badge-label'; +import BadgeStatusIcon from '../preview-examples/badge-status-icon'; import AvatarImage from '../preview-examples/avatar-image'; import AvatarInitials from '../preview-examples/avatar-initials'; import Blind from '../preview-examples/blind'; @@ -337,6 +342,26 @@ const routes: Routes = [ path: 'avatar', component: Avatar, }, + { + path: 'badge', + component: Badge, + }, + { + path: 'badge-counter', + component: BadgeCounter, + }, + { + path: 'badge-dot', + component: BadgeDot, + }, + { + path: 'badge-label', + component: BadgeLabel, + }, + { + path: 'badge-status-icon', + component: BadgeStatusIcon, + }, { path: 'blind-header-actions', component: BlindHeaderActions, diff --git a/packages/angular-test-app/src/app/app.module.ts b/packages/angular-test-app/src/app/app.module.ts index 0d4dd91390d..600cb855076 100644 --- a/packages/angular-test-app/src/app/app.module.ts +++ b/packages/angular-test-app/src/app/app.module.ts @@ -30,6 +30,11 @@ import ApplicationAppSwitchExample from '../preview-examples/application-app-swi import ApplicationBreakpointExample from '../preview-examples/application-breakpoints'; import ApplicationHeaderExample from '../preview-examples/application-header'; import Avatar from '../preview-examples/avatar'; +import Badge from '../preview-examples/badge'; +import BadgeCounter from '../preview-examples/badge-counter'; +import BadgeDot from '../preview-examples/badge-dot'; +import BadgeLabel from '../preview-examples/badge-label'; +import BadgeStatusIcon from '../preview-examples/badge-status-icon'; import AvatarImage from '../preview-examples/avatar-image'; import AvatarInitials from '../preview-examples/avatar-initials'; import Blind from '../preview-examples/blind'; @@ -292,6 +297,11 @@ import WorkflowVertical from '../preview-examples/workflow-vertical'; AvatarImage, AvatarInitials, Avatar, + Badge, + BadgeCounter, + BadgeDot, + BadgeLabel, + BadgeStatusIcon, BlindHeaderActions, BlindVariants, Blind, diff --git a/packages/angular-test-app/src/preview-examples/badge-counter.css b/packages/angular-test-app/src/preview-examples/badge-counter.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-counter.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-test-app/src/preview-examples/badge-counter.html b/packages/angular-test-app/src/preview-examples/badge-counter.html new file mode 100644 index 00000000000..29149a2d264 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-counter.html @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-test-app/src/preview-examples/badge-counter.ts b/packages/angular-test-app/src/preview-examples/badge-counter.ts new file mode 100644 index 00000000000..63cefcb7101 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-counter.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; + +@Component({ + standalone: false, + selector: 'app-example', + templateUrl: './badge-counter.html', + styleUrls: ['./badge-counter.css'], +}) +export default class BadgeCounter {} diff --git a/packages/angular-test-app/src/preview-examples/badge-dot.css b/packages/angular-test-app/src/preview-examples/badge-dot.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-dot.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-test-app/src/preview-examples/badge-dot.html b/packages/angular-test-app/src/preview-examples/badge-dot.html new file mode 100644 index 00000000000..a6196e151f4 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-dot.html @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-test-app/src/preview-examples/badge-dot.ts b/packages/angular-test-app/src/preview-examples/badge-dot.ts new file mode 100644 index 00000000000..67471f0625b --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-dot.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; + +@Component({ + standalone: false, + selector: 'app-example', + templateUrl: './badge-dot.html', + styleUrls: ['./badge-dot.css'], +}) +export default class BadgeDot {} diff --git a/packages/angular-test-app/src/preview-examples/badge-label.css b/packages/angular-test-app/src/preview-examples/badge-label.css new file mode 100644 index 00000000000..e8543b9428b --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-label.css @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} diff --git a/packages/angular-test-app/src/preview-examples/badge-label.html b/packages/angular-test-app/src/preview-examples/badge-label.html new file mode 100644 index 00000000000..179187e989a --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-label.html @@ -0,0 +1,34 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-test-app/src/preview-examples/badge-label.ts b/packages/angular-test-app/src/preview-examples/badge-label.ts new file mode 100644 index 00000000000..9aab90a8aac --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-label.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { addIcons } from '@siemens/ix-icons'; +import { iconInfo } from '@siemens/ix-icons/icons'; + +addIcons({ iconInfo }); + +@Component({ + standalone: false, + selector: 'app-example', + templateUrl: './badge-label.html', + styleUrls: ['./badge-label.css'], +}) +export default class BadgeLabel {} diff --git a/packages/angular-test-app/src/preview-examples/badge-status-icon.css b/packages/angular-test-app/src/preview-examples/badge-status-icon.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-status-icon.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/angular-test-app/src/preview-examples/badge-status-icon.html b/packages/angular-test-app/src/preview-examples/badge-status-icon.html new file mode 100644 index 00000000000..ebfacbd6941 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-status-icon.html @@ -0,0 +1,32 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-test-app/src/preview-examples/badge-status-icon.ts b/packages/angular-test-app/src/preview-examples/badge-status-icon.ts new file mode 100644 index 00000000000..dc4674ba367 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge-status-icon.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; + +@Component({ + standalone: false, + selector: 'app-example', + templateUrl: './badge-status-icon.html', + styleUrls: ['./badge-status-icon.css'], +}) +export default class BadgeStatusIcon {} diff --git a/packages/angular-test-app/src/preview-examples/badge.css b/packages/angular-test-app/src/preview-examples/badge.css new file mode 100644 index 00000000000..875f0b6238a --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge.css @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + margin-bottom: 1.5rem; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1.5rem; +} + +.styled { + width: 7rem; + --ix-badge-max-width: 7rem; +} + +.styled-ellipsis-4 { + width: 4rem; + --ix-badge-max-width: 4rem; +} diff --git a/packages/angular-test-app/src/preview-examples/badge.html b/packages/angular-test-app/src/preview-examples/badge.html new file mode 100644 index 00000000000..68b161a507c --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge.html @@ -0,0 +1,31 @@ +
+ Review + + Bottom after + Messages + Device +
+ +
+ + + + + + + + + + +
+ +
+ + + + + + + + +
diff --git a/packages/angular-test-app/src/preview-examples/badge.ts b/packages/angular-test-app/src/preview-examples/badge.ts new file mode 100644 index 00000000000..2b00985a311 --- /dev/null +++ b/packages/angular-test-app/src/preview-examples/badge.ts @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { Component } from '@angular/core'; +import { addIcons } from '@siemens/ix-icons'; +import { iconInfo, iconStar } from '@siemens/ix-icons/icons'; + +addIcons({ iconInfo, iconStar }); + +@Component({ + standalone: false, + selector: 'app-example', + templateUrl: './badge.html', + styleUrls: ['./badge.css'], +}) +export default class Badge {} diff --git a/packages/angular/src/components.ts b/packages/angular/src/components.ts index 1cadcb1b060..07d38cb729d 100644 --- a/packages/angular/src/components.ts +++ b/packages/angular/src/components.ts @@ -111,6 +111,29 @@ export class IxAvatar { export declare interface IxAvatar extends Components.IxAvatar {} +@ProxyCmp({ + inputs: ['alignLeft', 'ariaLabelIcon', 'background', 'badgeColor', 'border', 'enableAnimation', 'icon', 'label', 'offsetX', 'offsetY', 'outline', 'position', 'tooltipText', 'type', 'variant'] +}) +@Component({ + selector: 'ix-badge', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property + inputs: ['alignLeft', 'ariaLabelIcon', 'background', 'badgeColor', 'border', 'enableAnimation', 'icon', 'label', 'offsetX', 'offsetY', 'outline', 'position', 'tooltipText', 'type', 'variant'], + standalone: false +}) +export class IxBadge { + protected el: HTMLIxBadgeElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + } +} + + +export declare interface IxBadge extends Components.IxBadge {} + + @ProxyCmp({ inputs: ['collapsed', 'icon', 'label', 'sublabel', 'variant'] }) diff --git a/packages/angular/src/declare-components.ts b/packages/angular/src/declare-components.ts index c463b1265a6..4bd66630a88 100644 --- a/packages/angular/src/declare-components.ts +++ b/packages/angular/src/declare-components.ts @@ -6,6 +6,7 @@ export const DIRECTIVES = [ d.IxApplication, d.IxApplicationHeader, d.IxAvatar, + d.IxBadge, d.IxBlind, d.IxBreadcrumb, d.IxBreadcrumbItem, diff --git a/packages/angular/standalone/src/components.ts b/packages/angular/standalone/src/components.ts index 9d1ca8c30d4..6c406a74416 100644 --- a/packages/angular/standalone/src/components.ts +++ b/packages/angular/standalone/src/components.ts @@ -10,6 +10,7 @@ import { defineCustomElement as defineIxActionCard } from '@siemens/ix/component import { defineCustomElement as defineIxApplication } from '@siemens/ix/components/ix-application.js'; import { defineCustomElement as defineIxApplicationHeader } from '@siemens/ix/components/ix-application-header.js'; import { defineCustomElement as defineIxAvatar } from '@siemens/ix/components/ix-avatar.js'; +import { defineCustomElement as defineIxBadge } from '@siemens/ix/components/ix-badge.js'; import { defineCustomElement as defineIxBlind } from '@siemens/ix/components/ix-blind.js'; import { defineCustomElement as defineIxBreadcrumb } from '@siemens/ix/components/ix-breadcrumb.js'; import { defineCustomElement as defineIxBreadcrumbItem } from '@siemens/ix/components/ix-breadcrumb-item.js'; @@ -220,6 +221,29 @@ export class IxAvatar { export declare interface IxAvatar extends Components.IxAvatar {} +@ProxyCmp({ + defineCustomElementFn: defineIxBadge, + inputs: ['alignLeft', 'ariaLabelIcon', 'background', 'badgeColor', 'border', 'enableAnimation', 'icon', 'label', 'offsetX', 'offsetY', 'outline', 'position', 'tooltipText', 'type', 'variant'] +}) +@Component({ + selector: 'ix-badge', + changeDetection: ChangeDetectionStrategy.OnPush, + template: '', + // eslint-disable-next-line @angular-eslint/no-inputs-metadata-property + inputs: ['alignLeft', 'ariaLabelIcon', 'background', 'badgeColor', 'border', 'enableAnimation', 'icon', 'label', 'offsetX', 'offsetY', 'outline', 'position', 'tooltipText', 'type', 'variant'], +}) +export class IxBadge { + protected el: HTMLIxBadgeElement; + constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) { + c.detach(); + this.el = r.nativeElement; + } +} + + +export declare interface IxBadge extends Components.IxBadge {} + + @ProxyCmp({ defineCustomElementFn: defineIxBlind, inputs: ['collapsed', 'icon', 'label', 'sublabel', 'variant'] diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 2a62dbd0e69..811f51857c0 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -9,6 +9,7 @@ import { ActionCardVariant } from "./components/action-card/action-card.types"; import { ThemeVariant } from "./components/utils/theme-switcher"; import { Breakpoint } from "./components/utils/breakpoints"; import { AppSwitchConfiguration } from "./components/utils/application-layout/context"; +import { BadgeAnatomyType, BadgePosition, BadgeVariant } from "./components/badge/badge.types"; import { BlindVariant } from "./components/blind/blind.types"; import { BreadcrumbClick } from "./components/breadcrumb/breadcrumb.types"; import { AnchorTarget } from "./components/button/button.interface"; @@ -65,6 +66,7 @@ export { ActionCardVariant } from "./components/action-card/action-card.types"; export { ThemeVariant } from "./components/utils/theme-switcher"; export { Breakpoint } from "./components/utils/breakpoints"; export { AppSwitchConfiguration } from "./components/utils/application-layout/context"; +export { BadgeAnatomyType, BadgePosition, BadgeVariant } from "./components/badge/badge.types"; export { BlindVariant } from "./components/blind/blind.types"; export { BreadcrumbClick } from "./components/breadcrumb/breadcrumb.types"; export { AnchorTarget } from "./components/button/button.interface"; @@ -278,6 +280,103 @@ export namespace Components { */ "username"?: string; } + /** + * Overlay indicator for counts, labels, dots, and status icons. + * **Attached** (default slot has content): the indicator is decorative. + * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. + * For `dot` and `status-icon`, provide a host `aria-label` and a naming role + * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). + * Override max-width with `--ix-badge-max-width`. + * @since 5.2.0 + */ + interface IxBadge { + /** + * Left-align label content. Only has an effect when **type** is `label`. + * @since 5.2.0 + * @default false + */ + "alignLeft": boolean; + /** + * Accessible name for the leading icon. When unset, the icon is decorative if **label** provides visible text. Only has an effect when **type** is `label`. + * @since 5.2.0 + */ + "ariaLabelIcon"?: string; + /** + * Custom background or border color. Only has an effect when **variant** is `custom`. + * @since 5.2.0 + */ + "background"?: string; + /** + * Custom text color. Only has an effect when **variant** is `custom`. + * @since 5.2.0 + */ + "badgeColor"?: string; + /** + * Add a high-contrast border on filled badges. Ignored when **outline** is `true` or **type** is `status-icon`. + * @since 5.2.0 + * @default false + */ + "border": boolean; + /** + * Play the attention pulse animation. Override duration with `--ix-badge-animation-duration` (default `2s`). + * @since 5.2.0 + * @default false + */ + "enableAnimation": boolean; + /** + * Leading icon name. Only has an effect when **type** is `label`. + * @since 5.2.0 + */ + "icon"?: string; + /** + * Visible text or count. Required for `label` and `counter`. Omit for `dot` and `status-icon`. Counters accept integers only (decimals truncated); values above 99 render as `99+`. + * @since 5.2.0 + */ + "label"?: string; + /** + * Extra horizontal offset in pixels. Only has an effect when attached. Added to the type default. + * @since 5.2.0 + * @default 0 + */ + "offsetX": number; + /** + * Extra vertical offset in pixels. Only has an effect when attached. Added to the type default. + * @since 5.2.0 + * @default 0 + */ + "offsetY": number; + /** + * Show the badge in outline style. + * @since 5.2.0 + * @default false + */ + "outline": boolean; + /** + * Position relative to the slotted anchor. Only has an effect when attached. + * @since 5.2.0 + * @default 'top-after' + */ + "position": BadgePosition; + /** + * Display a tooltip when the badge is standalone. By default, no tooltip is displayed. Add the attribute to use the badge label (or host `aria-label`) as the tooltip, or pass a string for custom text. Ignored when the badge is attached to an anchor. + * @since 5.2.0 + * @default false + */ + "tooltipText": string | boolean; + /** + * Badge type (`counter`, `label`, `dot`, or `status-icon`). + * @since 5.2.0 + * @default 'counter' + */ + "type": BadgeAnatomyType; + /** + * Color variant. For `status-icon`, unsupported values fall back to `info`. Use `error` only with `status-icon` (other types map it to `alarm`). + * @since 5.2.0 + * @default 'primary' + */ + "variant": BadgeVariant; + } interface IxBlind { /** * Collapsed state @@ -5172,6 +5271,22 @@ declare global { prototype: HTMLIxAvatarElement; new (): HTMLIxAvatarElement; }; + /** + * Overlay indicator for counts, labels, dots, and status icons. + * **Attached** (default slot has content): the indicator is decorative. + * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. + * For `dot` and `status-icon`, provide a host `aria-label` and a naming role + * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). + * Override max-width with `--ix-badge-max-width`. + * @since 5.2.0 + */ + interface HTMLIxBadgeElement extends Components.IxBadge, HTMLStencilElement { + } + var HTMLIxBadgeElement: { + prototype: HTMLIxBadgeElement; + new (): HTMLIxBadgeElement; + }; interface HTMLIxBlindElementEventMap { "collapsedChange": boolean; } @@ -6755,6 +6870,7 @@ declare global { "ix-application-header": HTMLIxApplicationHeaderElement; "ix-application-switch-modal": HTMLIxApplicationSwitchModalElement; "ix-avatar": HTMLIxAvatarElement; + "ix-badge": HTMLIxBadgeElement; "ix-blind": HTMLIxBlindElement; "ix-breadcrumb": HTMLIxBreadcrumbElement; "ix-breadcrumb-item": HTMLIxBreadcrumbItemElement; @@ -7044,6 +7160,103 @@ declare namespace LocalJSX { */ "username"?: string; } + /** + * Overlay indicator for counts, labels, dots, and status icons. + * **Attached** (default slot has content): the indicator is decorative. + * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. + * For `dot` and `status-icon`, provide a host `aria-label` and a naming role + * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). + * Override max-width with `--ix-badge-max-width`. + * @since 5.2.0 + */ + interface IxBadge { + /** + * Left-align label content. Only has an effect when **type** is `label`. + * @since 5.2.0 + * @default false + */ + "alignLeft"?: boolean; + /** + * Accessible name for the leading icon. When unset, the icon is decorative if **label** provides visible text. Only has an effect when **type** is `label`. + * @since 5.2.0 + */ + "ariaLabelIcon"?: string; + /** + * Custom background or border color. Only has an effect when **variant** is `custom`. + * @since 5.2.0 + */ + "background"?: string; + /** + * Custom text color. Only has an effect when **variant** is `custom`. + * @since 5.2.0 + */ + "badgeColor"?: string; + /** + * Add a high-contrast border on filled badges. Ignored when **outline** is `true` or **type** is `status-icon`. + * @since 5.2.0 + * @default false + */ + "border"?: boolean; + /** + * Play the attention pulse animation. Override duration with `--ix-badge-animation-duration` (default `2s`). + * @since 5.2.0 + * @default false + */ + "enableAnimation"?: boolean; + /** + * Leading icon name. Only has an effect when **type** is `label`. + * @since 5.2.0 + */ + "icon"?: string; + /** + * Visible text or count. Required for `label` and `counter`. Omit for `dot` and `status-icon`. Counters accept integers only (decimals truncated); values above 99 render as `99+`. + * @since 5.2.0 + */ + "label"?: string; + /** + * Extra horizontal offset in pixels. Only has an effect when attached. Added to the type default. + * @since 5.2.0 + * @default 0 + */ + "offsetX"?: number; + /** + * Extra vertical offset in pixels. Only has an effect when attached. Added to the type default. + * @since 5.2.0 + * @default 0 + */ + "offsetY"?: number; + /** + * Show the badge in outline style. + * @since 5.2.0 + * @default false + */ + "outline"?: boolean; + /** + * Position relative to the slotted anchor. Only has an effect when attached. + * @since 5.2.0 + * @default 'top-after' + */ + "position"?: BadgePosition; + /** + * Display a tooltip when the badge is standalone. By default, no tooltip is displayed. Add the attribute to use the badge label (or host `aria-label`) as the tooltip, or pass a string for custom text. Ignored when the badge is attached to an anchor. + * @since 5.2.0 + * @default false + */ + "tooltipText"?: string | boolean; + /** + * Badge type (`counter`, `label`, `dot`, or `status-icon`). + * @since 5.2.0 + * @default 'counter' + */ + "type"?: BadgeAnatomyType; + /** + * Color variant. For `status-icon`, unsupported values fall back to `info`. Use `error` only with `status-icon` (other types map it to `alarm`). + * @since 5.2.0 + * @default 'primary' + */ + "variant"?: BadgeVariant; + } interface IxBlind { /** * Collapsed state @@ -12000,6 +12213,23 @@ declare namespace LocalJSX { "tooltipText": string; "ariaLabelTooltip": string; } + interface IxBadgeAttributes { + "type": BadgeAnatomyType; + "label": string; + "variant": BadgeVariant; + "outline": boolean; + "border": boolean; + "position": BadgePosition; + "offsetX": number; + "offsetY": number; + "enableAnimation": boolean; + "background": string; + "badgeColor": string; + "icon": string; + "ariaLabelIcon": string; + "alignLeft": boolean; + "tooltipText": string; + } interface IxBlindAttributes { "collapsed": boolean; "label": string; @@ -13047,6 +13277,7 @@ declare namespace LocalJSX { "ix-application-header": Omit & { [K in keyof IxApplicationHeader & keyof IxApplicationHeaderAttributes]?: IxApplicationHeader[K] } & { [K in keyof IxApplicationHeader & keyof IxApplicationHeaderAttributes as `attr:${K}`]?: IxApplicationHeaderAttributes[K] } & { [K in keyof IxApplicationHeader & keyof IxApplicationHeaderAttributes as `prop:${K}`]?: IxApplicationHeader[K] }; "ix-application-switch-modal": IxApplicationSwitchModal; "ix-avatar": Omit & { [K in keyof IxAvatar & keyof IxAvatarAttributes]?: IxAvatar[K] } & { [K in keyof IxAvatar & keyof IxAvatarAttributes as `attr:${K}`]?: IxAvatarAttributes[K] } & { [K in keyof IxAvatar & keyof IxAvatarAttributes as `prop:${K}`]?: IxAvatar[K] }; + "ix-badge": Omit & { [K in keyof IxBadge & keyof IxBadgeAttributes]?: IxBadge[K] } & { [K in keyof IxBadge & keyof IxBadgeAttributes as `attr:${K}`]?: IxBadgeAttributes[K] } & { [K in keyof IxBadge & keyof IxBadgeAttributes as `prop:${K}`]?: IxBadge[K] }; "ix-blind": Omit & { [K in keyof IxBlind & keyof IxBlindAttributes]?: IxBlind[K] } & { [K in keyof IxBlind & keyof IxBlindAttributes as `attr:${K}`]?: IxBlindAttributes[K] } & { [K in keyof IxBlind & keyof IxBlindAttributes as `prop:${K}`]?: IxBlind[K] }; "ix-breadcrumb": Omit & { [K in keyof IxBreadcrumb & keyof IxBreadcrumbAttributes]?: IxBreadcrumb[K] } & { [K in keyof IxBreadcrumb & keyof IxBreadcrumbAttributes as `attr:${K}`]?: IxBreadcrumbAttributes[K] } & { [K in keyof IxBreadcrumb & keyof IxBreadcrumbAttributes as `prop:${K}`]?: IxBreadcrumb[K] }; "ix-breadcrumb-item": Omit & { [K in keyof IxBreadcrumbItem & keyof IxBreadcrumbItemAttributes]?: IxBreadcrumbItem[K] } & { [K in keyof IxBreadcrumbItem & keyof IxBreadcrumbItemAttributes as `attr:${K}`]?: IxBreadcrumbItemAttributes[K] } & { [K in keyof IxBreadcrumbItem & keyof IxBreadcrumbItemAttributes as `prop:${K}`]?: IxBreadcrumbItem[K] } & OneOf<"breadcrumbKey", IxBreadcrumbItem["breadcrumbKey"], IxBreadcrumbItemAttributes["breadcrumbKey"]>; @@ -13173,6 +13404,17 @@ declare module "@stencil/core" { "ix-application-header": LocalJSX.IntrinsicElements["ix-application-header"] & JSXBase.HTMLAttributes; "ix-application-switch-modal": LocalJSX.IntrinsicElements["ix-application-switch-modal"] & JSXBase.HTMLAttributes; "ix-avatar": LocalJSX.IntrinsicElements["ix-avatar"] & JSXBase.HTMLAttributes; + /** + * Overlay indicator for counts, labels, dots, and status icons. + * **Attached** (default slot has content): the indicator is decorative. + * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. + * For `dot` and `status-icon`, provide a host `aria-label` and a naming role + * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). + * Override max-width with `--ix-badge-max-width`. + * @since 5.2.0 + */ + "ix-badge": LocalJSX.IntrinsicElements["ix-badge"] & JSXBase.HTMLAttributes; "ix-blind": LocalJSX.IntrinsicElements["ix-blind"] & JSXBase.HTMLAttributes; "ix-breadcrumb": LocalJSX.IntrinsicElements["ix-breadcrumb"] & JSXBase.HTMLAttributes; "ix-breadcrumb-item": LocalJSX.IntrinsicElements["ix-breadcrumb-item"] & JSXBase.HTMLAttributes; diff --git a/packages/core/src/components/badge/badge.scss b/packages/core/src/components/badge/badge.scss new file mode 100644 index 00000000000..0a3fe453670 --- /dev/null +++ b/packages/core/src/components/badge/badge.scss @@ -0,0 +1,427 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +@use 'mixins/shadow-dom/component'; + +$predefined-variants: primary, alarm, critical, warning, info, neutral, success; +$status-icon-variants: alarm, critical, warning, info, success; +$border-radius: 100px; + +:host { + display: inline-block; + position: relative; + width: fit-content; + max-width: 100%; + vertical-align: top; + + --ix-badge-offset-x: 0rem; + --ix-badge-offset-y: 0rem; + --ix-badge-max-width: none; + --ix-badge-pulse-color: var(--theme-color-primary); + --ix-badge-animation-duration: 2s; + + @include component.ix-component; +} + +:host(.attached) { + display: inline-grid; +} + +.anchor { + display: contents; +} + +:host(.attached) ::slotted(*) { + grid-area: 1 / 1; + position: relative; + z-index: 0; +} + +.indicator { + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + border-radius: $border-radius; + font-size: 0.875rem; + line-height: 1.43; + letter-spacing: 0.012em; + max-width: var(--ix-badge-max-width); + z-index: 1; + pointer-events: none; + user-select: none; + white-space: nowrap; + isolation: isolate; +} + +:host(.with-tooltip:not(.attached)) .indicator { + pointer-events: auto; +} + +.label { + position: relative; + z-index: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; +} + +:host(.attached) .indicator { + grid-area: 1 / 1; + position: absolute; + z-index: 1; + pointer-events: auto; + cursor: default; +} + +:host(.attached.top-after) .indicator { + top: var(--ix-badge-offset-y); + inset-inline-end: var(--ix-badge-offset-x); +} + +:host(.attached.bottom-after) .indicator { + bottom: var(--ix-badge-offset-y); + inset-inline-end: var(--ix-badge-offset-x); +} + +:host([type='dot']:not(.attached)), +:host([type='counter']:not(.attached)), +:host([type='label']:not(.attached)), +:host([type='status-icon']:not(.attached)) { + display: inline-flex; + line-height: 0; + font-size: 0; +} + +/* Standalone host uses font-size: 0 for sizing; restore text for nested tooltip. */ +:host ix-tooltip { + font-size: 0.875rem; + line-height: normal; +} + +:host([type='dot']:not(.attached)) slot, +:host([type='counter']:not(.attached)) slot, +:host([type='label']:not(.attached)) slot, +:host([type='status-icon']:not(.attached)) slot { + flex: 0 0 0; + width: 0; + height: 0; + overflow: hidden; +} + +:host([type='dot']) .indicator { + width: 0.75rem; + height: 0.75rem; + min-width: 0.75rem; + min-height: 0.75rem; + padding: 0; + line-height: 0; + font-size: 0; + flex-shrink: 0; +} + +:host([type='counter']) .indicator, +:host([type='label']) .indicator { + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; + flex-shrink: 0; +} + +:host([type='counter']) .indicator { + padding-inline: 0.25rem; + font-weight: bold; + line-height: 1; +} + +:host([type='label']) .indicator { + padding-inline: 0.5rem; + gap: 0.25rem; + font-weight: 400; + line-height: 1; +} + +:host([type='label']:not(.attached)) .indicator { + width: 100%; + box-sizing: border-box; +} + +:host([type='label'].outline.with-icon) .indicator { + padding-inline: 0.4375rem; +} + +:host([type='label'].align-left) .indicator { + justify-content: flex-start; +} + +:host([type='label']) .icon { + flex-shrink: 0; +} + +:host([type='counter']) .label, +:host([type='label']) .label { + line-height: 1; +} + +:host([type='status-icon']) .indicator { + display: inline-flex; + align-items: center; + justify-content: center; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; + padding: 0; + line-height: 0; + font-size: 0; + flex-shrink: 0; + background-color: transparent; + border: none; +} + +/* Relative on the stack only — not on .indicator (breaks attached). */ +:host([type='status-icon']:not(.outline)) .status-icon-stack { + position: relative; + display: block; + width: 1.2rem; + height: 1.2rem; + flex-shrink: 0; +} + +:host([type='status-icon']) .status-icon { + flex-shrink: 0; + width: 1.2rem; + height: 1.2rem; + min-width: 1.2rem; + min-height: 1.2rem; +} + +:host([type='status-icon']:not(.outline)) .status-icon-stack .status-icon { + position: absolute; + inset: 0; +} + +@each $variant in $status-icon-variants { + :host([type='status-icon'].#{$variant}) { + --ix-badge-pulse-color: var(--theme-color-#{$variant}); + + .status-icon:not(.status-icon-plate) { + color: var(--theme-color-#{$variant}); + } + } +} + +/* Filled plate bang: black vs white (fixed — theme tokens flip by schema). */ +:host([type='status-icon'].critical:not(.outline)) .status-icon-plate, +:host([type='status-icon'].warning:not(.outline)) .status-icon-plate, +:host([type='status-icon'].success:not(.outline)) .status-icon-plate { + color: #000000; +} + +:host([type='status-icon'].alarm:not(.outline)) .status-icon-plate, +:host([type='status-icon'].error:not(.outline)) .status-icon-plate, +:host([type='status-icon'].info:not(.outline)) .status-icon-plate { + color: #ffffff; +} + +/* Error uses alarm color tokens. */ +:host([type='status-icon'].error) { + --ix-badge-pulse-color: var(--theme-color-alarm); + + .status-icon:not(.status-icon-plate) { + color: var(--theme-color-alarm); + } +} + +@each $variant in $predefined-variants { + :host(.#{$variant}:not(.outline):not([type='status-icon'])) { + --ix-badge-pulse-color: var(--theme-color-#{$variant}); + + .indicator { + background-color: var(--theme-color-#{$variant}); + color: var(--theme-color-#{$variant}--contrast); + } + } + + :host(.#{$variant}.outline:not([type='status-icon'])) { + --ix-badge-pulse-color: var(--theme-color-#{$variant}); + + .indicator { + background-color: var(--theme-color-ghost); + color: var(--theme-color-std-text); + @if $variant == 'alarm' { + border: 0.0625rem solid var(--theme-color-alarm-bdr); + } @else if $variant == 'warning' { + border: 0.0625rem solid var(--theme-color-warning-bdr); + } @else { + border: 0.0625rem solid var(--theme-color-#{$variant}); + } + } + } +} + +:host(.custom:not(.outline):not([type='status-icon'])) { + --ix-badge-pulse-color: var(--ix-badge-custom-background); + + .indicator { + background-color: var(--ix-badge-custom-background); + color: var(--ix-badge-custom-color); + } +} + +:host(.custom.outline:not([type='status-icon'])) { + --ix-badge-pulse-color: var(--ix-badge-custom-background); + + .indicator { + background-color: var(--theme-color-ghost); + border: 0.0625rem solid var(--ix-badge-custom-background); + color: var(--ix-badge-custom-color, var(--theme-color-std-text)); + } +} + +:host(.border:not(.outline):not([type='status-icon'])) .indicator { + border: 0.0625rem solid var(--theme-color-1); +} + +/* SR-only description slot (light DOM for aria-describedby). */ +:host ::slotted(.description) { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +:host(.enable-animation) .indicator { + overflow: visible; + position: relative; +} + +:host(.attached.enable-animation) .indicator { + position: absolute; +} + +/* status-icon pulse: solid halo from center. */ +:host([type='status-icon'].enable-animation) .indicator::after { + content: ''; + position: absolute; + inset: 0.025rem; + z-index: -1; + pointer-events: none; + border-radius: inherit; + background-color: var(--ix-badge-pulse-color); + transform: scale(0.521); + transform-origin: center; + opacity: 0; + animation: ix-badge-pulse-status var(--ix-badge-animation-duration) linear + infinite; +} + +/* counter / label / dot pulse: expanding border ring. */ +:host(.enable-animation:not([type='status-icon'])) .indicator::after { + content: ''; + position: absolute; + inset: 0.03125rem; /* 0.5px */ + z-index: -1; + pointer-events: none; + box-sizing: border-box; + background-color: transparent; + border-style: solid; + border-color: var(--ix-badge-pulse-color); + border-width: 0; + border-radius: inherit; + opacity: 0; + animation: ix-badge-pulse-border var(--ix-badge-animation-duration) linear + infinite; +} + +@media (prefers-reduced-motion: reduce) { + :host(.enable-animation) .indicator::after { + animation: none; + opacity: 0; + transform: none; + background-color: transparent; + border-width: 0; + } +} + +@keyframes ix-badge-pulse-border { + 0% { + inset: 0.03125rem; /* 0.5px */ + border-width: 0; + opacity: 0; + } + + 5% { + inset: 0.03125rem; + border-width: 0; + opacity: 0.5; + } + + 45% { + opacity: 0.4; + } + + 80% { + animation-timing-function: ease-out; + inset: -0.46875rem; /* -7.5px */ + border-width: 0.5rem; /* 8px */ + opacity: 0.1; + } + + 90% { + inset: -0.59375rem; /* -9.5px */ + border-width: 0.625rem; /* 10px */ + opacity: 0; + } + + 100% { + inset: 0.03125rem; + border-width: 0; + opacity: 0; + } +} + +@keyframes ix-badge-pulse-status { + 0% { + transform: scale(0.521); + opacity: 0; + } + + 5% { + transform: scale(0.521); + opacity: 0.5; + animation-timing-function: cubic-bezier(0.637, 0.43, 0.928, 1.008); + } + + 45% { + transform: scale(1); + opacity: 0.4; + } + + 80% { + animation-timing-function: ease-out; + transform: scale(1.6); + opacity: 0.1; + } + + 90% { + transform: scale(1.8); + opacity: 0; + } + + 100% { + transform: scale(0.521); + opacity: 0; + } +} diff --git a/packages/core/src/components/badge/badge.status-icon.ts b/packages/core/src/components/badge/badge.status-icon.ts new file mode 100644 index 00000000000..055f1e03a07 --- /dev/null +++ b/packages/core/src/components/badge/badge.status-icon.ts @@ -0,0 +1,119 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { + iconAlarm, + iconAlarmFilled, + iconCircleFilled, + iconError, + iconErrorFilled, + iconInfo, + iconInfoFilled, + iconRhombFilled, + iconSuccess, + iconSuccessFilled, + iconTriangleFilled, + iconWarning, + iconWarningFilled, + iconWarningRhomb, + iconWarningRhombFilled, +} from '@siemens/ix-icons/icons'; +import type { BadgeVariant } from './badge.types'; + +/** Variants valid for **type** `status-icon`. */ +export type BadgeStatusIconVariant = + | 'alarm' + | 'error' + | 'critical' + | 'warning' + | 'info' + | 'success'; + +type BadgeStatusIconPair = { + filled: string; + outline: string; + /** Solid plate under the filled glyph. */ + plate: string; +}; + +/** Fallback when the variant has no status glyph. */ +export const BADGE_STATUS_ICON_FALLBACK_VARIANT: BadgeStatusIconVariant = + 'info'; + +/** Status icons by variant (`outline` / `filled` / `plate`). */ +export const BADGE_STATUS_ICON_BY_VARIANT: Record< + BadgeStatusIconVariant, + BadgeStatusIconPair +> = { + alarm: { + filled: iconAlarmFilled, + outline: iconAlarm, + plate: iconCircleFilled, + }, + error: { + filled: iconErrorFilled, + outline: iconError, + plate: iconCircleFilled, + }, + critical: { + filled: iconWarningRhombFilled, + outline: iconWarningRhomb, + plate: iconRhombFilled, + }, + warning: { + filled: iconWarningFilled, + outline: iconWarning, + plate: iconTriangleFilled, + }, + info: { + filled: iconInfoFilled, + outline: iconInfo, + plate: iconCircleFilled, + }, + success: { + filled: iconSuccessFilled, + outline: iconSuccess, + plate: iconCircleFilled, + }, +}; + +export function isBadgeStatusIconVariant( + variant: string +): variant is BadgeStatusIconVariant { + return variant in BADGE_STATUS_ICON_BY_VARIANT; +} + +function resolveStatusIconVariant( + variant: BadgeVariant +): BadgeStatusIconVariant { + return isBadgeStatusIconVariant(variant) + ? variant + : BADGE_STATUS_ICON_FALLBACK_VARIANT; +} + +/** Status glyph for a variant (falls back to **info**). */ +export function getBadgeStatusIcon( + variant: BadgeVariant, + outline = false +): string { + const icons = BADGE_STATUS_ICON_BY_VARIANT[resolveStatusIconVariant(variant)]; + return outline ? icons.outline : icons.filled; +} + +/** Plate icon for the filled status stack. */ +export function getBadgeStatusIconPlate(variant: BadgeVariant): string { + return BADGE_STATUS_ICON_BY_VARIANT[resolveStatusIconVariant(variant)].plate; +} + +/** Resolved status-icon variant for host classes (falls back to **info**). */ +export function getResolvedStatusIconVariant( + variant: BadgeVariant +): BadgeStatusIconVariant { + return resolveStatusIconVariant(variant); +} diff --git a/packages/core/src/components/badge/badge.tsx b/packages/core/src/components/badge/badge.tsx new file mode 100644 index 00000000000..e41fa5a2bd0 --- /dev/null +++ b/packages/core/src/components/badge/badge.tsx @@ -0,0 +1,646 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { + Component, + Element, + h, + Host, + Mixin, + Prop, + State, + VNode, + Watch, +} from '@stencil/core'; +import { a11yBoolean, a11yHostAttributes } from '../utils/a11y'; +import { DefaultMixins } from '../utils/internal/component'; +import { + InheritAriaAttributesMixin, + InheritAriaAttributesMixinContract, +} from '../utils/internal/mixins/accessibility/inherit-aria-attributes.mixin'; +import { + ComponentIdMixin, + ComponentIdMixinContract, +} from '../utils/internal/mixins/id.mixin'; +import { makeRef } from '../utils/make-ref'; +import { convertToRemString } from '../utils/rwd.util'; +import { hasSlottedElements } from '../utils/shadow-dom'; +import { + getBadgeStatusIcon, + getBadgeStatusIconPlate, + getResolvedStatusIconVariant, +} from './badge.status-icon'; +import { + BADGE_ANATOMY_TYPES, + BADGE_ATTACHED_OFFSET_DEFAULTS, + BADGE_POSITIONS, + BADGE_VARIANTS, + BadgeAnatomyType, + BadgePosition, + BadgeVariant, +} from './badge.types'; +import { formatBadgeLabel } from './badge.utils'; + +/** Slot name for the screen-reader description. */ +const BADGE_DESCRIPTION_SLOT = 'description'; + +/** + * Overlay indicator for counts, labels, dots, and status icons. + * + * **Attached** (default slot has content): the indicator is decorative. + * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * + * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. + * For `dot` and `status-icon`, provide a host `aria-label` and a naming role + * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). + * + * Override max-width with `--ix-badge-max-width`. + * + * @since 5.2.0 + */ +@Component({ + tag: 'ix-badge', + styleUrl: 'badge.scss', + shadow: true, +}) +export class Badge + extends Mixin(...DefaultMixins, InheritAriaAttributesMixin, ComponentIdMixin) + implements InheritAriaAttributesMixinContract, ComponentIdMixinContract +{ + @Element() override hostElement!: HTMLIxBadgeElement; + + /** + * Badge type (`counter`, `label`, `dot`, or `status-icon`). + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) type: BadgeAnatomyType = 'counter'; + + /** + * Visible text or count. + * Required for `label` and `counter`. Omit for `dot` and `status-icon`. + * Counters accept integers only (decimals truncated); values above 99 render as `99+`. + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) label?: string; + + /** + * Color variant. + * For `status-icon`, unsupported values fall back to `info`. + * Use `error` only with `status-icon` (other types map it to `alarm`). + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) variant: BadgeVariant = 'primary'; + + /** + * Show the badge in outline style. + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) outline = false; + + /** + * Add a high-contrast border on filled badges. + * Ignored when **outline** is `true` or **type** is `status-icon`. + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) border = false; + + /** + * Position relative to the slotted anchor. + * Only has an effect when attached. + * + * @since 5.2.0 + */ + @Prop({ reflect: true }) position: BadgePosition = 'top-after'; + + /** + * Extra horizontal offset in pixels. + * Only has an effect when attached. + * Added to the type default. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'offset-x' }) offsetX = 0; + + /** + * Extra vertical offset in pixels. + * Only has an effect when attached. + * Added to the type default. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'offset-y' }) offsetY = 0; + + /** + * Play the attention pulse animation. + * Override duration with `--ix-badge-animation-duration` (default `2s`). + * + * @since 5.2.0 + */ + @Prop({ attribute: 'enable-animation', reflect: true }) enableAnimation = + false; + + /** + * Custom background or border color. + * Only has an effect when **variant** is `custom`. + * + * @since 5.2.0 + */ + @Prop() background?: string; + + /** + * Custom text color. + * Only has an effect when **variant** is `custom`. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'badge-color' }) badgeColor?: string; + + /** + * Leading icon name. + * Only has an effect when **type** is `label`. + * + * @since 5.2.0 + */ + @Prop() icon?: string; + + /** + * Accessible name for the leading icon. + * When unset, the icon is decorative if **label** provides visible text. + * Only has an effect when **type** is `label`. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'aria-label-icon' }) ariaLabelIcon?: string; + + /** + * Left-align label content. + * Only has an effect when **type** is `label`. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'align-left', reflect: true }) alignLeft = false; + + /** + * Display a tooltip when the badge is standalone. + * By default, no tooltip is displayed. + * Add the attribute to use the badge label (or host `aria-label`) as the tooltip, or pass a string for custom text. + * Ignored when the badge is attached to an anchor. + * + * @since 5.2.0 + */ + @Prop({ attribute: 'tooltip-text' }) tooltipText: string | boolean = false; + + @State() hasAnchor = false; + + private descriptionId = ''; + + private anchorElements: HTMLElement[] = []; + + private slotElement?: HTMLSlotElement; + + private readonly indicatorElementRef = makeRef(); + + private hasDisconnected = false; + + override componentWillLoad() { + super.componentWillLoad(); + this.descriptionId = `${this.getHostElementId()}-description`; + const hasAnchor = this.detectHasAnchor(); + + if (hasAnchor) { + this.hasAnchor = true; + a11yHostAttributes(this.hostElement); + this.inheritAriaAttributes = {}; + return; + } + + this.hasAnchor = false; + // Preserve author ARIA for standalone mode. + } + + override componentDidLoad() { + this.syncAnchorDescribedBy(); + } + + override componentDidRender() { + const nextHasAnchor = this.detectHasAnchor(); + + if (nextHasAnchor !== this.hasAnchor) { + this.applyAnchorMode(nextHasAnchor); + this.syncAnchorDescribedBy(); + } + } + + override connectedCallback() { + if (this.hasDisconnected) { + this.syncAnchorDescribedBy(); + this.hasDisconnected = false; + } + } + + override disconnectedCallback() { + this.clearAnchorDescribedBy(); + this.hasDisconnected = true; + } + + @Watch('label') + @Watch('type') + labelOrTypeChanged() { + if (this.hasAnchor) { + this.syncAnchorDescribedBy(); + } + } + + private readonly setSlotRef = (element: HTMLSlotElement | undefined) => { + this.slotElement = element; + }; + + private readonly onSlotChange = () => { + this.applyAnchorMode(this.detectHasAnchor()); + this.syncAnchorDescribedBy(); + }; + + private isDescriptionElement(element: Element): boolean { + return ( + element.getAttribute('slot') === BADGE_DESCRIPTION_SLOT || + (!!this.descriptionId && element.id === this.descriptionId) + ); + } + + private getAnchorElements(): HTMLElement[] { + return Array.from(this.hostElement.children).filter( + (child): child is HTMLElement => + child instanceof HTMLElement && !this.isDescriptionElement(child) + ); + } + + private detectHasAnchor(): boolean { + if (hasSlottedElements(this.slotElement)) { + return true; + } + + return this.getAnchorElements().length > 0; + } + + private applyAnchorMode(hasAnchor: boolean) { + if (hasAnchor === this.hasAnchor) { + return; + } + + this.clearAnchorDescribedBy(); + + if (hasAnchor) { + this.hasAnchor = true; + a11yHostAttributes(this.hostElement); + this.inheritAriaAttributes = {}; + this.descriptionId = `${this.getHostElementId()}-description`; + return; + } + + this.hasAnchor = false; + // Re-apply author ARIA after leaving attached mode. + this.inheritAriaAttributes = a11yHostAttributes(this.hostElement); + } + + private getResolvedVariant(): BadgeVariant { + if (this.variant === 'error') { + return this.getResolvedType() === 'status-icon' ? 'error' : 'alarm'; + } + + return (BADGE_VARIANTS as readonly string[]).includes(this.variant) + ? this.variant + : 'primary'; + } + + private getResolvedType(): BadgeAnatomyType { + return BADGE_ANATOMY_TYPES.includes(this.type) ? this.type : 'counter'; + } + + private getResolvedPosition(): BadgePosition { + return BADGE_POSITIONS.includes(this.position) + ? this.position + : 'top-after'; + } + + private getResolvedOffsets(): { x: number; y: number } { + const type = this.getResolvedType(); + const defaults = this.hasAnchor + ? BADGE_ATTACHED_OFFSET_DEFAULTS[type] + : { x: 0, y: 0 }; + + return { + x: defaults.x + this.offsetX, + y: defaults.y + this.offsetY, + }; + } + + private getFormattedLabel(type: BadgeAnatomyType): string | null { + return formatBadgeLabel(type, this.label); + } + + private getAccessibleText(formattedLabel: string | null): string | undefined { + return formattedLabel || undefined; + } + + private isTooltipRequested(): boolean { + return !!( + this.tooltipText || this.hostElement.hasAttribute('tooltip-text') + ); + } + + private hasVisibleIndicator( + type: BadgeAnatomyType, + formattedLabel: string | null + ): boolean { + if (type === 'counter' || type === 'label') { + return !!formattedLabel; + } + + return type === 'dot' || type === 'status-icon'; + } + + private shouldShowTooltip( + type: BadgeAnatomyType, + formattedLabel: string | null + ): boolean { + return ( + !this.hasAnchor && + this.isTooltipRequested() && + this.hasVisibleIndicator(type, formattedLabel) + ); + } + + private getTooltipContent(formattedLabel: string | null): string | undefined { + if (typeof this.tooltipText === 'string' && this.tooltipText.trim()) { + return this.tooltipText.trim(); + } + + return ( + formattedLabel?.trim() || + this.inheritAriaAttributes['aria-label']?.trim() || + this.hostElement.getAttribute('aria-label')?.trim() || + undefined + ); + } + + private getTooltip(formattedLabel: string | null) { + if (!this.shouldShowTooltip(this.getResolvedType(), formattedLabel)) { + return null; + } + + const text = this.getTooltipContent(formattedLabel); + if (!text) { + return null; + } + + return ( + + {text} + + ); + } + + private syncAnchorDescribedBy() { + this.clearAnchorDescribedBy(); + + if (!this.hasAnchor) { + return; + } + + const accessibleText = this.getAccessibleText( + this.getFormattedLabel(this.getResolvedType()) + ); + + if (!accessibleText) { + return; + } + + const descriptionEl = this.ensureLightDomDescription(accessibleText); + const anchors = this.getAnchorElements(); + + for (const anchor of anchors) { + const existing = anchor.getAttribute('aria-describedby'); + const ids = new Set( + existing?.split(/\s+/).filter((id) => id.length > 0) ?? [] + ); + ids.add(descriptionEl.id); + anchor.setAttribute('aria-describedby', Array.from(ids).join(' ')); + anchor.dataset.ixBadgeDescribedby = descriptionEl.id; + } + + this.anchorElements = anchors; + } + + private ensureLightDomDescription(text: string): HTMLElement { + let descriptionEl = Array.from(this.hostElement.children).find( + (child): child is HTMLElement => + child instanceof HTMLElement && this.isDescriptionElement(child) + ); + + if (!descriptionEl) { + descriptionEl = document.createElement('span'); + descriptionEl.slot = BADGE_DESCRIPTION_SLOT; + descriptionEl.className = 'description'; + this.hostElement.appendChild(descriptionEl); + } + + descriptionEl.id = this.descriptionId; + descriptionEl.textContent = text; + return descriptionEl; + } + + private removeLightDomDescription() { + Array.from(this.hostElement.children) + .filter( + (child): child is HTMLElement => + child instanceof HTMLElement && this.isDescriptionElement(child) + ) + .forEach((child) => child.remove()); + } + + private clearAnchorDescribedBy() { + for (const anchor of this.anchorElements) { + if (anchor.dataset.ixBadgeDescribedby !== this.descriptionId) { + continue; + } + + const existing = anchor.getAttribute('aria-describedby'); + const ids = + existing?.split(/\s+/).filter((id) => id !== this.descriptionId) ?? []; + + delete anchor.dataset.ixBadgeDescribedby; + + if (ids.length > 0) { + anchor.setAttribute('aria-describedby', ids.join(' ')); + } else { + anchor.removeAttribute('aria-describedby'); + } + } + + this.anchorElements = []; + this.removeLightDomDescription(); + } + + private renderIndicatorShell( + _accessibleText: string | undefined, + content?: VNode | VNode[] + ) { + return ( +
+ {content} +
+ ); + } + + private renderIndicator( + type: BadgeAnatomyType, + variant: BadgeVariant, + accessibleText: string | undefined, + formattedLabel: string | null + ) { + if (type === 'counter') { + if (!formattedLabel) { + return null; + } + + return this.renderIndicatorShell( + accessibleText, + {formattedLabel} + ); + } + + if (type === 'dot') { + return this.renderIndicatorShell(accessibleText); + } + + if (type === 'label') { + if (!formattedLabel) { + return null; + } + + const iconIsDecorative = !this.ariaLabelIcon?.trim(); + + return this.renderIndicatorShell(accessibleText, [ + this.icon ? ( + + ) : null, + + {formattedLabel} + , + ]); + } + + if (type === 'status-icon') { + if (this.outline) { + return this.renderIndicatorShell( + accessibleText, + + ); + } + + return this.renderIndicatorShell( + accessibleText, + + + + + ); + } + + return null; + } + + override render() { + const type = this.getResolvedType(); + const variant = this.getResolvedVariant(); + const position = this.getResolvedPosition(); + const offsets = this.getResolvedOffsets(); + const formattedLabel = this.getFormattedLabel(type); + const accessibleText = this.getAccessibleText(formattedLabel); + const hostVariant = + type === 'status-icon' ? getResolvedStatusIconVariant(variant) : variant; + const showBorder = this.border && type !== 'status-icon'; + const showTooltip = this.shouldShowTooltip(type, formattedLabel); + + const customHostStyle = + hostVariant === 'custom' + ? ({ + '--ix-badge-custom-background': this.background, + '--ix-badge-custom-color': this.badgeColor, + } as Record) + : undefined; + + return ( + + +
+ +
+ {this.renderIndicator(type, variant, accessibleText, formattedLabel)} + {this.getTooltip(formattedLabel)} +
+ ); + } +} diff --git a/packages/core/src/components/badge/badge.types.ts b/packages/core/src/components/badge/badge.types.ts new file mode 100644 index 00000000000..2a950a8e281 --- /dev/null +++ b/packages/core/src/components/badge/badge.types.ts @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { ChipVariant } from '../chip/chip.types'; + +export const BADGE_ANATOMY_TYPES = [ + 'label', + 'counter', + 'dot', + 'status-icon', +] as const; + +export type BadgeAnatomyType = (typeof BADGE_ANATOMY_TYPES)[number]; + +/** Pill anatomies share chip semantic variants. */ +export { CHIP_VARIANTS as BADGE_VARIANTS } from '../chip/chip.types'; + +/** + * Badge variant. + * **error** is only for **type** `status-icon`; other anatomies coerce to `alarm`. + */ +export type BadgeVariant = ChipVariant | 'error'; + +export type { ChipVariant }; + +export const BADGE_POSITIONS = ['top-after', 'bottom-after'] as const; + +export type BadgePosition = (typeof BADGE_POSITIONS)[number]; + +export type BadgeAttachedOffset = { + x: number; + y: number; +}; + +/** Default attached offsets (px) added to **offsetX** / **offsetY**. */ +export const BADGE_ATTACHED_OFFSET_DEFAULTS: Record< + BadgeAnatomyType, + BadgeAttachedOffset +> = { + dot: { x: -6, y: -6 }, + label: { x: -10, y: -10 }, + counter: { x: -10, y: -10 }, + 'status-icon': { x: -10, y: -10 }, +}; diff --git a/packages/core/src/components/badge/badge.utils.ts b/packages/core/src/components/badge/badge.utils.ts new file mode 100644 index 00000000000..e43ef16c4c9 --- /dev/null +++ b/packages/core/src/components/badge/badge.utils.ts @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { BadgeAnatomyType } from './badge.types'; + +export const BADGE_OVERFLOW_THRESHOLD = 99; + +const INTEGER_LABEL_PATTERN = /^-?\d+(\.\d+)?$/; +const OVERFLOW_LABEL = `${BADGE_OVERFLOW_THRESHOLD}+`; + +/** + * Formats badge label text for supported anatomy types. + * Returns `null` when the type has no text or the value is invalid. + * Counters truncate decimals and cap at `99+`. + */ +export function formatBadgeLabel( + type: BadgeAnatomyType, + label?: string | number | null +): string | null { + switch (type) { + case 'counter': + return formatCounterLabel(label); + case 'label': + return formatTextLabel(label); + case 'dot': + case 'status-icon': + return null; + } +} + +function coerceLabelText(label?: string | number | null): string { + if (label === undefined || label === null) { + return ''; + } + + return String(label).trim(); +} + +function formatTextLabel(label?: string | number | null): string | null { + const trimmed = coerceLabelText(label); + + if (!trimmed) { + return null; + } + + return trimmed; +} + +function formatCounterLabel(label?: string | number | null): string | null { + const trimmed = coerceLabelText(label); + + if (!trimmed) { + return null; + } + + if (trimmed === OVERFLOW_LABEL) { + return OVERFLOW_LABEL; + } + + if (!INTEGER_LABEL_PATTERN.test(trimmed)) { + return null; + } + + const intValue = Math.trunc(Number(trimmed)); + + if (intValue > BADGE_OVERFLOW_THRESHOLD) { + return OVERFLOW_LABEL; + } + + return String(intValue); +} diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts new file mode 100644 index 00000000000..ccbf086fbd9 --- /dev/null +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -0,0 +1,728 @@ +/* + * SPDX-FileCopyrightText: 2026 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, Locator } from '@playwright/test'; +import { + iconCircleFilled, + iconInfo, + iconInfoFilled, + iconStar, +} from '@siemens/ix-icons/icons'; +import { regressionTest } from '@utils/test'; +import { BadgePage } from './badge.page'; + +const html = String.raw; + +regressionTest.describe('ix-badge', () => { + regressionTest.describe('rendering', () => { + regressionTest('hydrates standalone badge', async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + + await badge.expectHydrated(); + await badge.expectStandalone(); + await expect(badge.host).toHaveAttribute('variant', 'info'); + await badge.expectLabelText('12'); + }); + + regressionTest( + 'hydrates attached badge with anchor class', + async ({ mount, page }) => { + await mount(html` + + Review changes + + `); + + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.expectAttached(); + } + ); + + regressionTest('formats overflow label as 99+', async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectLabelText('99+'); + }); + + regressionTest( + 'accepts preformatted overflow label 99+', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectLabelText('99+'); + } + ); + + regressionTest( + 'renders no indicator when counter label is missing', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + + await badge.expectHydrated(); + await badge.expectNoIndicator(); + } + ); + + regressionTest( + 'renders no indicator for non-numeric counter label', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + + await badge.expectHydrated(); + await badge.expectNoIndicator(); + } + ); + + regressionTest( + 'renders standalone dot indicator without label text', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + + await badge.expectHydrated(); + await badge.expectIndicatorVisible(); + await expect(badge.label).toHaveCount(0); + } + ); + + regressionTest( + 'status-icon falls back to info for unsupported variants', + async ({ mount, page }) => { + await mount( + ``, + { icons: { iconInfoFilled, iconCircleFilled } } + ); + const badge = new BadgePage(page); + await badge.expectHostClass(/\binfo\b/); + await badge.expectIndicatorVisible(); + await expect(badge.statusIconGlyph).toBeVisible(); + await expect(badge.statusIconPlate).toBeVisible(); + } + ); + + regressionTest( + 'status-icon outline uses a different glyph than filled', + async ({ mount, page }) => { + await mount( + html` + + + `, + { icons: { iconInfo, iconInfoFilled, iconCircleFilled } } + ); + + const badge = new BadgePage(page); + const filled = badge.locator('#filled'); + const outline = badge.locator('#outline'); + + await expect(filled).toHaveClass(/\binfo\b/); + await expect(outline).toHaveClass(/\boutline\b/); + await expect(filled.locator('ix-icon.status-icon-glyph')).toBeVisible(); + await expect(filled.locator('ix-icon.status-icon-plate')).toBeVisible(); + await expect(outline.locator('ix-icon.status-icon')).toBeVisible(); + await expect(outline.locator('ix-icon.status-icon-plate')).toHaveCount( + 0 + ); + + const filledName = await filled + .locator('ix-icon.status-icon-glyph') + .evaluate((el: HTMLIxIconElement) => el.name); + const outlineName = await outline + .locator('ix-icon.status-icon') + .evaluate((el: HTMLIxIconElement) => el.name); + + expect(filledName).toBeTruthy(); + expect(outlineName).toBeTruthy(); + expect(outlineName).not.toBe(filledName); + } + ); + }); + + regressionTest.describe('variants', () => { + regressionTest( + 'applies filled variant class on host', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHostClass(/\balarm\b/); + } + ); + + regressionTest('applies outline class on host', async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHostClass(/\boutline\b/); + }); + + regressionTest('applies border class on host', async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHostClass(/\bborder\b/); + }); + + regressionTest( + 'does not apply border class for status-icon', + async ({ mount, page }) => { + await mount( + ``, + { icons: { iconInfoFilled, iconCircleFilled } } + ); + const badge = new BadgePage(page); + await badge.expectNoHostClass(/\bborder\b/); + } + ); + + regressionTest( + 'falls back to primary for unknown variant', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHostClass(/\bprimary\b/); + } + ); + + regressionTest( + 'sets custom variant CSS variables on host', + async ({ mount, page }) => { + await mount( + `` + ); + + const badge = new BadgePage(page); + await badge.expectCustomVariantColors('red', 'white'); + } + ); + }); + + regressionTest.describe('position and animation', () => { + regressionTest( + 'defaults to top-after position class', + async ({ mount, page }) => { + await mount(html` + + Action + + `); + const badge = new BadgePage(page); + await badge.expectHostClass(/\btop-after\b/); + } + ); + + regressionTest( + 'applies bottom-after position class', + async ({ mount, page }) => { + await mount(html` + + Action + + `); + const badge = new BadgePage(page); + await badge.expectHostClass(/\bbottom-after\b/); + } + ); + + regressionTest( + 'ignores position class when standalone', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + + await badge.expectStandalone(); + await badge.expectNoHostClass(/\btop-after\b/); + await badge.expectNoHostClass(/\bbottom-after\b/); + } + ); + + regressionTest( + 'applies offset values as CSS custom properties', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectOffsets('-0.375rem', '-0.75rem'); + } + ); + + regressionTest( + 'applies dot anatomy default offsets when attached', + async ({ mount, page }) => { + await mount(html` + + + + `); + const badge = new BadgePage(page); + await badge.expectAttached(); + await badge.expectOffsets('-0.375rem', '-0.375rem'); + } + ); + + regressionTest( + 'applies enable-animation class on host', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHostClass(/\benable-animation\b/); + } + ); + }); + + regressionTest.describe('attached accessibility', () => { + regressionTest( + 'sets aria-describedby for text label on anchor', + async ({ mount, page }) => { + await mount(html` + + Review changes + + `); + + const badge = new BadgePage(page); + await badge.expectAttachedTextLabelA11y('Review changes', '3'); + } + ); + + regressionTest( + 'does not set aria-describedby for dot badge on anchor', + async ({ mount, page }) => { + await mount( + html` + + + + `, + { icons: { iconInfo } } + ); + + const badge = new BadgePage(page); + await badge.expectDotAttachedNoDescribedBy('Notifications'); + } + ); + + regressionTest( + 'merges aria-describedby with existing anchor ids', + async ({ mount, page }) => { + await mount(html` + + + + Existing description + `); + + const badge = new BadgePage(page); + await badge.expectMergedDescribedBy('Inbox', 'existing-id', '5'); + } + ); + + regressionTest( + 'updates hidden description when label changes', + async ({ mount, page }) => { + await mount(html` + + + + `); + + const badge = new BadgePage(page); + await expect(badge.description).toHaveText('3'); + + await badge.setLabel('8'); + + await expect(badge.description).toHaveText('8'); + } + ); + + regressionTest( + 'removes aria-describedby from anchor on disconnect', + async ({ mount, page }) => { + await mount(html` + + + + `); + + const badge = new BadgePage(page); + const button = badge.locator('#anchor'); + await expect(button).toHaveAttribute('aria-describedby', /.+/); + + await badge.disconnectKeepingAnchor('#anchor'); + + await expect(button).not.toHaveAttribute('aria-describedby'); + } + ); + + regressionTest( + 'restores aria-describedby after reconnect', + async ({ mount, page }) => { + await mount(html` +
+ + + +
+ `); + + const badge = new BadgePage(page); + const button = badge.locator('#anchor'); + await expect(button).toHaveAttribute('aria-describedby', /.+/); + + await page.evaluate(() => { + const host = document.querySelector('ix-badge'); + const mountPoint = document.getElementById('mount'); + if (host && mountPoint) { + host.remove(); + mountPoint.appendChild(host); + } + }); + + await expect(button).toHaveAttribute('aria-describedby', /.+/); + await badge.expectAttachedTextLabelA11y('Messages', '3'); + } + ); + }); + + regressionTest.describe('label type', () => { + regressionTest('renders standalone label text', async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + + await expect(badge.host).toHaveAttribute('type', 'label'); + await badge.expectLabelText('NEW'); + }); + + regressionTest( + 'renders no indicator for empty label text', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + + await badge.expectHydrated(); + await badge.expectNoIndicator(); + } + ); + + regressionTest( + 'renders label with icon and align-left class', + async ({ mount, page }) => { + await mount( + ``, + { icons: { iconStar } } + ); + const badge = new BadgePage(page); + + await badge.expectHostClass(/\balign-left\b/); + await badge.expectHostClass(/\bwith-icon\b/); + await badge.expectLeadingIconDecorative(); + } + ); + + regressionTest( + 'names leading icon when aria-label-icon is set', + async ({ mount, page }) => { + await mount( + ``, + { icons: { iconStar } } + ); + const badge = new BadgePage(page); + + await badge.expectLeadingIconNamed('Featured'); + await badge.expectLabelText('NEW'); + } + ); + + regressionTest( + 'sets aria-describedby for attached label on anchor', + async ({ mount, page }) => { + await mount(html` + + What's new + + `); + + const badge = new BadgePage(page); + await badge.expectAttachedTextLabelA11y("What's new", 'NEW'); + } + ); + }); + + regressionTest.describe('standalone accessibility', () => { + regressionTest( + 'standalone dot host matches 12×12 indicator size', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.expectStandalone(); + + await expect(async () => { + const hostBox = await badge.host.boundingBox(); + const indicatorBox = await badge.indicator.boundingBox(); + + expect(hostBox?.width).toBeCloseTo(12, 0); + expect(hostBox?.height).toBeCloseTo(12, 0); + expect(indicatorBox?.width).toBeCloseTo(12, 0); + expect(indicatorBox?.height).toBeCloseTo(12, 0); + }).toPass(); + } + ); + + regressionTest( + 'standalone label host matches indicator size', + async ({ mount, page }) => { + await mount( + ``, + { icons: { iconStar } } + ); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.expectStandalone(); + await expect(badge.indicator.locator('ix-icon')).toBeVisible(); + + await expect(async () => { + const hostBox = await badge.host.boundingBox(); + const indicatorBox = await badge.indicator.boundingBox(); + + expect(hostBox?.height).toBeCloseTo(20, 0); + expect(indicatorBox?.height).toBeCloseTo(20, 0); + expect(hostBox?.width).toBeCloseTo(indicatorBox?.width ?? 0, 0); + }).toPass(); + } + ); + + regressionTest( + 'keeps standalone chrome static without default live region', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectStandaloneStaticChrome({ + visibleLabel: '12', + hostRole: null, + }); + } + ); + + regressionTest( + 'keeps author role and aria-label on the host for standalone', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectStandaloneHostAria({ + role: 'alert', + ariaLabel: 'Urgent update', + }); + } + ); + + regressionTest( + 'keeps opt-in status live region attributes on the host', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectStandaloneHostAria({ + role: 'status', + ariaLabel: 'Cart count', + ariaLive: 'polite', + }); + } + ); + }); + + regressionTest.describe('tooltip', () => { + async function expectVisibleTooltipText(tooltip: Locator, text: string) { + await expect(tooltip).toHaveClass(/visible/); + + const metrics = await tooltip.evaluate((el) => { + const slot = el.shadowRoot?.querySelector( + 'slot:not([name])' + ) as HTMLSlotElement | null; + const assigned = slot?.assignedNodes({ flatten: true }) ?? []; + const slottedText = assigned + .map((node) => node.textContent ?? '') + .join(''); + let width = 0; + let height = 0; + + if (assigned[0]) { + const range = document.createRange(); + range.selectNodeContents(assigned[0]); + const rect = range.getBoundingClientRect(); + width = rect.width; + height = rect.height; + } + + return { + slottedText, + width, + height, + fontSize: getComputedStyle(el).fontSize, + }; + }); + + expect(metrics.slottedText).toBe(text); + expect(metrics.fontSize).toBe('14px'); + // Guard against host font-size:0 collapsing tooltip glyphs (empty bubble). + expect(metrics.width).toBeGreaterThan(8); + expect(metrics.height).toBeGreaterThan(8); + } + + regressionTest( + 'does not render tooltip when tooltip-text is absent', + async ({ mount, page }) => { + await mount(``); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.host.hover(); + + await expect(badge.host).not.toHaveAttribute('tooltip-text'); + await expect(badge.host.locator('ix-tooltip')).not.toBeAttached(); + } + ); + + regressionTest( + 'shows label text when tooltip-text attribute is present', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.indicator.hover(); + + await expectVisibleTooltipText( + badge.host.locator('ix-tooltip'), + 'Label' + ); + } + ); + + regressionTest( + 'shows custom tooltip text for standalone counter', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.indicator.hover(); + + await expectVisibleTooltipText( + badge.host.locator('ix-tooltip'), + 'Twelve items' + ); + } + ); + + regressionTest( + 'uses aria-label as tooltip text for standalone dot', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.indicator.hover(); + + await expectVisibleTooltipText( + badge.host.locator('ix-tooltip'), + 'Unread' + ); + } + ); + + regressionTest( + 'ignores tooltip-text when badge is attached', + async ({ mount, page }) => { + await mount(html` + + Review + + `); + const badge = new BadgePage(page); + await badge.expectHydrated(); + await badge.expectAttached(); + await badge.indicator.hover(); + + await expect(badge.host.locator('ix-tooltip')).not.toBeAttached(); + } + ); + }); + + regressionTest('accessibility', async ({ mount, makeAxeBuilder }) => { + await mount(html` +
+ + Review changes + + + + + + +
+ `); + + const accessibilityScanResults = await makeAxeBuilder().analyze(); + expect(accessibilityScanResults.violations).toEqual([]); + }); +}); diff --git a/packages/core/src/components/badge/test/badge.page.ts b/packages/core/src/components/badge/test/badge.page.ts new file mode 100644 index 00000000000..9395fb33c85 --- /dev/null +++ b/packages/core/src/components/badge/test/badge.page.ts @@ -0,0 +1,274 @@ +/* + * SPDX-FileCopyrightText: 2026 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, Locator, Page } from '@playwright/test'; + +/** + * Page Object Model for ix-badge component testing. + * + * Usage: + * ```ts + * const badge = new BadgePage(page); + * await badge.expectHydrated(); + * await badge.expectLabelText('12'); + * ``` + */ +export class BadgePage { + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + /** First badge on the page (single-badge fixtures). */ + get host(): Locator { + return this.page.locator('ix-badge').first(); + } + + get indicator(): Locator { + return this.host.locator('.indicator'); + } + + get label(): Locator { + return this.host.locator('.label'); + } + + get description(): Locator { + return this.host.locator(`> .description, > [slot="description"]`).first(); + } + + getButton(name: string): Locator { + return this.page.getByRole('button', { name }); + } + + locator(selector: string): Locator { + return this.page.locator(selector); + } + + async expectHydrated(badge: Locator = this.host): Promise { + await expect(badge).toHaveClass(/\bhydrated\b/); + } + + async expectAttached(badge: Locator = this.host): Promise { + await expect(badge).toHaveClass(/\battached\b/); + } + + async expectStandalone(badge: Locator = this.host): Promise { + await expect(badge).not.toHaveClass(/\battached\b/); + } + + async expectHostClass( + pattern: RegExp, + badge: Locator = this.host + ): Promise { + await expect(badge).toHaveClass(pattern); + } + + async expectNoHostClass( + pattern: RegExp, + badge: Locator = this.host + ): Promise { + await expect(badge).not.toHaveClass(pattern); + } + + async expectLabelText( + text: string, + badge: Locator = this.host + ): Promise { + await expect(badge.locator('.label')).toHaveText(text); + } + + async expectNoIndicator(badge: Locator = this.host): Promise { + await expect(badge.locator('.indicator')).toHaveCount(0); + } + + async expectIndicatorVisible(badge: Locator = this.host): Promise { + await expect(badge.locator('.indicator')).toBeVisible(); + } + + get leadingIcon(): Locator { + return this.indicator.locator('ix-icon.icon'); + } + + get statusIconPlate(): Locator { + return this.indicator.locator('ix-icon.status-icon-plate'); + } + + get statusIconGlyph(): Locator { + return this.indicator.locator('ix-icon.status-icon-glyph'); + } + + async expectLeadingIconDecorative(): Promise { + await expect(this.leadingIcon).toBeVisible(); + await expect(this.leadingIcon).toHaveAttribute('aria-hidden', 'true'); + } + + async expectLeadingIconNamed(ariaLabel: string): Promise { + await expect(this.leadingIcon).toBeVisible(); + await expect(this.leadingIcon).toHaveAttribute('aria-label', ariaLabel); + await expect(this.leadingIcon).toHaveAttribute('aria-hidden', 'false'); + } + + async expectCustomVariantColors( + background: string, + color: string, + badge: Locator = this.host + ): Promise { + await expect(async () => { + const resolvedBackground = await badge.evaluate((el) => + el.style.getPropertyValue('--ix-badge-custom-background') + ); + const resolvedColor = await badge.evaluate((el) => + el.style.getPropertyValue('--ix-badge-custom-color') + ); + expect(resolvedBackground).toBe(background); + expect(resolvedColor).toBe(color); + }).toPass(); + } + + async expectOffsets( + offsetX: string, + offsetY: string, + badge: Locator = this.host + ): Promise { + await expect(async () => { + const resolvedOffsetX = await badge.evaluate((el) => + el.style.getPropertyValue('--ix-badge-offset-x') + ); + const resolvedOffsetY = await badge.evaluate((el) => + el.style.getPropertyValue('--ix-badge-offset-y') + ); + expect(resolvedOffsetX).toBe(offsetX); + expect(resolvedOffsetY).toBe(offsetY); + }).toPass(); + } + + async expectAttachedTextLabelA11y( + buttonName: string, + descriptionText: string + ): Promise { + const button = this.getButton(buttonName); + const describedBy = await button.getAttribute('aria-describedby'); + expect(describedBy).toBeTruthy(); + + await expect(this.description).toHaveText(descriptionText); + const descriptionId = await this.description.getAttribute('id'); + expect(descriptionId).toBeTruthy(); + expect(describedBy!.split(/\s+/)).toContain(descriptionId); + + // Description stays in light DOM for aria-describedby. + await expect + .poll(async () => + this.page.evaluate( + (id) => document.getElementById(id)?.textContent ?? null, + descriptionId! + ) + ) + .toBe(descriptionText); + await expect + .poll(async () => + this.host.evaluate((host, id) => { + const description = host.querySelector(`:scope > #${CSS.escape(id)}`); + return description?.getAttribute('slot') ?? null; + }, descriptionId!) + ) + .toBe('description'); + await expect(this.indicator).toHaveAttribute('aria-hidden', 'true'); + } + + async expectDotAttachedNoDescribedBy(buttonName: string): Promise { + const button = this.getButton(buttonName); + await expect(button).not.toHaveAttribute('aria-describedby'); + await expect(this.host).toHaveAttribute('type', 'dot'); + await expect(this.description).toHaveCount(0); + } + + async expectMergedDescribedBy( + buttonName: string, + existingId: string, + descriptionText: string + ): Promise { + const button = this.getButton(buttonName); + const describedBy = await button.getAttribute('aria-describedby'); + + expect(describedBy).toContain(existingId); + expect(describedBy?.split(/\s+/).length).toBeGreaterThan(1); + await expect(this.description).toHaveText(descriptionText); + } + + async expectStandaloneStaticChrome( + options: { + visibleLabel?: string; + hostRole?: string | null; + hostAriaLabel?: string; + } = {} + ): Promise { + await this.expectStandalone(); + await expect(this.indicator).not.toHaveAttribute('role'); + await expect(this.indicator).not.toHaveAttribute('aria-live'); + await expect(this.indicator).not.toHaveAttribute('aria-label'); + + if (options.visibleLabel !== undefined) { + await this.expectLabelText(options.visibleLabel); + } + + if (options.hostRole === null) { + await expect(this.host).not.toHaveAttribute('role'); + } else if (options.hostRole !== undefined) { + await expect(this.host).toHaveAttribute('role', options.hostRole); + } + + if (options.hostAriaLabel !== undefined) { + await expect(this.host).toHaveAttribute( + 'aria-label', + options.hostAriaLabel + ); + } + } + + async expectStandaloneHostAria(options: { + role?: string; + ariaLabel?: string; + ariaLive?: string; + }): Promise { + await this.expectStandalone(); + await expect(this.indicator).not.toHaveAttribute('role'); + + if (options.role !== undefined) { + await expect(this.host).toHaveAttribute('role', options.role); + } + if (options.ariaLabel !== undefined) { + await expect(this.host).toHaveAttribute('aria-label', options.ariaLabel); + } + if (options.ariaLive !== undefined) { + await expect(this.host).toHaveAttribute('aria-live', options.ariaLive); + } + } + + async setLabel(label: string, badge: Locator = this.host): Promise { + await badge.evaluate( + (el: HTMLElement & { label?: string }, value: string) => { + el.label = value; + }, + label + ); + } + + async disconnectKeepingAnchor(anchorSelector: string): Promise { + await this.page.evaluate((selector) => { + const badge = document.querySelector('ix-badge'); + const anchor = document.querySelector(selector); + + if (badge && anchor) { + document.body.appendChild(anchor); + badge.remove(); + } + }, anchorSelector); + } +} diff --git a/packages/core/src/components/badge/test/badge.spec.ts b/packages/core/src/components/badge/test/badge.spec.ts new file mode 100644 index 00000000000..00181443839 --- /dev/null +++ b/packages/core/src/components/badge/test/badge.spec.ts @@ -0,0 +1,160 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { + iconAlarm, + iconAlarmFilled, + iconCircleFilled, + iconError, + iconErrorFilled, + iconInfo, + iconInfoFilled, + iconRhombFilled, + iconSuccess, + iconSuccessFilled, + iconTriangleFilled, + iconWarning, + iconWarningFilled, + iconWarningRhomb, + iconWarningRhombFilled, +} from '@siemens/ix-icons/icons'; +import { describe, expect, it } from 'vitest'; +import { + BADGE_STATUS_ICON_BY_VARIANT, + BADGE_STATUS_ICON_FALLBACK_VARIANT, + getBadgeStatusIcon, + getBadgeStatusIconPlate, + getResolvedStatusIconVariant, + isBadgeStatusIconVariant, +} from '../badge.status-icon'; +import type { BadgeVariant } from '../badge.types'; +import { formatBadgeLabel } from '../badge.utils'; + +describe('formatBadgeLabel', () => { + it.each([ + ['dot', undefined], + ['dot', '3'], + ['status-icon', undefined], + ['status-icon', 'ok'], + ] as const)( + 'returns null for anatomy type %s with label %j', + (type, label) => { + expect(formatBadgeLabel(type, label)).toBeNull(); + } + ); + + it.each([ + ['3', '3'], + [3, '3'], + [100, '99+'], + ['99', '99'], + ['100', '99+'], + ['99+', '99+'], + ['3.7', '3'], + ['-1', '-1'], + [' 5 ', '5'], + ['new', null], + [undefined, null], + ['', null], + [' ', null], + ] as const)('formats counter label %j as %j', (label, expected) => { + expect(formatBadgeLabel('counter', label)).toBe(expected); + }); + + it.each([ + ['NEW', 'NEW'], + [' Beta ', 'Beta'], + [42, '42'], + [' ', null], + [undefined, null], + ] as const)('formats label text %j as %j', (label, expected) => { + expect(formatBadgeLabel('label', label)).toBe(expected); + }); +}); + +describe('badge.status-icon', () => { + const unsupportedVariants = ['primary', 'neutral', 'custom'] as const; + + it.each([ + ['alarm', iconAlarmFilled, iconAlarm, iconCircleFilled], + ['error', iconErrorFilled, iconError, iconCircleFilled], + ['critical', iconWarningRhombFilled, iconWarningRhomb, iconRhombFilled], + ['warning', iconWarningFilled, iconWarning, iconTriangleFilled], + ['info', iconInfoFilled, iconInfo, iconCircleFilled], + ['success', iconSuccessFilled, iconSuccess, iconCircleFilled], + ] as const)( + 'maps %s to filled, outline, and plate glyphs', + (variant, filled, outline, plate) => { + expect(BADGE_STATUS_ICON_BY_VARIANT[variant]).toEqual({ + filled, + outline, + plate, + }); + expect(getBadgeStatusIcon(variant, false)).toBe(filled); + expect(getBadgeStatusIcon(variant, true)).toBe(outline); + expect(getBadgeStatusIconPlate(variant)).toBe(plate); + expect(outline).not.toBe(filled); + } + ); + + it.each([ + ['alarm', true], + ['error', true], + ['critical', true], + ['warning', true], + ['info', true], + ['success', true], + ['primary', false], + ['neutral', false], + ['custom', false], + ] as const)('isBadgeStatusIconVariant(%s) → %s', (variant, expected) => { + expect(isBadgeStatusIconVariant(variant)).toBe(expected); + }); + + it.each([ + ['alarm', 'alarm'], + ['error', 'error'], + ['critical', 'critical'], + ['warning', 'warning'], + ['info', 'info'], + ['success', 'success'], + ['primary', 'info'], + ['neutral', 'info'], + ['custom', 'info'], + ] as const)('getResolvedStatusIconVariant(%s) → %s', (variant, expected) => { + expect(getResolvedStatusIconVariant(variant)).toBe(expected); + }); + + it('uses info as the unsupported-variant fallback constant', () => { + expect(BADGE_STATUS_ICON_FALLBACK_VARIANT).toBe('info'); + }); + + it('defaults to the filled glyph when outline is omitted', () => { + expect(getBadgeStatusIcon('info')).toBe(iconInfoFilled); + }); + + it.each(unsupportedVariants)( + 'falls back to info glyphs for unsupported variant %s', + (variant) => { + expect(getBadgeStatusIcon(variant)).toBe(iconInfoFilled); + expect(getBadgeStatusIcon(variant, true)).toBe(iconInfo); + expect(getBadgeStatusIconPlate(variant)).toBe(iconCircleFilled); + } + ); + + it('treats unknown variant strings like unsupported chip variants', () => { + const unknown = 'not-a-variant' as BadgeVariant; + + expect(isBadgeStatusIconVariant(unknown)).toBe(false); + expect(getResolvedStatusIconVariant(unknown)).toBe('info'); + expect(getBadgeStatusIcon(unknown)).toBe(iconInfoFilled); + expect(getBadgeStatusIcon(unknown, true)).toBe(iconInfo); + expect(getBadgeStatusIconPlate(unknown)).toBe(iconCircleFilled); + }); +}); diff --git a/packages/core/src/components/menu-category/test/menu-category.ct.ts b/packages/core/src/components/menu-category/test/menu-category.ct.ts index 63dac55dcd1..e2392612c1f 100644 --- a/packages/core/src/components/menu-category/test/menu-category.ct.ts +++ b/packages/core/src/components/menu-category/test/menu-category.ct.ts @@ -491,8 +491,10 @@ regressionTest( const menuItems = categoryElement.locator('.menu-items'); await expect(menuItems).toHaveClass(/menu-items--expanded/); + // Wait for hydration before programmatic focus — otherwise focus is lost when + // Stencil replaces the light DOM / attaches the shadow button (delegatesFocus). + await expect(categoryButton).toHaveClass(/hydrated/); await categoryButton.focus(); - await expect(categoryButton).toBeFocused(); // Press ArrowDown should move focus to the first nested item diff --git a/packages/html-test-app/src/preview-examples/badge-counter.css b/packages/html-test-app/src/preview-examples/badge-counter.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-counter.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/html-test-app/src/preview-examples/badge-counter.html b/packages/html-test-app/src/preview-examples/badge-counter.html new file mode 100644 index 00000000000..e635b2f5b09 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-counter.html @@ -0,0 +1,63 @@ + + + + + + + + Badge counter + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/html-test-app/src/preview-examples/badge-dot.css b/packages/html-test-app/src/preview-examples/badge-dot.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-dot.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/html-test-app/src/preview-examples/badge-dot.html b/packages/html-test-app/src/preview-examples/badge-dot.html new file mode 100644 index 00000000000..3a8166a15f8 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-dot.html @@ -0,0 +1,63 @@ + + + + + + + + Badge dot + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/html-test-app/src/preview-examples/badge-label.css b/packages/html-test-app/src/preview-examples/badge-label.css new file mode 100644 index 00000000000..e8543b9428b --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-label.css @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} diff --git a/packages/html-test-app/src/preview-examples/badge-label.html b/packages/html-test-app/src/preview-examples/badge-label.html new file mode 100644 index 00000000000..d98fdb501b9 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-label.html @@ -0,0 +1,60 @@ + + + + + + + + Badge label + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/html-test-app/src/preview-examples/badge-status-icon.css b/packages/html-test-app/src/preview-examples/badge-status-icon.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-status-icon.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/html-test-app/src/preview-examples/badge-status-icon.html b/packages/html-test-app/src/preview-examples/badge-status-icon.html new file mode 100644 index 00000000000..14a98110f43 --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge-status-icon.html @@ -0,0 +1,53 @@ + + + + + + + + Badge status icon + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/packages/html-test-app/src/preview-examples/badge.css b/packages/html-test-app/src/preview-examples/badge.css new file mode 100644 index 00000000000..875f0b6238a --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge.css @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + margin-bottom: 1.5rem; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1.5rem; +} + +.styled { + width: 7rem; + --ix-badge-max-width: 7rem; +} + +.styled-ellipsis-4 { + width: 4rem; + --ix-badge-max-width: 4rem; +} diff --git a/packages/html-test-app/src/preview-examples/badge.html b/packages/html-test-app/src/preview-examples/badge.html new file mode 100644 index 00000000000..a60075aceea --- /dev/null +++ b/packages/html-test-app/src/preview-examples/badge.html @@ -0,0 +1,57 @@ + + + + + + + + Badge example + + + + +
+ Review + + Bottom after + Messages + Device +
+ +
+ + + + + + + + + + +
+ +
+ + + + + + + + +
+ + + diff --git a/packages/react-test-app/src/main.tsx b/packages/react-test-app/src/main.tsx index 1e2e45e96e3..e1da8f0e39d 100644 --- a/packages/react-test-app/src/main.tsx +++ b/packages/react-test-app/src/main.tsx @@ -28,6 +28,11 @@ import ApplicationHeader from './preview-examples/application-header'; import Avatar from './preview-examples/avatar'; import AvatarImage from './preview-examples/avatar-image'; import AvatarInitials from './preview-examples/avatar-initials'; +import Badge from './preview-examples/badge'; +import BadgeDot from './preview-examples/badge-dot'; +import BadgeLabel from './preview-examples/badge-label'; +import BadgeStatusIcon from './preview-examples/badge-status-icon'; +import BadgeCounter from './preview-examples/badge-counter'; import Blind from './preview-examples/blind'; import BlindHeaderActions from './preview-examples/blind-header-actions'; import BlindVariants from './preview-examples/blind-variants'; @@ -67,8 +72,6 @@ import CustomField from './preview-examples/custom-field'; import CustomFieldValidation from './preview-examples/custom-field-validation'; import DateDropdown from './preview-examples/date-dropdown'; import DateDropdownPresets from './preview-examples/date-dropdown-presets'; -import DateRange from './preview-examples/date-range'; -import DatetimeRange from './preview-examples/datetime-range'; import DateInput from './preview-examples/date-input'; import dateInputDisabled from './preview-examples/date-input-disabled.tsx'; import dateInputLabel from './preview-examples/date-input-label.tsx'; @@ -76,7 +79,10 @@ import dateInputMinMaxDate from './preview-examples/date-input-min-max-date.tsx' import dateInputReadonly from './preview-examples/date-input-readonly.tsx'; import dateInputValidation from './preview-examples/date-input-validation.tsx'; import DateInputWithSlots from './preview-examples/date-input-with-slots'; +import DateRange from './preview-examples/date-range'; import Datepicker from './preview-examples/datepicker'; +import DatepickerLocale from './preview-examples/datepicker-locale'; +import DatepickerRange from './preview-examples/datepicker-range'; import DatetimeInput from './preview-examples/datetime-input'; import DatetimeInputDisabled from './preview-examples/datetime-input-disabled'; import DatetimeInputLabel from './preview-examples/datetime-input-label'; @@ -84,8 +90,7 @@ import DatetimeInputMinMaxDate from './preview-examples/datetime-input-min-max-d import DatetimeInputReadonly from './preview-examples/datetime-input-readonly'; import DatetimeInputValidation from './preview-examples/datetime-input-validation'; import DatetimeInputWithSlots from './preview-examples/datetime-input-with-slots'; -import DatepickerLocale from './preview-examples/datepicker-locale'; -import DatepickerRange from './preview-examples/datepicker-range'; +import DatetimeRange from './preview-examples/datetime-range'; import Datetimepicker from './preview-examples/datetimepicker'; import Divider from './preview-examples/divider'; import Dropdown from './preview-examples/dropdown'; @@ -173,8 +178,8 @@ import MessageBar from './preview-examples/message-bar'; import MessageBarRemoval from './preview-examples/message-bar-removal.tsx'; import Modal from './preview-examples/modal'; import ModalClose from './preview-examples/modal-close.tsx'; -import ModalNonBlockingPreview from './preview-examples/modal-non-blocking.tsx'; import ModalFormIxButtonSubmit from './preview-examples/modal-form-ix-button-submit.tsx'; +import ModalNonBlockingPreview from './preview-examples/modal-non-blocking.tsx'; import ModalSizes from './preview-examples/modal-sizes'; import NumberInput from './preview-examples/number-input'; import NumberInputDisabled from './preview-examples/number-input-disabled'; @@ -301,6 +306,11 @@ const routes: IxPreviewRoutes = { '/preview/breadcrumb-next-items': BreadcrumbNextItems, '/preview/breadcrumb-truncate': BreadcrumbTruncate, '/preview/breadcrumb': Breadcrumb, + '/preview/badge': Badge, + '/preview/badge-dot': BadgeDot, + '/preview/badge-label': BadgeLabel, + '/preview/badge-status-icon': BadgeStatusIcon, + '/preview/badge-counter': BadgeCounter, '/preview/button-tertiary': ButtonTertiary, '/preview/button-subtle-tertiary': ButtonSubtleTertiary, '/preview/button-subtle-secondary': ButtonSubtleSecondary, diff --git a/packages/react-test-app/src/preview-examples/badge-counter.scoped.css b/packages/react-test-app/src/preview-examples/badge-counter.scoped.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-counter.scoped.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/react-test-app/src/preview-examples/badge-counter.tsx b/packages/react-test-app/src/preview-examples/badge-counter.tsx new file mode 100644 index 00000000000..4cf921ae5be --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-counter.tsx @@ -0,0 +1,167 @@ +/* + * SPDX-FileCopyrightText: 2026 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 './badge-counter.scoped.css'; + +import { IxBadge } from '@siemens/ix-react'; + +const CUSTOM_BACKGROUND = 'var(--theme-chart-11)'; +const CUSTOM_COLOR = 'var(--theme-color-inv-std-text)'; +const CUSTOM_OUTLINE_COLOR = 'var(--theme-chip-outline--color)'; + +export default () => { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/packages/react-test-app/src/preview-examples/badge-dot.scoped.css b/packages/react-test-app/src/preview-examples/badge-dot.scoped.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-dot.scoped.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/react-test-app/src/preview-examples/badge-dot.tsx b/packages/react-test-app/src/preview-examples/badge-dot.tsx new file mode 100644 index 00000000000..95f9ddf73fd --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-dot.tsx @@ -0,0 +1,262 @@ +/* + * SPDX-FileCopyrightText: 2026 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 './badge-dot.scoped.css'; + +import { IxBadge } from '@siemens/ix-react'; + +const CUSTOM_BACKGROUND = 'var(--theme-chart-11)'; +const CUSTOM_COLOR = 'var(--theme-color-inv-std-text)'; +const CUSTOM_OUTLINE_COLOR = 'var(--theme-chip-outline--color)'; + +export default () => { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/packages/react-test-app/src/preview-examples/badge-label.scoped.css b/packages/react-test-app/src/preview-examples/badge-label.scoped.css new file mode 100644 index 00000000000..e8543b9428b --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-label.scoped.css @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} diff --git a/packages/react-test-app/src/preview-examples/badge-label.tsx b/packages/react-test-app/src/preview-examples/badge-label.tsx new file mode 100644 index 00000000000..d6da45ae553 --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-label.tsx @@ -0,0 +1,263 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { iconInfo } from '@siemens/ix-icons/icons'; +import './badge-label.scoped.css'; + +import { IxBadge } from '@siemens/ix-react'; + +const CUSTOM_BACKGROUND = 'var(--theme-chart-11)'; +const CUSTOM_COLOR = 'var(--theme-color-inv-std-text)'; +const CUSTOM_OUTLINE_COLOR = 'var(--theme-chip-outline--color)'; + +export default () => { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/packages/react-test-app/src/preview-examples/badge-status-icon.scoped.css b/packages/react-test-app/src/preview-examples/badge-status-icon.scoped.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-status-icon.scoped.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/react-test-app/src/preview-examples/badge-status-icon.tsx b/packages/react-test-app/src/preview-examples/badge-status-icon.tsx new file mode 100644 index 00000000000..2126c991cbd --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge-status-icon.tsx @@ -0,0 +1,192 @@ +/* + * SPDX-FileCopyrightText: 2026 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 './badge-status-icon.scoped.css'; + +import { IxBadge } from '@siemens/ix-react'; + +export default () => { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; diff --git a/packages/react-test-app/src/preview-examples/badge.scoped.css b/packages/react-test-app/src/preview-examples/badge.scoped.css new file mode 100644 index 00000000000..875f0b6238a --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge.scoped.css @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + margin-bottom: 1.5rem; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1.5rem; +} + +.styled { + width: 7rem; + --ix-badge-max-width: 7rem; +} + +.styled-ellipsis-4 { + width: 4rem; + --ix-badge-max-width: 4rem; +} diff --git a/packages/react-test-app/src/preview-examples/badge.tsx b/packages/react-test-app/src/preview-examples/badge.tsx new file mode 100644 index 00000000000..ef68b643ad7 --- /dev/null +++ b/packages/react-test-app/src/preview-examples/badge.tsx @@ -0,0 +1,137 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { iconInfo, iconStar } from '@siemens/ix-icons/icons'; +import './badge.scoped.css'; + +import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-react'; + +export default () => { + return ( + <> +
+ + Review + + + + + + + + Bottom after + + + + Messages + + + + Device + +
+ +
+ + + + + + + + + + + + +
+ +
+ + + + + + + + +
+ + ); +}; diff --git a/packages/react/src/components/components.server.ts b/packages/react/src/components/components.server.ts index c7fb903f835..f348760a3fa 100644 --- a/packages/react/src/components/components.server.ts +++ b/packages/react/src/components/components.server.ts @@ -18,6 +18,7 @@ import { IxActionCard as IxActionCardElement } from "@siemens/ix/components/ix-a import { IxApplicationHeader as IxApplicationHeaderElement } from "@siemens/ix/components/ix-application-header.js"; import { IxApplication as IxApplicationElement } from "@siemens/ix/components/ix-application.js"; import { IxAvatar as IxAvatarElement } from "@siemens/ix/components/ix-avatar.js"; +import { IxBadge as IxBadgeElement } from "@siemens/ix/components/ix-badge.js"; import { IxBlind as IxBlindElement } from "@siemens/ix/components/ix-blind.js"; import { IxBreadcrumbItem as IxBreadcrumbItemElement } from "@siemens/ix/components/ix-breadcrumb-item.js"; import { IxBreadcrumb as IxBreadcrumbElement } from "@siemens/ix/components/ix-breadcrumb.js"; @@ -202,6 +203,32 @@ export const IxAvatar: StencilReactComponent; + +export const IxBadge: StencilReactComponent = /*@__PURE__*/ createComponent({ + tagName: 'ix-badge', + properties: { + type: 'type', + label: 'label', + variant: 'variant', + outline: 'outline', + border: 'border', + position: 'position', + offsetX: 'offset-x', + offsetY: 'offset-y', + enableAnimation: 'enable-animation', + background: 'background', + badgeColor: 'badge-color', + icon: 'icon', + ariaLabelIcon: 'aria-label-icon', + alignLeft: 'align-left', + tooltipText: 'tooltip-text' + }, + hydrateModule: typeof window === 'undefined' ? (import('@siemens/ix/hydrate') as Promise) : undefined, + clientModule: clientComponents.IxBadge as StencilReactComponent, + serializeShadowRoot +}); + export type IxBlindEvents = { onCollapsedChange: EventName> }; export const IxBlind: StencilReactComponent = /*@__PURE__*/ createComponent({ diff --git a/packages/react/src/components/components.ts b/packages/react/src/components/components.ts index 19d788d6cb5..28614aec98f 100644 --- a/packages/react/src/components/components.ts +++ b/packages/react/src/components/components.ts @@ -17,6 +17,7 @@ import { IxActionCard as IxActionCardElement, defineCustomElement as defineIxAct import { IxApplicationHeader as IxApplicationHeaderElement, defineCustomElement as defineIxApplicationHeader } from "@siemens/ix/components/ix-application-header.js"; import { IxApplication as IxApplicationElement, defineCustomElement as defineIxApplication } from "@siemens/ix/components/ix-application.js"; import { IxAvatar as IxAvatarElement, defineCustomElement as defineIxAvatar } from "@siemens/ix/components/ix-avatar.js"; +import { IxBadge as IxBadgeElement, defineCustomElement as defineIxBadge } from "@siemens/ix/components/ix-badge.js"; import { IxBlind as IxBlindElement, defineCustomElement as defineIxBlind } from "@siemens/ix/components/ix-blind.js"; import { IxBreadcrumbItem as IxBreadcrumbItemElement, defineCustomElement as defineIxBreadcrumbItem } from "@siemens/ix/components/ix-breadcrumb-item.js"; import { IxBreadcrumb as IxBreadcrumbElement, defineCustomElement as defineIxBreadcrumb } from "@siemens/ix/components/ix-breadcrumb.js"; @@ -173,6 +174,17 @@ export const IxAvatar: StencilReactComponent; + +export const IxBadge: StencilReactComponent = /*@__PURE__*/ createComponent({ + tagName: 'ix-badge', + elementClass: IxBadgeElement, + // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project. + react: React, + events: {} as IxBadgeEvents, + defineCustomElement: defineIxBadge +}); + export type IxBlindEvents = { onCollapsedChange: EventName> }; export const IxBlind: StencilReactComponent = /*@__PURE__*/ createComponent({ diff --git a/packages/storybook-docs/.storybook/define-custom-elements.ts b/packages/storybook-docs/.storybook/define-custom-elements.ts index c2f06c3f4ca..6aad06c5165 100644 --- a/packages/storybook-docs/.storybook/define-custom-elements.ts +++ b/packages/storybook-docs/.storybook/define-custom-elements.ts @@ -4,6 +4,7 @@ import { defineCustomElement as ixActionCard } from '@siemens/ix/components/ix-a import { defineCustomElement as ixApplication } from '@siemens/ix/components/ix-application.js'; import { defineCustomElement as ixApplicationHeader } from '@siemens/ix/components/ix-application-header.js'; import { defineCustomElement as ixAvatar } from '@siemens/ix/components/ix-avatar.js'; +import { defineCustomElement as ixBadge } from '@siemens/ix/components/ix-badge.js'; import { defineCustomElement as ixBlind } from '@siemens/ix/components/ix-blind.js'; import { defineCustomElement as ixBreadcrumb } from '@siemens/ix/components/ix-breadcrumb.js'; import { defineCustomElement as ixBreadcrumbItem } from '@siemens/ix/components/ix-breadcrumb-item.js'; @@ -115,6 +116,7 @@ ixActionCard(); ixApplication(); ixApplicationHeader(); ixAvatar(); +ixBadge(); ixBlind(); ixBreadcrumb(); ixBreadcrumbItem(); diff --git a/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts new file mode 100644 index 00000000000..c260d59e49e --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts @@ -0,0 +1,120 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { ArgTypes, Meta, StoryObj } from '@storybook/web-components-vite'; +import type { Components } from '@siemens/ix/components'; +import { genericRender, makeArgTypes } from '@utils/generic-render'; +import { html } from 'lit'; + +type Element = Components.IxBadge; + +const meta = { + title: 'Example/Badge/Accessibility', + tags: [], + render: (args) => genericRender('ix-badge', args), + argTypes: makeArgTypes>>('ix-badge', {}), + parameters: { + a11y: { + test: 'error', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +/** + * Standalone badge with a text label. + * Visible label text is static chrome (pill-like); no default live region. + */ +export const BasicUsage: Story = { + args: { + label: '12', + variant: 'info', + }, +}; + +/** + * Standalone dot badge: host accessible name requires a naming role + * (e.g. `role="img"`) because `aria-label` alone is not valid on a role-less host. + */ +export const DotWithAriaLabel: Story = { + render: () => + html``, +}; + +/** + * Standalone badge with optional live region: author sets `role` / `aria-label` on the host. + */ +export const CustomAriaLabel: Story = { + render: () => + html``, +}; + +/** + * Attached badge with a count: the anchor keeps its role; count text is exposed via `aria-describedby`. + */ +export const AttachedWithCount: Story = { + render: () => html` + + Review changes + + `, +}; + +/** + * Attached dot badge: the anchor must be named; the indicator is decorative (`aria-hidden`). + */ +export const AttachedDot: Story = { + render: () => html` + + + + `, +}; + +/** + * Attached badge merges `aria-describedby` with existing ids on the anchor. + */ +export const MergedAriaDescribedby: Story = { + render: () => html` +
+ + + +

Unread messages in your primary folder.

+
+ `, +}; + +/** + * Standalone overflow label: numbers above 99 render as `99+`. + */ +export const OverflowLabel: Story = { + args: { + label: '142', + variant: 'primary', + }, +}; + +/** + * Standalone badge hidden from screen readers when the count is redundant with surrounding text. + */ +export const DecorativeBadge: Story = { + render: () => html` +
+ Notifications: 3 unread + +
+ `, +}; diff --git a/packages/storybook-docs/src/stories/badge/badge-preview.css b/packages/storybook-docs/src/stories/badge/badge-preview.css new file mode 100644 index 00000000000..014818d9eec --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/badge-preview.css @@ -0,0 +1,193 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +/* Mirrors packages/react-test-app/src/preview-examples/badge.scoped.css */ + +.badge-preview { + display: flex; + flex-direction: column; + gap: 2rem; + padding: 1rem; +} + +.badge-preview h2 { + margin: 0 0 0.75rem; + font-size: 1rem; + font-weight: 600; +} + +.badge-preview .edge-intro { + margin: 0; + color: var(--theme-color-soft-text); + font-size: 0.875rem; +} + +.badge-preview .edge-note { + margin: 0 0 0.75rem; + color: var(--theme-color-soft-text); + font-size: 0.8125rem; +} + +.badge-preview .edge-intro code, +.badge-preview .edge-note code { + font-family: var(--theme-font-family-code, monospace); + font-size: 0.75rem; +} + +.badge-preview .theme-section { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.badge-preview .theme-panel { + padding: 1.5rem; + border-radius: 0.25rem; + background-color: var(--theme-color-1); + color: var(--theme-color-std-text); +} + +.badge-preview .theme-panel-title { + margin: 0 0 1rem; + font-size: 0.875rem; + font-weight: 600; + text-transform: capitalize; +} + +.badge-preview .align-host { + outline: 1px dashed var(--theme-color-soft-bdr); + outline-offset: 0px; +} + +.badge-preview .variant-grid { + display: grid; + grid-template-columns: 5.5rem repeat(4, minmax(5.5rem, 1fr)); + align-items: stretch; +} + +.badge-preview .variant-grid--attached { + grid-template-columns: 5.5rem repeat(3, minmax(5.5rem, 1fr)); +} + +.badge-preview .variant-grid-corner, +.badge-preview .variant-grid-header, +.badge-preview .variant-grid-row-label { + border: 1px solid var(--theme-color-soft-bdr); + background: color-mix(in srgb, var(--theme-color-soft-bdr) 8%, transparent); +} + +.badge-preview .variant-grid-header, +.badge-preview .variant-grid-row-label { + display: flex; + align-items: center; + justify-content: center; + padding: 0.5rem 0.75rem; + font-size: 0.75rem; + font-weight: 500; + color: var(--theme-color-soft-text); + text-align: center; +} + +.badge-preview .variant-grid-row-label { + justify-content: flex-start; + font-size: 0.875rem; +} + +.badge-preview .grid-cell { + box-sizing: border-box; + border: 1px solid var(--theme-color-soft-bdr); + background: color-mix(in srgb, var(--theme-color-soft-bdr) 12%, transparent); + padding: 1rem; + min-height: 4.5rem; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: flex-end; + gap: 0.5rem; +} + +.badge-preview .grid-cell--attached, +.badge-preview .variant-grid--attached .grid-cell { + align-items: center; + justify-content: center; + min-height: 5.5rem; +} + +.badge-preview .grid-cell-label { + font-family: var(--theme-font-family-code, monospace); + font-size: 0.625rem; + font-weight: 500; + color: var(--theme-color-soft-text); + line-height: 1.3; + word-break: normal; + overflow-wrap: anywhere; +} + +.badge-preview .grid-cell-pulse-group { + display: flex; + flex-direction: row; + align-items: center; + gap: 1rem; +} + +.badge-preview .variant-grid ix-badge { + max-width: 100%; +} + +.badge-preview .demo-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); + gap: 0; + border: 1px solid var(--theme-color-soft-bdr); + border-radius: 0.25rem; + overflow: hidden; +} + +.badge-preview .demo-grid .grid-cell { + border: none; + border-right: 1px solid var(--theme-color-soft-bdr); + border-bottom: 1px solid var(--theme-color-soft-bdr); + border-radius: 0; +} + +.badge-preview .animation-spec { + display: flex; + flex-direction: column; + gap: 1rem; +} + +.badge-preview .animation-spec-label { + margin: 0; + font-family: var(--theme-font-family-code, monospace); + font-size: 1rem; + font-weight: 400; + color: #9747ff; +} + +.badge-preview .animation-spec-note { + margin: 0; +} + +.badge-preview .animation-pulsing-row, +.badge-preview .animation-live-row { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr)); + gap: 0; + border: 1px solid var(--theme-color-soft-bdr); + border-radius: 0.25rem; + overflow: hidden; +} + +.badge-preview .animation-pulsing-row .grid-cell, +.badge-preview .animation-live-row .grid-cell { + border: none; + border-right: 1px solid var(--theme-color-soft-bdr); + border-bottom: 1px solid var(--theme-color-soft-bdr); + border-radius: 0; +} diff --git a/packages/storybook-docs/src/stories/badge/badge-preview.shared.ts b/packages/storybook-docs/src/stories/badge/badge-preview.shared.ts new file mode 100644 index 00000000000..dcacceeaf8a --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/badge-preview.shared.ts @@ -0,0 +1,342 @@ +/* + * SPDX-FileCopyrightText: 2026 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 { html, nothing, type TemplateResult } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; +import './badge-preview.css'; + +/** Aligned with chip / react badge preview custom tokens. */ +export const CUSTOM_BADGE_BACKGROUND = 'var(--theme-chart-11)'; +export const CUSTOM_BADGE_COLOR = 'var(--theme-color-inv-std-text)'; +export const CUSTOM_BADGE_OUTLINE_COLOR = 'var(--theme-chip-outline--color)'; + +export const VARIANT_ROWS = [ + { label: 'Primary', variant: 'primary' }, + { label: 'Alarm', variant: 'alarm' }, + { label: 'Critical', variant: 'critical' }, + { label: 'Warning', variant: 'warning' }, + { label: 'Info', variant: 'info' }, + { label: 'Success', variant: 'success' }, + { label: 'Neutral', variant: 'neutral' }, + { label: 'Custom', variant: 'custom' }, +] as const; + +export const STATUS_ICON_VARIANT_ROWS = [ + { label: 'Alarm', variant: 'alarm' }, + { label: 'Error', variant: 'error' }, + { label: 'Critical', variant: 'critical' }, + { label: 'Warning', variant: 'warning' }, + { label: 'Success', variant: 'success' }, + { label: 'Info', variant: 'info' }, +] as const; + +export type BadgeVariant = (typeof VARIANT_ROWS)[number]['variant']; +export type StatusIconVariant = + (typeof STATUS_ICON_VARIANT_ROWS)[number]['variant']; + +/** Showcase stories — a11y deep-dive stays under Example/Badge/Accessibility. */ +export const showcaseParameters = { + layout: 'fullscreen' as const, + a11y: { + test: 'off' as const, + }, +}; + +export function cell( + label: string, + content: TemplateResult | typeof nothing, + attached = false +): TemplateResult { + return html` +
+ ${label} + ${content} +
+ `; +} + +export function themePanel( + colorSchema: 'dark' | 'light', + title: string, + content: TemplateResult +): TemplateResult { + return html` +
+

${title}

+ ${content} +
+ `; +} + +export function variantGridHeaders(): TemplateResult { + return html` + + Filled + Outline + Border + Pulse + `; +} + +/** Attached grids omit Outline — not recommended on anchors. */ +export function attachedVariantGridHeaders(): TemplateResult { + return html` + + Filled + Border + Pulse + `; +} + +export function iconButtonAnchor(ariaLabel: string): TemplateResult { + return html` + + `; +} + +type CustomColors = { + background?: string; + badgeColor?: string; +}; + +function resolveCustomBackground( + variant: BadgeVariant, + custom?: CustomColors +): string | undefined { + if (custom?.background) { + return custom.background; + } + return variant === 'custom' ? CUSTOM_BADGE_BACKGROUND : undefined; +} + +function resolveCustomBadgeColor( + variant: BadgeVariant, + outline: boolean, + custom?: CustomColors +): string | undefined { + if (custom?.badgeColor) { + return custom.badgeColor; + } + if (variant !== 'custom') { + return undefined; + } + return outline ? CUSTOM_BADGE_OUTLINE_COLOR : CUSTOM_BADGE_COLOR; +} + +export function counterBadge(options: { + variant: BadgeVariant; + label?: string; + outline?: boolean; + border?: boolean; + enableAnimation?: boolean; + position?: 'top-after' | 'bottom-after'; + offsetX?: number; + offsetY?: number; + hostStyle?: Record; + custom?: CustomColors; + children?: TemplateResult | typeof nothing; +}): TemplateResult { + const { + variant, + label = '1', + outline = false, + border = false, + enableAnimation = false, + position, + offsetX, + offsetY, + hostStyle, + custom, + children, + } = options; + + const background = resolveCustomBackground(variant, custom); + const badgeColor = resolveCustomBadgeColor(variant, outline, custom); + + return html` + ${children ?? nothing} + `; +} + +export function labelBadge(options: { + variant: BadgeVariant; + label?: string; + icon?: string; + ariaLabelIcon?: string; + alignLeft?: boolean; + outline?: boolean; + border?: boolean; + enableAnimation?: boolean; + position?: 'top-after' | 'bottom-after'; + offsetX?: number; + offsetY?: number; + hostStyle?: Record; + ariaLabel?: string; + role?: string; + custom?: CustomColors; + children?: TemplateResult | typeof nothing; +}): TemplateResult { + const { + variant, + label = 'NEW', + icon = 'star', + ariaLabelIcon, + alignLeft = false, + outline = false, + border = false, + enableAnimation = false, + position, + offsetX, + offsetY, + hostStyle, + ariaLabel, + role, + custom, + children, + } = options; + + const background = resolveCustomBackground(variant, custom); + const badgeColor = resolveCustomBadgeColor(variant, outline, custom); + + return html` + ${children ?? nothing} + `; +} + +export function dotBadge(options: { + variant: BadgeVariant; + outline?: boolean; + border?: boolean; + enableAnimation?: boolean; + position?: 'top-after' | 'bottom-after'; + offsetX?: number; + offsetY?: number; + ariaLabel?: string; + role?: string; + custom?: CustomColors; + children?: TemplateResult | typeof nothing; +}): TemplateResult { + const { + variant, + outline = false, + border = false, + enableAnimation = false, + position, + offsetX, + offsetY, + ariaLabel, + role, + custom, + children, + } = options; + + const background = resolveCustomBackground(variant, custom); + const badgeColor = resolveCustomBadgeColor(variant, outline, custom); + + return html` + ${children ?? nothing} + `; +} + +export function statusIconBadge(options: { + variant: StatusIconVariant; + outline?: boolean; + border?: boolean; + enableAnimation?: boolean; + position?: 'top-after' | 'bottom-after'; + offsetX?: number; + offsetY?: number; + ariaLabel?: string; + role?: string; + children?: TemplateResult | typeof nothing; +}): TemplateResult { + const { + variant, + outline = false, + border = false, + enableAnimation = false, + position, + offsetX, + offsetY, + ariaLabel, + role, + children, + } = options; + + return html` + ${children ?? nothing} + `; +} diff --git a/packages/storybook-docs/src/stories/badge/counter.stories.ts b/packages/storybook-docs/src/stories/badge/counter.stories.ts new file mode 100644 index 00000000000..3617d8317a9 --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/counter.stories.ts @@ -0,0 +1,432 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html, type TemplateResult } from 'lit'; +import { + cell, + counterBadge, + iconButtonAnchor, + showcaseParameters, + themePanel, + VARIANT_ROWS, + variantGridHeaders, + attachedVariantGridHeaders, +} from './badge-preview.shared'; + +/** + * Mirrors `packages/react-test-app/src/preview-examples/badge.tsx` + * (`/preview/badge`). + */ +function standaloneVariantGrid(): TemplateResult { + return html` +
+ ${variantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell(`${variant} · filled`, counterBadge({ variant }))} + ${cell(`${variant} · outline`, counterBadge({ variant, outline: true }))} + ${cell(`${variant} · border`, counterBadge({ variant, border: true }))} + ${cell( + `${variant} · pulse`, + html`
+ ${counterBadge({ variant, enableAnimation: true })} + ${counterBadge({ variant, outline: true, enableAnimation: true })} +
` + )} + ` + )} +
+ `; +} + +function attachedVariantGrid(): TemplateResult { + return html` +
+ ${attachedVariantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell( + `${variant} · filled · attached`, + counterBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · border · attached`, + counterBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · pulse · attached`, + counterBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ` + )} +
+ `; +} + +function badgeCounterPreview(): TemplateResult { + return html` +
+
+

type="counter"

+

+ Solid cell border = alignment grid; dashed outline = + ix-badge host bounds. +

+
+ +
+

Variants — standalone

+

No default slot → standalone counter.

+ ${themePanel('dark', 'Dark', standaloneVariantGrid())} + ${themePanel('light', 'Light', standaloneVariantGrid())} +
+ +
+

Variants — attached (anchor element)

+

+ Default slot wraps anchor; counter overlays top-trailing (−10px / + −10px default offset). +

+ ${themePanel('dark', 'Dark', attachedVariantGrid())} + ${themePanel('light', 'Light', attachedVariantGrid())} +
+ +
+

Standalone counts

+
+ ${cell( + 'type="counter" label="1"', + counterBadge({ variant: 'primary', label: '1' }) + )} + ${cell( + 'type="counter" label="12"', + counterBadge({ variant: 'alarm', label: '12' }) + )} + ${cell( + 'type="counter" label="99"', + counterBadge({ variant: 'warning', label: '99' }) + )} + ${cell( + 'type="counter" label="100" → 99+', + counterBadge({ variant: 'info', label: '100' }) + )} + ${cell( + 'type="counter" label="142" → 99+', + counterBadge({ variant: 'critical', label: '142' }) + )} + ${cell( + 'type="counter" label="0"', + counterBadge({ variant: 'neutral', label: '0' }) + )} + ${cell( + 'type="counter" label="-1"', + counterBadge({ variant: 'success', label: '-1' }) + )} + ${cell( + 'type="counter" label="-99"', + counterBadge({ variant: 'primary', label: '-99' }) + )} + ${cell( + 'type="counter" label="-100" (literal)', + counterBadge({ variant: 'alarm', label: '-100' }) + )} +
+
+ +
+

Attached anchors

+
+ ${cell( + 'IxButton anchor', + counterBadge({ + variant: 'alarm', + label: '3', + children: html`Notifications`, + }), + true + )} + ${cell( + 'IxIconButton anchor', + counterBadge({ + variant: 'info', + label: '5', + children: iconButtonAnchor("What's new"), + }), + true + )} + ${cell( + 'IxAvatar anchor', + counterBadge({ + variant: 'primary', + label: '12', + children: html``, + }), + true + )} +
+
+ +
+

Formatting

+
+ ${cell('label="1"', counterBadge({ variant: 'alarm', label: '1' }))} + ${cell('label="99"', counterBadge({ variant: 'alarm', label: '99' }))} + ${cell( + 'label="100" → 99+', + counterBadge({ variant: 'alarm', label: '100' }) + )} + ${cell( + 'label="3.7" → 3', + counterBadge({ variant: 'alarm', label: '3.7' }) + )} + ${cell( + 'label="99.9" → 99', + counterBadge({ variant: 'alarm', label: '99.9' }) + )} + ${cell( + 'label="007" → 7', + counterBadge({ variant: 'alarm', label: '007' }) + )} + ${cell('label="-1"', counterBadge({ variant: 'alarm', label: '-1' }))} + ${cell( + 'label="new" → no indicator', + counterBadge({ variant: 'alarm', label: 'new' }) + )} + ${cell( + 'label="99+" → 99+', + counterBadge({ variant: 'alarm', label: '99+' }) + )} + ${cell( + 'no label → no indicator', + html`` + )} +
+
+ +
+

Position and offset

+
+ ${cell( + 'position="top-after" (default)', + counterBadge({ + variant: 'warning', + label: '5', + children: html`Top after`, + }), + true + )} + ${cell( + 'position="bottom-after"', + counterBadge({ + variant: 'warning', + label: '99', + position: 'bottom-after', + children: html``, + }), + true + )} + ${cell( + 'offsetX={6} offsetY={-4}', + counterBadge({ + variant: 'info', + label: '2', + offsetX: 6, + offsetY: -4, + children: html`Offset`, + }), + true + )} + ${cell( + 'Custom offset', + counterBadge({ + variant: 'alarm', + label: '1', + offsetX: -4, + offsetY: 2, + children: html`Custom offset`, + }), + true + )} +
+
+ +
+

Animation

+
+

Pulsing (bool)

+

warning · counter

+
+ ${cell('filled', counterBadge({ variant: 'warning', label: '1' }))} + ${cell( + 'filled · pulse', + counterBadge({ + variant: 'warning', + label: '1', + enableAnimation: true, + }) + )} + ${cell( + 'outline', + counterBadge({ variant: 'warning', label: '1', outline: true }) + )} + ${cell( + 'outline · pulse', + counterBadge({ + variant: 'warning', + label: '1', + outline: true, + enableAnimation: true, + }) + )} +
+ +

Live pulse

+
+ ${cell( + 'standalone · 2s', + counterBadge({ + variant: 'primary', + label: '1', + enableAnimation: true, + }) + )} + ${cell( + 'attached · 2s', + counterBadge({ + variant: 'primary', + label: '1', + enableAnimation: true, + children: iconButtonAnchor("What's new"), + }), + true + )} + ${cell( + 'standalone · 6s', + counterBadge({ + variant: 'warning', + label: '1', + enableAnimation: true, + hostStyle: { '--ix-badge-animation-duration': '6s' }, + }) + )} +
+
+
+ +
+

Width

+
+ ${cell('label="1"', counterBadge({ variant: 'primary', label: '1' }))} + ${cell( + 'label="12"', + counterBadge({ variant: 'primary', label: '12' }) + )} + ${cell( + 'label="99"', + counterBadge({ variant: 'primary', label: '99' }) + )} + ${cell( + 'label="142" → 99+', + counterBadge({ variant: 'primary', label: '142' }) + )} + ${cell( + '--ix-badge-max-width: 2rem', + counterBadge({ + variant: 'primary', + label: '142', + hostStyle: { '--ix-badge-max-width': '2rem' }, + }) + )} +
+
+ +
+

Container bounds

+
+ ${cell( + '32px IxIconButton', + counterBadge({ + variant: 'alarm', + label: '1', + children: html``, + }), + true + )} + ${cell( + '24px IxIcon size="24"', + counterBadge({ + variant: 'alarm', + label: '12', + children: html``, + }), + true + )} +
+
+ +
+

Accessibility

+
+ ${cell( + 'role="alert" · standalone', + html`` + )} +
+
+
+ `; +} + +const meta = { + title: 'Example/Badge', + tags: [], + parameters: showcaseParameters, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Counter: Story = { + name: 'Counter', + render: () => badgeCounterPreview(), +}; diff --git a/packages/storybook-docs/src/stories/badge/dot.stories.ts b/packages/storybook-docs/src/stories/badge/dot.stories.ts new file mode 100644 index 00000000000..6541bc3c759 --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/dot.stories.ts @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html, type TemplateResult } from 'lit'; +import { + cell, + dotBadge, + iconButtonAnchor, + showcaseParameters, + themePanel, + VARIANT_ROWS, + variantGridHeaders, + attachedVariantGridHeaders, +} from './badge-preview.shared'; + +/** + * Mirrors `packages/react-test-app/src/preview-examples/badge-dot.tsx` + * (`/preview/badge-dot`). + */ +function standaloneVariantGrid(): TemplateResult { + return html` +
+ ${variantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell(`${variant} · filled`, dotBadge({ variant }))} + ${cell(`${variant} · outline`, dotBadge({ variant, outline: true }))} + ${cell(`${variant} · border`, dotBadge({ variant, border: true }))} + ${cell( + `${variant} · pulse`, + html`
+ ${dotBadge({ variant, enableAnimation: true })} + ${dotBadge({ variant, outline: true, enableAnimation: true })} +
` + )} + ` + )} +
+ `; +} + +function attachedVariantGrid(): TemplateResult { + return html` +
+ ${attachedVariantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell( + `${variant} · filled · attached`, + dotBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · border · attached`, + dotBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · pulse · attached`, + dotBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ` + )} +
+ `; +} + +function badgeDotPreview(): TemplateResult { + return html` +
+
+

Dot badge

+

+ type="dot" · 12×12px circle · no label. + Attached default offset −6px / −6px (top-trailing). Standalone dots + need aria-label on the host; attached dots are decorative + (anchor carries meaning). +

+
+ +
+ ${themePanel('dark', 'Dark', standaloneVariantGrid())} + ${themePanel('light', 'Light', standaloneVariantGrid())} +
+ +
+

Variants — attached

+

+ Icon button anchor; dot overlays top-trailing (−0.375rem default + offset). +

+ ${themePanel('dark', 'Dark', attachedVariantGrid())} + ${themePanel('light', 'Light', attachedVariantGrid())} +
+ +
+

Attached anchors

+
+ ${cell( + 'IxIconButton · alarm', + dotBadge({ + variant: 'alarm', + children: iconButtonAnchor("What's new"), + }), + true + )} + ${cell( + 'IxButton · primary', + dotBadge({ + variant: 'primary', + children: html`Messages`, + }), + true + )} + ${cell( + 'IxAvatar · success', + dotBadge({ + variant: 'success', + children: html``, + }), + true + )} +
+
+ +
+

Placement

+
+ ${cell( + 'position="top-after" (default)', + dotBadge({ + variant: 'alarm', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'position="bottom-after"', + dotBadge({ + variant: 'info', + position: 'bottom-after', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'offsetX={6} offsetY={-4}', + dotBadge({ + variant: 'warning', + offsetX: 6, + offsetY: -4, + children: iconButtonAnchor('Notifications'), + }), + true + )} +
+
+ +
+

Standalone a11y

+

+ Set aria-label on ix-badge (no + aria-describedby on anchor when attached). +

+
+ ${cell( + 'aria-label="Unread messages"', + dotBadge({ + variant: 'alarm', + ariaLabel: 'Unread messages', + }) + )} + ${cell( + 'role="alert" · aria-label="Action required"', + dotBadge({ + variant: 'critical', + role: 'alert', + ariaLabel: 'Action required', + }) + )} +
+
+ +
+

Pulse

+
+ ${cell( + 'filled · pulse · standalone', + dotBadge({ variant: 'warning', enableAnimation: true }) + )} + ${cell( + 'filled · pulse · attached', + dotBadge({ + variant: 'warning', + enableAnimation: true, + children: iconButtonAnchor('Live updates'), + }), + true + )} +
+
+
+ `; +} + +const meta = { + title: 'Example/Badge', + tags: [], + parameters: showcaseParameters, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Dot: Story = { + name: 'Dot', + render: () => badgeDotPreview(), +}; diff --git a/packages/storybook-docs/src/stories/badge/label.stories.ts b/packages/storybook-docs/src/stories/badge/label.stories.ts new file mode 100644 index 00000000000..6f89f6e568a --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/label.stories.ts @@ -0,0 +1,291 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html, type TemplateResult } from 'lit'; +import { + cell, + iconButtonAnchor, + labelBadge, + showcaseParameters, + themePanel, + VARIANT_ROWS, + variantGridHeaders, + attachedVariantGridHeaders, +} from './badge-preview.shared'; + +/** + * Mirrors `packages/react-test-app/src/preview-examples/badge-label.tsx` + * (`/preview/badge-label`). + */ +function standaloneVariantGrid(): TemplateResult { + return html` +
+ ${variantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell(`${variant} · filled`, labelBadge({ variant }))} + ${cell(`${variant} · outline`, labelBadge({ variant, outline: true }))} + ${cell(`${variant} · border`, labelBadge({ variant, border: true }))} + ${cell( + `${variant} · pulse`, + html`
+ ${labelBadge({ variant, enableAnimation: true })} + ${labelBadge({ variant, outline: true, enableAnimation: true })} +
` + )} + ` + )} +
+ `; +} + +function attachedVariantGrid(): TemplateResult { + return html` +
+ ${attachedVariantGridHeaders()} + ${VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell( + `${variant} · filled · attached`, + labelBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · border · attached`, + labelBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · pulse · attached`, + labelBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ` + )} +
+ `; +} + +function badgeLabelPreview(): TemplateResult { + return html` +
+
+

Label badge

+

+ type="label" · text pill (20px height) · + label required · body-regular typography · leading + icon in examples. Optional + aria-label-icon and align-left. Attached + default offset −10px / −10px. +

+
+ +
+ ${themePanel('dark', 'Dark', standaloneVariantGrid())} + ${themePanel('light', 'Light', standaloneVariantGrid())} +
+ +
+

Variants — attached

+

+ Icon button anchor; label overlays top-trailing (−0.625rem default + offset). +

+ ${themePanel('dark', 'Dark', attachedVariantGrid())} + ${themePanel('light', 'Light', attachedVariantGrid())} +
+ +
+

Icon

+
+ ${cell( + 'icon={star} · decorative (default)', + labelBadge({ variant: 'primary' }) + )} + ${cell( + 'icon={star} · decorative · warning', + labelBadge({ variant: 'warning' }) + )} + ${cell( + 'icon={star} · aria-label-icon="Featured"', + labelBadge({ + variant: 'success', + label: 'Featured', + ariaLabelIcon: 'Featured', + }) + )} +
+
+ +
+

Align left

+
+ ${cell( + 'default · icon + text', + labelBadge({ variant: 'info', label: "What's new" }) + )} + ${cell( + 'alignLeft · icon + text', + labelBadge({ + variant: 'primary', + label: "What's new", + alignLeft: true, + }) + )} + ${cell( + 'alignLeft · --ix-badge-max-width: 2.5rem', + labelBadge({ + variant: 'alarm', + label: "What's new", + alignLeft: true, + hostStyle: { '--ix-badge-max-width': '2.5rem' }, + }) + )} +
+
+ +
+

Attached anchors

+
+ ${cell( + 'IxIconButton · alarm', + labelBadge({ + variant: 'alarm', + children: iconButtonAnchor("What's new"), + }), + true + )} + ${cell( + 'IxButton · primary · warning badge', + labelBadge({ + variant: 'warning', + children: html`Messages`, + }), + true + )} + ${cell( + 'IxAvatar · success', + labelBadge({ + variant: 'success', + children: html``, + }), + true + )} +
+
+ +
+

Placement

+
+ ${cell( + 'position="top-after" (default)', + labelBadge({ + variant: 'alarm', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'position="bottom-after"', + labelBadge({ + variant: 'info', + position: 'bottom-after', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'offsetX={6} offsetY={-4}', + labelBadge({ + variant: 'warning', + offsetX: 6, + offsetY: -4, + children: iconButtonAnchor('Notifications'), + }), + true + )} +
+
+ +
+

Standalone a11y

+

+ Attached: label text via aria-describedby on anchor. + Standalone: author ARIA stays on the host (pill-like; opt-in live region). +

+
+ ${cell( + 'aria-label="New content available"', + labelBadge({ + variant: 'primary', + label: 'NEW', + ariaLabel: 'New content available', + }) + )} + ${cell( + 'role="alert" · aria-label="Action required"', + labelBadge({ + variant: 'critical', + label: '!', + role: 'alert', + ariaLabel: 'Action required', + }) + )} +
+
+ +
+

Pulse

+
+ ${cell( + 'filled · pulse · standalone', + labelBadge({ variant: 'warning', enableAnimation: true }) + )} + ${cell( + 'filled · pulse · attached', + labelBadge({ + variant: 'warning', + enableAnimation: true, + children: iconButtonAnchor('Live updates'), + }), + true + )} +
+
+
+ `; +} + +const meta = { + title: 'Example/Badge', + tags: [], + parameters: showcaseParameters, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Label: Story = { + name: 'Label', + render: () => badgeLabelPreview(), +}; diff --git a/packages/storybook-docs/src/stories/badge/status-icon.stories.ts b/packages/storybook-docs/src/stories/badge/status-icon.stories.ts new file mode 100644 index 00000000000..3c96cd50aae --- /dev/null +++ b/packages/storybook-docs/src/stories/badge/status-icon.stories.ts @@ -0,0 +1,249 @@ +/* + * SPDX-FileCopyrightText: 2026 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 type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html, type TemplateResult } from 'lit'; +import { + cell, + iconButtonAnchor, + showcaseParameters, + STATUS_ICON_VARIANT_ROWS, + statusIconBadge, + themePanel, + variantGridHeaders, + attachedVariantGridHeaders, +} from './badge-preview.shared'; + +/** + * Mirrors `packages/react-test-app/src/preview-examples/badge-status-icon.tsx` + * (`/preview/badge-status-icon`). + */ +function standaloneVariantGrid(): TemplateResult { + return html` +
+ ${variantGridHeaders()} + ${STATUS_ICON_VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell(`${variant} · filled`, statusIconBadge({ variant }))} + ${cell( + `${variant} · outline`, + statusIconBadge({ variant, outline: true }) + )} + ${cell( + `${variant} · border`, + statusIconBadge({ variant, border: true }) + )} + ${cell( + `${variant} · pulse`, + html`
+ ${statusIconBadge({ variant, enableAnimation: true })} + ${statusIconBadge({ + variant, + outline: true, + enableAnimation: true, + })} +
` + )} + ` + )} +
+ `; +} + +function attachedVariantGrid(): TemplateResult { + return html` +
+ ${attachedVariantGridHeaders()} + ${STATUS_ICON_VARIANT_ROWS.map( + ({ label, variant }) => html` + ${label} + ${cell( + `${variant} · filled · attached`, + statusIconBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · border · attached`, + statusIconBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ${cell( + `${variant} · pulse · attached`, + statusIconBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + )} + ` + )} +
+ `; +} + +function badgeStatusIconPreview(): TemplateResult { + return html` +
+
+

Status-icon badge

+

+ type="status-icon" · 20×20px circle · icon from + variant · no label. Attached default offset + −10px / −10px. Same a11y as dot: attached = decorative; standalone + needs aria-label on the host. +

+
+ +
+ ${themePanel('dark', 'Dark', standaloneVariantGrid())} + ${themePanel('light', 'Light', standaloneVariantGrid())} +
+ +
+

Variants — attached

+

+ Icon button anchor; status icon overlays top-trailing (−0.625rem + default offset). +

+ ${themePanel('dark', 'Dark', attachedVariantGrid())} + ${themePanel('light', 'Light', attachedVariantGrid())} +
+ +
+

Attached anchors

+
+ ${cell( + 'IxIconButton · alarm', + statusIconBadge({ + variant: 'alarm', + children: iconButtonAnchor('Error state'), + }), + true + )} + ${cell( + 'IxButton · primary · warning badge', + statusIconBadge({ + variant: 'warning', + children: html`Messages`, + }), + true + )} + ${cell( + 'IxAvatar · success', + statusIconBadge({ + variant: 'success', + children: html``, + }), + true + )} +
+
+ +
+

Placement

+
+ ${cell( + 'position="top-after" (default)', + statusIconBadge({ + variant: 'alarm', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'position="bottom-after"', + statusIconBadge({ + variant: 'info', + position: 'bottom-after', + children: iconButtonAnchor('Notifications'), + }), + true + )} + ${cell( + 'offsetX={6} offsetY={-4}', + statusIconBadge({ + variant: 'warning', + offsetX: 6, + offsetY: -4, + children: iconButtonAnchor('Notifications'), + }), + true + )} +
+
+ +
+

Standalone a11y

+

+ Set aria-label on ix-badge (no + aria-describedby on anchor when attached). +

+
+ ${cell( + 'aria-label="Action required"', + statusIconBadge({ + variant: 'alarm', + ariaLabel: 'Action required', + }) + )} + ${cell( + 'role="alert" · aria-label="Critical failure"', + statusIconBadge({ + variant: 'critical', + role: 'alert', + ariaLabel: 'Critical failure', + }) + )} +
+
+ +
+

Pulse

+
+ ${cell( + 'filled · pulse · standalone', + statusIconBadge({ variant: 'warning', enableAnimation: true }) + )} + ${cell( + 'filled · pulse · attached', + statusIconBadge({ + variant: 'warning', + enableAnimation: true, + children: iconButtonAnchor('Live updates'), + }), + true + )} +
+
+
+ `; +} + +const meta = { + title: 'Example/Badge', + tags: [], + parameters: showcaseParameters, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const StatusIcon: Story = { + name: 'Status icon', + render: () => badgeStatusIconPreview(), +}; diff --git a/packages/vue-test-app/src/Root.vue b/packages/vue-test-app/src/Root.vue index f676d0b3ace..a6350968be0 100644 --- a/packages/vue-test-app/src/Root.vue +++ b/packages/vue-test-app/src/Root.vue @@ -26,6 +26,11 @@ import ApplicationAdvanced from './preview-examples/application-advanced.vue'; import AvatarImage from './preview-examples/avatar-image.vue'; import AvatarInitials from './preview-examples/avatar-initials.vue'; import Avatar from './preview-examples/avatar.vue'; +import Badge from './preview-examples/badge.vue'; +import BadgeCounter from './preview-examples/badge-counter.vue'; +import BadgeDot from './preview-examples/badge-dot.vue'; +import BadgeLabel from './preview-examples/badge-label.vue'; +import BadgeStatusIcon from './preview-examples/badge-status-icon.vue'; import BlindHeaderActions from './preview-examples/blind-header-actions.vue'; import BlindVariants from './preview-examples/blind-variants.vue'; import Blind from './preview-examples/blind.vue'; @@ -276,6 +281,11 @@ const routes: IxPreviewRoutes = { '/preview/avatar-image': AvatarImage, '/preview/avatar-initials': AvatarInitials, '/preview/avatar': Avatar, + '/preview/badge': Badge, + '/preview/badge-counter': BadgeCounter, + '/preview/badge-dot': BadgeDot, + '/preview/badge-label': BadgeLabel, + '/preview/badge-status-icon': BadgeStatusIcon, '/preview/blind-header-actions': BlindHeaderActions, '/preview/blind-variants': BlindVariants, '/preview/blind': Blind, diff --git a/packages/vue-test-app/src/preview-examples/badge-counter.css b/packages/vue-test-app/src/preview-examples/badge-counter.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-counter.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/vue-test-app/src/preview-examples/badge-counter.vue b/packages/vue-test-app/src/preview-examples/badge-counter.vue new file mode 100644 index 00000000000..1e842d58a5b --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-counter.vue @@ -0,0 +1,59 @@ + + + + + + + diff --git a/packages/vue-test-app/src/preview-examples/badge-dot.css b/packages/vue-test-app/src/preview-examples/badge-dot.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-dot.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/vue-test-app/src/preview-examples/badge-dot.vue b/packages/vue-test-app/src/preview-examples/badge-dot.vue new file mode 100644 index 00000000000..16f06970ddb --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-dot.vue @@ -0,0 +1,59 @@ + + + + + + + diff --git a/packages/vue-test-app/src/preview-examples/badge-label.css b/packages/vue-test-app/src/preview-examples/badge-label.css new file mode 100644 index 00000000000..e8543b9428b --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-label.css @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} diff --git a/packages/vue-test-app/src/preview-examples/badge-label.vue b/packages/vue-test-app/src/preview-examples/badge-label.vue new file mode 100644 index 00000000000..c9dbf8254d7 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-label.vue @@ -0,0 +1,52 @@ + + + + + + + diff --git a/packages/vue-test-app/src/preview-examples/badge-status-icon.css b/packages/vue-test-app/src/preview-examples/badge-status-icon.css new file mode 100644 index 00000000000..2744070b513 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-status-icon.css @@ -0,0 +1,19 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.container { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + column-gap: 2rem; + row-gap: 1.5rem; + align-items: center; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1rem; +} + diff --git a/packages/vue-test-app/src/preview-examples/badge-status-icon.vue b/packages/vue-test-app/src/preview-examples/badge-status-icon.vue new file mode 100644 index 00000000000..a5a085253e6 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge-status-icon.vue @@ -0,0 +1,49 @@ + + + + + + + diff --git a/packages/vue-test-app/src/preview-examples/badge.css b/packages/vue-test-app/src/preview-examples/badge.css new file mode 100644 index 00000000000..875f0b6238a --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge.css @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +.row { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 2rem; + margin-bottom: 1.5rem; + /* Room for attached overlays and pulse rings above the content. */ + padding-top: 1.5rem; +} + +.styled { + width: 7rem; + --ix-badge-max-width: 7rem; +} + +.styled-ellipsis-4 { + width: 4rem; + --ix-badge-max-width: 4rem; +} diff --git a/packages/vue-test-app/src/preview-examples/badge.vue b/packages/vue-test-app/src/preview-examples/badge.vue new file mode 100644 index 00000000000..57edb99cc57 --- /dev/null +++ b/packages/vue-test-app/src/preview-examples/badge.vue @@ -0,0 +1,49 @@ + + + + + + + diff --git a/packages/vue/src/components/components.ts b/packages/vue/src/components/components.ts index 93d43296420..a4443b784ce 100644 --- a/packages/vue/src/components/components.ts +++ b/packages/vue/src/components/components.ts @@ -5,6 +5,7 @@ export { IxActionCard } from './ix-action-card.js'; export { IxApplication } from './ix-application.js'; export { IxApplicationHeader } from './ix-application-header.js'; export { IxAvatar } from './ix-avatar.js'; +export { IxBadge } from './ix-badge.js'; export { IxBlind } from './ix-blind.js'; export { IxBreadcrumb } from './ix-breadcrumb.js'; export { IxBreadcrumbItem } from './ix-breadcrumb-item.js'; diff --git a/packages/vue/src/components/ix-badge.ts b/packages/vue/src/components/ix-badge.ts new file mode 100644 index 00000000000..9dc4837eafe --- /dev/null +++ b/packages/vue/src/components/ix-badge.ts @@ -0,0 +1,25 @@ +/* eslint-disable */ +/* tslint:disable */ +/* auto-generated vue proxy */ +import { defineContainer, type StencilVueComponent } from '@stencil/vue-output-target/runtime'; + +import type { JSX } from '@siemens/ix'; +import { defineCustomElement as defineIxBadge } from '@siemens/ix/components/ix-badge.js'; + +export const IxBadge: StencilVueComponent = /*@__PURE__*/ defineContainer('ix-badge', defineIxBadge, [ + 'type', + 'label', + 'variant', + 'outline', + 'border', + 'position', + 'offsetX', + 'offsetY', + 'enableAnimation', + 'background', + 'badgeColor', + 'icon', + 'ariaLabelIcon', + 'alignLeft', + 'tooltipText' +]); diff --git a/testing/framework-tests/__snapshots__/badge-aria-snapshot.yaml b/testing/framework-tests/__snapshots__/badge-aria-snapshot.yaml new file mode 100644 index 00000000000..fb42fab9702 --- /dev/null +++ b/testing/framework-tests/__snapshots__/badge-aria-snapshot.yaml @@ -0,0 +1,14 @@ +- main: + - text: "3" + - button "Review" + - text: "1" + - button "What's new" + - text: "9" + - button "Bottom after" + - button "Messages" + - button "Device" + - text: /\d+ \d+ \d+\+ \d+\+ 8 8/ + - img "Unread" + - img "Online" + - img "Alarm" + - img "Success" diff --git a/testing/framework-tests/__snapshots__/badge-counter-aria-snapshot.yaml b/testing/framework-tests/__snapshots__/badge-counter-aria-snapshot.yaml new file mode 100644 index 00000000000..5d605d2d5c0 --- /dev/null +++ b/testing/framework-tests/__snapshots__/badge-counter-aria-snapshot.yaml @@ -0,0 +1 @@ +- main: 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 \ No newline at end of file diff --git a/testing/framework-tests/__snapshots__/badge-dot-aria-snapshot.yaml b/testing/framework-tests/__snapshots__/badge-dot-aria-snapshot.yaml new file mode 100644 index 00000000000..4c1f55b5a2b --- /dev/null +++ b/testing/framework-tests/__snapshots__/badge-dot-aria-snapshot.yaml @@ -0,0 +1,33 @@ +- main: + - img "Primary" + - img "Primary outline" + - img "Primary pulse" + - img "Primary pulse outline" + - img "Alarm" + - img "Alarm outline" + - img "Alarm pulse" + - img "Alarm pulse outline" + - img "Critical" + - img "Critical outline" + - img "Critical pulse" + - img "Critical pulse outline" + - img "Warning" + - img "Warning outline" + - img "Warning pulse" + - img "Warning pulse outline" + - img "Info" + - img "Info outline" + - img "Info pulse" + - img "Info pulse outline" + - img "Neutral" + - img "Neutral outline" + - img "Neutral pulse" + - img "Neutral pulse outline" + - img "Success" + - img "Success outline" + - img "Success pulse" + - img "Success pulse outline" + - img "Custom" + - img "Custom outline" + - img "Custom pulse" + - img "Custom pulse outline" \ No newline at end of file diff --git a/testing/framework-tests/__snapshots__/badge-label-aria-snapshot.yaml b/testing/framework-tests/__snapshots__/badge-label-aria-snapshot.yaml new file mode 100644 index 00000000000..4968d3b4261 --- /dev/null +++ b/testing/framework-tests/__snapshots__/badge-label-aria-snapshot.yaml @@ -0,0 +1 @@ +- main: Primary Primary Primary Primary Alarm Alarm Alarm Alarm Critical Critical Critical Critical Warning Warning Warning Warning Info Info Info Info Neutral Neutral Neutral Neutral Success Success Success Success Custom Custom Custom Custom diff --git a/testing/framework-tests/__snapshots__/badge-status-icon-aria-snapshot.yaml b/testing/framework-tests/__snapshots__/badge-status-icon-aria-snapshot.yaml new file mode 100644 index 00000000000..ea45513b2b6 --- /dev/null +++ b/testing/framework-tests/__snapshots__/badge-status-icon-aria-snapshot.yaml @@ -0,0 +1,25 @@ +- main: + - img "Alarm" + - img "Alarm outline" + - img "Alarm pulse" + - img "Alarm pulse outline" + - img "Error" + - img "Error outline" + - img "Error pulse" + - img "Error pulse outline" + - img "Critical" + - img "Critical outline" + - img "Critical pulse" + - img "Critical pulse outline" + - img "Warning" + - img "Warning outline" + - img "Warning pulse" + - img "Warning pulse outline" + - img "Success" + - img "Success outline" + - img "Success pulse" + - img "Success pulse outline" + - img "Info" + - img "Info outline" + - img "Info pulse" + - img "Info pulse outline" diff --git a/testing/framework-tests/tests/generated/axe.ts b/testing/framework-tests/tests/generated/axe.ts index fbad853e355..2f6255f1cba 100644 --- a/testing/framework-tests/tests/generated/axe.ts +++ b/testing/framework-tests/tests/generated/axe.ts @@ -11,6 +11,11 @@ import './application-header-axe.spec.ts'; import './avatar-axe.spec.ts'; import './avatar-image-axe.spec.ts'; import './avatar-initials-axe.spec.ts'; +import './badge-axe.spec.ts'; +import './badge-counter-axe.spec.ts'; +import './badge-dot-axe.spec.ts'; +import './badge-label-axe.spec.ts'; +import './badge-status-icon-axe.spec.ts'; import './blind-axe.spec.ts'; import './blind-header-actions-axe.spec.ts'; import './blind-variants-axe.spec.ts'; diff --git a/testing/framework-tests/tests/generated/badge-axe.spec.ts b/testing/framework-tests/tests/generated/badge-axe.spec.ts new file mode 100644 index 00000000000..734c279c1c7 --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-axe.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness, createAxeBuilder } from '../utils'; + +test('badge - accessibility check', async ({ page }) => { + await page.goto('/preview/badge'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + const accessibilityScanResults = await createAxeBuilder(page).disableRules(['page-has-heading-one']).analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); +}); diff --git a/testing/framework-tests/tests/generated/badge-counter-axe.spec.ts b/testing/framework-tests/tests/generated/badge-counter-axe.spec.ts new file mode 100644 index 00000000000..8b049a469bd --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-counter-axe.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness, createAxeBuilder } from '../utils'; + +test('badge-counter - accessibility check', async ({ page }) => { + await page.goto('/preview/badge-counter'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + const accessibilityScanResults = await createAxeBuilder(page).disableRules(['page-has-heading-one']).analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); +}); diff --git a/testing/framework-tests/tests/generated/badge-counter.spec.ts b/testing/framework-tests/tests/generated/badge-counter.spec.ts new file mode 100644 index 00000000000..92e186a7541 --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-counter.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness } from '../utils'; + +test('badge-counter', async ({ page }) => { + await page.goto('/preview/badge-counter'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + await expect(page.locator('body')).toMatchAriaSnapshot({ + name: 'badge-counter.aria-snapshot.yaml', + }); +}); diff --git a/testing/framework-tests/tests/generated/badge-dot-axe.spec.ts b/testing/framework-tests/tests/generated/badge-dot-axe.spec.ts new file mode 100644 index 00000000000..a9ce0a254aa --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-dot-axe.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness, createAxeBuilder } from '../utils'; + +test('badge-dot - accessibility check', async ({ page }) => { + await page.goto('/preview/badge-dot'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + const accessibilityScanResults = await createAxeBuilder(page).disableRules(['page-has-heading-one']).analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); +}); diff --git a/testing/framework-tests/tests/generated/badge-dot.spec.ts b/testing/framework-tests/tests/generated/badge-dot.spec.ts new file mode 100644 index 00000000000..be3fe4b6426 --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-dot.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness } from '../utils'; + +test('badge-dot', async ({ page }) => { + await page.goto('/preview/badge-dot'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + await expect(page.locator('body')).toMatchAriaSnapshot({ + name: 'badge-dot.aria-snapshot.yaml', + }); +}); diff --git a/testing/framework-tests/tests/generated/badge-label-axe.spec.ts b/testing/framework-tests/tests/generated/badge-label-axe.spec.ts new file mode 100644 index 00000000000..36ceffedbf6 --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-label-axe.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness, createAxeBuilder } from '../utils'; + +test('badge-label - accessibility check', async ({ page }) => { + await page.goto('/preview/badge-label'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + const accessibilityScanResults = await createAxeBuilder(page).disableRules(['page-has-heading-one']).analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); +}); diff --git a/testing/framework-tests/tests/generated/badge-label.spec.ts b/testing/framework-tests/tests/generated/badge-label.spec.ts new file mode 100644 index 00000000000..6aa6e8a198c --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-label.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness } from '../utils'; + +test('badge-label', async ({ page }) => { + await page.goto('/preview/badge-label'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + await expect(page.locator('body')).toMatchAriaSnapshot({ + name: 'badge-label.aria-snapshot.yaml', + }); +}); diff --git a/testing/framework-tests/tests/generated/badge-status-icon-axe.spec.ts b/testing/framework-tests/tests/generated/badge-status-icon-axe.spec.ts new file mode 100644 index 00000000000..3e9e139f668 --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-status-icon-axe.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness, createAxeBuilder } from '../utils'; + +test('badge-status-icon - accessibility check', async ({ page }) => { + await page.goto('/preview/badge-status-icon'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + const accessibilityScanResults = await createAxeBuilder(page).disableRules(['page-has-heading-one']).analyze(); + + expect(accessibilityScanResults.violations).toEqual([]); +}); diff --git a/testing/framework-tests/tests/generated/badge-status-icon.spec.ts b/testing/framework-tests/tests/generated/badge-status-icon.spec.ts new file mode 100644 index 00000000000..0a3bb9f669a --- /dev/null +++ b/testing/framework-tests/tests/generated/badge-status-icon.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness } from '../utils'; + +test('badge-status-icon', async ({ page }) => { + await page.goto('/preview/badge-status-icon'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + await expect(page.locator('body')).toMatchAriaSnapshot({ + name: 'badge-status-icon.aria-snapshot.yaml', + }); +}); diff --git a/testing/framework-tests/tests/generated/badge.spec.ts b/testing/framework-tests/tests/generated/badge.spec.ts new file mode 100644 index 00000000000..6aad615514b --- /dev/null +++ b/testing/framework-tests/tests/generated/badge.spec.ts @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2025 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. + */ + +/** + * This test was autogenerated by 'testing/framework-tests/src/main.ts' + * Do not edit this file directly. + */ +import { test, expect } from '@playwright/test'; +import { waitForReadiness } from '../utils'; + +test('badge', async ({ page }) => { + await page.goto('/preview/badge'); + + // Ugly and not the reliable way to wait for Stencil to be ready + await waitForReadiness(page); + + await expect(page.locator('body')).toMatchAriaSnapshot({ + name: 'badge.aria-snapshot.yaml', + }); +}); diff --git a/testing/framework-tests/tests/generated/index.ts b/testing/framework-tests/tests/generated/index.ts index ec437ab17ae..a3d295c9fc0 100644 --- a/testing/framework-tests/tests/generated/index.ts +++ b/testing/framework-tests/tests/generated/index.ts @@ -24,6 +24,16 @@ import './avatar-image.spec.ts'; import './avatar-initials-axe.spec.ts'; import './avatar-initials.spec.ts'; import './avatar.spec.ts'; +import './badge-axe.spec.ts'; +import './badge-counter-axe.spec.ts'; +import './badge-counter.spec.ts'; +import './badge-dot-axe.spec.ts'; +import './badge-dot.spec.ts'; +import './badge-label-axe.spec.ts'; +import './badge-label.spec.ts'; +import './badge-status-icon-axe.spec.ts'; +import './badge-status-icon.spec.ts'; +import './badge.spec.ts'; import './blind-axe.spec.ts'; import './blind-header-actions-axe.spec.ts'; import './blind-header-actions.spec.ts'; diff --git a/testing/framework-tests/tests/generated/test-ids.autogenerated.ts b/testing/framework-tests/tests/generated/test-ids.autogenerated.ts index cb3f5d20d6c..b90cd1f6abd 100644 --- a/testing/framework-tests/tests/generated/test-ids.autogenerated.ts +++ b/testing/framework-tests/tests/generated/test-ids.autogenerated.ts @@ -238,6 +238,11 @@ export const testIds = [ "blind", "blind-variants", "blind-header-actions", + "badge", + "badge-status-icon", + "badge-label", + "badge-dot", + "badge-counter", "avatar", "avatar-initials", "avatar-image", diff --git a/testing/framework-tests/tests/working-with-axe.spec.ts b/testing/framework-tests/tests/working-with-axe.spec.ts index 41e10ec2a1e..edd92d36306 100644 --- a/testing/framework-tests/tests/working-with-axe.spec.ts +++ b/testing/framework-tests/tests/working-with-axe.spec.ts @@ -73,3 +73,10 @@ import './generated/chat-axe.spec'; import './generated/chat-ai-message-axe.spec'; import './generated/chat-input-axe.spec'; import './generated/chat-user-message-axe.spec'; + +// Badge tests +import './generated/badge-axe.spec'; +import './generated/badge-counter-axe.spec'; +import './generated/badge-label-axe.spec'; +import './generated/badge-dot-axe.spec'; +import './generated/badge-status-icon-axe.spec'; diff --git a/testing/framework-tests/tests/working.spec.ts b/testing/framework-tests/tests/working.spec.ts index d1b00632ce3..14876835fcb 100644 --- a/testing/framework-tests/tests/working.spec.ts +++ b/testing/framework-tests/tests/working.spec.ts @@ -73,3 +73,10 @@ import './generated/chat.spec'; import './generated/chat-ai-message.spec'; import './generated/chat-input.spec'; import './generated/chat-user-message.spec'; + +// Badge tests +import './generated/badge.spec'; +import './generated/badge-counter.spec'; +import './generated/badge-label.spec'; +import './generated/badge-dot.spec'; +import './generated/badge-status-icon.spec'; diff --git a/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-dark-linux.png b/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-dark-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5476232700b25187f17b118fb8edee22062740 GIT binary patch literal 59910 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 ZFV9=(Q;kWj_(`s_L6&wF^%rm6{|^ED-~j*t literal 0 HcmV?d00001 diff --git a/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-light-linux.png b/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-counter-1-chromium---classic-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..510750eb87945d78c3f8e5281af74b4dd1862ab5 GIT binary patch literal 60359 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 >2t^&bVduR3skQsP{!<$cZVkjqc=N(9O)Fju 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 a1+t*-Srhd5*L~m>GGzsI`LgG4KKx%jkxd!^ literal 0 HcmV?d00001 diff --git a/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-dot-1-chromium---classic-light-linux.png b/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-dot-1-chromium---classic-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..aaef51f50134892892241ea0030879679ccd0993 GIT binary patch literal 38288 zcmd43XH-*L*e)6iSWrQdPKpllCS60JyFA=CuX@ zKtepd+;jah@$iC4=@I~N7ohn1I`HJRADGdIn-_YDK_UPj2L-Bj`*kY2G@?Y{T`A#~7?)^*m0v`*~$ay*y34>6aMh zBC*edfH(nbA>V8)dmAB+=EVkyTq6p*%RkZt@m`DzUd0?qq7J13nBVN$( z3C;wP?l{`X%A%~z^+`!T1MN(f@zs-c`&tp3raJ-O$aGj~&T8|PTj{M*w6s)L*3V5~ z8XEF}^beszLyF;L5r##=za~ZP<Dpid6r@kMl*?{$xX)B^x1?g8^~4 zPLuJftMbZdXKWzPor-AVOgMG${MS8^iQiwTDh}qHRu7u@xa7JGs;v?H+-)o@Ml&Re-d@l$;|t`OTwiVF@LrK54cjTI_O6-KR0=vX%qY=vVxRmC#Zr8 z6mV)%`bFiLtz2@Y{ecxaXKcgdFQbYbN=oAAeoWdXc@Kp^W_xR;+vrC)C1|2_%mdjg z^9Gj%{eRzmY&gWGiCEteRw?N4aIr=7@d(45r-S*=p=}4BRrGMKxI0=BlE#m1Zkh5c z1|uw46butKzptgkLtQOi1a-F&v?3Qi?hoecq2*k|Hw&ew0~fVrB+-yX#2R~{otv}O zc9K)MWfh0;Q^>EV8;R%ggLngBy_;G|5ZSdngNBSA9`+S&;ts@UOv%h`sl= zD;>gYQwP>`rJ6?ehfu(3eOd_e*5>%I{KlcqQ|<$pBXbk@H$iJRmP{o}oJ;m`wn2XE z&m`W1#V~0DUb|Z969<@sw${O%l1(T})kaZO2aiOMavOtjt4qrsJfOdif_W5WhQ>S- zX~E=<8Ee}^@l-f^hUjlGad8iaQZv|Ka!MX3umlY?sI;q~)5|BZG+nz9)ix>Ky_BpR ze(*_oLnllmS=FQF&4{+fn)8rOsvV)sUiKwgQ-F($Fwf#qODql!dR~`w`vTsiHdEis z3EF9&s~AQEw2W5FwaoCIFD*OSqfWKdGQkCC(N_oJTtP)T4=53N#Z{t}%SXm(d+Nt0 zTowv?s>gBEyYco`t0>NLX+nCMN3jKdF4ON@FjgkEEF;@j74?&ny`T?1_w5d5Z7d@; zIJt{+*Z9;6J!Bk-R4=M@TOYdJimb5KSl&=Ih*+!;t)FG*(l8!ckM9UJ?lNX9s7#pG zsUIFKvEt_GD$M`6u3_vxfh02D#A1Rnupj)Cl)>RoK6^^96@~6P-yAq?q$mxOQ;s^nNGW| z=svB3$d4~h4vO?rIH1!J$ut4gf7a5YGtrlV=}+kn{q#1ne7P&vtTFqt*w9|DSa?!E z`mwueTgZYjM*#@8aGKN1G*_gO8y}XF@mq`rh_%Q!ilZh#ObERD>Lqf<3> zYT%`gTB9K^RJU}ob|tPm12N4a$g0S5FSDY^)H9|MM=g(;qh`6$o!yYJm3Cd9>CuRv zPrkX9I0g^R!zyr=M#zoLFod$OWgg$Up8zqx0>KHg%aqj3TZ|NPKLNW0+=;x(V%2;xRBmIecYpNby zE89j5c07(5EYO3w7~A$-MBQMt#-2v|P_uDCdgJl}C0V~S(0dVvntUf}rt%r3&|a|T z0%{{SN6;t>AiIT+ho;s-sH+a($<%F1FiX|x)R=TtDkWZA1iF*(mm%ow=#KkB7jwAj zhme<>{MMJxzC}J3e~Q|MZ*sL_qY*q3m%}kaeD3y;qFQq21+!SLc98OJLaHzfr>c-j z!QfdEDn94<4zJ2d)#v7{OKp{7G9irl(sj7l?f^NwHjOH~X0JpoTobRO)P9WCi`T~M z{9a2RE^O|vov%i$XJm6ltG=I?NDD>O2}jNdOde_3K4M|(QvGUY=w`LCkcZ!<$?v*( z&q*tT*HPsX+?aKIAfxeG%2D6vy(2$U#R6@_Oj@g!U^^mGND5pI zLFFJ3Ss`S$9Hj^yk1wnF?H#D6xIhBr2A>WcH-mZjj{6J3`xMeaaRx>wf|g3Epp_Vk z=2+*rE&_bq9;WmyH<)~oRDRjAD+nlk8vQ|IL7^mGPq%H9@bj2z3MMQ$Ca9%>3Arq5 zoRzEUl4%R}nGNiZs~~aKf34zOf2!A9m!fRLeCUAZB2%VSyDp-d@ZQeH!0p|ul3M2W zVu{+k{^GWAEeRg9yY_skcUIb}b9aHiY=$4@CkVxdpenb)AG{vg@6Uc)NPtjD_Gw|i z13;h1`@%$ABOG|4bo&{(7#Tqm4jw->0hinWeY2!wkL}fuTg%x{LDyt)&QmN!do+Gi zhqQT#LNg9IR_@jo9*RpXa?r8B(J1%#AqBH088`mCNWv3EWkjUU#gdr+92XEGz=TVw z8XGK=n#XT$a!+WPI}4e-UF8_tv5Pw>ACfath-;R3PsxQTk;)?VTjFbL!*!N6JKDPtAHKkT3(sB8kLh4I_>9KQzK)Fi?0ZT+=HHX zp1pS7uMuhNqtGvgKHwn>H4r~Chb=A&RcvpwwxSwTR?~-y+%OrwRD)%lVys13xF3l* zwhCsb;N_WKX=G*Sao^xL6R$A`1LKFgOMfF5#r2Y=<0Ym&PUBff$jvd^PoJ$|wGqp^mQ zg_X|<`D-2f?&nvu3wWRbpkD%s$zO5DyrQqnu9FK``&Fj)_1cj3y&2Wk*(*(knmPTY zzha;QX9*p6s@@(w5)3QBq;t3_>zl|vIt&QbQHoEk zjNS5uXyneLkJ8pmB7@u0dP}Rzw3(OT{58=Wl{ntAbTVM^4NNV$3#``mC9awgd;vZb zpD}Sig5T&DHnU^X^A1}^R~nSmjIu6OaPk2S%#MY+Osu^59nhOiEzO3E+1nWH0^FeZ zdK*aXhwEnBL{E%QDM#m_m;K4tlrHIvWoh~PS^N7)DM+WtCENR8%*%d3gHZQ*a6TCZ zs^oBAcBlQo+%caWSYtEYk_GZMgV?drO^g#C>v4uzf33ez^U}74PP?-^?u~tP`5f@X zyCHgwe7s5n!^*1YVbJKnY9s=anlqtL+1+8sq4sZ36tyhd+vTxLm*M34g>g_A)6#~| z;L5Dv*eMP1>8d}ZI8?`@XO;&xS!2P3iK5SUx+sR0DP(jb#>}H>uT5Rut+|bNi2TFQzX4Xn7Y(?8~+(>KG zYXKyZEae;_+}Km`$QY^xTVGlKk{)im;+pFW?ad#JA`Vx08n=UH{>|r^yR_)~;w!BFU z3^Y!GxS)OWi^scQkA@^yqEVDqit3JX`39(;sAG3+#rUw4w$pW$a7*<&aaV54e@G5( z8Bc}f`=SzZs)wXhS}L5nqXHgKiTvb$fL7iKicib)EXYX7^j^&*$GEj+ICpowQakBg z|DvXRbIk8IH1n{Fs@obuSzB7U{ZU#{nxiOy?Ss<28@-{iBkJEYhpSGVEDnOQ`VlC@ zvW5M6`?*~pvm_^qpTT`+a%|a}(WI2wY`K4#OWV@U9V=2~h5NyPE~==n^(#?ou|(#U zv*F(Kg@KjyqWws&#f@rn)xNp5*Z?h(IjrFtVamx_AFt5B2wBKcj>N;h%gU)h?`b~I zC$w5=yzc90Hnw)xF*Xgx3E`rfqT&%^2O3g?Qlr-}XcOXk1?ar|*3+qKBFF;^CD6P{ zO6~AFw7;H=xXX~Ki3!iqpHNY{U;f^B)(8}RC%IXG5tt7&7L*cd{}KA;udwzE$ty-*eV*XjLtwp?1DiKXeN!D5eaTJuR#VtE6erK&I=r zm2uj<@#$UcMyGVu6p6@~BaLuhJxyVCw@+9S?~VgJCK&QDEK1JMavsq}7lUf!7*&^2uzhgT~YR1m<*chFkPoeCquIXZRlunE~w%US}w6q64FO#wc*VuB{x0NWie!9k>yugOY zq>^0sq=+I^B3ZBcS{Bp{^zm3)5NG-;S7fE*<$MwR(IP z2FWEgV1uKJF)Ue4uR--~kk~-veXWe8lDtwO8!jiWpZT^{LqUmpol#E~LAvpl6lcio zX=G7OvdZL4`>QS^M2Hb0I4aVlO`oy<$ooxsxw>at*O1$_ye;JgOp+b5jninV7=qIM zT&;j-?BK(+Ff4vv8G;+aYw88lNkA%OOril^_!Hl>H3ujPet>q%X*h!8?=|6YdF(3n zJ4l3(mA=vGN@+J5iE7sw3e08qR8e;g&OFbjpG++9_9(gNc`u|552GouIwd!^G>6rk zk~ueLw^iIQ=g9kW=Mns-o<761fQ*_g4UZ4-P1VB4p@$M&tm@0&T9&C_=8o$8;%Y>m z@^y@2p0bKdd$%Su+cC?qK;V* z0918;uWC5M+oJQ%e$D6IG>r5NaJR@m=v*7z`jZRHp zYAM>uAK_XwG}LKZh~ejR1|}6ntBj9tdj7|29{KqHMp64uCAa_e7x;a;T>X;Q(|bP- zyIyn`)t4t!pquL@i(fSv+p5XM75^y9Gl|!lxd(8#{X0wqi<)q%8!t+^RJWh8GTtE+ zf3wnii{yph(xr_X=+Wbq=F^-Z=2G=#uKtdQ;yx-xQpM|+xjzCM%=m^)dBoOS+|4-} zA5wh?N{oI$_Y`vWbi^WeD=yVQC@PMO7GS8AAD+ho`ubS%$zw-VLs6mcas1{r zy3~eSJS|EO1OeXiz_&innbiv(uq=MxIW2eM#tHh*J7>QFpeQaos3}JJRB;$iTILxZ zcvzy|7@fyt&q7m!`bkRFohR!MHXmZ{1O>Wc=$Kbn~dwBzR{=J7+ zDxOE0es~*H-j`&ssvY+AbZ}*6I!d}DAtsU{7YUC*#}^shvs5=;qD|h&eRnMnw{w%r z)=!%Av9`0LPf@$}`_hdZmo{2i7cV8J6fg7+7F?(#Xq+MVv=TK_#Ov*I-ix5rbn`Mw86Xrc0VH#%yH zsbFTM%G=BBCT)h#+o#&vM}0nmw*ZD5BNlwQ5k#5n{M`y~duvy|)}3VGJfjF{S+hy| z)`FYwXbUQH`WO;1`eI&@l1;dLzlk3u(R}&FcjtMzpn{BVTg%oBcqkupC~Jds(V~hu zC3d)J>pV?H1-X33^S%(0bdwjM*Xz9N=Gn7*<+>GvhE`oXG-nd7R%cbD>(hYwatGzQ zm9ArzFoj#Ucy&faGX;a_1ja(mn6tDc&Z5N~;@f}2rc1GAUWeQeA%q-Qv*NpS@|V8$oL{j`ht zU@VHj1Ti*M6VGirDWlh~Tw+wk9GrA;hP2Kz+|DWVonNi^4VaRjsdt-Fr>G`e9@jj7o{0PK`Y11i)%mtjmF$7I6r;kgW(yMPmSq=4 zy&+7s(v2ZOgb9c!gG>V`UTk9eu1G4T^_L|^<7OQz+lrH6!Y3b!w^h5NVGjY6wl$SO z1t!?CEJ;rT)zSOA9gzyzoS5HJnV3|eqncjL%MM?6s1)f^$=+@awH7t^7-qr?E(-~r zZ*{`wQrgG!Kzf5&5`BH zpW*shEnI+w|(vtyDADu+ax&Ep_lWoJCvqYN0kmT#X`J7ve+H1H9 z3LU+Gm}kWkKu=(n3Wv8=2ENiZj*lXY3_DEb`as9si(Hq}U21nw(q0Sj!r`XN=i z%wS32uS^Tvm&cOz2??~Kk6WHGvkqGPM8SGFUv&_Lu;V9Tk1iQfdDnl=zRBuF2yWIo9>e4oGf>ZC(J9>gts(4h)XOIe!}4x_mlsM@&cZ$AD(lxGHOTE0kT+mVw$w*01vLv($Zcf zwn6~Fr0d>)=57722ipIOefB@O#kiI&7x}Hmm^3&n9393awV*-zs%5EVNuiub-n~Ee zU7Zq_!(Vn#*<%M(5-WMx+*;T>7@`mw4iaKOOuNS?c%scWu-k zCn#CwY*%yXc5~xetZz-LFEr{Y_IhN4%)G}w`&s5I^@Cpw>aZo3ta+XMrLr3%gYeF* zDq9yT5rb$Sg))->49R59Wld#e8;XnVlb^f7chc6E0!2X4OkS>bv*eaH0ZT2mYDqqX zezSNeQUnG&jH+atq_KZ?mHa-S2S+NHkX=-R8Du;&mrvyzY1^S;g{@k^K(xtAIT**0V6i$JNh7P@PB7U~gTvw3PvS3>QJDUCS0v#{ zL3-zr&}6m1dKa$QHh>JUq~)tkIL$hcI#FB78uwnkKEL=#5f~#X&+A$H?rl)~53$IT z6@McWv`klPTdr`kKfGoq89W$2Q}0V(vz^tLwP}!t#*x`|-7|wEZ~UG}vhpt2`|486 z;qrwrU>lzQhz<8)q{iE7o2^vCx=}RoxxTAm!eW+hIJNzRJ16G>;@){i1o?bb$uhG| zs{7dWUh?XL-d`r0oU3-W``Af#sk-uTIvzj@d3DXxR_jnF9EKIHEvg%&WOjMpLD1rh)g|d)Z`vL z<)Vaw{_`&ZOC_d`y{0uxd-q*Zhd53mQICZoBas6Y4*BV1!O9^bLHYr?{Fg+!HE)Io z^vX`#IIJ(;p%mca>}B&bcmLi z+g3EyzYr(@FTiA1-~Z`mZ^4iS>HJFu;{?1D_zNqp%zzuUogIuwRr_xHuNDy3upgQ0 z(tt?4vuN`*}`}uzNxd}mYx#N2p!M0!{HMH-A%~L>1!I5%5JFfRW z`PBf(@QdYF>f)a`{(i@d)@Va-hWhE5zAT+};*rR>h99iE5a6a)JO%p*F6{-8Q4^*(X)93NC8Vd z7jhc@_KR!sxbQ4J`3$|(Y}!ZOai2K#Wr&kJ#%DK1XfhNi!y$l24Lel#y#Tx@z<59r z*cR62Hx>p+9>Xgp;h3(#oxTZ=Aex^jJ;y14eM4txH6I$eAbsG1?Xl6Y+xiTmE&8 z3)J}SSM7m}jX=*Wz_EPFg5Bw_4sraNOl^(8W)!E@ILCa(E$&nAU+CT21pZC?i{eSR zx)SL#SJ<-o?9Bd`w_;R1+?04x)z7W-mP|R$hR-`BDdo4Vt*!536LJNC$`Pi&X5d@r z@gJj)>CEgUl^6ee(Z*3U)9fp?6lhf9M6P_y&9~^pH?%|-MAMH!8==aBxRy};2T%j& zNxqC5FJS#eyc{OeiP8o#8UngB(#ujJUT=Ed*t|KhywL9(g%(jIHL;7g)D+iSmPHV*Ih3}E|?gATni>mt>u4`=&xr}M9Vd5YsMSsZ6^&ga=McybcI5Gp`VZk)%*@%bh# zTIU^Z^>1dm4oyufI1vb9y^soy%O!HnC%pWutl9-G585pXtf;OR*OXPfZRF9j=EcRW z2PyRoJ2uo6hon@c?L%NxR(*o#e2D;#n?>2o-WuMVmfMPZb8Jb zqDT6S^A&;Pt*hue1D8ap8&V%_bD;w))yn`9qKw)5Fq(tuEMpQ(vUzSoFgE_LM! z!5Og*QM$MAd)u*>)=Cjw>@AC}904Pg1IYxiD1Bk(;hOPC6IKzG97pRJx&!Nk z$2jHu#?rw5Jti8?978%FRU3R@=(xO1iXd?)bl`Eb_{p)UYnG6q_vU@v-3NxmS#>U- ztxR2I+|4w(lJ|0)$(b)9g1CA-kTS%WQkhh##-3mr3r(t-3uA_eu08HA8PAcOjO<E%< zo}%2brvWUlPt-iMXL4)UYtx@{NT%*Dw=uRPG2mI}U6EKqTC8FZKUt^(vfa<&8rKJG)&Y;6a zf{Vdiwowy<@L#sbzDICk-P9qu0kv?9Zi%UQ#)|p5sC@umtVNesbeM$=3JOIfQW9Tl z0t*4(QLi=YV$^LVV1nR3?wvesAjjOP6Cobtm(WI!Kh~tdGckA$w%v(kZUFXd9<<&t zNtQ{xtrdKSwJRAbEnHg+$UB*C@bxFByDzB$c(F;dls62dR#y~w8eiWKa*pKi(5`E;s4v5C>^-Ohx)!5+jz{!R>EpaIs{F+pu7k!sw zL|8qDvc=ldrw@{LqtyT}WCX2y3bT9D5PUW=76Z;|}ZhIxNYG5o%fHU2~RHCpX3)t zH)$bJ!t<48#y*Zm9m~G*hy+j_zn=*DH-lNl6W@*YXjz_&xFo zGvYPhuR5p*A~UDZfmxZcQs;ewA3~&Kh*KN}?bN*p5mUk+#;hI@*RaJSmk^&2AD0tSK+iSeXrMIVd_*)R zzf$<$djyBO2PUl0D8l*A8y`nJEogzbEM|5Sppf|Oa>>)a z;aHnEx@ICbB{D;+(|&{6ZjRdJ?;%-?L1;+c%K|29TGJ#C=bm1(BGc1~dnOA7go5&# zz2P#eTCMLw0X`9DZSe~Aoy{vEI^g5q`1$GjD&PI`*!0h#bketk)dsl~hrF#74z$~a z+i^|FLyFTP;dIlh=7?OSaxl!f(xP(z%r{K4p+#jN{BG)m*7-}nuW{1u0}v*ryy!X$q|F=^W7QB5CF z$@oJQ@Xl6Y>!YK3R~AwEi`7{dsEK`{hl&=`kE+Qn{suWd`V#1oO~=M5(XNz;`H?>S zEKwD#`c_3bY-iq9x6J%kDA1k6&hQhJmzAWc^UC zE|tNPE7&tvYxARZw%mh%cqy%@^_vS)$WaP>-}8s0P_lTT%TVpYk?G_c6Iz%e+pTvQrBPXMWs#@D(1VWXl7+qoQQarruBg!6M_ zHxA&eGL671RLhARvEL5AF7h7@#N~|a;9X5P?}Lo{7v=1NE&1(QRf<+<*kb*Ti;0z> z8ko|f`fOFI>@b*~hq=%YG+xxIv2ag{d3ld^M03_YA-cs_!`Au6h!!(2je>%W&daEQ z(X(`sGjl!HGQ?-EVr2PGi@-R3=TD1ZMqK<@1)KzMiu1f-_{+camqd|S){1W<@8y!W z%pF?sNFwAyZ$F5Xp8n+~3o%|ewp%^PD3cvLDAH)pjlXI1EAtsh2dq_}XSnFv&eNaw zSiE_Pw|i1+*`?ABEr$5)q{qyn$ULW?#dpvab_f;!!qSelAZ28Ta+;kxk%$+!U6EC~ zLR^r_OozW8brz}-3X9Itm6V&O?uqy}o)dW+LE!z=BT(a>!9wkTPhWocxrQf@yZj?* z&njuYakaShyVq~$LN|h{{g^g*#?6Xh?h_6zvcZhCErh#MngKFns{?A4CqwsY7P4yC z&nhfmyM!oG3qE;6KaptF$wytT!cRXA+?8)s8B}JjfBQXY$B0B57%_V~oIVgRd+X&( z{rn#jppm3QZR6g+9`x=e1EDjiYMpZQM^Awrw%hER5@_D+_Ty254`DTjGBfpfVa;nc z{*yHy6nc85UR)?3PyTY2SBZ75+EZ&$CWyZ8nR?mxdv`}YUC~wi+^6?U22M`4;3fdM7W)@1?o8)Hh~#E38hh5CtnDo zX#N{&OYz4(7ji&60+N01GLA3K^7RkfyPYhSy~lOcpM)rUfGZh~jZbc8T;(EgYUu`6 z-oB@3b#^$BP08_!23)kG7&C0C0isYgoGvcm4 z&lyj~V`hi=*@C?ruFN+2J>Xy1{ttCk%j**D?U9pQfw1uz4i zsP!22hUO5=pp4tU;wrq>$HH-VCM2LCz3w`;GIkZZvcRVjK6p*OqTP6MD^tYAU4Lvo zK&SOv#k0=bYE(a%8Li~ClYX?a9&BbySn_1RJ+;Sir#oB%U|&riFo_5X#%y}K4h(a& zg|mf?-r0oh26xNEh=J1pAJ5n9@{f+a9bJl#nh(zsADU9l`aCIt-VA+7RHf+l`ZQ(O zPuIK#2CgU83Jl{FU!J!lc`PqfSXaZotg*AR-^K{oEDYb9*&&t-7iQFEe|`(?D=z}> zFvWq|^%=e+D;4!Fro&Yzlb(={u&Anyc_?jibC0JU?l66GzWRU!G3ztw8mSNGGB_1WeOlOadN2 zgxfF7UwgFXO#wDl5v{rTU@@Yxteh%?pAnkoSaHcYxnkn`lfX_?WiLkD+PcEIi)@{3 zTnO6PB|^n8aTsu;T!z@&)S{;-O{%%1PvoveNgHwaPjJ3k2>c{VT>D9%B7Huq=QzK^ zZ-_sdv#nG%3kiLG-QvYT==QtO@n4y5@`?GiGfOnQ;+gY$j)lPIbsP^~%V}29Q0R`z zX%WmQ;lW05u9KGgPqwEZyg)88E6&gzL7{`|-Wzy;{Q5<%+dR)OE|sf%0fF(}9JLuS zPE$6{tKxb&5pS|^FBRrDX@;7u-*0B6MNe!A5$Qte0KI1`u>3WwwwSbBo-j3)g#9Cr zniz@0SleeX!ybX_8X+xFCB{2+uV}A|j zr%lr8XhLTf?Yj-n*)j?0Kh04M=7C^Qu5YfRjQZdAh5@MbHO&j1)gp|7tgDW+Z}Kl! zmqj|23)e3ZCRDO0?R7#m560PZkGw6aD157{k)K#)UB0|Cf}3dYkd3I9^$*GL9X?Ea zV(*c%n?1QJ1o&7(>3G8I8*q#3yuIxp%C&Z1z~(5lToq4b!#>t^kG?1J+8g!%N;eRY zbI2_P#u)g+nc*78kv?i3%Guc`C*wwiL?o{v$l2e$BFONTQSeoakM~a+z+T{s z&R8+Vw`Mx(L(f*T z>4lh1#c~{&0~IKbj$g>icstOhCFiGAFUtISPvFz$BX2FYj@cH{rwr9o66zA~3dju; z>qX!IRNz9N;IGr)Tl|Nlj5HMD{uhO~(#@Rmf!CVyX0KUtaPy9k29fm}GMxRmHmtYf zK}_(e>b*JsTG1%R@zeBd%edzcVz0gm*UdhU~XJ1qwT{@K`%Azo^L zPX9-LQmDw~!rU!vd@!4IY{U=h71zT)@}Rcb4L6N}&`RNEqE_mxbj*-Xw^J_@HyUDs zo_{~Sd~Cv#$PGv_aq^xY-$Tq&k5Gb|3-DQiHqQ0U6R$~0d)kRDc%tLnZ1|mPa^no% zn%^n~foJgw>6%SqXgtYgt>!|npTa}=iXChL?mQN2^z$S?TutR`qTovV747yRJLRr} z%LeYzk}C)U`Rp|DYJ|=%FgL9@d$821UeaxjM^;vr2Nll254RcHALqY407i_k0{kocpW8fRzy|>M6 z85|fVpnbN%5;0Y4hP_Ae9MEcCcWVFyLthZRe(=%Js>x99X0XAEm zcEOm~FS>KejD;!$Z0S?uMmR*#Lc*PZRa}2 zaL<@L(~}$Fnuv>JH~?@qT*p{OT|^jMv4Rlo4v|TZz~H5SY}qE0xRNrp%9a1o63nkn zc~{s)%U-H%^8$alr_zJ|BSb%+1uGUGR%))6&s{>gUQXcEy|DY3p1Ts2@4Id;5`TPD zNq)Aq&U!v^;FkP!ubgxJKSpXOJrz8OenQVTS(T^a0W4{Lx81_MKYS2-6vQ-tPpFx<<`(+624mdmC z5D#t8RFC_`kXLfAFU3Sg0F5Tr_s|!eBS$Xph?5=W;|`lpAnuDazwq-q#-OO0X&Ij# zhJXFMbJEV)z**QKtV8ip*V6aX8j1-?gDw2op{-KJ_zi9N%oT+LBIqU`g+=CVU#s@J88r~hup zzE1IH9{d3OZzWg%61<8^BEWw7^w1f;v&oO$PHQo2d$IKJ?BUtc!EIvWOe95ySwt5a zb>p%Fxgd6O>`JX?dA+`Ci7rjpozQrO*hoqI|G=!)k4{#Him-Rk2V4zLtKBEyY?1b! zUx?r}X&Y+?5xG-2-E0v3iPZ5QYBf(@M~plc6+3jBDnu*1dF=oD0>5rdN4}6Sam&%( zblYj@p0sD&-S{rUSunN(%3ZW)%)NafS60OkX8ryBOC*vLemPAn3+zK zPed*PD>dR;2Kr~`uDFGT%}vI{gQ%sS&@ft4;(R0qRs<7%f^acLl#$;=xp>82S8xWC z?d))sWVchZEs>16ot8s!VGkgp%Lk57!hu31vCa?^D-)tFdy$^T)&f3e({11?2;sP{ zfcP6_wi?H3G`JtOek>Q?w*H&A%Kz2^w$-`~1-cW2JsNc{0jh0#Rzlc%a#7#e+H>-;*Ln7@a5149s$-;t%PCSC<+ty%&P!*BRwG&0xDuU$@ReRa# z_&h4bk=RqgOo~o=!q)N;AVhhvOny{7m{FvjP?M7isvU^~wRRGYQZz$^{D5a>MonV4 za=pp1gQ1O`oPrfFEpR~b(}*RwTt5#?jU24-wHNfaJ?YjP6+1EU^xiCxh+oOeWxP)> z-Rf|mSeDFg7Qm(*C83kY2T>b>T|SFFOx;86_vK*||8PV66lp>wIqsvOIM}uM z@I$DG+#Om`qA$2f!_Jcbl8fHcm8x9m3NyRlxQ(@y7Dbu zE?2m!P*6ypcdV@8DOV^|-*qsS(d+rHpVl&Y7?f&mPNy{$Cb}S=1ltO|&=uj9MEy8O z!#U5QU|eMTBvGiMd+$odr3-65Z6Kp~-|F1uQDreHO!}Mm!kEnkP-M6i*v>9wVJ1gS z^>%mdKwoV>z{Nb``sQ)-ly!`rdZAxcRpNdK_GfYT(B}HhwU=b58ol$di|LC7s=ke` z2S#67L^+j9OM@)GY(5WL(&NyI9289DjJO8bi}vgGI@FxIB8te`HDQmWxSa-<^u=0-6iSR-zn zk+GtLG4(?(j`80f7U`Xui>Tjv)q;yNxP74_dNX31jw-a%)wBr;4Gg9S-#TovOKSB**G!rW zc0aU&t^fDX47*TEx(Lpw?8ty|sqj;uU#iPx&3__Gp67WQzg)}RD&&=w*2SUc+!yH} zT6V*0dEkvgv_VMJs}TKGsBqEqAL`#O=cG05{^NrXmD${2h=@rm7Z>lHH^m};y0g|k6<p%LjL+5V=@aEps zN^kZ*gbnrSRW9YA+(@l^bz$CUzPW}@DUV2t{$si)EvsKx`~rTX8dOcpqc5VRp*HV; zL5zHNF2bT{qi8=IH=Y&pio$>Cp>L%mOedp%UBmJN2Rl-z?Kit`)^B}>I+6S3edSgB zm5uWfLLMj09iWVJF)lq!9|sT;Imi9ePM3h`oG0AX2^~-C-4EZG{5TT9(J!%Vranfu zEp=gc)4vW~kPM zr>b=k;`BY)HIK^knMrN{b{A=iYw5%*?Q3(gE_2G90L^)iq6|?mt9ltwMf42LBv&fFGNNez>_ZKl&ZKV%i2$9n( zGh>Nc36J%Reg1(D;ru86KIVVL zC;XSAKIB9?^l$RYL2(bJ6pEjs(iA{Uj)b#eoTM+LMG1C^O+^@jI zbmY)o!)ziNJ-z+i|7bY7jfF`4eR3^|s<%nkRYX?cpNO3TLi56{()so+H^0EX1DTb< z=iZSAr03FEA1>^SDmmqM?iR>i6Mv6v=$O{u2JOvbH$bqXT{g;O;qVdYRLah=_2xNA zxTH(}ZE>QGTfbSp$f*!|$o7^=WGLlS*LeU9B}|gTj1$GdD55B`HYbwBDGgcUoWPx) zjZ5`!R*2ap2)m^d>5p&^p+LT(Eg#JAttmPxkyT>1U9y@#_ndW0XbxNk0>}Eqb1)NX zCkg+pz4wf2vRnIoQ6EJ`zzWh;K%^^GYD5&I3rKGwBGP*&M5Rers&whScLE7grT0$g z0YVEcBqWgR8`pZ?ca5{p8Rx^^<6Zll@qS|@H_6PL_dUyX{r|tKbb*J749xx7Ip$Ep zscrWnHOOVA?aD7!`A4Pb9}iE~htQTnvOHpt8)w0NwV!-rDJQG;P^=Acn}tf-r-02A ziRnsLBN2p^)Vri>*RsxzC$|5T(FV!4$&JRxLhXfCtWOue})bpPR-<6jeIC;NpjWp1fp(6+riPgjXsnJ1C( z*_O*UGn@tkDXg{W=Z15HU0F;;l%zODZ)QbSDYpTU|p-tGyUw= zl=E4Dq3~EqxR}#1PGQcP*OEyQ5!H8>vrC|q4H|Ib8e`e-t6)Bnko`sAgr=0*QwebE^FDRZVV z${OX%K6kbdS~-rF3yHCp`^d@|@3jdzAH1?Jp3&U&z^t{?&RF&`N3QcJ43mq_zv?kk zf6x1ZJH8P+^n!WR-x+0%)8hlh z&-j(WTtG_nkdyL{-ZhDEb-gcm#5KrGpF6Q4|KSUcF)<@rsFnHDJeb>(ZQfx-H&Q;1 ze<+0;YW3ds&GV)AeyW~@oyOo41g95}QI#4o`*UpnJ7~IOmb-(PM=@OmPC9$;s@Z2z z=$HmJ%fQ~o&4_;bS;14PfA*BOnG~m_G`lungPZY?3FLdgXL#%=52%_*Uo$5JP5LSc zQHA3_X?LthFB_d)9lJ~|%!p$+J}ky#)@jCrTY>)mggCfd$E^`Qa-U5P)-O;dW;JYk zi^E04wcB0!PePTugHibX@9Ucp?$c`cWrK^YL6j*pr%dO_P6wJlU$7UBAk8IDZFBSy zcEF-R;mb6GXO_?>uaNu2?unSsBk6uFi=y>CN6c}Z9lgmmm#+%EP<@4(3Ug_XmfL|l$~;p%8NXJDS{SS|{wv?$dC zZSNR>)g-PCTfM~C^&BFKAH$F9-sAA(Gu3O6Yv!sRs{-fwL6)i_ zC5!jRTT@;N^bdS=CR2b0Z%H_p8J$U)P8&w5;hY!{x$c>oiIN2*;$T7?e1dNt7%*{o4H?1$6{BXH8}|i+cH{YNcQ60{A#eJHZ1w^WPyN|WKp8|i ztK|u7HL|XclQ%_c2!GD+Yo`ZP)y|d`aFi6zyKis5yxXB~NdsIn6v&^!AByc z2)5fVIR6GMIU%_^GF#c*Lkz^ibmYRWF+3t$(4RaWv5(2@$XCi9Qirwpo;(Aa_fPSM zsIeC@@tx_Az$Yz3h_!B$17`kG9bZN%u}5CtJFW|Q)TOp^ku}+$W!`;0b_ULGxmac1 z{P2R#m0qu;96fD4p{!;iG&9+HkDH}?>h<;HqtUIND+3dLpjouokvcdix})Qw)QL_p zuocYBnorNXG*|7Uo3!_mKUv&egRO}5!iDu*)d^$3xJ_K2@2{eROcbQo@_v)M`@5OU z3$POlYK`lN-mzN!z!M@W)M-@TAo9$u;qO?$<66T+F>X}@Yw*}oa`|H^Z8U>XwOMP; zwEs&>N3TTyN>=^0w0N4e%5-%dr4StLdZ)B>u3}=_n}o|khHAD1WU_T?yxwuRlC3lK z4=1Vr)^9}2KjgXu@npZgu7jH^4>p-i)+#xl2#-zVq~YHu)xPZ#H4=K|Q@qG9U}8xm@1*OG+UoS4sa(av++TqHIUCQZ%tsW7T~@fLH;B}zb-6ng2Z zPBtQ2cp&-1#{`M&GXJ2p4%ZtmkpRiU8@WC@#$VKJC}gA)YcYk4%3v`N0X?Ucw!m~) zXtc1q>#4fg6?1x`0;{=)Ek16YWkxGVea7xD>m|g6&5+JL?*eRR9u|s9gO5YT4qB5h zdWyuar$y99=$s7A{Hqp;0}hf{OjnJ(&LNql4r~0AMT}{9!*B8wN9uPQUsym7jHki= z1V=A*I~5lVC3;P7bM?SdjTJJZ*%Uxx$oxA!H!;Nq9$V}|?QQjdHww`5TJ#5xOiXuM zUAUsVp1JgpEA0_oi>%9Z*;A5mE0Fb79Thj%J5-X7J#VNz541*R;Zh*5;q=MQZ{UMgPrfESw;iql{acDuU*h%ze5EB=S4r(GxUAvqIhP>c2|Fr=WY(QFC}hM244 zdKa?Y{;{%7JWEe`JML|RrWMm))vBLvFptjeWn~Lrk(jTyZ0uz1`Mmkod`eUs*mfxB zl|2Q^m1P!nAe=g)hWof@$6UkhwZ#36m=#!@PNkW<+`k>G#q0X~i@PMHQ}~Wp%3S)- zCCGs9nmqkk0uGQ`%gS9#K6#N_yB=zsMJM3&$GSuRhz;E0w->n4*o&DO$12$d6>OVl z#{mye!xt4(eNujpVni_}z@WaNZlz4nAqL6Stq<=iV0%B0)A!a&x&5?oiZ*_8){dQV zQ>AS``?XiF!hS)Nv!^Yn zqiAVdJ145++>QCO6&9a)&aZ89@|Sxt{j{&f$%bj5rC%&?tb+c(OPTKZNl%`3scw3+ z+}Uyby8A?ixzyAuOdS%cj@9y%F|J|n)ZhJnkb}E;uyifz?hQ67bbsY)eCSM0yAOv| z%h$w~M#E4HD-@gKKibLM=<0tR(@j358qlu7RM-n6_Uuzj-^f8lQ_6HxS7);@$7P_y zhA##ab4RtM$FFC=rSg0VXB}YMqrX~Tb{{R=|8?Q-rTEE1s^i1r${^{}wk1dEh=Rlzq<3y;cz4UT;qy!_qk??13*Z?P&YO+Cg>m zf7UZef868hOzf9}h3;H){|i`+fdykb>0I;Jc*W|QlOaMEy6H1vEHZ)$-ybQ|2Zo;= zPgHsuR-~q0LmEtfe?8Z|tH*wcn&I*Ll}~3fsBTOrY}{9g^H(=q@s9RV$KA!8q^2y>Oz#U9%^YSmL{Co+IGrwUK?!0B8Z7&lU>ASY+$3!3$pQhK%E zdTOkc{4Z`)~v1C2%*32ph?Gc=&M?rhT1J#>kgDN{w z)hH$2qmH!3{t*4CnK2LG;-B_a6wNzL<6ja(LE76@aXjHkQ|jmAsNYLBJT82G3){jF z7u3op#f%#tQF~=nF}QW(IRg#t+)}9=icZzDTsPtsWH~%+y~D8qz$%7zNPy8H0;smy zuelzC{*IW!a5aO}sK-xQiqP+T(9SeP%KC|G;{!eYCb7)`2b7HL2xe*@fDYKucA2eWOj)ViKlTf+ZUnR8HD9? zV+DLXk90=b$7$89WcUk&jlT@sMtA>0WlJK-cVW(P?*;}oJqC1J>{ z_t9nXh9h9OiR%@qk)VmAZnB=rIb=ig@)gFihu`OsM&`Ho++-D(_^3T?@8MeLs#C8y zemBD+n^!MUx^lZdcBfgg=V+SikEh5@f7mZSUvMTli&x?*55wH7USsZTF`a!#xPsB{ z`!98hG5i!F=C(7o5^uJ5Jp#}ZVG8;O*+PeA$@gmwVzo@U3*U?fmQJ0t(}mK*`#<)vJfH2B6tzIcxe2SC zAy(xRa+``~clLz^<>lGga&jI9R!=@iJ-Ne)s)sF@8di;o!$l5`UB{#JZ$P;qo06HO zp9>vkJ}BAc7Z;492;l0#vMY{)nj`VOA{hO<4RzN7S4@y3>sNdB6})IP?~$#e`RBE4 z-UQl-9rsGw72T_DGchK`-I-f=SJ$ts(m9VX+rc{;%1^@olN8Im8O_<_CQJ_RE|Smv zz}fQ;vhL0oi(7F!ht*?%W7#Bn)ajRD_PDL*u{kmPQB}w9N6sr%Sr-qY9vYtrHYS6Y z6^)#XJg@3VCdL`eoLuUx;ZT{0VQ(~3_Zf?GpNWi||3)gj-L&2XTjcU_F05{@{lIA4 zbytelt|NK$xU%oF$=K;mMb=tT-{M4Uw3~NCg|DWFzGzk6Ti}*@U95d>QZG(t9po1C zz=HjSTJ$Z}irP1LDk};_L~v#4?%V0_PyyGMsRv7!0j!54q{lgcouX1yYUDxO?;6{I z>|)M_$xR;blsgiYaXVH0x(%kb`ZHv#$E8?r>470317z)QL&KfP!&R)13yi;c;QA^8DPAll6S5 zUQAO)UfKH;Wc!p#@N-tqbIsVjicB63a9`-L3P&Ed^#J}PI%1*mpu|=9;r@WeNK|g$*YHgTpV7P>$uR}rm{y<$m@gs7P ze}H0O(Op{ljwruxaz&if(e`K0tLWfJP({jyQ|eAe8h?KoGltqaH(MIIk{`6zHtRC2 zt<6dh4+L?YWH^RCVg%R&X*g-vocAnI;Y_g6q)p45CeE?+qF+hP_Q0MW>@!`_j-np$ z+%-1e9G#RdJm59Z`t8>h?UfDPUlMo|9}n$#$g96+GhLMTb9y*r+KYteITf(-HS4VI z!JjO}&mENV--s$(;Ghd#MNCu~aPc0*3X5>~Cd2bHlX@VI2&%}$crTN@{_9{1!$UHI z&j?b0>Z@*wgu;>4>^Thfr8$OmOGwEV4<?K(%IT3v{f@&B1MW)eZ`5x}un5chNP=%($jq}ecz)XSMaa&*(EdZnAVc7&K6(_c?a8Q$OeP(RKD z9j)LTr1spqrd$86w27Jc`$&xgm^yxul{nAIo=Zkx;Mn5ym(Qi~Ku zWVrPQegoMR{v8YG3qSS$ne^+_9jW4k~!pbx(LI9`jw6PKU z*~Iw|tJoHRoHoohQF)GE+U(&Z&OPo-Qsa;^SwWw0^B3)A`CFeh%_i+%;DBtb*-X+u z&31Fsuz8{19U7oG5+d1C((YKS`WHsLoqg4k&?l#~;2!@EcJEJqK1a9b@6F8q$?h#L zhTZvA$mJSbxIfWvEe;urhI0&-mOSCtZ}5_N@zzG;o&Ta|He6hnmU(NlYilLxV!e(0 zstAeh-1Lts*ibWg*bn(dkePI6tP2m zyE|FvW6k5bC}+a&^|C*(c2&>Ed3TcE{n&Le`qqk*9~&dlIfe4p@^S`LcNO3$(?Chl zS?k$x#o&g?vQ$Kalanj?0+7<$iJ_Gi4VgaxL%>aY0+%Br4@v6V~m z3FgN2y-`L{iDH@pa-FZV?uYmA2K@NYwtHI?STKd4cRw+)d$xaOwP(j(YDp3j;}qlS ziC1q5sP|6ka;97oKz)#oma0Vj-u>30`4qwIeh^=^ zlYTQ(RaLo^C|GklS^)IG8=PIore;n&Y8D?2Nw6&Do3K$5;MX{Gg8#DOv&f%&<_5*#xru-qxFR^#BwqDg>Kqjk- zDvHT8v;ZCC-S9-mS0zWC?Wz@gX>9DqO&V7TvQ3L@sk=jmegFw*t`4zuov7>aJ33=x z@@fdZ+HdN#Xz}GGcP>S^^)yq`3GI%T?L}n7#Ty;m21Mq(>7;p&{+fq&zmjR-`O>CD z9p3451o2R!N4jY)bfc>hc+qGlg)e%*_=2JP?``FQmW8TovD>Wj=lm5`O_XAWAmN>2SC~EdisEJ*ZLxtr8X7jKmw&MKkiCPU^tsh{eUPD!hFe&Noo?hz?FFyo zvDCO|{g1~gFX}Z@En@H=kC6rYtEcnuYfSv`)@&Ywo}^kMD+%NL>C__bAz6fBEwjZ4 zYs^X%?X8DRlfH8OT=TvjQzpZ}F60?yBD0@M-tTD_=)D=de0X$@2uwpnWKLayuR88c zXb+Od;|X#o&4PBTnlMtD#bO^4A%GILP3$tR=fqjMA|#{6{nzy$UJNJoKVurG6m+!{ z8?11oiGq#su;ov%Of5lYw7Z9k$D__4b_SgnY40m+YSwuNJ3HN_J%ht^hrTw^^h zwYPG+WB64=j)8G~lkIrf8BzH-D>%~J){Bq55vkl55!KjxM~#C`GDXYj4zqsdSj}7r zt!T#9%&@Wh$WdI?FIyUItGVo1r?>O#Nl3I6Y2uP-yJzX_5ks_+Z726w<=K|Zpq4g1 z{h<9Y52dFGOa^s~;Zn^c{yFn={z?;9BtU+!Ygg>v3TO@n2AqVD;j z-m%PlBTa4;3@=4xv`8TV>A&|vggHRkT@y{@DZD8zMn3WFq(VyX@JFsIqm#*r`o67Y z`oZZYhQwuCW53Y5*!*0nPv)>99!}8TCfPE>w)3s&heURa`D|OJeLAOiszwi8j4*FR z$BX5x^eWO)eyMFC(2hkGj1N^r0@j9sY$a0ZE+P`oN%PY>u&7yn|& ztYl*;hud4F%Q*?Huv}7LJL8;}_V$~9<({OLT4+hp#tDEjn!i$efA#nvs>R#kCod}V znno%l)s^^uvdcUBddeJxGXwG~nRXyMhRJ-aX{M6xj2E5%@r)O(X?w?W zH@HiPJKZ6+(j3|~w7Ny+Fl(7`_g)2Ctj9{pnx#!*Ze~FTr+%{Hc7DBwo6GxG*vvFO z$%hJ_Qdt!M9&}>+l*Ux8r-uC#nvS!y&Ec+f0p*rmvn4bZw1j~YQGd&q!K7J4 zfku#b>fRFi^=6$%hy9yPLEqAyeWgWpIZlo;l0<<)%G#DTO@-xg_~QKxwE)AphK>A^ ziQ@8OLu=|>aX^2uAaJbuIgZ;+x92=4LQSv23bSt^px>wsFMI0Xu6I9v4Q&PC&+ErC z7=+vJylV8YE%a&De?2AHu*bC!{6yjV=Q&>c#Uv<`iY)?d-)C4UY~3?nWa~*)A0$7u zsO}gp))GxxRh2)$6)@2$rKy^f3z+plVc#`$4M%JXXMv@xFS5xMU447>>)iM+^y})0 zhFr_=E-AHHjTahQxaOag@8wMo_5n+=w(ViD_`Fnx_oQG^uk(jxaMp^EX8^BVfGz)T z&KQOnwl+CKE4h-TFUdv1-0{WTmYx}(@9%Y0NhFF3HZ_6q1=h8$Y6rAeQGUrf^Z0}_3F&B&Luo$-LrM|S&=4K9TUCq2_jqIm(Eft2s32Svbhg}opY@_%?m z5#91!S&)N4oRP)5oOP&1YK9&vq#9#E@-lJ@$kKGG5YPs!S{ihsW{s+}fY466290{5 zxa9T3))G^(ayKQf*Eo84mp}Brqp6h|^k;TgKE+byDRrRwY6AW}vLYxp^LYA%*P55u zld3|odQ81jedS&`WsIfBuR(tM*!q5;`Us~UzJv(z;yCub% zkfxiczgvY?c;%$t(UQ9zssW?VwiZ86QfFjv8}-dA(=y;v6( z6D3a>eMOft!)igoSVyj@!ceGSRI8WiarSkiP)>~E3 z^1E;wh-h$gIcb;9qX<^dB)Cl#mT7gx!?hEF?Xx)e500;kiFI5Trq)AK8+H^Qc ztjb;0J)z#eqvhGd+;=b_^1yX@;MUc+98qR1P$CP#kT~8M7F<{nH<43}K)ErL2|sia1ee@t6NZVw0+L&zRT&5V7p9F&CF9 zYPW3~&sXXQIN<)EwNF`A_;lm-%lbu!vAc8i?cC=rozWWs&OD(ts{`mR8;rByM4Uug zIc{g#XsGHWJo$xWzEn``4}m(ESWOE-@jg&7u8|yDHFbKOfQZDa!-I9tb(e1~{zi-dT=%LS_{_f(RZbNjCN zpl{{fUq#yM(i-hco*6292$V5O`}+)Pwv@q2VH>;mv_n#32R$70^nNhZ>FWyc>%~^z zn_GdhM9QJwDk!8PAsfn_%ap(Xnf#!ot&1)bnv*o^-%w!?yv4yGx%d9LS#5a7Z90#^ zi1)^ap!RWBx&w>$mm)^tMd6Bi$AvA$@!sEx*@BQH&6AFXuoXSWMPkwgrTY)(1#~GU z`fVN2=C;G3@ahs3m0+g%yFL%r-rFIP6C`1r0+{jQ`WUu@ii)`NEWDiOI6X~)QYf55 zdw{G|$T#k`X~fQ6c4|WccM;kaQT9<4n0GrQZYtb&JkZfA=Fc_mXrK8^_W~3bYu{%q zwzgFHJ)q;Mnepnlr1^G2L+wi+ia5BK^H8$?ZyHgHxQ9HAsg@pS>Km`P(ZoQSp~U$i{i zTww~ND_xyu#a}5^Vnnb3*6EqO+L9Y)BmN(X z$V!;bhM~EZdVR^tM&JFht!5&@uP3D>0cQ!c=M4Vz=mc`{!?vV=@aa_s;QxNY?*rd|(v{9_GbjqwaC>l;wzp#uwVMBa zD+6@*Y1STq6G@p}vnDf?sASd5ncshAp@|O1r2<$&U`N()^Dqb;JAlTmzb-cTsRUI` zWo9qAs&_P=a*{(l@f>2{ONK8<`T~AW1v)Bvp+_DomlcM;N;~e%iq+=sBx&Y0SqykJ z!EXJCjU2y5C-4sUI7Q^?qr6Bvv3@=T>n&Lq{@$j_+MVk}UW4OA8TVPQ5$FZ-(ONnP z@ylxIoyr)K8q%B|6VMVSI+wRTJnHEZIcZO6-0<&dDFfSoRC7AN90021YAEzO3C97Ld*4>l;EEVM??nu1<@G zb!j+yLmD?!>PEZp5#TJd6VvvrW*JBYZX*W-Dzj1pesS)JKjbl2Rpm9wC78Dy+Z;Fk z^NNBgyD*0U$?e{9YM1T9)2)G*qEykoZ&UAiDfA7Qb*lMHon($^5qexnmZfzb@u>4i z`25$4`H_-D>d3!3lBK-IjgL`xWq;oVe;riCO6{$W#M-WTTjyMk&}x|dGl?BC+kF|k z0B_vxue>0kYjz=!Qut)aB4gfTkC;F2F(3ss8|YVy9P@SV&~xWPM;8RZ`JcK2KDSi_ zuNOdNl11i5#G$aexoM~GQI)(S_La7Apdw$+O5_i-{^`~2YINj~t^wlnaV(B*L{t|RB ze5&b8txbYt$0GT#XIezyQ2_>}X%cI&hg!>3HS$sZKCuZl?VHxL5C=O91+iyCaP!IX zzK=^il@VR`(x;7HExd~lR_;5FfWtW?C(>^F1)3an4V<-L@Zx!g$WzbRzW@`TP~(2g zI=3eTY~k*x(7xDe!stwS_g+WD6XmcUkEM3{$!}V?9>oEp(yc^y*ZT5}rfzj`mN{PQ z1Xavbax31WVHj-!IY>wMf6ofVRu@Qk?yolC6R-e zbIK|_@^@SLeS`IP)7dAMh@W?W*H|hY<;=h5z7Y8BdUhpt2jzI!~ke43#`ru~NLcuC?RbI#dpyHLPN zhBf(oC}A^MCJfj09O%WxMZe2Ilr$2N3G5Kw$z#aG2_ewr6uThf$L#F_tLu(|&ExU- zqh;t+K;h6eOVIEp#%n{>%CCNh7WlyCu`ycr&s1>m&P1ss2BSHjupT)xy~|k&!bVyc zdv5eVJzL0bAp)Dy$%sd}IyiaYBAr7yO_gM;3JZFhR&IX9?51uX9hWa|^bZ<$!&i4SKPR%rslk>8y3g$8qa> zCrQCm%&5ALH8aD`0Ok@bu-lU8x@4t+_Z>(B%`awoqw5bxV#7?A?VFIRsr~it!sy|? z($X}Dko}zd4x?umZqzE?t_h6^9)~>Lfth@QJ$VD){q9L_aL)Nl9KwYE2r3 zi3oAAN{>FpSzD{uk7?N_OWNukQVz#!O+i7GDJT?i#LEvjmOf)@82kP{EG6z}Xb4g& z&fUQI@%?O;dc&{q+KWew)uc4gWKs^LK-e4nN3}aN;N1~0tPBq+*k0QID^l?ZRs6{Rq;c88xYYpIqJ*;|-Z{ zMN0{`jj6luC-px}cqrG=-f=rV#*JuKzRm&}Z6A%EPad}Pd&wfEg>$Sv4I4y!e3d99 z&bc^OH~6!z=rpJSN0Wo$LwL<^G8B^>>>BF_Xcr1bX7AQ42G^sOPhO%9IoB2z1C!)( zXR!$XL8B`MSTu+=E4|glFW{+@1BL}OX98O3mk4_G{OJ}8e~;A04XM!&|Ll(&p9aQ4 ze+8Oj5$_OIpwSP*uMwFFg4$}7!WYTAayM;`_QL?OcGBfjbeeRGZ?u4zOKUeo)th5& zh;>9-5&H5Cj5Z$pV7rsrBJ2QcXEhDVZbRek9M?(GJ83Z(tSrW_MMYDDO-+Gb)KL7? zbrIG?=Xn&Vil@?Isaq=@L4)A)5n~jl*PYx@oa`}AUnG$A9s`uEUEb`JMp&mnQna1|?TvRDr<9w$tx)v#FlX47au{@xfv+N!K@K zs6(l@25@G_^BeM~`}s7GrUY_%ZUPAVPj&;UDCQ5>Kbq~;AST;l6_Ug@c^6*v>gCw;3h z=0?h}!>r2;KJQD&x!~`x&5rQBgV|b0T+L1?&5Z^gF%iW3$5aR6jPk_+P{E`6CdJV2 z`1USAfrs47n*>78i7(}W{)N9uo&KBf13&Rs+JtYGbk)sS5xx7h(_^P#gh!)5X z3x&&~lu|}MyLnC0Pwh5bHmNgnk_&t0u?fq`!%J`WI*SJsNnGJ90co?XVR-O zS2I54X)LicY>QJ_^u(yCTq@kG&Fq5E9krdv`I>mAB>hG(eT?PqSA0#tErz&ux71VM1nQK3QDzj{3RODx}2=39z2Ofclc}D-}H2 z%NG1`nIaub5T^La#EKoO?xd(pW{8rL%bl+BEkCllX{>vU=|HFSI;6B+|s}8`+(QF7(Kyp{nG7Ez^QQ zu|)2(w5mokwO65vNoL)1PUR4_Olq|xA;Yhwl{G6TlfL@5_L(--&?<><6^B_)uo-^& z<+XPMW}>i*+|_HXN#4W_HDdM0QcI^7hGn(5Oln92+6A|*nV3Tvn&cI#aM?o7v_%^# zh+FN2d{w#Y<;Usqb$j*-^3lBKV9jE)LiA%c$@h=t!x$R~2SpiWRr#4JCR!G&z9&No z_o;>Wrv}yY%hMI*4fiAzW6Nn+=d~W+-Jub;z~q>dsh5XFy<0nh>VsFXVhAh{r~dNRz3K zT|Ngv}ty-QTUpd!kvhbPf1d3k<1V zGZGLLF7cH8R(W2{ASIJ+wc|10+Tnv_8q3RL43~7YtHm+X2D%z{q>W0-mt%IzW&XK+ zIj@@>pPBc7lCue_)*RQ;AcXddxH+)tL!_n~ZO&T53WM5)FaFtv|K)?hOsBVT)!v$w zF&{Ea7{uEapsB}I2-k-8k_A`BeCJRG7gj%VCeq_dHX(NWrBGw;@<;|&?akOZvw7sNB&z`fs>yJf-0f-$;q>U?haX=U1q@FC3@E>=FC7-anHqL> zuO5l(&c5?I+u`NOx}Ptb@Wj1c{q?m-K~vyi{eDu%hTPm+MxM6#{wGBKg1=({Cz&wf zEwn=IY1XS@YC&@H;GW;%GO}T!c(2~AAh2lLzAxrj4RY%FHbgGj;aa$Ejf2eU!fJ;M zfRG;RN*0p!Q-L{Ks?o5VOuL&eBt*N#>)Z`uz_ha8_)4F{PLEiS z*_keA;m;fn8wnN6g&N5hvoKXnZZa-S-xaZ$v`o`%4Rqbydk*A9eX#pt^Z4ln>*uJe zFofhw&tM|A1LdwK=f|%y_OBkRPVau5s7K1qAh(BQWR*V~O-xww_+ZTdJLIzcAmZup zz4PaARkBxHF_?(bm?%@#!8hTfYf3jX{elt>TZN8RRTpGB9Dj+=yK9+9KvjQZc8W>- zI&R7ep&~!*8t-%Z%4wX$Z1K(ro<|oHcK7n~+u>=NPsgs*4xX6|^3>c}I5r$(ESSHR zDTgaV)sMS?$|KUp)ujX>j~G?rznAV~X&7uI=i}{6^2Wod5y|QVmN_JTZ3~qbPSu)|yb|Q7#n#zq98(ZB1kK~8%w+aOf zcm+j-9Y`@uZaSnyypy!BHDir8itT&9OIg@uLw4}2xr_l(Nqq-R@=#LLiQY1P~k3NOlrJp9tvUuZRTtV8d_IdCPY9LDS$ zr|cUiHO*F_{dbNOG$#6zXzuOSvIdU?kW0H?q)ZZ!u`dGgo9LxknMi2rc;NhPgxF?p zC3)dW4I=UO>LT~8Fx#RyRSM98%Xlas)Rr72f0Y0;a-Ngo{t_s)d+G_ycR#{Kg#dh4 ze@D7Zf94oO+{>8ZCVegoTUx$7)udFOIxr}8L|0KV?o+{W_aoZG4{Sn+D?OV9v#)Q) zUI%$$s97G1sWOD!P-yjE&OD9Fv}j+bw9Bq!pDg1Mli}j(LXDFr^YL);r;1DQN&gZ! z%sc2Pd$a7|o{iX%&M!Q;3U-)Hxj})+99Dt-cz>BvNq`xAI%`?$^tCkdx6g{txCHrZ zpR>601A_gSC8&{|^Y~oop1+UT$B-wl7}d`=&dgZW4*U!*r@jrM=VL_D1!(Q02l_Mk z#YhWzBgQs%x26$$j=-UQjfHeL9_jmIy07+R2p_kP4#Pcl91FWEz10?PQq4jtBuyV` z`^s3LHClF`=oIgB5eOWlgK2v>79j@GJ9!Z#NDKZjnOC*q{}h1Xw<_OiS+dh0Ufr;X zD77{+ad(a&~#FiNgHsz+72Q6C2dOPVGM=YHxXUH%B!34#taHe-#H3`Vu#kj*IfA9w zQANdhY%@Zl;91@&(CN@dX@B>-Z!%~S*W$v?82PM`32O;u+B>k9*K9&TucY^0!hMDG zRv+$z9!=(n{H@k<$LQxeps0J`EtR^?GT;1CVS=s@aoD&pGWk1 zR|$-`%a1?An4D!~Ld5yMDg0{1fxa21uM&~zx=;OsC(Y)v1$ z*;Yd|OnAM2Jv*w9FBiVNFgHrlfss}eHs`6P`>%|Q(oJCzuagNAhmny``w&AK39G!# zN=kOs+`FldkK_Em^G2T>%d(@hPGF6@$_~RR-9?wCdX92zPIv8%n3lNgIhDP0yP4=? zV~>n_GDo7mL>M@MdSP;rGKndVN3P%0FmhfQu-{%+_3mLIPUsmhFpEe#9yKi$TwxZ= z==(9f+&Pj)jOQD+_lDq=<^+2LVfc+grT!Bu`qam+8eTqcrc-L$05C)>dHg9hZG<{` zhsY_xH24egacvH9Hbhcr zl1>t2!&IRI@9C!tQfe{h>$ad8HCuh|l!~u@lzT;$5swG1!0nywi#I=E3pZFu;vB{6 zd9v3;H|!sCqOgW36<2Q75W%GE64RqMvANuk{RfiEL*zx4*c^t<&``HyX1_P+e&T7` z2*{~H_My2iB&xhda$5&-BsJWKxpZcZejRk~9jf#%KBZP}wcxqkfXbTF-_#&3y$YLv ztf7+~QN7wZFK1eN5@DWN8n)iq-5f{qHMf$lO{G7JX=QDpkMKD?pJET8E}k6|c9HA# z-_%7<*QOy1!W%iwk$#sb6K@JD97dfRIMM$Z}gHieyIVxe{1EXJ($ zGZD8AT8v(z8?m*^oobJGbxsaZ@+?GH9p0`{M#uSZ^7vq_X|6Ip#rFb?IK7SWl8<0a zcOh|A{_&DK#NPNssOCs}l_cc2l;}zV4DEv6Gn?IoDt>#*&(lbt0hJ^x8gTnvk)4r& zLb*uh>O&4SA^~D^JKh=<#c?6`**v4PG0^cqkP85Ap+C%mk zvHj`XJHz!!gy1$FKR%@47yV$`YfV&24-^`ss4M#~6(ovCv>466?y%Oni|O7Vqnm&`eK! zCM$bVVVnIDF^k_><@_V5@6-jtnE5sWLq-w@gXSZk+kr8-Cz10Y)wA}_Ys~&d5pTBS zZxBco>reXLPHJ*IwY|j(Jt&#UDt}LoKDX%-}zO2j>qo$5kV8D27B_^_Hd{( zx>MxXW@c?(k-iTxvdo<9Okx{pYyRkKQXDzGXHeFRwsd5KdBiTQ19+*(W{andW~La9Y}*v zP*P^pa-u|m)C{|4NTG6+5dNEbrd@-K;QQbA;1slc*BGC^4(?R5~Tb`!L^N9a6DN-h|L{Iir(Kq1jz_w0Yj@E86i8+!J_|CXXnz^DS@lh6Ow!cqU- zhX1Brk2~aFJ6fICnafd>&pv9d)DK5d?-95Ox zY5#kleVz}`JDzdQmy<8dk%YO{nrqJczOLWASHj<_%Hv{DVgUdETtx*L4FCWY(L^4` zKt}wLq*Foy00;nzGOx8f()SmzB{jEZ1djzU*Mkit6_7s!O6Jh7FupcWsF6A#0dcv4 zMut{}3yO6vANS`ir`&5ACw8WULB(#xLvA@)eTE!0HH9_bwcFTV2h&?4TO&&aO8(+v zCAfmJBK`g*Spp*OIJ-TqaPd@&WlAqNa#`&Ec(xHGk2sINuYh6~>3_G|o&qqR|NH$H zNJOUp{=f_w*!J&s7m7jv;`IN%zF>X>Jo#7qDe?Ap`){>5_lv-p8T_%UOV?-O7agC> z>IPf7%`&JYJP&H0unw|67`?Mh_mBA$wGvC4N0-nIzcS5#j@$~C)(@EZwLZYC ztO4}NEa!Q>j0=Q}*;HeBz8-27yH+AXD(FfqS*Uy=E%R;?BM>n(Iq0F1^rq^M%C_42 zT*wzrs6LsVuM2b_g#YxoY<$kzwx6p#SI0?63_f7OFv$c!Wk$!xn^o*4x8@ZCF+XlD z8Wqb1vsevQrC~7$xFg#u>O1>iD6>1`TW$4fV+ldFwl>zkX)(U(+fYq^=iI>9dfiV& z;!JuoB6N3IqI(a16q`Y=*hqTA9--~D@XvTUISybx_dm3wIy8so;#sL;;jV`NX8crc z!NFs3ps#n`Kcl2fC>5X1&Pd?IXdk$+w5*)CwZE7$wj^3Ou++dtCnOTcN|pi@gCrK8 zZ+CBAE%9BOJY4?9ZA)CLl*7f{_~+{8IoOfN@;T!#wp5GK`IQAo@hs_s12t<3I%h;SHV1ReAs9$ozbFTm6==NLoUR!^A%;lf{>pP9=jlvB4H^STsIkw&;|PEbF`n4$R-eCcuqKXQQ=QDjgFi^KP&*m;haG zVs7cso4C)iqGysHGz!#7EDxqrxtij%l_zPZ6JBqKn4e5$wWLSI@+MhX<^qo~4E5Cm zu&qcJGf*lzU6QQwnH6(TTNQphOCmKt>aPJy1v?$?ZeYh9Z=DTfso83w&NP9|H$+~V z#xAoKa4D*gMam%0Ux6I3llsqGE;f1&eSUa9J_I>(d?j1fxH7V+oS*j3rFk1zPx(j7C3l64~tiM1w-rayrjCC9Ze$y?q#4v=Y>JX18kmbyx1 z(|xwyFr&vB8v4Xbtfd|(6K_@gpq8+Z%<^R z(?c5CEXmnfK3@H0USO&e_NclOHzmzPzuDk+PX-9mLE-+=^2j2Z!GH-7Cf$PL* zY2l71HuiQi6&?f~_P(Z>`9-%sT}<78G<~u(61^jT>%HuZI`2)%rt&$-Q7`$G;0sE% z^jMZerQeR+3-J>oG6pwfFt30?=(|$ zKf?p*S*UXx%lB42_n5*tTezDmSQOD|lR@%<>sxxl`7w z+WC3+P>K35UsJAENurU^5_R zj;sB(kN9DYOFu7$G%L_xpP5zpt)RK81$@a%7nu)e)OSsc=n^p9Slb~#2yAQz7vt|; z2srAQM^1;D`PP~$`v>7LC@C6b#L984j@L^jhH;#oO3g?fy(w+}NuY?9`bDv{Y;Asu#Kf`g9bG5_%`I6rTD`ze z77CZLGMa&W?Xh#cV8;d9A=h!%S1kt|H(UCK@ky~P3mJ~(609O@E}+zU3EkOLZEJxI zhKWj_nl6DSd3uxlot@YBD%qDYCd9EJ{hFL9gsPggmT3|a{(CHexBgU`70=L|_=s*5 z+99#i)?$a-?()*au(XG0)P(5yKgq*~-1STiv@)5%u{57lQ15*Kl%ntIJ?`RadT_Bl zvg^H5UsN)wKTGI@X(X1x4$C32f=o2lKTkGrk0eTa`-gVQcVkZjKV5t%DrpEEAY=ZF zp8tw_i0kQqaZQL&NJnEp>}iQER~Gb&)aAnNLBs1nvV+`U-LBm8TPi99s>VLVAC0HT zKjA6#WH6{TmgL1HEfgv!J8E)2#YPh39iwk-e|;k(6+7+lwT~2-heP0l&((Q}W(A6U zNS9;fd5iN9SGW}UZCknqpPSvhexwck67TL>WIqwU z|Lc>h*EacT_yFke>K2H*UfLPvas6_T zM;yZ+eh+}aeyZ&g&`(>#F*{N(qLacF&QAa<9_h=kH}{@FOHhBWy!Tn05o83c)vE7m z3LaE$$bB{Id@^l|gWt7vv3fc}f2=t2U10zZ6g(He_cZs(e$&t}5vIHetnQ)V-S_QY zQTdP947JyEaf564K6FtRhh5-Ook&OaWIpZ8Yo3)dOPdVC{HLc~m(Cf&H{d+#n^)`& z)cGxcv@-y(^hBW8O{17o^plC+=Tu3Z*!08(uki6vYi1>-gr61{BCF1E0{gSE!h+a% zingxxr~R8J`>&cAgNy~LQ$>72(-@*J7>;HOrf~ZSr(+Qs58pHW1wt;K1KWv@)z(3}T}Q(DCoX)zBMK$n0Das>%C9+fVWNu83D!hmlet$Nn zk>xUlh-E=h=DEhw6Ng6(P{yM-(?6!`oOe`b#3oh~W_To0qaF-G&3RMj-6E&9=B_)> zj#j|t*bJW!kEV;CR+t?jH2LAIh-=D~<7W5e<>hlh4gDWZ$Ak)#DZr1cO)P_ulW#{I z7cJfa$Z24!prM*l%UEK%dds_D3&>j+syC>if&qMzrAD^C ziTj0|dUVGXC0B=U_+p!bU}@sRmpRt3^X7@~-Z@h^UnJ!WY3CHvybgxR)Wkh>X9<6Nu$&UdIy*YC)rapR z)0JJs_=aDu#F609kf}m+fAC#XSc(g(w3mGJtBuK)J6ypV@E>mn0JPx;e4R6^*QoFu zE^+MJqngqmbn8rfN9!Rq0(luky7E9N_`bM%^Ba5JGk%L>hTPACjZ-9V%bz`cYO5dv zOTZIX4&_i(p-k-gCf(ZBhK@-bON=Hl?l(sV>EU^*z%IjPvnn#-oc&UJHVb1L>umi} zuwJXYCk}3f*2-qX7W7zc-&-{3ed$*ZIt$hQF~oJTB*kw21eVH7M7HReiVL?+#~)l; z;FX0VE<4mL5{MjT>E2kdLiJQaSG`E^m zU8!$bf`oxKUDlpHe6s%xjRnG(qZuYz@tL3?U+%ITV(y9MTz%$z=h!v^<@h@o06&0( zLPnO`yO^K9(+gIWwi6$7ZAdnpL&)kDF=QA=OwTCTV1pIs{w!|b*(i-khvC~zvOSVc z{as9%P4J0IZ_j|{#{%L8Nj+wcB{( z*})ftCtxH+<<$mZQ$hAH%@GezZ=8J{ zi?^K@%B7ZilKN7mb&XuP3cQu47kayjNu?cV)^Z1XFHUdwL#x) za|S-@NwBXLRgPy>G2r4?%P8*c*H+Xd4t+%eIjeN$BOcfxWKf!`oH_-XUAGEcUY8xh zQZ?%COq3QIS;5mc^u7<1aD$n&sZ4Jhz$0`TkA#m^K^AM5Amcc~_AtYm| z+1=oFh`*xt;hf{)Hz7wOI;(WYR<`NN7g2p7KAnPA4QGxyy>mCalMgFtUmw4QQteMG zv-im#Onc))nS57P_5;Uj5-*HDEH}lSrgt>1GjCpen9T4)e)X7n=KrnW&}RyY9ylez zcKeJe4?V)*L01xH_i~7nY-K^WlcKdyems^*6{ow2Co(JbWX55USa`vH)e4e`~RAu0~HM| zRbQp>r#YWSkOn=Loi_XK`CaT6&zv%-t-76q%|VEmuaKu9a?Im{7+#BuVyMU2P@Km{ z$h->2)PCa5(VJkO0+%4fT&C**BP>|N6<$<)K0zy(_ck34_283txaMDmv2~H3@#q}J zTKOb$3Y^6S-vg>WQ{-5u6(5 zBM>oRt;j^}4jjqC9gG`Cci+OX0naxjv5#927)U;aUCmIyZa%;eY-2aod6vn&^TBmK-a13 z%b&D=7|-P;ZPi$U=;w6c&cIIWvc0p8jj&$ z{$aNnwHG^Px7^zTgqRks{@(ygOtHY4qCTuVZFo#vz3mM3>D7gpu035BURuHn|3ty$ zC`S;xQnUqK-OFDDcN8%06dIUC>`f|`5HcX(2wlM8we3?4>V?X!oXJr;J@=D0ulGkM zu&wfBb@rQcEV{XkM6!Aos)~PN9+@liPURA^N(i&wXm1Adm-^ z>$6QH_RL7d;HRl5RqgPtUW?bGN|innOMzR2(0+tS=IZVWsw10?d|l`s-!H5_w~FhS zuK&{PsxVeDSpPfRq{bepNULf!XId8w>eG=bL^ie0W;zaH3beA|PFXVm+jrM;8Ax!w zjuG4;CGzl|P7gWD>2bujpKTUv`pSi8CjDpwXuJHx^?8j*g|s1WHk(w$uqu9{3KjpP z!5xoJhj#iTFV>!8rt1A#CdWmp&&)iVl&ja#B!~)3Jr%jhqp_>2`{9qGy!x`D+Ks^ zpa^gqOX^UI8RyuK7L}(DuuV8KLAD2?NSx=`3mH5?`qw*gm0l?7PXWiiZJ?^)Rz(}J z`Kdx}8~EpC;y12z3YBGrZSzd}25N3)o7V(A^3O2ki(I--IcjEEEFO|rH$G>P^dhG6 zbKyXmI@hzgBZrQ1_#STuymF0o(CDB(CoEWIFeTkZ$xu@xQzTYb4QKHeQ<{= z3X}XB7yPqcpa=xb|C<;#ovEVWM>u_X0V&kr3QMfR*?nPNN#EZ=79#uvfU3&#Zy zhaH&br-j(sb2klY$hs?=gdYgCvTP8yxFyv5j0MM!+M(;cbTk>D4g7;oV6QUDONEM2 z@a|!kFb;G}Mhjt8WdE!;iGh~{qIiPy5ffla3~ZAS)iBV{VF|X`sS2jH&82QFZ}9OW zd9C7BIDR9O2m89^T)#Tw^1J;{3?jeb=svZ@P`_!cNx=rbH*|3Faqdd3!Cr%mxNa8M z#d_6bE=L4HBA7*-6JL6K*SF53MQf`2_zR?@SCe@=960{Ya0*yIMqX}ID;WMnTLsY8 z!XPNsyN`OMlM&dcUC?=X+VfM-hA-HV&QLR_ws@fK_;55oaUv#%0z39&3AXZ^G@)-kFw--lG(Gl*?YjvP-VwT@=4 zR3x9V9;;BZFHGz_ezHIMu#Zf(J=VyD(e*B}s{8|H*p9KlNo^Pt1Ue8v#*(h*G=w@FKGP1*J zh?7hMy#QT;sXUIN|Hv*xemA74{@?bX{+~$I|3k4s1J~+0OALWk;(J|R4P;&djUA@; zphNeJPCmySd{!$HT{n%`TSK905ud*%El=#)X>TN1yg0#pAIGvb!8?;j*$Mxh(%XEp zc49j+tyrN)HuV&*!hThx>_VfEfeJ30wN9muOnPxy>dAWq@5QM~tWZ}iF4XhOEG8@4ISPmQO zKiv;k-o=e{-K282-WF?`RjM16^3r8R28hxl4%qZOKi7@R6SYEAo_%~q_5S=^Zm45; z=cK%J;LZ#K@ch;J=Yo~}DZ9O+`Sqmzgp<=;DLwfD;)%sZGup%7Cf@yz^+sH;0Ra`+ z(TAbi)nAwHCrECO6*kh#{WjbihR+siJU&_OzDDRVdHJ>%NQRjfpM35LjG$h=@%!W= zaLk)s;&rWenMOSKg#P~hv&$5S3DCQo7gc5AyvVqe$Hrt1ohDWj74m-|?n$XnGCKA> zQ9tb^_sUn`G@v&|T8>5I0TG)_6H^qxge87K%wwseSfxDdX3-2bvJZm&yKU7 zpc3F@>6$)i+1zk&06uCqHmYM6ThvKZE`rg_+}p%Ve(ow1r!2LbK>L0Av}HR1yRbIG zE5U?1&%6oeUMaw@7K{Jsp?&imnb$|soX{Pc;Y8p|1Jipiek!)Akt)S!YJ5&#kZ8P- z^29?(f{uPj&&7`HW=v-FoNjwvbNO&1&c2aTEK8n?B}PGpk-@K1C5oz)Q^51A7n}Sm zNMRFi<`sDEMRQ0Lc?bnvX3O(|8ITLB!X&NGoJr4@@2}Dq(%7hdsQhMMH8V(C-^XMc z_%AhF_!9!!^59-oB9kDO!ooE;M<;E3#GbO=Hk7`E;@>PlwPqp!PkaK}sc}nb3>AJR zzonCHWg;nnZl_6k&Wh=Ef?w!s`b6Bl=IH?^^+QSqbYXT+%WMe%s7+>VXY9@AYXZ}1 zt_HNNN32=q4H-A5hu2yrZ69&JdBv7sUD8-Ok}UH<-m2wS9V=5oPOGskgV&999_F|Q z^8FrLwL{s#y{2Dy;()C5k>VA$`ZwB;?U6dtXPu*ia?#uz>UFe6+DtJG=&DUbMiV(Z ziXBTZ62dSTY8D|fpq|>thKkPbi@LAddM1pF0w$(wY^+)^LT<^)*!StsG=p=v@| z_W~#YCm}&&_zIb6JFtoQu)uF4>+>psa6NA4Jt-=#zg_yF(y&$q-0}y?iY>`Ro2hC5 z=`{v3V+`fWt(*Gh&BTP%ZxW`M^1-7y4uXr`*7mIs0AR@W{6(9%50XJj3&>l?Vs2qB z}(K8R|{D&cz%YOz&L^Mb+Tk!a59fRg`bHQbq1prt5Hh|(V$WYI0uV!F8ca}v#F`YXLu3(cG6u-{Y&%Ac7sW_o?1@) z%kzC_TT;jQI^2VM6Wf{mLX#Yl;0qs*f}p|ech(WXjkq>Dc`kf(6tdQ#D3GD#TUDyz z37>VY*9^5!UW$|Z$RWaxbD=4zaEiM3;HI%}+TjK%Px-qFMsAkc(o!xCj=kRy&4z}C z+smWwVvjXtp3-+Mwl%G#gBMMEXO$NuPGdS&pE1{;mo`f}5Pa_3Y-BQt2TGpa`JjF} zGiC=8<)BoQtLm8YJ<5JbRnmM1{LKL{ByzJMrp?E=UD!J;_LKeI0Db*%y=^M)Ozn`^ z7KL6Z&@CEzvr(?lM#RfAJruH^&AeDTrx$3>2xj4^ScKV@ zTuT0gT;8NFFn2@9kJ%SLgYU)2!wY7FG9xn|acv(3gc;~+BW1{^ay+HG3l)ZiT&7Y9 z<}Zr#Z$veb^h2dAv)L3edPh`@{G+W`IK7c5v#`aP{>;a#(N`+z1NHAkkXj9$Jx{PB z6Z&=mcw5KW9dtg&esv?CO+1jwSEKm(Ya+?G8Z~U|M5@`rmzmCfn?)~Ij!C9<8&A%f zLIGLTIQJ8M*rZx8EAfd1J$9+nz|{{a5nM_Hgo2MML}!I}Q|@v6KWh6(D3MOE07)`N zvn?%x<}+L$v)~*@9@XnYt`Ftgl@8P5T(farQ-I|HC8yr$ zFOj3>+vpZ=KHkjY($Y?WWDpppv+sX|H>Rx2&g~6J%|W1fr!W0)wtk%P0<}_~yqsDLdtqC? z#wP^;B$?sqOgTkj-7Cek@CtT{c^rS&Vh4e2PR?^JYaJaN+`(WG*X`k+nQ~ON{@IMQ zN{g9O^Mw5}8uu=MnXO)ht!I%I=Sbwtu3-aZj8}?b7JE3^UYv|V#hAl`9ag0IxRz8i zavSrCauaMYt|7m zC02&0bH$a1qMO@bJe#KY^}6OAQ8>$j)Hf+}%qwM{6u+#tRo6e~3{Gg|)fnxk>Y zlqM;RmheZY&v_{|=746@>gFoMN6QO&Mc6LgA`&Es)b-EeeRTtTx1>jht>UD0*;&qO>3!jr62PCLx z=?FaAMU9vGt|l&xCk_%)2n?*=mLW{I)c^IOH6vW|{b+qVWb2VVaW zdj)y@`jd#n-Epy|$;y;G-F*geTX>c*sgOb%)LR~jK}BU*C=oFd9~!kiBF->NxjfqRu`MpMNi%cpCXMQ@l9QG2e(~oeP zb4qQ&wRA=LMV4(7R{6AEPkXn9qL!*h!7!xA07Lue$^nWSopHP*3Dh0 zrKfbgSwwXleFz({oc?ErWE&dQt7g!uWe7IiQ{T88y}v;}K|qEq3%Zw>!3Sv<3}15El^e)%mpG zj4yMK#c;7IqwmN=>1+%Du%0ie1*91E-gQ#Mm=9$dg$!K-fRO<1quNBTD*~Y-&yHB# z;U|$bj#MYir19u5gc4Fh<2lG=J6R{@@n~rx6H6BMtBbnYH*wHTBK)()#+UOJwubgo zNXD+ajkZ5+Tu+wI$2;q*2?Tya4RA60+3YjykI(8i;i!`zyj@N$b|TGG0L6e9o zAS+Z_17T%vcM$nGwma;-e~ta|M)N<#kk~+BYoE2&4|MrUEt^}BFj05M zN^|J{@~!aH?b5pN$Nd)}@^CcF;U}G?>*<${eA|t4iTmWQ5q`NrNS1sXJy6>*(Rk=; zD8Vr`hdTWQ92%{zzJJ|Lw^It%pUL*e19125jvl(O3Qs-o7#XS9P4U^XQ`Bg?8u2-c zx3oUw|5VVlmdPS-0!tNcO)iau;v58dpav*Y`q^B1UAs!ek9Ol8;$!$B^{|cTI~p*u zs~8+TfW%wY%53cE|KN~$f-BW+mAdA~>QNGs52-{;K_)RLzJ>)&36f*4>a`P>$=7T# z*CugM08hQG7jmaIA77|uO;Ek+Ol};u;fN2aQIxX?@BVa205E-%1Fk0Y%z}G)F`)&? z#lHN3B$Ox4QXFl{po!m7MS}#OeTLYAdEz61|Ma{vxzUaZO%`Kc(Zd1?i zy@V*VUTqyyL`2LdlR2Bx{`$qa8e9vkNDq6*S$b-A@7ic>E@ct zv2FiBzN2bZB^K}9x3`KPh>W$D3KNW;RYwRBu5M#|#L1yu)6-$*sl$4W89s{1Kzy>B z_v;K^l%_+tGt#|vbA7uu!B?QVt)E)@Yq|N{YCdHAQsQAJCiBqYj~A_N_u#MJrz}Qb z8C0Y1|0#|i{y*Q0q@Dj<^lujM-&frK_q20bUClz&QSXZL_Ipw^Y~NFDb;G^oVQ-!X zxf@;L|9AXtc#XN@j1aO?Ej?v`N`khWEMsu$<$S7`hOJ!>h zgcHcie>OX|O=vDrGIk&hBqGWqmSS0*P!8GJ(-tUY9Q_dugP&b?7h9=j4A;CgKrQs# zfz|V+c)+g;f37!aK5R|&V%lmRM0kl`;2#%m)4d2punAE$L4hnsnHzi39@d9!X# z>D8;DiS9?5HmjPfUwSbs$^>W&8rsau=)y?e-6ZWej>r}<`}vE~JIbPk#sX2dsd;N9 zHmKwM=LoTK_0_%vKhWWB*~aVfq68VAtPgt3U3h{y0qGRg0DpO6o8R)ZakTDcOsr%w ztjBg`A`_#|+47IYWqSfQ3W!yt+)Q{MV6|?cDX(k-<31%*<>mKX=(#?&J`@z{X1jUW z2#d^o9Vx<*QM-x_xLR5M1{dt$85*2Rah%R(xZGFro>fb81-bLSM;UbR2 z90O@xPqW_`@Mw3QXE!kwj4WDt)f8L$N24JDx}hbmj){K>{&+?Mt3v1sDjhxceWlxI{W|5?G7;>jOh^U}jcenc$xsXeZU&H6sMkj4G($IFlU?i!3iQLtZ?sDDzu{W?nWXT#=| ziG*Hil;J;A5%!ky#7d`-X+vUM`)FL7X)6dSA&&jhNe%!YH*2Wo63gQAIG3Y1Y+%?$Sc7 zUmnV+k+(I*{eoHSlr;!CJ;Pl(U)WuKW~B0ignz*gzUgmWLyqURL?Jdht1S%g3i+X> zMk(#Emh`gIzr@%NUZWj4JD$ozUPFPlRHy+SQcI~zq4uFOE87gtD(c&Pa&q~Y)(xaY zz%gEB*p_;vB9JIX;j_s{%{4iWew9U^(_bNGRIv@xwSx=pIF8w~Hvc1<7%5VW=OITA z2vDX9o39ir5Y!kwxk>ocoLTZ4p10d45{H@0UAG=GsXKLnH{KdLQBGu_Z#TyiJehu* z_VMQ{3&HVYp}kN}f2SwnI`A2-QunJc+VjunvOlJXkN}THL2;%ZnTTZ-idh;IV+?16 zxR7-m>|SExIHFs%%;pvQeSSJ+*Q$2?xx28AWV^87p>(rry=|G^pvf0=Wa%y_D71RA z>Zv&KLZfEN!kmZ!l~3S+yqn3P?HJr`i%NKkK%BF=eLT^TURn&~T(9P zx20>?s*>$;fh8m*A&N6YD6o}zl5$2)G<0}iaiG3BA;BcAb^8UQ=jUdM2_>q0gqstly{6*Xm@t2PT<%nF7sBF-8oU*aG zrEu+CY%=n#tax?eqD|VKCoyW_kWhSNZbn?%edK=LH}D3zAm`L@^k?9XEQqgWGj1VQ zQFk1qWcjwYw0+!gTpH+ggXiC!RUaKki4c?ef0Hd5k!hLW*T|yi4T`PYPUcgnSpF;h zBw!#h-zJPGMab3Xhmo!doBiJOrXm z1tvYvl$SS!mh9feDxanAQ4P-;S2RRcEtp-|hq;n<2#f?#*)A9@h>eUD)Ra~rghB8V zXEnRB5wXEE?U{+$Fq6rxn*B1!KPM8(E0emlPB<;l-Gn2fK*RjTRS< z>|b+27Br-d?q2~iD+)MxM0S}rpWIL#wQS{qY;8wvk6~S*T`pTgxFV_JB;w>tDnK4mDQ+}MB+A=qiZ3gXq(n@#7d^}PWl9- z;IgzcdDzwOE52j=;MdiqRCH7gnH+wnjIZEUNAvxpVfilz2;w<-8mgND>G(fIh(`>W zb{nY9L6V$g>Ks1mv4GyQGg6cxZ-_X5@Uz$Z#c`z51ODm|2-DXU)ITvkmn15e&M z4P~bgLuFf8dJsJ27iH<9HKf`4BV&}~PMn*P3KfK#D_h?;Z9IbIH=g@$*ydM8DQdo` z_X3iz<7Go4QL>%Gv0<}!2OM|Gk}qGIEt4C!6?-r(YBMHt!7+ZGp_QzEREM+(7=!Hi z-yQ9O_Brv2X@%uB&SVd?*d#97WW40dvd046B!q72Sei0MQibcgG({!Sj&L##8wYf4 z1;Q{8dvAEH)n?nq7A>{J%l*tr}ckSp$V5+FAztr-bre>4%NDfDy zdy{mrGx&&Y%c@L?7*Fk!ZyuEd)DGiVv47a4wE698xX-5MLPj1Vkmnh9B4j!Th49na z67WTIpFc?AWLwEmo^t{FUw*r#5I>C58}+cxPxjJeMS{@HaAA?Z8K2Q}<-#U9+bp0M z=KF@9{khb~C(@35+G)E7oV&X?@MV_DyLVmr{o~6klZK-tJ3Hj&Ti9zJA^({1FG|tL zQZ_&X1N{#UZ4+eiwsDrg2;cb1ro%_#{hztC!pHm8(lA z1o>@q-J{ndCI8BadTHZc*fb^EZU&oYPlXIYiB97bSP-o4Dcl48QO(%>ZH~YKC|3ZC z?PEtR(9m%A%}V2Dp(!*9DIfjCAdUO{od#x?x{vZGI;k6_R12~c#ko0nYzZf$^bn2u zd%@Q;{2SFRgc*2`i;JtA*nB)Ba`a$!wD{%AmaU!LN!RhQQ?u8K)JUTn^k{#da>XfD zYjeL>aiP`T)3*KQL$NP{R>Ij+gvzy()^G%gt=byAAjxkn`V(wT8r<~)lVOu9iSL8% zeo}8{{_#QC>YE$Qu$zRe?%Y9RIM1soPAsB@7OUx}rj#6`qJ2{^v1chCnV`j02_pz1 zqI7bh^J zx&>pX8lIkWuI^UQghj@yC?vO9UI%A8O3xa)vT2`IRvM4l3%dmKB0yqv*0#AWQ&PMA zQJyg4*;5&T-P@XS>-BB>E)4irubTS-gTW#QxaQ>?)srt3`Cd0Un_Y}deMj%}R-N9+ zhi4k6iKKF*fRem@b$;%5SO_nFIPJ)}3K<^DVwVkDpCc`nsRE^( z&Kn@1#(s6$W7msjC6zzfSmkQeUH+vZE9M>2o~{;a(|Y5m?wp|G0{lu%#4O-Ns2cl< zUt#ferGX3cAUH~d_{E(@O8!A;ZGR!;Q@f&TmB<9&SKT)guCKWq_AJdQu%GPBviNdT!(|!5g*d)hc)Rp8HNXCr zB(7A`A@g@RuLi60rLf)8gZBz#u354VaZ*i1i@PuByHP3v^K&MD9KaJ^KFWa65@d-D zp_!pSXa-9Mz7rz5QfOy$A|9?zGQ-q)alx8U@i{t4OLyu`3hzdons_HqjPgi1IN zNl3<|-dmnlNiT!#XPDC!d=AouovwqWVv^zzh zD5rrv2Y*c+6Y*d3l0nRz5kRt($=R&IQ2r8HMzZ1i1IYS2GU#aBPJt=hXPOa@$_o06 z!sYiHF=M!_SuX-GmJ7xL!2A%eMvXm~*d9L;)N;yyY*;#T&zTb`-?9VCyFV?aSX1{x zNGo$=Giz6MvzDJB&)bX42nnc_^Mm5}@?Q{F6cWPl*Y&AA6RgtMf%_$;M1U*WYg@#^3)Z`ihsbf-{v=Z{&LMAmbZN$ zG%tu?gYOSBWkWYJ#nBywdE>feq1#`3ME=6Z2kBxq!Ev)i#Y;t?s9TFQy`<*7dn~4$ z8Bff%g@B|9znkC87$T3nsl7xng@1l8;Gdi#v1jwu(j)Kr{$jp4Z}@id(}dm4GnmBV z;UxG3n`eAtqVspx^QSoI5(@v&Nck3=G!#20O3wLJ4pDb-@^93(JFV~+`G_ZMN9JAO7ne1T z-uZFLNftFJPHm+KKTpLG5CV=W(hTw>{1j>3HwP=XUL)=QrTZ^U7Clg?kN=^NUvj)R zy*qgi2I$>JhJEsjcLe<6wyQKM5cKF2V4*~~ySD$^9l9HNyC~0jK5t!R{^|G|w>~!SOF)WoFdc77Wn0+86u=@`j zYpz}(ROwf()ZPD7X!0KE2DyKY^KWqwJ(9Z?APHXt$(EZrSgd_IzVOYDW_?C>) z86j|Wc|B|-ewjX|QZyG96Nx3`dCNEmOp>M+vJ(BpwYbK!C^=%kkA*hj010uhvA5nw z$0kB`FzMgkpK|ihp->M`%q(4BYdCsK^9XeeCS89QQ!K2h^HxbZUCVs}B9zmG%zov@I7fiaKNqjuxI8ANr`dM@g-Y+cR&7?~oJ92jHjycRn$UlsX5L$vQFIP3UzDTb*^g0|dCO|;{ zQ!ksPeI_uaBj^GnD$l!y2 z9@D=SSJ_FghCY3?7oHi@0P*&Ce?+r6mBVpN{ZU19*Mk5lsA4y2-VSv8lXnRvdonHg z4FA+($@zLv{>0Vg$l8y`wkeUHpVmNwW4#wN;w|BgL1hv1%QzZgqbjkY+&vczl;c_Q5~C7ri^H+7B`o7q8k93s0JZ-}p9|q%YTtiMj~? z_Z0HKQZTisrvIHnIyT=-oS0=C93)0RePA=$@*@-!zgkJDY8@+hxvCak31>qjfR|58 zlK&SP^B=nY&0h573_tn$in@8$xoIbDte_+iM*^r7t1zheqg9=w>8&-X3*+w*!qulT zVqH}@04!Bi5n$pzzj->CSb@lYx9 z3TzSo&#|v@X>5{qZ-1%OTd5pZsUDeTFUYY^%Wl55jMw=|gWto02YdiR+?Z%t4B+Rv zrvS4Mm(xC;E2x15{v_k%3DiR`1oUN<`Tw{(>%S@&wNIlU2ofUQpp-Nc3rXqj1_33c zq`RfNTe?e1y1S)W^rE}FV;*$7_davZ%zNIM_njZ+KUkkN_j^ASsx&`hOGgUT zd+o88_dYUCCtxYgKG~(a$AI1Nh#b~6+6c#i%C4Y+6&Pt8q?S1t=J?=byls%Z%YOZc zyy*A|wZx2QonwOR@DIv~5i8^PzaV4-#L3Cg5Ec#TEg5D;DDVFEM)u6?vxn(EEN%0A zcyo@Ov1JbFkXIu1K#v0n*J~0kd)4u7m4y8~qYQv|sw}O}Rc#-J9FhBkWZudTw2OX{ zk7eq76e3J7HDD1y*u_K}w4>tCJ8DSX2+YPqVx9JBT&1I|=1chb_ojLhHs*67({*XC zPnw~j)xIrTHv>p^%aA( zl8*RXa&u5jXC56ueYsW)L0CAVc{V6b0_w*nyYBej=X9qr=a~q9H;_QYvaoNaN&rCJ zFVr~oI;p_qO%1HFAMU23FY(e%kP8igN;Pa$`Qa5TC0#$-N`|!d)!t zdc*wBTW!V9@`qvJ@g&@)M|&WmuG5bCQGt6tjH~-Ahqm>Tc2_D`cJeu3ar@kLN1ege z^V%3?L_)Bg#;50|jP(=t`hA=9bzVev>Mq20cl$rKTGu_Gpo;oNjvdCdU-%1J4|J5gGDA%Wr0{h7|1R+t@^{#pbJ5n#&#zlwF*pIT zWsU6ZlJgRiGHuMo21b_t5f#{xRSO+6x>SsEx{A8ar@oFYuUL7DHjukD>e7F@jjWgT z1x`gT?#dDXJS{jQJgyAwGU$J(s5sW32ZzLdcXUYpEZ;acE+rRUW@G1Wx`Fxc!A{Af zYed(V27%s8j z6>|E_uAw}9dxz9HgJvR;(yTp!Qs zQ{`)u*I2k?$H>c+9D^?F%=y>+ia~i(i-%M~>e|TqY-;i*%##YvHAm1|*rJdzONc5%JAL-8OL?;S;?k zYf|70b;o9)yv1GpPx`4V;JnuQmXF-AS->x2*}=9e@#6Ugy?*UH*MwDG(L}7brt2iF z3Bq!YY)~{x&7xxcVUk%bC~5Ok*=M4Gj?hkKw5)H@*#fqT=fWhLAx0R z)AYf>)ayA`4bXX#5;$Ig=1S+$-vr8oEP_?De1l2|Yr5HJL;cb!2DMUqM|)*Og`S>X z5}OSb2xNDEcWaMf=DeAOQJ`EnUR5#WYUiRkp8VK!dJFN8>jy<~G*&m#<5CrY!UI9k z$E1UU%Fo&MvuXv={!%D`=W3kJ&tX$*Y^5)rSjl|D9{0BLaOqyt(VGT&10w-ss|;Br zM7F-Hd|emNwj)bpP)?g6sKALufu*GQ{ggP&oAd?~A}+3OfVVu1!GfepYG6#G!P918 zWHJf02k-qWC3%c8XchSw~6Ry*ivl&A`z*%I4)k=+hjt|3CNTo<3z z2Y|-M#^}__H^lNFdqerN5U1YD_<|9yHu(=)o1KIExR0Gj-kc~?(<{hurCci5>E}J| zc@_|;M^#D5E3j|_68({Jq?M4AFWX@vqyY5?6LGqJj;wlyFl%-jklMsHilni9x8W0< zCmnE%iqhg3%ax5CW?bg3#(AApfA zf_~`|B9`Uln6X3K_}e8C7cx`j+5K`~6|`P|58427Vo{e??H^~|%at$RaRAyx-Gk z>w-F_Auy}o3_Uc^T2hZFJz3h~Zqco6#uL3AYTCN8e&oXTPMBgCT9_@?6qqP`;^OY) zq8|Ka0k|Wzk4}7sYm19injiClNTJC;_VN5A(qiut|{8)ntjEYlb zQxcs34|U#u&rE{#rpe541iG-m0zjk?gO_Gog~0I~D_Fk?=1x-HpJ1OZ_b-2^CB)q3 zC%+^-E71Xa_0mdfW8e8fn4|*D!D$&XqYT~~xU;S_UlR_Gy&V$#K62Yx@_iJmZ! z-C3GQc3qfuv&fB()xcn=z6t*{*F|!nJPJ8B>V}e5s|&B4=srxhIZxLcofQrl_*5Q7 zd48|_(S99I-g-xaV<-4gr?0@X%?&(xi&yOPyiSO|Iv{4+#Irk=(bMKeOX%D67F!{;t!Z_=>uHtG98q7v6rk%+pJFNcH58%=dizPpUg*nxK{#Jd}k@-NR1d^3e>Pa_jnVz4nt(dk&}H{( zrkqs!*qO#m&|F79tK$fsHKlL7uj%dU40biN8~7VIhTAM{>r3!V1`lhEh~C#9Y0<1F z+(&lMt{UJopWqA(h_!(!|B8^CV|Lxbr*jT)2zQ1bmPDvfLzhKoU#fJ5&-Dn5JL3G= z9DT7YS325_kjR(K-`9LydOYeXkJzODzX3W+cu?{vqYRxpM$j3Rsbi^gt7Oo-MS0~A zqVLyY3w8;xI~Wz28GlM-2U(CQ$;f%aTL+wT`6lg4M%R>f%BIQNO_LRDwG&)l0`-#%mhtST?yTBx=pvrbM4K)6iOlC%%c-gRiJ!ws6^7WgMf^3%Q)XyTpTC!!R^bZCqrmqn=*pM`!J4vx7;%q?+9DZdI*j>Jj+7ws$lCs#>^l*8H2V-iD>+%3i9hFH|b6izC~%Ge0>IQzJ7SzR#mz#LvV_StaS}HH#U6mYZfPqBL_V9rQ}i?iC>#4 zsp0bpHC!2qj#oymQD96JPcpv_++NG1eNRCJx#nGM7Rq>Yet`PYg}0Ns%Y8+tsP6btcLn%kFa%k1_u9X=bzrY;W=M2;+vqYkvQEY=wPB13Ug)9yC zc|_Y`8`>D?hXXtjgjni-ll z-50}*jAB{Zw^vp9`S}MiIw?fgqbYajXn1WO7$nGjaTUiXZ1+W@i=vUIbdzC>mo>7i zYqpa$q`6pB02u*CPCopl^c)W)8n8RxjlcxYopMK;dmF6Q)~_M>c`wZO*DIb5s^ zUxQY~r9Y%;LxVY{=X_TRW(VSlnoZx*Lw&LO6|DRMFu!}6>xC7I?2OG_2@cv8veRsj zga&G&&a?|DbLP`C7yC5*Pn0fO7sGgAZZJYkoftt4JNz>|9Jt$4gaM)J00f>oSMWG-jJ7Aq~twNnnfkOwyd4P2QYlDO|d%x8RLu zaDv-#*fBuR0oj%Sqj?oFZgkKZsC^Wi>16-Dxa`u3WLxJg_&d*U^2vifRz?$Z0~Vz} z`7q6uv%H_xo+V^uh465^h8ME>bx%a?xvo<-1W>*Sc5xOPK!O?+9wR=WkIsiOjD;^n z1IT@?dW8wuk!M2}gxO`Y=GIXm0&bjL>YZKIf|G{X=1W}V~Es~Ez%>?H*184hFj@4PS^V4 z-Vfs?Pne%-9S>WMmP6zWBN-D_bNji&2kjGY^`IZia~;8UurSEKA?q^!1(9Amo~RF{ zn>^yg%I5gQu;liRMQ4tJC8uK!-02UL{X0<+J4=zl$Q1j6nSIjTpF<3OdXq%x^RwY2 zMN^RVN&Y9;5CzRW7tOuyw}u>sSa`D`%5`p*5EtdweM9_J)~=Ob9)6e={{lw~xVJ;g z-uJs?^=o^_F!+g?L2a>4RY2856X-AfG=UkXIHrdVOj$%RAh8yl)2V^=FKk2GK4HZBsA8+8r}#uS z2R~HpPv^L^^6%xfKf546HIpI1QjR6Wni8uz!*uq5T~!-=%c5 zlOxT$RBr2@qPOh50xw$#?Kb+f_vl8YHt7&Q%%-P8Bcaer13~q*Z{j@(Kl}o$4qR?` zstJGt%IRb4>XZ2V?(TwSsQDq;9<(}AdE$IGrFAPzd;eZYsI%3(`;umQ>wbS8R5qJe z7yR>X>KR-4y=8ZDoAwV0bl#vwX`W{Y@#nWTw;7~T87nXzdRyY-H1)ozI!hpjiU&{` zbUS0LZ$9ioOf9{~;Vd!kMfjOnZGK+4(lL1aEHJ6TW2Itj+xgN!aAvrG`uXk?>)geG z%5gbno7e2q613}$o(4Rnu9vru6kp34!Ky{st>^X*hR-{ft6J!b@7b=L8*ihu&)=I- zs~y$=7uELn6KBGTIDwa_{$3XtAQsc|@3SlY6!h=eDoGr=fg;wQICauqHtuk7>RDSN zgw@VNcQ?H3*89g(qqeDr_|}%H#T=71yf>vc0b_t}KOmM<&! z$%5He7p^4hp*K(;!ql_Wc=#!k-*p@RAn0e4eK{*-+|Dy-(0@tA!4}|K{@sYHmPn}Z zJ1p1agDcu<`rwM5zICL0ae5|q{+h_&cHxWAi4vyR9Rb4kic!#uTN8K$?YXH|Twik7 zG=)dguJA0GCqyHikRncjoH+6y8Khbyn|QQ zx;_frcdVOmWO66${?idn#j6!0D;V8ct!4IC_%T4wOhhL3;uvUx_g~Y04IYD~oAXe3 zYguu6?V=&XiK%0+t%mjR3KFq85+f8*mL41u)l_wbfwn0&T;Q-V^uGOj1&=oJH1~Ru zhU;T=T>*IuG>;dBPZ`ZxD_)bmOppynAd^mG#XhinCH7u>8OiMp*l%!EJRa`h43Afr z_f7}WpFI>tQEbp_KF3p%Vo$UKJ*K=RtF!rJ>Q2a3B}q{eJ>h!uYz*S3fO$~Q)*(8lOFOZ z>z!=kAWy>^u<6-#$CJ#FboHv?!cSW^OE0dv)O6pZ#m@0xNiok6J%N+qdGen5e(@t* zT}F*`#<+8N4Z2Ac7`E+5$ln6^&THVZV7F1w<3KnP%EejDmr;9@Pa}vVoi2l)iYMdB zB$jM?{Y)CmX1~|wJ0mmD8U&53w2ft3Wj#r_c(jpGR?Ue_@uh9`uo_=VF2Z`*r^*1a z6R)`GaL!3{Iy;-Z5cdA_X9G^Vz1flsQAyq+zNlJf2h&9*oVPcS{{&yP7xt1S<^Hxl zc>l-eIzn0_C2wfM<8#HPBVqcE^bB8FQ+%;1aO;;*$V&Ccno`s(gyA)JSRW;_+Mppm zl4#iCcs>l%>Hw;EgW#bvtmM}HOSy4$M1QrSqQ@vcR$?V4aqHFflaq+RH`f!NJ%(;euC{y}mcMpJEa{_nf zl21CaW`LtseVW|T*3?qrAfPr3)^w;@&i946G>N^qv zKb>rU0LbDDZ;VKxzkY{AYhZ(W)klxolBxMKN^Y;*Lr01+<8r?uNLc~h;P?W^XV<9S zt2MdWIH))Mc+3_cvBP+)npwzs^#N*!Tj=Qix!E6d_fWa`{=qjTw~d9ESJj;VH#687 zi+iy`r_YqX5v-FT5L>4FV}|Wdty*m7-qXj)UC6Dyfr)n-} zEDS2mXu8KTnyj7vgX30*oCW0pH4VxCoG0cQF^kY7i+D$loE$tNsC>PvC zMtP02vgIqXc?%CbVAk4W?kpi3VTmdWK2Ll$sj zqG)4#C#_)sdKc;pw7Fu94-J**_B`9KKi=ax+w1SPFRHA>G($u|=_O~6Iy%l{g+MO$r zs}S*4d{@;TP_R%^^f54JaJ4WfLvN@?p`HHF(C3KAfF}4g0V%g=_>Qs(y&{CaCU}gY zJoO!Ov}jg)k3@diTwr)590mvQ0S++P{LnzAPe~v8WcA^77g=j*-T`VpSrT=tkwST4^|!+vrjtqo;mml|sNV zg4ITH;g&2!5r{g0QjtI%#>q1V@pMgM6|=5!S0TwWil|BMLt{NawSswP@MFuwY-h|OVM}8!&rNB z;l6T8`eOJup^yF!W#vPSN2w83GKpV%_qrYTfzObGkaipS$eJIH74OB!9`jJq*j>pf zwbFA(W7OIkc=k*_E$TvCGOnMc^h?qmlrEaY^Oq+U+^0&cc)_#>e?=rBjO^UZM!P#m59K{Q9^1KI zEGp+TwibtSUvW@;LF2KZvJ7K&I}drx_w{SD70nZJj1EfzdNRRGWpwrIx)CY_h0lih zW6J6@RSEZUC{Lpm>v;dDN63j)f^=h7thkI9zg$mMh8}jJkS)+zz4bE4M|E)~6qMQ~ zlElRIzlqvdE&$^1JlAmJ1{>L$xIf<#SKs33YIvt3rLpEOPJGu;*Gl7s87b(?Bi9m8 zO6e&eA&oaPb-L~+Yw1mFqgbVMoyynumN>aJDCmCcDAcA}as{pe(X13uM@xa8DM5wC zQomXO3D=4mGNeC?7C{fvB}zA;&co7t`ixIdSvIt17)4CeOA~!T9oeoDF$E?t#vNHT z8GA63{L_%lEc{S69@#Tloi33_SNYSsecG768&d9e(uJ)>q{V_Dblwu=s03&kauDac z%k_E46`kv%cWrHL+$1)v&dJwY@2mDbt|xYG?IofmusJQQAf;7@H_*J;=nhABP{n`O zP)P?E96UDdOX2=_1Ha3UIz5dJH;S6)zYXx$eDAX~yZ_Z_%<;vy6yoveJItpsJittw zNp881#ypZg9W=t2H#dBiSTC^>3v3Vhor~|@G}r&8%AwKVw2qpkvzyA}^9!1Oh)U(S zAC#2fP(A3NvR*@AVc~J$Ta&iNB*IZ@L@gvbczuZCF7?5?4}L-&bkS05n7tT6Wt( zZl3FZVOUjnH^*pT% zcT)>5efPVxoK%%an4y2R%PB_UAuD0c4aX=j88f5EHD8G)rfs-YuwB!B+uFx~e|W(I zvZBlNrKQo0t7t@`)r_3oiyw6c76srB5B6(<*=tL4n!Is;-cH`uz2kUQFh@g@n2e$| zvdE0hMLeL$5W9QQc1{jg_3j=Y_=W>#^;_<993-q2P@Tshs~HwvN2}Qd4-CsT@{lJN zzoskaU@dn_RNh~K&+c#|m@ugwo&Duy-Het-!k`rOb6 zPgA$iW;JyY--C6_We^-Ewfre^CejS{j++CL(4kNCi?S0 zG{yA)y;~`J%oO!Esb$Z`JVYF=MP<;Jse zKY;@NK~Ic7UCX1v`@8?8)f(re3*3l)1YFZsb}3=0T|5U*zlJ2n)hQFZI{0#j#Ma@`u{xh_?^PxM4tUJa zYy)}b9*aS7T=#ekb)AKe;nv8@^|pfrwIeH~)OO_?K9@cEE62q0Um5%Q3Hh+4mSBsA z_RemuIyw{89I8Q0azubC4?VuoD9O1Ay6%ScshfDJC!vdX*F)?aHp*aQXE1mxtK|R$ z`Z{4l;hD_O)MM+)3-%Hl-e@K#U+4?#Q&{3A-w1ok->aT?EETB>0>4aXXx4z)@!-Zq z(?eL8autZ#pCve)YTeC%tK)%Cy_tG*diAGY7oci= zhH0EqK*zhu1D(mNEDv5%AZ~qm{2l5Ki^x_?ECv^f5NAKM@#46~kB>$*H@|TR+nux8 zu>5?B1=V`4I;X!;Y5=-6K}^C^;qvV2a>zR)%Hak`a4iquRkSIrczg9ID;_=llj`Ewr)Llb=ov>cck~QV0Z0OHUKw3!7W2$ zwsFIDJ89UItHQX~j>ag>Cz5$1#7A@XU72IgncFP*zye&C)_dgB0@|vLqPn(PD)ebN zHw3#7zMd(YdWhqrIPP%$`|X~!OjJKE4tBgh4wxoz@P0q*p1R}v1XHoNGbgdQFmo_k zxrl_rw;lRzPy;uy77O6gxJd^I3_N||5g`-Bj(C;IcQ_NVcjGoW%HPwD-)nE)HHH5n zu?ASh_Vfy7?PnW(g*BE(stSeCm@ehxseVLM*Hz33a=Y+_9lVYkz%QT`gyLkwPk;#| zc77^ArRew~Shb1;_a(zzi)t}*tgVBjeQt5FvehPkN|>+^wG=UA`0D1pEl`$G2nm9} zXJUK{ap~R<*dq|VsJOCJ!^4QJ%aHFEuCN_f`YKWAXk+q0h7|nWEO)E`FD`v$(QJe9 zj^r<^Ylh=S)bp(O>9Q-F9_RUc2Zy&wLRxX9B`21zaS7=4PLDXJvYit^{Gx&b0%M0hng;6n06gf{;kUq&TN^|dm&#J_s zt70iXtI*mrcvEtz;2Sk}mL4)ryuXsyHb2aK7dE@^K9Fb`cl(Vpd?m7W?3n- z()J0>v19Yq6jsHJgR#;e&~|OHX zHchUcomFaHx8^F_RLyUh*6Dq2%2G~z>asHR@DfCtXr^Zl7J;Y&PP& z?Fr$VLZSHDJ724qfd66(w9}x8-#1W^22=h{NaKS! z(qSbncwO&G?q5DHo`DhQy{{@phN(QX=gnu=k1=kfQeSA-pFo*Qwe9(p*2sHpoXi2$ z^?PhZSp8aI?Ih7!rt^+clB`Knr5|<1G340X3_r2G=BU@Zt<|hd_xj2Pw$HZOdbv3M zd9bNlMa?Z?@>PrWAzJ(eYi3QXl(f95zVu3Uw}6m*k^2^h2{E{alzKQ;hvMBa>2K{R zVZpD5yr#e5iWSmFt*Ke6E%;vIv%0#vlG3=pe2%4+)%pH>sPbWFtfpG2BiP7AJz>{w zVqI_d^+I;x!1H7m{g{qE{VT?=~)@n z5$q1!!^K;HM`gd&1M^gF(sqz?q3-6W+Iw#bvW!!wH2uJkX8{eZ$%qY(t-F=G7338X zlm&qkYSZK`;t8YnHchS#LKl4huz8SxIyGR+L8{MIR(7HC7HYz}l^vPy>nNe`;H)l7 z>Wb>is)OxFgou>qZ(%z*0BEV=4u5ub<@Lkw3QUGc@x89W9pu8|cBZvq3iHe7T+)!G zkG^=CX*);Ut>3BM=o1Q#r9W5Oe{(|VX0f`Prla5y6+Jej1(M1K6)5Et?Fzzr)^@jx zo-R?8JvT)#tvK<^hRd3MHuRSab@mkgU^SvIP)p^Tf)boLn=cB%-Gb+NU9b?4rv!}M zZ+Uqd;e^3PPjCi`bVU^L?f@<~|CjXg`*j zcW*7!O-w@VvWi%`shP(h^x)B5MGbk+P<7Wjl882xtobfrzY5YcxARJO}@6rIN_jTp6v}V;o9X1Q5moDn#S#g+X zM>qp&EqRmE^C)?$8Xi?tz+Enx@A%XUq-FQMR%HQAP@*L0XwthnK5tgciZ*s&#IN2s$_M>zDbPDacWB6)RL(%#80#< z*_DerLF#&zF8QQt-=trVbVvbKUP~}Zg`Ohl!EW?0ujjKSFN&=8J`kd`bvvcbk0iKW zX36jCLCY1}AqFzAoid?M|CP%qb{t`?n5GnKbg0_5+cgl)Kval&$0|q8 zg0iv>&LX{0lLO}4R@xCB2PE0L8mZwg_{#&*rvkC+)S`nrguxi z-;>{6R4`3qnK~xhuSTsV(NQ5=^B=P9#DQogUmjjlTVrjt?0gsDih#KBh^IcOEoK9F zc4a|mbH%x(Cmube(Ad0r z$y}F`(S^`$E~+p*@x$i1qWwphf*}XbWiyH}f8BlJbp{_1iqUh_KFgw)>U$p>q`W0= zc}CD<##coDrE8nbE~?%o`e~eYv4mM@TE?CS96dYDZb~w*0#^ju`SF%?taWbSm7|k^ zweVfV?IaVc75Z_x-JYx(dCOIYMppeut1>>)K{jr1!)01FUIn-3F=NR~7Y~)-VAtgx zID_vs`59*dUseo%c6+N-tP`CCJGMmL8{|ye9zTr~73gZGj1D;6o(GJ}R`n1U*BxoM zD|v~}h@LGB@%Z^K^QCv@BB?YuthaEENmcOnsj~Vs&UYNQ@>+mI)Q_;Q0T1NRpL{HU z?@0vtuLQe;52sL2!k9ue<3idx5c^tPu=mcTa9y{_9k7T0G(~;JHC8;EZAqv#d~z5= zBH6qqTC(T*9@S)t?(i8k=j?L`9*6;34V=~p{j*{dR8ZO$wu7f@=d9WlJgTvlYy8j7 zCGjYakJbD?ELV2v`0Lh@sm4HVX^7sh%&_8U`oQ+egkhr=3mf*y=^9 z0}r(@fvY3gHKktky%Dl}?FZT?U&#hT~=-73JVr;j~QsI2{yLHl@9W(2@>i;$`lYlB=uVwJAxEqOUKTPA@BZcdP1?wz#wqlco=x zYdHKsTPUlI_@;2Z@ST8pJB=oOe}7q3T}E*Z+FK$YxQSP6!@||g)Ye7k?Nb#~q37j! zu;)Kxp%CC5AYMkx3@CN(99R2(Nfn}CZAX8@CzY2YKdPuTmd%-6d}U|V1Lwk}5i>A| z`Lo>MoEsjKp$#l{sy|qJ?X!%V&}F~Xp?e%2$yf6^z~aRMCH^!8Bp!l+N9-~1KX2=L>n@tv@YG4$rFU^+EmG+ zRoKbCCcwF#0;B}z6o?PMbBDPgT)1|)Sl6F|YxsM+=3R=gu`7)}W^M5Qk#LD}ig^BO zcTAPDSE2OfuSGO@@Gtgv<*ANrZc~ni4x}FeYgbx6bm+d3A5CfL6N>oJKQ%(6SbLSx z%Xa@IK6J3f=|56V9$SCB&0GMFK zE{2VzEpV|bPKPtWfLbX3@Pg)#kUNylTm$a z%G(LfRl{n+rSESP@T^+6ww~O^$>-eO$F7b;tE9EoqCVet|C{Z0_1>K2T-#qL5Ry?f zD6q{m5+ny^_3sKB2B&`^|MNgn#V;% zQ&3G7P@S0X{S!~RFr8n0%L$$fTlSCqk&Fpz$!)qU@t|DRDhq(@G;@}u?;0{Am7E_z z@!;csch147_xkNzP869>^!d$6vHxD>v+!dV{YGqmZ5VJalaaS_60j@@xipx;^OKS} zoWSa!&j#v^5-Qv9^0cs~yQ{5lLPwc)dlg-O-lN&sLRd2#o z}(J4Px;Si`Tm ztJzgU%A?=3E}Mi1CS-cvE7&d#$P(Q1Udkz`+vtmrl1JUApTaHehYmhYc?SGuy8lh{ zrtb}$2giSAk*-ZIi{ zHcmr^DC7ys&zU4h;GnfSw{hj*5NOOkGk6wCg#kW%`ASjp}05^23MR_wH;=HrVi6T+#st7+Q{z3>PI2lu-z>t4e}7gnS!oO z*nJU${XX+`l5ef=@}Zv!k4*#?nWld-CT8=J|X*{39HbZ1ZvMHEBMr5Gp+D zT;iUmGg??zN&Yvp7h7-r*=L@+^RwIyskJA0vIm48;;aB z(e!|OZ9D0NT~xaNn?lZNL8Bpbtd(`+LJ;-827_M_ZkEs)#Ur(HOKe8LV^Zf|$E;k5 z9_}$f#EC8G6mhroXCvn$1HQ*2u0f_0#F{0+K%Jl9@(Z8UPEv%pAR{<{02VKzV?Pl} zjWHH^&X2(wlZH(GLZb54n~VHxgYG2$VQ`j`BnLuFhXAohE|^$pc0+ zXj+>y*7U{p4jlm)7L27PCMK$?suWU5z5V@=CN~}cU1~WRc5EpYoSN8rgmcpyOFsgc z*!Wx!dXyC%~I zb0FHA@`TdMGoMH3d?+WJ0mKjmB-P{65OF+ZKfKtYdM9*TSB~-WN_VBL^w@v+w>@c& z=6*H9Mpf#t$#!l zmGHx|DhIZv>Yb|PU!L3hCr|Scd-QjvXpe0H^TeYc1O0gC?}z2^;Af@2O;mbDo6y9e)x>nwPL zADM_)AR?vQ4ypJJ@K{b@M}K!Vs=F3g*$y_1mG!lbNlTVl!Sk$tUhCpHJ);z~fol7g zM0Jq0i!%pNHF3(n`fn=lyeobLe)Sb7@3hSqA^`7cF8=h<#>SvuCSGZn0c33tXZ~}$y$3<8l+c5?43fS#{aN);_P3aRaw>m%I0U<&0fH+(3 z=YMWjQ9yH-rM|X|-4XY|!z4@Qrq=7!?g`Qdub=H*$QiB^dj!uo&79zhn;HRo&*TW^ zCR^Tnj2TbUsEeLPzho)eYPXz{a6QVeirmL9!ZMd}J&mvL?J$hrhGD@t>J2#RMbJa@ zpQbtz1B-w9=1luOFPAP{nQE0qjRMzKLO+DrB1)LS(SWG-$jRCeM~u^}o-Z$W7d)1K z&rkV@$rA7IvJMd$!3`C|%?mfH+X&(NqRyB2m=F*?`g8Yk@9t`-O@#0+ns$VD%bl-m zaJG^~o*1NHp&lj;05U==F7AIm0_+mQoinYiySeP3I+{_T-Z@o*&Hhq?={jk5{V4fv2 z6hE)zOHTUh`O#g+DKJp3yc9DEP{WZ{0nZV1Y$wVZm~ zU2ZWPJZ8v?BwEh3)S*ZPeZrJnW2}JREP!Hv+SCk@VJ*^YNLa)Use(D}3wArPIW%H^ zzi?8dtUAZiOw;|O;%>+aI{pmEX^3F#l)%l~vf-fygLIul?ojJ4gE>h9k5J@j~SXMqutK3n)9*(xy_T!EXshh;0gcU$05^n&Ac|2= zOZp`dT`|wAoI4NIM&=YZwGY|uS;k^L1k>X^CX%Q~tY zcB^B=vNS1M*!>^Tgc@p(B&5cR2-e4DyD7QR-g;9x)HE>K@K?kT7c-10`6HxcXzn7c zkfgG*d%bgS;v?+Ht$qI14~M^BF}FYGak&{~g*OXM4MgaxvsLKEp)E@LAL=~7njL)3 zgWl6{YszV8FzNM1NpoMKHwmPRf)qhy5il#yT^9EU94Pf{vfEqIn*UxADh1I1|D&XN zf^KUk2hZ^HIowz-39IIN6!YKZ}=#gB`h+$Z6l#e%7piPLYBSc1uQG>fYhQ`%(vKl<3~ka3_2&pbnoX zBP&ahMEHazQAFypx#evIr2m4QZBM^v8GanYdx4+k$GfRL8uP-awlzX4qj_pfyfOke_084j7r5#!nX-=%Za;Pc4wFuM z^yfjQMEnMpZfu_x>ao()De^)_X|7r1|C(mk-PYD6gc|-YHymwsTh06^zpS%Ee?Bq> zldSWaA&)X<+y3?ImksHYZy?c1vZ>nQ@>z}3+BJ}ySjTq;PSJRO%#accd>lJ-$@a@! zS5HY1kc9FFWkYpVA>^-!Ue!j2)<;~`fxf4Q&#+h*1buyJ?6sA;h)Hld@~dtnOw;w` zU5tg4*owz0lX(XH2q;f63$8MmE-g9WZ(Em9js6FFZyna=x@h}SfeO|_f#Pkk;>8^b zEpEl#-JRgHr9g3aNpW|V1b27W0KwfMoLR z#!rF9{PbO)p0r6hMg(Jb~Dq9>X z=%IEr_>I*>624eTF?A1@hg87QRd0kRcB-__W z`ip|NvvNQM8Y=4Ykt5e zzp|1b=4M1hh3XZ2E+^bGN15PuXXoDkB9R|OMw-cA<}RD>xHoK4lt9%o>!L!fwO?;C zr67wwiO7EWjVosUqv151RgkO(hD5%Nm^Sb}raU7F`-*lSV1GkYawzM`BuT|`DY3hF z11H&5c}&nmFwyjb+ut&SvSrpzh1%_*+ok84@EZ{%gvpdXqccuz+1OCW=0}D~vta}2 zs9VHvT092MGd2eIxt3U|uf z5`UCGy^>?|*V&$vx_>Cb4E*>%{!I#BNY_oYyX189o6`xIGenN@pDJ(wrBCWsEx3i0 zFP;)K;jy!{xMy$v?&+Ti|D=t@9lk6cdj}RbT`gFOcNd$n4o3{q?{+#SRqYJEQ@nU5 zCudb$ZkmKn<9gY`2>$Dzy3o-DnT8{9$+;xsKT#o8&*ljip?A^e>0Gs#28 zXa{c}lE%L-YHDpf_y2kx$n)r-e=6b`fDsy~(hg((Fz=#0&XH5wRhpey)sym3(bPxL z!7i)h9;(?*feH)F$QD4o95~RzvN5Xi51rk~EXg!CEW4q5JKw-@q8_5_`w6$LO&pjP zWW!h;!;;i=WO^OwL_60ImZ`Ahjr99*ug^H;vZ8HO`St{oz7S?{*-9LsGGg7M=R=-e zWek%Yb|5%de6r<$;A>g#kXXZc7gAFuLy0(FW2H>Vp)~*@qj}g`m4Dh=%yaB=l9(XD zM8rIzr1nnds6d&pIUmlXEMXO9&hjCb{sx%ikk3NYqXo zxqd`mzN!qo-&$9(67?<}Lg7+%t*&%sq$cGdG)->a+59(>_;~Hkzbo2Az?PDLSoa;L z2dC8PeL1}P5Cw!6#q5JB(?65o7oPe!N}X3v`aL`_w5{qEP6xIWlm-1rv1r7lS_`%b ztIAP*m6@o7h=|{28;c@}H&^^H3SLBqzfXC={IW!whF7Pg-VEo0#M7e~D8R;i^=I+s zy%!Y!0xchU^3N!E6?$hui_w%Sg8xGw{}}a8>9;u^iN5(S8TkK;xAT9T*8e{d;C`8B zmu{=4y4gNF900k!4UaN2v&zc@A*@QD&E|pslmx8cY|Z(k;+;Y($e(*sHleQ0v3~j zh3*jPqH41r$FeyBd}gDWfq~E0SXl}7Mht*(eQ{$+3kwD8v-Q6W{`^3Jw=TEm060f@ z7va?lszM!PWRyErK51>a7Jb*vGq-zmEL21k?sU7RWCM<6AP;wNzc+&RK}^i|+-vxygw2W*{RoSP@$DSe&VbO)TAYE-Vn=$6|yL)vF=s=-#(& z1%G7m1;FS2*BUi{ao#^aWm%j*Kc6eeb~vy!5-|c_Z{({oTw}z0^ql4%IA)GzjF=W^ zU*iP5=2Ky$rESntej67iUkTe5&`ITiLz4zs7xDKdy^N-|jgp=x9qFHB6-jR73|6`E zU0jPho%IOtHyJv3oiq!IOyHFW)GT|K$M_tKd2PXT_-i&wClG2e{J6x+cL*8rh&C<@ zdXn2gjujwA-d<9hXO|JPPHDsMy3$&P-t*}lB6VDC;DSoX_?(5G*Ih5ZVs1kwypYen zx+xrA(2BExLxJ;>{kGD|<&)p=HCc_dxA$Hm+#hkx9GL6dxv=nth>3UYsEDlR?BFh6 zk3wl6;a2`|XvdU54vl8)>=YuuL+c+Cf}Eu7ad!p*U|8^<#0i`AEjEqvmm<8O8#x7V zW$xQg-VGbxynK9!YOp%=QwYW93Oq6M^WMZ^&v%sM*@JKFC1@)d*xh@qLPTDZ>@OFp zbP2$D-@Qw(DLFV93KI_K$iM-Jh9EyV*9lakJ*%mjqhiQL_rVCO&rQ8jFnta0Y2zxZA64-Nn5i=d95Ap}q@Qg{m z#wWxxC2jw5vhLFI4ZK?dGQuQ+c(cJ(|I?8>HEAZD2s zd|PKbCkOj*fr&=jJc15B8q41$rqdxkWEc5ISeDiY~c({jGoDZs#@sOIi(1RZ+ zZ=@7|RKU&jQv)2V%jnd5@as5OPh}&L^U>SFCwL~GXZIdTDU(beWkp)j&Q$0@QfaMf z8QL&#%XdPpu6Mq*QVJ!5IdM!{8)^!dTtADnn=mAk8KyrG`N8QH`Nh#Y|2xsUc1i$@es!MyZx-Cm(Z7j$nt->8srJBs2 z=}O_$~u*$ zYpXw_?k&nevfhBKj7bTs7C_g{b*GVaCHoglox1N8R#Q72-+T6o@ z9}9k-KF|groNL*KRE(KdI^4FG`YiUZSw83|{({h0>wZ+U+BSERT&`4mb{7&?T>S;7 z*f{xRgTG`O%!-tl%az&bH~U#1L7Cg4mEBOpj=WM9r&f8@B|JgpFi2e`ZGIKkWxw-O z&hpjVNDY;3hTTdXmQ_;f=giy9;vzLsLqsIpQ+$yF$BmSKXochYAm~Nc(>Td z{!65#R!cK8*WqofQ@ab~2VU*tmc!wZ9Ybfi?Bwbx@99 zsGM45-Pgdi#apwN+94e=AtHu~Iz^UvQbEaBR3CfwX^a*4(ieQkc9Bir#vpYeidzuH zedq1r;e^gu|8u@m1rs2x#1R4opg-U@!@n+w!K2Ad9rD<2qWO1zRdybwj9EgCPkE1D z-|vH`IA?M3Z0r5z;g=T5b?`^UP0-{8n#A5C-gZw8II7IfM(}b^ISHfVJ zi+3kLFZf&)4*)hW3WRQi5V|;-d)$(0yDzjEWV*hLzZ=744A!dgK1eXziP~Revqbyg zkW5i>h9`r~9CS$E1N_yy8rz&n{S7j2@GzvSguVJCDJZ7%&^O|4X-gAvH!Vy{)9Z=E zTXcmkc<(MGMI32bSu3h{v zefgGZm=5pt#u(rLpB-g-0ccZf>57`&5zOPXE@9Bnv@H**?VkP!Z#G-$2gQvKFzu`4 zb3YCfMPWXGAZ%A~EdXDCb>4fZ=Iu73jdDBC&ywOS>j}G&%KQRHNU3#06%X5SvmK&| zsI>#jK<+#hgsA%r)ViG=!~Al?D1@Lr<%a7vO-ER7t-MH%jb)%^I6phv+fFwR2YY$( z@$t#>#jxKyU{MBp`@7)_-(XiO0{Ha{i?4P21w7O_XT9^v3AD^e;=Z;qVGGNkUISW` zs=g>Kyp6ZvfD3b2&$s{XB=5p1v<>QwVQ!e>l(EAk;e8(?fdGEdImEJaa5OYD5OX`4 zuI)~Jk2cyHl%6TKbS;-~p29#_R+*{_RjYWFXks@zES-uqL*QfYqIMK0M)W-+pHe%| z4tTdw$`sbgq29|D2vi&g3Z!!&$;(SX6V@x>tY_SR06#yR2!Dn^9@*n^EgP48EUw z`udRHz75=&(oqMaHQA0y*xK5s$((y*xu=Ov=0#xOAk_I>_5 zU1-!7n=NdgXS~AAx7CIhPxayDV7w8vEKC4VOcU~QvM!D!;<3%cxaMb0Yst~JpP8TO z0H5SwpCUL>b`+N5`s>HXltt%ZHjVrS8&bD!dlOFd^z_GaKos6)_g?HE6Q-cBR5>Re z#Z-Jwinpa%m*Y6(!4*FYvfnUcDS0`GtP|t&2t6VGr(#QJQoYEpO@>)Rm>}?R<%YP<=WcX5=Lyl^;&SHySqCfA%Q5p>-~LfnJQrj zS$lv>X=Y{m!D6e~%7O}*W^?&sD7zIcIQT4||3oRvy`A+N>=uuWoqd(%o-fYgKv?Zt z$Q!Fc(;vK3GHS}WzYvnD#p%9f!SZ4zGZx4b>FK+jmrakb)K+s^%_QYZbpbHVR-4qpm$^Lu1j&zWp~d(jL@;k+J@ zj-hG4GlYp`l;xM(>zi)UHmO-8Fj<^K1ZJ-Hd17Kzq$#m|T0Ul+gbt`)UuJQD8?n>q zqjar61>?1uPCQGA>oz@rM?A%>o#bdzfOYzxILr?DAgsM7rZM%!wVC8>F#JEvx}LG# zZq5?+QkAuZ^UizWJ>=;I`q2^{*Jn0LN=hsAUHk&)IRY?hN_G@c8ln=St2bu>3-0n+ z7FnOz|GQeOrMczqk7q4UFo?ZqAg;d`tGxn@>+3Cvj_K;0PT{&jV5gXT!{Dm{C0@Xy z`idUjXOjYms#lVm9b#`U`R334b_&_Z1VM?9a?pb*GqO96&GUrHoS}HaxtW!fQrb)| z2--aKPcTdE^%O45DFeZOz`NS&&adOY44}Bak(Az*+#d$7CTsQ(ibxwTQ#3-Bm`O_d`41UkOr+)cT zwjX%0U%j{4a@w%ecsv8uQPgViyU!4$-)HqXYQ&>H-_NHvznx72Ij9Q?>{uS%ADO?& z_b+Tes+f4^82ZZ3jLs6UQ6OYl1nJ)VU~?KV|C5ETYbf78q5Qq1?714d(%E`f1t%xz zj19s3K z`p;I~lI-ep4?Q_kv8Qo;f|x%83u3$%Z=0rybx7x#PZ76627}G4h4Jyzj<`C3Ax$Cz zW+q;`Xx*16j{@F8Av-%kNrl*?iK*dl0)PY!`)2~?Nr``2bHktx>JcypCHmz ziLBvtENju~8cr$&`GH{2;CW`zJ`p;|k`i2IMrV1yw@8ooJbZ1lo&r&!??jwY@{^t&Bq_1ze;UyZg%syPmYa63FbtJJhzvSqKtYIPpM#IVnT&*6MlK~ z0Q@A@Ozc0_quyIY11$pmO{yUio!9lK&_O@hz@MRU%M;rcO6ze(Oh?c3qH?$Jd;e(> zRe%)#J*%HsbX5T9;+~s(V!};)hZrUKkfw6&@Obw+Y5)-gOmUx<=PDy~Cm;kB>89Je zF#RusZUKEw5}3=gm!|vhlMqFKxQmi!hO%?oFwF*{E{v?5>8D$;3BL7a>2twn0i(~} zVjpd1wVs^iCn>+&8tH;wUnz{`rgAw6O^sUOpg^+(PNLsq{T+)mr`t%N=^Ubj^mXjJ zc>Y z2YqNB(^!aLPyQz#^t;jj=!4ck&P6c3YFQFo&MtFA-Rc|emAuwM2HPnOgaZCHk?w}h@5%d->(oidU7*$PeAc9pSj{RlL zx_@Z_?2LPA5waqWI|5zw<$g^+^TBa$(8@54re!_uy&kQY0+-JI9<;HxX6^NyvY(xY z^P#LoKjpyn*`GAC{99l@tG#y@hd#(K0jS2-}`sXZX zBb$Kr{Qc%D+6K^;l%X?yKM#G1@-rb02$|N^Z52qIlG1G^h3bB~XL5IS(-tJDbRXMiUq(^l z4gp`yc#gG_5~sx@qVf#yPqcZCPxyb>MzJBft@%*;`kp*^^4Qi@D}~r)CGWC-Y0$kZ zrG=>OHZBXEH>nx+G*m?9kv9}S3W`{>e1hU%Z|{={6o|{`pcgO&Y`G<1yfhjzeg@e( z&7qP`RFsqZmMr4A69Pj%C`mXu-#hO_Ng?=4FV#!_8So(L&c;aaur`2E!cZ{ z$fWW60gKxQkOoiEi~EO9gv1ZJcoC*uINEvA<*~sIF*RJRCv8X~+3xbme-df;x`X~E z(%#vwLE%Ydz^zW9KQHsu^;yO@t7Ly@v=_K==!TWA5&pe(w@~1L@$)E_NlR7ues#^# zLiOE1RRStG(L+x>OFhf8<-zJ+R=6m<>aO^*a4c7||S@=jNY9R*4Rt<1v%vqMKY8 zKYz012dqZ7>3*T^P0o+(@$TNv>!IqU!CX#6?TYAU-)nK2v-R8>yM8-o&Oq10drUp? z*&@#qy+8+Kzv4DmHN_%u>15rvELeY{lbLyNH5Rk~4gGQ&Ce8>1v);16k9WHk9}^;O z_JnNDVr4xx@;k6dLFuPb+F9yD8$qpzriEw1H_k>=;TNaY-JJqr?x#KQ&h1DXDZm7;F&z1rICrUap z4@$evt!z6dI9Pj;{p#h3Ts^^rlR;SV?&JWp_U*Xe{*H>Z+4nXqza~92_}}vV?#k^^ zN;Sp7ANB!XIvs{$;^M~4PJQuFB^l$=M~>u`5gqqdy;E}t-kW{(KEp8jLVDzc*_pjo z;%6FTC|+V17Da&T*j6adm569KxhRl=Ps4}e2IoXDspK{b#=;%^=+{((@Kiigg?LGc9hcHy!Ae2Mco)`uIU>oIm8WWvANUEkCfIP0bHZ@gh3Rhw z^qE4*`W9m~=c~4IBcE!7N02aXlt##vfZaAWM_44t-o3+XiXDuN*}jSpdf-2-lFF;u zE0cgvv0U0yALW06NM(#52vtKeI@UHe5v#$?ZVfh{r!%Vy zpceI{0ZyX11&tqfXhT*f@{2h-{J!{V^!3fUl<7rTdadL>dnS4e_!Cv7(o<4}uWq&P zc{-w|N#c*)ymIWKi9tmzUT@c?!HNP2nObr=;A6B>P>53Y@n&adP37U>^`>M)u6r)G zeY{@ht6{{x??AxXfqZqqv6<6ZfmpRK*8k`UaHJIA4lXF+jRL3` zlxW|re=Bs5xEZLm>@h$k7fS%`ovCmf42+#9K!;vNQm8cy<%Z1O@|BbbVELXu^nro9R)kX~F~7Qz3rx}*7c?dhc+*$=CA@#a7p}G8 z%Lp{*sxG2mVDZOL*OEsm{I)o-UY;>~h-J*1pVr=5V*C~;qw^i1>lU7n-kt2;Xw%It zw0S;eWC#^P*Rd=E%W{zPp8OnrY5G zAo!;xANQ#JdC2^R_J6lmwP@hHVdtd${FUvPvdPbbx5^gl$o4)T>2T#}J>(*hdQMJo z9uKUNQPAWB>XD^EhfGXGC(&xw=O@~4Tz0+VwIn5?b$R+n_7p!w*WsDG zP6nupq3>~$^b4_)kto9?^;nQ6Y|ucNzGlAr^Mky8Sh?6t=9F@3KTNp~BMk5Cf@P$a zQF(dp&M-xOOe9}YGS?t!Jdm;-!+A0d`{impbqk`2Km?VX$Jz>kSIx-J zKNiQvRuzOxUoUT7!&6BExJb44+Q?^JIeay(Qh#*P;D-dPM1xKAqT(nHneb06sL=== ze_z#42t>3$zvP5VW1ZyQP8sKzJA%qQ$n@ig`-NFEic^z^$H{TC$#f3~Ma-M6QH?hcZq z@`lN@q(vVws_&JNJlY*ZWl>3bI!IQ=FWP6FFLsa=r|$YP?5W2s$ukFcc%(AN08Cyf z?)}6(-Zc;KCDL+JA9_wU`P=7^@}WH9e9sp!*C_Du^yC0lou1rkZTq+{>a!L^<2o#>Kib}8&8}Mj?Q>`dY(x|M?!JK2KfxC ztX+k=qlWs+;MdO}R9r(66rzy9)RKDN;>wfkgf_d+s$z3h$LjlMi3}qOkVku-xYoq2 zzeQX`DqSp8LlImwSo5#Vsfe!I4PyYH=9520NHR=4yu5Isj#?v@URJqhe^$=~?L&4f zPC;yrLHJLrR zyB#Y3(E(tqm?nG_%(5arR=dlq_3UUKwq{X}{x!Lj&H6da+`1(PrCd zZ}Q=HPtT@^lWRyUF_$C(J1b==1-`|kal67${jXW4nQnXcVBICxU}XP3$lHvD zY7&OG2zdSeeq*7<7#YIp3)gyf{+K;!+~RCgP>F(3g*6t@ejuepg!RI!Nbs)DJ99-v zdaO#fDV&yr@vZ-lOy1*@_xSDDym0 zKKGWRNz>|}SzK^ritt|2Nkq_^J~(T_({@z&EAS+-^TDw9B|R;aua|y`kMvKTAWz}^ zq(yhgss8ayXjV}NFPHVfcTu5*JrdWVw8F9J-wg==Z^$cxc}l76ozqNA9o^L2&zuIa z-TwKzFQoLgTVo2wAa#oRQipA|kMky?YK<=76#&LV=?MV5xe1hdDkT3LU67EDUF_|f z@Q2mH6e)wogzD^7t6BYoGCyEXc2d9f`_ENlq!vB8cy)-s8SVCsn;1ETdX+#<{RKfU z#g{iRLNw8jC9u^K$53y*sp1xGH0i8{ps-%mK?-Q{?Vvax@Z=_C$?mBd;Hx5mSoNbD zE6vJ%QM(bJtO$SrtEc9VBA2E*!1>`ku|g$g^5$}C{f3m0NK(e_#IDXfUZzJCLp2$O^*^0`A;^6NMAnDcMX zwWc}VA#DPtWg9McAD9g{51Ncgy)OBJrdHvMFv0^$rb^r1db!N-1*n`|j@-TW)v+u?oh$slZ9(?r&;+Bos7+yK;c@v8ml_7F~r9 z+~88)$7OSPyItMjedIU|E)vB6RB#kNDEyx06?a$5XI=}nE}!%3#NfP1SZoa;;!lri za$C}(1KC$S@GeJkV_5-@O5RjV9)@mVc7-J+@`h@L(ai#@%o|3W68fE&fn04s885rC zP^}Vpal3~$je+-5bIDWq>>$i#d!9lTb)>esa9M{=xPm1)vh{#O!b|_#cC!Zlj81X4 z?h-!Ce@cdPnT+zVofIFc8PwU0Dy9W=O7{e0SqOWE$1JEn##EPi{ z<#pT8jrM4_@j7*n5sKgQHz2tJ%HowpoS~oHdEG6jhOO=YfXBHU$JI%PyjV!l1x?x) zliu!kG)cXjr4N10<)~V;?l}JRU=RF&tW(5R!)o+LDEuR^l6cPP9f#Sj>@%cm;`1)^ zf)yXpP5~CXOW2Lfz9k^F`J;9JbQuN328CoS36FDd$jo_9HDVuK7#xu7K%rB^!^0^! zG3&)kza+&h7R|mDU>B~_Z|jzqqZ z%H#cl&858_PUmgd8ub_nhH>NGakp?{wYX^0lfMUhpLc8W)BYAxIv}HUaL^4 z(!)hiXyER9!NBKdPadfvKU$x9PsP3{jmvIq7!FgFZv6}ppxc|#I_?0Eri3h^BDqnK zCV0FT6_^p+uA#+%;f?HVNF)}6VS&II0EU$ci=){Y(y*(~AYVr{MPK|2F0UnSy8m&EZ~He(#|(h2`*o8 zfQ$rs@z5549vH4usy36hsDv){bFZO>5^dtC#^O<>0hKoY(Rpc2cAJHrR3)?Sg} z4<0Xkaj2VxZFJ*9e77AS{uGXinDZ7|_OmSfH+$9TfCZnBrKd>OQJuhZF3}m^d%;SIuSheAXy)cP zv#&TFe)Y<@l5LpRuD(iYf;W-gd9}Yd>rR7wfB4{46?27yXO~gP!%0p#b4aF7c#4uQ?hGOx9S{l7?OUG*1``tC zii4!;U=2Pw0MgQ@jFQ679(=tVpX7mCoG4r@W(COw-^{e*iJ;++U7fJo;5f6puFj`n zulr-Fo)^M~>>nb@)vr~;Z<=q?lE;Upmef?*zEhk@BzuRGzsX&Z@WfdHkRCmIBmcB{ z>Z{g}0o;1v?u}vd*C$@AA)pd_PX3XmrYZAUDpMM*Uk)bVxs$U&9?@VT7Qwb`FZbK& zm3NToXJu`o^BpLd_!lXxz@H7Ww4^li0FZl5i@MkOH&Q+#<~Pyk`mXu9M7q&1=;b559Wk9fc|B>i)96&e-*&AF}CI+qx>SA3RYp z(!Kn3L*nsM8sxHatD@tvxE&_7R{CCAlb4W=N6CC%VR+kSQ0y!|V!Mo-xAWvh!KUdM z)q8e^m2*8nX^SUv!=S26&2<9+?jx?ZvSNAIH{^i8q^ra5Z%0l=7d-jlH#+dbl7hA+ z+OKy-M+Zufn>(hbNFZG9mWO|c*K!}xKm76T=fj8p_uc=FZSb8jK*R8OHpN}jxmY65 zF)V19VQwG)LfM>k0gD5S9x+>~bYKPWtV`jkDUt}-cv{?7wTtSs?VbuTyJ0S>JaL`l zIsd)Omfgw6kqQ)+)Hzh>*T@#5xo)oLumwq}CNhgOQ`3(PwL_z5W0?Qg(J$CozghR` z_4M_u_%?SZNwIJHWF{IGQNfOlVH>-=Q5}}6zAfErN(YP*%e&XevW!fpJqME~)~!d) zbqvgToEC$PU8ATjzyH}+jRy~E>A~%#lnWm{%q~TgTQPD<}h((mi_Nvl0lLS}NkU5tnd(!EQTHOHjl(os|pzzui z@nxx_j6s|%)XEePmqj;DMiw%@nzig|jP>-WjX}3}+C`ClT-EB;xRPGy*Zp*#)N)7> z8{OR|Yj9zW?W7J`AwfXZp3^Te*+G>%4X8}SBs^2wIh!x6QQlr_ZM+I1O##wYhKI;_ z?vU=g=MNA9y}d$|Qg~_ElnDDI!f|x%ZqWRdEe-wojs z0nBNd-IiY{H&l1A09ud3&grOV7eR>~DKY)f0?^_8~^Tx`RvM5vf*|b}!1xQ<5SJc8H7S$69Uo9T{;tzo$_ZDa^ZCua49y+Ba0To6EDMcuY+`Q{{hARw*ytv!C z-DB%^f&0YLhEt3#mH{mY_aO_k$ce?b+k8ml@Kh+OJ_8~c#Y;<}#z`{$){2^S!?1+o z<&xk`ZFiK)fz)|%;X0-LOM-<$JcTL)>ruNu4mB%Btgl%|W(6wQxk(eR?U{`Vtw%Hh zdS-&~3|SWiX+nS%`ZN90#wm1m_DXc_6q~6o@7!Cy2R|H2Zj1ty2ehIkGux@DC(0mF zaSDajR|1)l7{`5QKZhCAYk1XWJWghuDF(F?e)YtIKFm25$?XyYLZ z@C{Mlv8mEye61Gwe3>sC#R}P>N_Hp!=Fl(sG5d_2{F5VIfl}(#)~;h&D0MV~akvG8 zeK|Yn658y54QU>k-{;CNEnoLM+i_q%QD_qwx zMw>~SeleZoGP#3*ILkpJGig~Dv;O4rA9!ll6q0({+G%xVAq;VctNq0!#A8~cmuhCI zr#p-Jj@5F`L*^TU;^0XtRAF;5w)8FmO2u0^Pei!Yf?-Fo7ECk7jaI_sf@0#tXurlDi@wmHUk6I{@`-(ZIj4P zVVjB)EV@4JpAT)4N|;%@+fSA#vS$oeFdvtW!xAf2cE?c6lYns9(`APq+x&2j<#6F3 z#=LTN)lV<)NTnY!DV6-_syy_I&pYGGE-FWLqjF0JrGVW@DE9CDu=()`TXXV8KtgI` z7oPE85|E-&da$R5#g%}m4=Yvd=imTCMCVZQdR`3{Ng69pUy6r=1KNhuz9?vcryiHC@AOl=Cox3Cr>NibeMPVQ`xzLu zg}kvf92Hac5!h{$yOmK@#w2zSYvXl9i3yI3~j$ zwQom=T1=~`kMAb2qyJ&`^3$w9I$YGG2|aaS>b^vo8%voDg<@MTTL3{`i^Jt>j?9uU zCt{WI_R6}RHL;1h0`sEl;C`7o)RPUN3N~TW0y>4fnB;Fo9P&lZo`M!$ZzMDyw^OMJZ{IuOfFA&{#>k$eQ7~#&Y12) zY#>x>ZrM{Zs{|YWjyrX26lekcV&5 znKV-X$GR0m@;b&xd+G0q7EY5xc*a(z8;nUzL#7jT3K7wI2D1zAW20BGv9)lD8|Q1w z#*q4x%5nKqCd@P2^eP&Bo>D3GaHd<=d=LF%-pDj%Jx&OkgMQdB#N#h}p9Xo{54D-! zT^KC)@Z<-EZ<;@3P|_Z|)|&ezajMvTg6p8rL2jdemcMV9Bd+M4u^O^!xcyiwedon8 zwT-7U0C;CG)OSQgZ$#Oq$KRsGH+Wv1^NPq)XU=JV&N_=ZuK>-`?^Fe?D7H;wps;*8 zMs`M1XrS7pk@_Yq;Rr4kg!Aq&eLb~~o@)zViw(!Q)V_RY&2m6O$?$PP?>ohPPjj|y z2QH^V&CWb*#nE|YQG-XO4b)5XUS{k(B!$SXAzhDR@XwIXKQB}X*k4hSQ2pMv!)fP_ zN?C=rdaBkcXOeu8Qk6{c6H&<4BNn4P3kD|N(M?;j)1nf#YPkO3{hl(#0W_y);XvoH zG$xd_S4ppRrRV44(=}7HPgBX7#NJ92i?I)Y77dKvy3f)XE!xbGELxf$@ev07AX6#P zEIf8!I5w_1Ennqt^r~(Eg9g}hV^YgE6j_#LxhnREn6thN)-={mGXA9nZ1U^kf%^^3 z8o70AT=y@H-5c!a4s1)&9lay67qDIexjB?_xDxAXeS%H zr~SrwpVFgLiexOjM7d{9e7SF!D@OWJr(`*m3gr`bzSP+u;WE4-imlDAwRyzu{+%gF zfAovo}Cxg+|o~TK8xKnSD-r z+{;5ZU;kV{=e0Nu8PghBs8*xxLI)C-3F?Ok*2{!fWHeK4-sZZFiWmX4X(8 zoL705m@GvDReyy+6(>2Xg+&$RShYoj_qMLXu4i%e{o$g2KTi_IyTuu|n|D#ltWD3G z=Zad3BYWpi+ZZT(QLur_MSvOtjma^IOd)~M0Rb8Z#=L&R@-KxFrjLu{MGl`86MnsF z6LC<($BDmEWuux$A!;d5Dn{x{3i0Q$R9rYZ(uG{@)CP}r{5b~T5WaaZ-Qs>@K^clT ztWp82sriyd^bIAEy-6a|S4mjC66HE|0u34tB9z(uD^`rVAZn#rf0q&Wf~a*zVxmRW zF&aaA=B!HpdTMitPLsq6_L#>^#rzv81SqR50tzb&-8! zTJRx@47BX>d#`-8m_%F}tZ;24WyF6pZsAI;j*Bx=Hq6G&qB@k@(@!$PH+RGDQ0TyJGtNbiB}5ZdU)_L3FD_NDOrC$`A}>7idlSQ{i0Jo|Q@kCPa2 zog55pEfzLTSe8W<*heZEUI2MMktvQWVzENEK(hV%F=fQ#6QWc(t|am8Ndq!Cv@c|0 z%1y2BPPS5whqDWz2Ser;85j=Wo>aQH2&t6t_fAVlmdy3_b>&YLRP*vzv0X0G4A^iI zdFWO`!~A~|a+CaCsb%+xJA-f+hi@Y%?L^kW3{100!tYiUMvW;O$U|3L?BkE0Ck{-V z_Up)$bB!n2H3iq;dOaCybWc4zZu#{E0 zoRLCa)K@f*f`H~ezC_GgY>KoR%sa{ztv*A8Olfce6el%kXp;8wJ3E);mAm&AR0o7} zN-uY2?cEni@%l9)A^g|TJ<_t0+drgh(N$f@WXJ162Rp5cr(daHS|9%)x2fOHeMEP$ zn|&VoBv3|df7#`*f51-Dh8pmD&0cOVGl@0Yom@APPho3up3OTIM5}RK;ff3O63JrL zoHw2&`HG?*ArnqPI~w+v4Nr>Hb9#Gv7$Kdekx@>m+^Plq4xWOTfc|z3DO~;;CExCj z!Q?#pIny99sT3YsK^Ma!+Hc(x^_Qlx<_#JwT9Hj$aN&zb)`kI18a4V-&fk<`q9cjs ze9k=%xmG-aH%)0C#E_Gw(frMjMY>-`!an7rLH2VDA9`{N=b5uYt( z=cEoAg}%a9I}!~NRucB$s&IXvSV~mk={}8hFuR;WE=Syq3tL}Z+2Rwyq9G%98_#V1 z#WPh3+;3yY(vtO?sIwa&^mvDLZ|9V*xs>X?4}G1_%m?{e*s>~eXkyl^7^JjPhi_dz zIGC?|HKkfQK4(5qh%gE;>my?JOk2>@Z5~6E?;~Dri8i9xz4k1zE~IdpAnDWwkM&;R z{Y;9}hK6=nt@4z|))pZu-$|Ym3m&~rbnL2h)A?<`uNMEW4fijxaak9WQiuUI_-sUj z7E0MWK#0e99;&>p42F-SUlv=SgCtoCm%t<>12i&w)7P&aSb3*`P2MHKwyEw!YYBdXv+qjO-nEKn6mfjo%wl+3v3k` zKXpX2b>4}zNQO8|#w@tWHzC1I#j6sZndM}j;@wo4`f_o8v+vy3By_e7oiw<)!`Q3x zSBbscTJi~cp9&y?oNo+`L5mvFjArKU%{0Lv11?vg-t_f86Uxt6zcryDy%yZ^c zZ%1dhYVfe-ne%=h)>0?3EFW;BQD#c6bR))0mVP?kq?#iXQbg&w@jZtm73gHKjYo`( zkBSR@Rev+N?pna517xyUB=FILxPdsJ)2Pzb`~E6ma`!t0ROU0^#k&GEIYWl{sfwjA z4x=IOV4N!crL`HfMQiH*o_N^i*p^>;v4BowRGEtbc;-xQ(VS_09p_xr>%b*r6wlBN zljPh}%5?^HBMXYVW@L5V>9pukzP(bZW%Xp^?`OMO2yHH&`wDub9F>=6 z#lNH{YV!VqwLHT*QUu$#FlQx6&UsDi6cs zw8v9HW0{~DhK`A^Q;{qOTc_XeMp$ruZ>*03YqG<{@>T3|*adRJ5_!6x>T9exb3!ki zC)+jL1dV8Ze+tR*>4RGL%>1>=y8SzUgBZzN~mUE;V>0kj$(PH3Us+1g3c_QxN8sR$u~Q4sowuvt%;J>dDqo^nu+={VG~pDkUI z?DuEBE@C|R(~9}|!Ns4(%CGO={BL-7DG+%~e$!MmLy92o$inon+;!CC${a-Zi2?bY z(#h>8l9K&TP%lE0IIlu^GG=r~7Wr~yy?D<2xo4WcSq_)NSVWDo+~0BlxW*gUmd3*$ zJR-RqVLb=;u3U!QjlKP3(*OnMSsuR68<2~(zdIqMyoh~8-Z6mnDkJf5ER7Z<4pmT z)OlQ;$l9a$Vb&kC_)jl)phBCjS5ML+dc~hzl((?p_JO~b_!o!-Pe>X1P{|SrR5sa; zPur1+gc$pXV&EnOg_-XMgf)@{q7wk{qEi@B(mi#z;Nk#;|YuRB7_mgtw~| zviXc!*FCbN7pO0ai9D~5{Q3F$1@5*Cc0IMM_DnSR3Esp|Y~J)b%acn434rz564miQ={fYHGffysWgw|HA? zB_`}A`YfaN?Xd$$lZkcTi=MDDm9OE3_EW*ALPs!x=Ym#IuVDybGxMz>v6a}0v95VgOt53A5s>;&> zH4k6`&J%2TE0BEt)ZM$T-mNP~zvKIyEfN+4K=`CFdmnf$nwJGnv>o;hF1!I1zq9ue#ShX@uk_+1mJ+ zOSK(F>^iYoe(=QfV3@s?A;H$B$o>k`sY&dW(YbC9(3%U`{g&SF5>_=GMafAeG8Gb( zPsq_|EjEp_-PFr?P4XU{)0X+y;oR4GSfsMT%{~bl7}D~l&M)XSZNTdtQaUQzyaN8N zIgB!u5G(k)0*|_M$Nv74^?O@0Ux_gGChhSY!;spd?bO04Ujz4t^i&Y55OT`Wkxz>S z?v47;7oAB1VF1~+PMK)W4&26hoewY(!TBCVTMlh4it=z5mI`^$q>86(zBdP8dW`lu z+vU*P=T+3x*{4tOTeZ{V5X1wvb@x8NZTbGF*><1x{{FuA9}EALhf>SVRA;>55&2kQ z$Uz&!jf!lzG~_zl8fRghW@Tyl%QoM&OWDx4wv4RP4~b%D=Ao><)}}|+9fAvw@{{>d zIV6@~i`AMUA)^SzFt2R;cg2C6@`Pz+K2`EdT*QbC{eRD zPQ>@HFB7=eCI=H^!1H!xOwx6JA3Cau$%#eo@IX?2jy_KZW{nUjJAGan!S`>&t{%4 zl{WAU*YrL?Yyh{^10_;mB3GXn z*0`HQOoX=lsDeZ8{0wWkDK#IDKg~1`ZBcN}ljtHH)QUXvB$A*U-hvAjnb~u+Et0nm z5c}Oq2}y^!Po|>)F%X^d1gsSkpZo3JSw7V7^`w)jSxUq_#M(Pm?D%l+57dowa%$>u&WTGK-BpUfQZMpsSfr z2}9b2=^8;XNvlsvDws3*{}+3271vhO^#9grp_CRaR$7V_FB+T{ifeJFxDzaRpej@3*abGVHcn&p z{u``VA72@y!=yY#YA@9FP3B|iJw>Xs2mNwc>tQo3+0siHhA%GHpVGn+C}*Xw&&K&S zEl3Oe@*0%Xo>A5e=Ul*gtzYwn+YUZ1it`YHMWqt!$rfJ%%mnossT)W~QzyW*)kpGV zH;gr&y@$VflTbUvF%RBLz51L@z4iS^;j&&#iu2efkRVawrlCefmBme1R6yg1i#xbz z$~b!mKD{#zSF~_^u2)Yz_E3>@^z6FwwTCesLlWiS*J0;=E6d(aRjx4S*8I-4uwvu( z5smY=025IF;&bJ`4vFK{YLP~nCaQ$;qm2x`Q_mBPG)|K7u;F?;@%#o|?YSYPtq)9; zS-)Os*Yk!@ny&p|ENN>_D3u0pwIi8W6~}s>Fm;LabuMg8;_y@AkntzRWhS_~Mluc@ zl+SEbylqE{_~dxo=BJ5|DmyTN(^Y-HZ2CV?@oKA&Nn zySovL#VyTOO*sqKiKSdag&GC$;3wUdLocx*G1ols4J=#XzNquZjOa)h?Ql$z3-Ox| zdBaD9^JdqCuqtdnGS4_aE8FTx36JbZp$ zcH@ENHlemqatESRSoICmpIqAKdykkj>SalSH2W8(kxez?%Jbp)M>8=p&6+asg<;Vp zbeZZkyXA>g`e*hvF7PV`{QRy@hMZD&oP~m)P9}!q@w47>-I!N zvr5wGF8OV9===TJ$9^wxV;Nc{uItcPVruN>FLta`;P;4s6$bBaw6=_4n_GTGw!IGD zlv&%CRl_a__BVWYZxT|%o9Q#_UCOZ-4tbwf@_H5f>zOGqmUO-x@+LnfG$zb|tRVHx z7jg52G^KMfBv$5kwLl*~0P{yPPgdSg@zr}$;z$-q5-m&FTzG5U_0&4(FHo4bfn z$|xM)K_FaJOJDNq5?+%7g0V+qDw<_s3z7z)%11RDf9e}Cgq!?pP?SK^#0-rK*&eF}_uJ$F{(3 zF!X=?@I*w?(Ddmrn-cYKK#eml?i~%6j2Mvw|DKhP+svmLM!1GpJe!_vo*s8hCK(x> zHLA6k(J=>3UIVHno0WnUP%6A2{RF&8tW+P362*=iSz#L{A2licKz3@YB9|B{Ef0CJMDLmYNBjIq2J)f!6q zIR7E*yNtC1Nw-<(Mh+IsjSeN zs2H#Rrs1^I-F$r1T$k^9w*V=waovfRdNiH!+0{?PL7mfBqI`KxAh(f%d39vm6d`Mh zN7iwdd%nZXq7SX?tD5HzFoO38A@5O?-k?m7#3xtB9J2J!clS+8&HtnA~Bi{B_UCMOW!a> zjv3EN>AO7ov$hw)gTt}t9LCHrodVlAf!eq?KzF=DvdNO>rR*TJiUV$JD#J-iDHh!z zCEf;sEQ~h;=TFfW@)zH4a(%w1BgQVn*evA~v!%%PlH|jGzxitN>(5KFiLOHTGc_)@ zxa!sqR)j36($3$X?^WpY`AFaJx+PHaG4)pNaHztpah1^)lcy2~4J^ChVE|I#5(-;i^!2*%Z{QLCumIOm)c_u zxXza=M(26+$ZpZ)_@3;n2TwZv!$=Qwv~)XLa=&=aav~%Jd4)cxzRK~?%2YlyZ7+%7 zyvu*90bWrvch?g_`!QbA+N}G(-yp^fv5FazqW;>Cqfvf@uaLR6Eo+@Ja9JtuVxA&; zRqR~;GsNrMWzU%rxtfoSqu#E|!e-Q4ECS5OO%>Mss--r-gSd9oa{n}T;er$Vcl86H znMAXUN@I7}TB~^;@aX_VHSUY2JlF1H?1&tPS1sXg znlhff7GoiV9(oH z%cHnq?`@PkHhhO8%YTwex;Ll|gC`Vl)FDslBGAwesmv?Cw$YKp79?du!oNWIEx z<0_k}Kgcav0ho@?%qOW+H2hG-@UyVWGJxLYek?+Hm<`^#eg3`6T`b!ywo#}_nOlh2 z49>;D%3HjbnvdUH{t>vN8^p#}HX*RXD7&*;Pj7(7Kg|nS5UNol%ouv2y4R$uMyjeV z7wnIzuiPsZC{sA=@$t-1I%&ZT! zUf;+ljzy4)mt) z8!}RF$rU0KP5D9n9P1H5PTWK(1f-_v#x2B}oMwzAP~kCVRp^pTybiR)T);H#9qPL0 zYo*Xz-mFaZ{FM{DD1%02`t?Gni8lEFN~mE%UTB_#L6TxH!>#qLtowGxNRl+++JBfS6Qs3vMIrs?Dq> zlE{D@h{wVPyra{HVQ=td_E#lW1^4J}$+AbL5UFmx8H6qAnxpRhbHaB{PHmRS_;>Rx6VFlFvl7{uKgRSZ${a}`%H zJ;U8_o%C1Gm=h4t?nga)ES>%yrBy^S4SQu*IsZw#3;lWA zF$Tl_p0=^0AGJ;rdo~=$2Ff)dMQ?EtH@izW1LwYrym0 zd9h#gJaaf_l>q=DOx1JU6l?cBRQ&|00)wPBUuf6+wtPHA>1OY zzLZ}YZem`x^GJ2x@hk5c;lP2muZdoAdx-|{8y3D)M`oh3nA!qx;^5-6qV}M)T)=Vn zw0>1z0t2DSXIX&q*SMjT(-w`b>Ae<7Bf6+8zj!+m>e^d^5m%2ucBc5IN~}~8IlTdw ztuc+77rjTWpofwo9r~R-!b%!y-dm@Wsa|aWW(8t(J2sATF`+I{&ee->94K-FkK{_+ z>Y+fR%`#I|WK~^mrSfKj)q<5IcxwFe_(}Ya8~=&kGqp9)fDEt=G(q8Af3XK)tK*-8 zJ9?v_GVwO8UIo^-QJf~2U|B$Yc2GmVfUW5;Xur;zfQ`o1pN27aprN2ggq2sdB}*?q zr*1@->@^X|&>yoZ4np+4nMnUzHHx@q~xd*TYZ)bQ+JVu>z?OnvtPE>z>{0 zv-s#Yo_5!>2E85!JI&Kw!R-)>w595F#ZX76)?AG)r zk8@LO&w%;29-gq5)pSP@?KfjU0s346Q1K6epeX{tn@ZBqMGPv`RW! z)`4yGLL|nBn&H7r!3Q%^&t48?3TRz=w9%_L#Y{l%GX{Q}lpz{~+e2KRpX+f$y)pbY zFTi8VcZpvyQTaE}mdkC+u)=!1@H9g1%v=_I+xbTdv$^@;UN7uBpnj^AxQQGgDDVq8pYiCoJNbns_Mtit zcvu=`sb{>CZQ>5kq6(K=!^^Q7qCdV`emFScs@2Iw=wRb8NHhLQ7>9q;B;ziowm>JE8{Qj_ZR!bZ@{aw zyMnOHAHvrH@=_U5EBSy;-*#c`XooILHOPM$0WI^38}#oNGT;OD%j1m0&1`jO+L7Yr zpGQe+MPocT;PVnqLv#@Z>^UiYfM1xUp#xS4NT zphzlKi<@=3QGlzvUZm9AAYffU> zj7d`;yzSJozyE20@n5piUG$#W-3Cy2SH-=_+j+O70ISsHk?jQms=awm47^+nb$AbS z7)JhT(%rr4`>__+gbFXk-R+2JxGd_iN_PkL%-=>}S_n1OV5M$^f*^yBk!g!NldfqP z5N`bB+{xf}!eLbp_149e>Ax9CZf-u~&lbOZgtlCBB0Y$8R=zLvJ-yyu2s3^o?H=vX zxK8d~6ud8S>T6{Fhs|(lu`K)-mv9B!8`SJCc>^p!_?DArq-mT=G69!X{^CndwpC0%|LC3fne(DB5a0h4dj!=XVdE2p(oz?ti-(lr9@2rr<>uuq)lwYwT5sH6FFXC9< zrR$~Yr0BIu`PF8q4w13zyhXV8aG%xW|NY#^Nho!FG(zO`=m>qJNM(GmV`VKedpvxv zfcY!Rn8&T#Zm{MU-SB-0Vib>?grZOClR3 z8~8Eaf}iM&ecdm83>>FG-6A-cv##3kBvIHIeMqw;)+ra* zsTfSo9mhn$%-K^x!G`;B$=x}N$+hiD9=9nH)lebwz%c0h~36G{(AGS zLW9Fod|%&t_uveo2#d4h4iRb!dX1j?fsViDclS<1dG7Oy#=K?&lErq?TTwrMq9Z^R z*TLpt4XTU=08?&G$y6p+?q3SbYe&YsS9z8>5Di=>?{wN8tDWdqbC^hRkARZ6bqMtF zB|G()?4~xB_etDH`AI-F(eGQ5Pj>(tiM?{BsiDni>KKj2<_|xr5Ty%eMU{^+*ZxjE z!hf$yWz0?MP4R4wQhhv1@5%v=@2_%a@nKRPU&f?CD!^X zb8Bw*DvZ#8&*E7l3BvBn2+rH}V1=RZ&$s{X#HG6Uez@EaZJi(y{KXwY-D?r^iG)W2t##LLp`Ax)~?Qx|x~D z>z)~APIt3P^;UH@NEFhDClT9;$L?cnwcsmAVT>7+uG4xdtIJB*rf+aQKkpz&HAWB+ z7Z)hQ8jE$6r0(=t9aExSab(RC$8C^sG{!Vdn9k3{P0Oy%N*K(S-k+j21SezR5MFym zd6i}y>ljXeUH{P)Y-VOBjrGIV_{6nd&a#@vJ(pDOa!fvWrC6nc zzfX}45YQ2}9!~iZ7uuIND3q#3UCf|;wcHo`D6G)oZk8qY=Pqs{<^H7gWHs)2!{b47 zUL*5*?1Viz1ls(!@SZpiOYTODnyqk&g*s=LsRewe5;qrY^Z7BsmHT~ z$cX2Sud!l(v&d*{2U zZ%+SM4j-~9y7Kh=?u2Bd=EqmkMZ(%?zqxh#>07LhN7IwiPj0wiPyU*!FjV|rc<31q zMK$3nX_)R0HAo-+N0Oot+qCaxIC%8L;M5fiI~nBp(l=aa5BbNTy_@tSRyX~*I2UUfDr zb*>awoM?^>mWEs0zi;`y;lmie=Z8%Z6F1w?D?0+}3R=Jku9&6xjeROBogdW1-M)K3 zF+$IIa6-wDog|r2lxrmx-*BpMP_s#RW0dj^?NK{CHgM74YZ@M~DG7m!u+I_I?)meP z&);4YRh`L<+b1?h%60fBi*U!n6&e?3c2Ug z0wtdb490a_uYN_rE_<_$RDBEk(T}l;Z)=fsPLh`|$L)Pq@*bO$&-LnFlb|@8MWk7@>D97^{n5o>UJ<_{=E{f_?^68Gui> zDv}+ND5I)3*{V9~dV&C33k#8rD<(C95<~;)gdDo>QC_mgc~EOER+q6fvHYU-F9GZt7oagfFtVQvomDcIr|Js=AXWYhK?dP-QM_^_^8@PL)!CKTO_*2kLHD1cy!T= z*&-CIUi9ganT&=J6&?-SmsMCIH>cm+dX69SYp`P*0GO`c-)Kn4a+5%fuHKqln5dm8 z-24f_b#6_9{V^z2_SdN8pU~u+qqG}7_)sq=nj)ihe(AI_SKq6jKY05MGk`n?#rycP zh94StS!e8QeX1(g`UNU+p=;*-?O1(tb$&~wVl!#Y4$|va0>T(d-y;ghA3)CRPPGQd z`C6z~?oqMNbG+YHjK_1p`x`5QP`&L1*7yzMZ89a6E$*a;&0NNQ{PErKX&Tq0m^J-e-O^cODrwG#Q& zX-`niwvM4~b=ix%;^bGe&Y?#8D)ru-4Gf;{9TJVV)+?`OP5T+rT4|=*r=+CQrKGr|Te@vmy###f&8aEH6J_j2ua3I4 z71!9((}f3B6cb`J>UK-w;QMnE6a}fAvKxh9(CaFWN`WH$*h1Bmej|scYf(3yr#4I0 z+c=amu1;E+!|q?~io$>JCFXo|I={wrJ4xXOA^BZ16A~0BvuI$*)=dYo$oTEAU*w-x`oUR`*OCQ;aAdH z^T59DH5*jFU13a!)QB77MPD-K=;Ui5*=|lg;{MR}T^L88Uv~IDcC_(R)BolI;yUtj zX%Rf3fHe~n(AT`_>X-A?4ohArxL@PNyiBS+VHbWhfnK1}m+L+fp)k|wTkrYNFFXLr z^z`!yE0jY)a$K~^TjqD7pvGAsClO&}fNf6E5AAejP2>8t%uuS8mxl)a{ zB!#9uOb(Hk51VAOnSPPgYn<&HN1F$2ljWNPWu93-Pvtt=^w#2&2@SwUI1($CVo~r- zqX2Givd{O1T{?D4*e85kW)0xDZ<7skuist=5*zZ@Ay)ZZtkzfk*6;DL{S2t!TO@ zW=BwsZY{?K)Iy5r7}a^{!wV=oqU+-TU)mJ$x5WKmE>Sc`Uxy_(X67>+qz}^5zz1%j zEqkqPIK8J|u>X=G328lYj|0(P;$QQrF^BZfkza`@?y(u<4+5_XVLwwIgs|4{gqQFo z4&}_$pas`T26;e^^LrmOIh()97ac5>Yo@H)<+8+79b25aTkFGWSv~-JCX>wz8c!$G73&aejM-gYyMa)11+u) zikmFGqu!~eH!S^4mZY<7Bm}y%Y@;-=El6X?&6Kd^mj?BXCN7f-Q=o;DlXJ{3YX&B` z1d@67san;(W1V{Pp7!Wjw30V zit&Z9LO9>>xBy|EoK#wJD}vRcF3+h)@|w!TA+ z^8<;tBs416o$vk=hB~*LyrzlwA!tY)`k*qgH@8wzRe>;9fQ}ZH3OvHVuWr_7x_ZSu zsows##w^4|jc18`lZ218pyZ$kgPx!VLM`8Knyt7eS542j<&`-63Wu=X8pcOc zAm&yM)VqT6rNxAlRuxtr=a+U4fWDssG4s(2CL)`ev=JsS>W98ecNL zi+rN6--Jm2J3jYH za7zdlNaR@}s|bOtAGHNJ!-r`lJVmHprAPB{PSZL(ceOQdYM8b-X5~B&%4K^iXb0NU zvDPTjT;DgEG8{n7!!Y|4nP2DL!lKzB2MSa}lX=rBYHIK=K<0HRkNz+|%3Q&0bCGWR zXzr-_qv4{QA|G{cJ6XhVy;;#d4cqCLr=tW`VjWPxpt#^3)|xq@m}>}?f62= zLaB9GM*z=xTtD)3qNtbkXNKtd?HUetb#4>Y`9z?9A##2hYZT zP$nYp&Vu=XO?jPnQ9VN+$o>vu(vd6eS73|rSyTs49PbOBkW{fYb4oVVjtnV|M zYY=9$tRLcL$xB1n#c?pvFHlQMC9YVK+6?M6qqU1N{1sf}_$Pf0r#Li9R7}@awNiT8 zwD!%33rak|0p(K3?DT`%`xcN8d7Va?INOg$g%`1_Z9BGcb4$e2%*^X`Bc;sjwA_Qy zD@wF^17K14`3GM+tX8s1I-;!$zB;|;F(abOeP-KJ@3&B*!%Zh^U=c?zF~=GIfZI1BKd zyZM16U1)2b^J^z?X=ZV$T5T_kSwvuvY$r*jRHrGtw|ju88rz3_PG0Py<>y)2N@VSf zAWL_>A72Qu10Q;VV+A!j`fpxO*>9Qec!Y)Xkk_*c56pf9)|PvWCo;Oa_A(;-FntSr zjw*y^NHj?v*#DRZbr z(6}4>R8I&t(talKB(RQlQ#rqEFhOC;M0We)4iNC_nhkU2p&|&&Wc`Q;c~Ng7N_C)y zxt2x%T;Xx%_-@ka*e|x)FE&?=*eo~CK+&GDS6)#=T4MlnFoTo>o!C|Hp%aTw;rfNy z-@pO-dov&1Tl&_XmC&8!rt}q)Z+>ggYoKLI$H#B<9BwVVGnNS7c)9F zlRlbv7!4Y`0iCaG&0-QGK(29p=e=2eCMxSr0nsiZiyuvxyCX}bob;T&iDYo;g%H{5 zmeXvg&)v-2V0;piO(*#s*f79ZElG)JfPp||1fM(tIG<8Ab;D&l8M+(svdqZJ+vHmZf-voNS=L$Lsi-_pAZjNt@`;G*z9r3%0iA#Q7k9KbC9tSZ2Ym-h+ zo|}fh=!C51uyyruBA8m-5bd#$#&7x_cAxbp);lCw6Z`jTX8)J#nww(dkmV#N5j?v- zOEXbPe0Q@YxdGi+B}zi3_8&Kl(=Z=b_)qsYIce=jZ)})up7f`k9mijXotT+#l3O2^ z)@IL6*gT0xoYA4I{EoW@rPG@~B7R3UzFVkbh5ewjX3tPFO{}4$nd{*(v)eu$h8v;hM7+(pE_C@?HtD*5+IzlwDZ;0Zq57$w zM#aNH-2}*_G#G#otURoc{ELm@ks$bhE6W>sLe060@#DrW2+WIv>WwGrzwVsM%pU}3 zk@*Pt+tdnQI>R%ky;-`uH5-OcnAS^n%jESlA8(QT^@FefihkWcC6E`gJSmPpLo=Te z{YMHv?E2Z?&oRY{k6wQNkHGyW!oR;|==?lz`zTeqMBO1n-EoQK!!{UL^#4Fc{^Dkf zxuW-;-22Y@zlg`CC-F-TzedsQHzo(xJ*fDD3sWR?^e@M6ACp1AjDameoySyOsl=ln z`zb|O=NG}iHw)p*^8fyW^Fmtm3FesMlV{GhYWtYT)#c-nlHU{L|2HOq`I_IjJG0!s zK?M7@N@13-g`*ow18{Q>ehi8yFLWEX6txkS-&tSI(_HySpztVn$T=q1Onx1d@J;Tv z)ic!uk`?0V70eqL)YN4D^r*lTyI1;PJ<=-x9y&~*N91Xr)h!>mo+*cwYf@2BJ=mOl zkmEWRb?guP^bx77vCW#^&)mpu@s)nUfL;)6>Qsi}mSw-2| zbEInK>Xp8|+*k0pxE1f15-5MEGHyE`5~cE6vw5+?J9BAOq(fwNtGAuo+212wsXGqq zz$KhqU*!D7c_BHzOAO#x7kZGXaz9W3O~t!)*ZwX@;Mv1d72%$AJIjNn1;?xSx)m&% zSBm6Ws@Q{dg)Fo{w$o&o03%~4TasN*x245dW+c5T8>{oJil=^s=@?fD;x343jVatl z^Hs*Ikdaa7Rc#wp+SlST3KTiGNO3adrlWE#Z}$PoUkjM~E`5za#O<*_Loq)B&|_2<^#`aJ=;3GG8V zA#e0%=@YCovfCyNFqpx5zP+uY=Csi;$V2M&-6C&Vd7KwqJZ(GD5jifmt3@;Tv!T>D+f*EBW|BS{gz|freJ<+EC4$OQykm``!lViJ+}Dl z_gd|KiT8hV0SYJkOui&Ay>CN9-8P;VP7;5&-F5fDZ1+y^Zu`(JqHr~uKith12SvB{ z=fWel0xC|g92b?=phBsG=P~JW2#>Svz`N^6kHCf}SGJII8|>ht0%)11?(n&2U@JlRL6;hT)`02L0HM?QIu|n03nrQ< zZA**fi1xO}6g;|x&H;=xss{SDtdP(#Jw9NaF1J{RnG5l3Z|Yn^T{sNu9|&ouL}mSZ z`fW23eOk7uZan)N=4Tg*SUXYSZr2+?yUED(5GX3Kac1XUv@U*)o_BZ}7kh=WzqCE= zwkC;4|FhDTK^5J_oho-0wHaUq0$s(YvAHVOqVXpDFChFqGXBW~DdOiR(HK0k0| z{_`U4%VysU~B06J&pfL0_Iyx;$tbedIIDVwcNoupC zTZU<6>%QsEWQz@BcW&o0!{GK!Xben93@+I);Rgj!*1kp zeeX0ES(pq_zy3-`#Ey|VMq$a;^L$q~jsj_u;xY}}D~hI`o_)F(yyrPHg;uw6cHY(z znC_$|7l9H>Tyx5|a_jV+ryf9Sw3kL95sf5*(RMXI-f2|c6{ULDrY z4=Qsf-!*$DD)e+(yUgfL@tPj5$- zTLYI7)Y+)-;LHk{clRTvsSyE>;c#&VCApSTyphMo!gU$~NPhUbPqvnkgaL@FQUQv6+XUb!!nCFABTLLx@YW&4XO- zNErCF)md!O3BkEhcCSGTc%74#wikV`zudd|RVFgoPI3EnX~um6P;xO)92RWD4&4*_ zeQUU)ch~sUuOpP+_qNi><9q$)_M-cr%&!_*gy#JSbdcfry7EGo`{(E#@v@1>_D zf4Lva|K)x(!$gz2Dg488kB-JJw?vhb2<6?M6pmEpd?AwTqNcTd^bd5p#|lsu_xq@b zHS2`D@77?j*>1O80XF(;mv~biWqN$aB zwI%b6jO;lVCrKz^D!?oQeyZmT7Zs~}Q`t&qWSJ7GeJ)za0i2IiFv88TS-?M>DZgxd zjlxYQEvp>$ez3`QaYA=zI5V(uq$Wtt=P>%L75mDWvMAd&Y3Ps8@0RQ~YS8C1;8bsL zUFGp__LYa%v>Mba*XN|H>3CHTl|$c^hy3$z{y98$aKSUKB8NSj<4uweQ5LP*#5Qnw z(QGbN!<^Alp20j^)uJpV=mv}NF z+x!}EzAp=5H8nL|^S-UuFY`emU8moYqeBcD1YHMoJE5|B-YEbx^YvFDzmJr+dFE4q zmAzvXjF~_E)lh}qy5BJ2jT^}CBcC#5k#o{9rkT7eC?nG&#o#HD|IggG=l=GDN_NUx zH8i0^G4sPDD3YaYv?06tRMGidK8Zx(WTab376&ps7Da`=fikja^ zI1rug@-yyb-!GoD5(>Ua--KQJczd|D= zB+ziX=P%CLU?e-%AIvgD9gJuHo|z9NVtn3?Wayr=$0H%Mb>U^C*ICH$X*|s_<5FyPO(!j%(eCWtRRHCiLbqf zIKXo$ciV}zUeB(K1Ig_caCw8tqrF6z^lo_W%S(-C+Ictl8@1>dFNdM#{o&_ zXl-EcgNI^RlJlfnRKjleCciOhrq|?YAszOn4<5YF-Zzmx8Y(D4E##$MtnH~Bg!B5; zRpw@Hn~1lG;mws5M$Z8zI01 z&yiAUO(OAJW8IYaoy8`Kre#f#CF{Q(+UvVpP&{*H8#)#udSC-3PBjEM<9&Re*PXqU z%GNE{ve%SN?e9(}KEnE59HOMg6&Ac{Vd@Q~-}I>1Hc)?dEiPs%$yxsE>K5yulfF$u zzu`3n^Jyuj4bZEXi_Mm!xtPp%6z+2ro&~?6P|f?Rl`F^%^V*M<5{0cI1L)B)OizdJB9#0@ zA8A4lECTW^M&Or&6AD@8H90z8iXuj~Bh7A%xiyBDZ(5v3n6~zsqtwOY+zBD$!!nzn zEI(z4jE^a^{W$fM*VL-O-(k96*XgoP)LgU>4*xjA+lI0#ViLffK3yhu4Y-iR^(gil zGERGEcTL=XF%Z97=3zV+4M>Vu>evxLcZ~;PdS*tTh|Yswh`0n&bil>aI1#~Y2#YCU)J&I=zt;~!HJf)(kQ)5{HcUF~&$ z&6WUPA2m@i1z0cALE^+sqAR+0<>HCEP-G^3I(Vs&`D32Tn0@PDK z2)^@LkKH=;KYVuN@IGfv5~pvEz7GKwd!b(+cmIOpz^S}?7F=JCT~HZJlPM~q*}gXB zCfd*Fr<1BHz~uL2kkc$ufwnq{RajpeS712|TK+CyjS(&0fRYDp^Kp4s7h{{TXs9wf`EzH2(PmFvqD zL)n))s=5`kfhOprk0`7;lW{IDWGXlDqkiV=O0&Hg%JhS8WzBatcTe!h1P!k*>`JqG zVsHNJ7b5o4KU#dMT`v1sia-^Ayrm$GlR1|(QB4!FJUFRYJV4;Fk-vstWhqf z_h>pMk8M9KDZur0c9_y|RcS7}kNMpQ?Z3SRnC(tQC;g~{n zUZT<5TwKn^v}%Z|d6tC36z8xx|QKM4r(Im922%9-jflB!6QI$YT#DU0? zpH!ED$Tjk7?N$aj)P*AQdL!cm%e59FuZNK@-}j~xMagB= zLPnf5%FIT6#DTyZsH}wxOBlH%j*l4sm(jWu8r~+H7lTYlOe-p3o(YeqiVw&${U0-EGW2W5K7oY!S6D z`ERK<4f6ZjV;0hnTQFJAnbg8JCE;OV{T_gw?eW}T5(9&Uv9Ynngh}f9;FsI zqDQ9LR$zqx?f$u}=l14=$SwWvyTZLxN4WSCD5HnYS=o&*@M&q(Zg=+>$y`e+Q~fU0 z_Tm#&$A`NVovuY|?KR8w0kRxTG96VusefADH(m93W9IX_a3*m49*Q^`#R>d)!@=#m zcGN2gc--EX&tNAo?%dXcRR1irFWK9AbDf{56XA1zb5@huwCp5U$9+}= zGbX>oHk0pP5DVMo&b&GuFnHK}2|zwakWmQNIJ^87QZx`gPY?I>YjR*l4S>;W@5EO7 zCFl9Pcs*|pe^B*#t#9?!?7X1ho$80)42kRtXQh0xXsMELwQ<9nCin@GO{zs?;BD8IgLzT4ArPqRxaBd2I(+XJ(? zt>TfHkd#eOS>y}5L1#Q_!tK)X(o_EE?}m-LcyDMJ>>&{cI+MQs*@1ZJg6<<=ltMjt zb4cXI8y!$Pf9uv8A5Kh-diHvQ#IY9G^@-{Z;pOWo-Mg`_`NZt5sm^S%mB4yG(twmi z&DB*E8CjmJ%jsD(;q{Hi*Vr+t|cffVu`wj0C}^_kI<@0#lzD@Zl1Hm%vY z04~tzujiZbn+dZ?ynI4+wWg2s<=?;G^r8-{&b3A8H|9e21jtyjZ}cU@!=0vFii&te z`SjJkv5^1f0>F15;K&{7>Dezua>l8UQVm4vHzcR~Nc5!lhV$`>_lZHCV!9oLPiMK| z?t)5x#~im&+jgi(6`)zG{IF}-WnbE^mY{f^VSoOLPg(%Xp*TuQ+a|w#yyBx%+jKow z4_iqcNE(EBsjBSgjEb=oX9}rFXjjD^pQ~J~#G*B@>FcIbPS3Ds4&Q0HdC&&F3CqCK zhep6g+bw#!GLQagJa6{$m$ZAROXJZDzd|{A6jyVky-^yek`;;|DeQvg#pZaXD4aM` z9_wdx>c4gEY!olUmesd>Tj&0hCfcCs7~3dQoj(;yq7ke?YydJu%2oE2Js8rQOB?T0@k@H_ zJS=p_U(H<5Y4IlUq)UhoZRvWL3ydpdkg`QC&!qnt+y0kStQ+UY{hdv%)lU^S<%d$+ zl}|j(o!jL5Y6jF)ew~|nxZ}o=6W27aSTny$@qy?TcW;)BZDsLi-!O|Es<8ifU?$_CAVqG14`l z9HdB*a+Hn~Lnkz8L8_=IRf?fYDAFu|5SsMR2~9{S(t`0=0D(a0NE3trflvhkBscgy zeB-{}XW#Z1$=F$$Yp%8TT=PGFGkZ7sVkCVSjGlZ(s>TRG4Y523yL!n`y9Bzy9G;Y;0~WrRrjMdnFY~A$f$*Z#B6hT#VTDJq4%pLS@4U5M zs6@tjMI~ACwzQK`d0y?Ts54ais?A_?-r zritxb-stEA;f~%Q#deHob3keYfS6jk+0z8yJU+(%luN zVQ4C`237f6#7t-EWZUZr=YU%^eu)uU(vRE`)8@VOkNqy3ZoRu_^BCvcYTkmu#@LWY zhcINuP?`vqhjf9B>blbB;xR|+qRu^B+LD^5dM*zbCy zDP!I?PYPoz(X__JvWR$nxC?_c41TuQP_)#4tUG*!Lv{UPhA&#{+ox*IqiaXmv{{Y= zBtM|?Zuo>TL>Ym>IkR*>+zLFG+Vpmbi9eLAE378Ft@4-0sw18)*GAhcNJ(9Zh*-;W zWC$ZL^3KHPDY9u62zjt(GGjjeP(eSEPT!RO#R2?+uT^s2x`~`~>$z1Tf>;giVcY!_ zGm3ez!${t9n6w8K3nI2spinhw*x)nz*kz`+w0=J;dp$;*sa((poB7Fin+xHn%99%Y zHuFaE*dt}oOSYAHx5>r~%KKMH5p3vJUFKVFLUUncuF#5Ki~{$x*)s2jh;(2nlkeXi zU#kgPCul+NoJ|+O=S*G-r%btCq?kNU-`Jyk=P{Ju@tg09aBGrVO_UN z#Ap*8=~Rd}eb4P-@jlH~i)R3L25#;yCy^A`A*J&Z$&7G^cAcAVN4Zn@+&;gyaxMH& zncvkd86X%Qi-n6DYA@LOI|)6{Kw~R+ngEs8vh#C=tD{rhbW=S!cvX8ObA`oI^0a&1 zU)dhd?^hr6bF3l&Ey;B%8-31^%))ye0oCPdk%&P$?~( zFOXBfP*)H6zD=@TINS9A=DJyUhd8^v9k}6kvTrl*r>_Zn6k4@aZpJbOktWP`W)+o2h6Rm3B2|-MlJ@|yh{ zt2ewLpIB@0b$v?-AGMJr-fS(@f=k!k0h2LJGagD43R5&MIZr}?K=7*^wNVYP#fTUV z8rR0Zz$t9-bgt=WoB5(WnB^TfhW`t9GTg}IQwg*r(p2AE zh17ax+}d?fQNpQWl_imzY^1VWD58dGW}>aA zqCFT&tsbqa^kZZ&jMk2pg*b04>DRViU0+)x>7QJwVwF(|N$oIbS02(3J`VHvLW!SZyH7C}vY(~oO-<%WLrM(TzVEN}9WHkYA}iX1!*Do+c3j%?sp+hsDI5aJBvngw zH*R(auuj+E)R_f@xz@qxwiW!R>4_o8M0it&K~?h*Q!@Srxih#G7kJ`DueQF`e=H;I zbO&MSKH)q;SF_#_RI4X&a^po=uM!x5q|Ky7QE-1~OZJC8o)5UCt&Vp*+w4qyHrRt&{N` zvaBRbNV-!v#4TL9I=dA+c+tiio#S!umv1|cd1sdc>7TdP>O-&5U|m5B%^I=OXMGW- z$-PkGLA81xY83E^NgKH3QL`oH7um%LZBh7Tq@>8W<#vgM zMNQub;C5B2w+(Xrk%)wZaIEC4uqbHfVFUgyq|Qp)YK%**cb_f9YgZWR(~fhrkq!_x zGIR{+6$Kga3(9(Rr3f>3tY6}jm5=W};u56==eJyttZobO*c`*!>)?REnvW906=wGg z0N@x-%0KCf0vy>x#xKh*HVIs>6k|3imNEv_bowTKY8%@mc+m_^P&jVOs>Lw}^|2(z z7ppfPU3ksq;WnTm{!i^^_OA6gx2(0av|r0YDZBM|EC?Dp@bDE)qfohsff+N6UT>fI6B;D(O;b%#N3Jgf^fKx~8jI$* zp$9_0wLl%jq*0=PDHHZkg=jGe$a^5x^gYVWD>q-ypx+>!5&vaie#Sc&{*WgxTF+;| zY`k;AVnAg>#asl{m^L6-u)FkjQYXwZ!7RWPdS8>>^8>moga2)o&eSNY<5nz2i${<( z{H957(VYIR`=GxeXlEL-;6I(QGK65*%T9{q%Wz<4C9{mluo*Z?p_9dgU@R>C}(SMRFus= z#nm21wSb&U$0BntM>v~-5flen$Uz+27xT6Q3u3_f!N7gyjtpV>#`_y4<*s$+!7Sm& zVmvAYgedx$VT@!Tw)ovm;>xtqY*uU>PhZ66SKRZwKMiwnBn~j9xB!8vMYxOwL`1D# z4i(Rqd0MV{qX_qe&?s60#WC^6qAH>WBn{y9g1o{+!R~=uJ-qK6>u(BSQAU^=kBH<7XzoRpR2p*1j=? zG%NkU$H~5Z*w$(|Fs@<9r!x6~*2s$AhyL+OP=7Vwq~63v1zK&!mI}}x5#29@*Bug_ z1@8*FQ0MrgJ%=GM;)AIV;jX6zt6Bv(Yc4lJudS%>Xc(zn<79aIb6w5sX0q8{L8F@e z_9whk@P^9oB|(1FqzNXx_an9gUjAcXCMGV%A&BgXeKh3UdE0ZZRSD@h?M9-^-=eXM zFNpu?DTvCM8@)`#XfI(RB4_8%bjGX9K2>j8wHxVN3!4xy?{oS}Pn_Ky==@V{sdM2> zOTp3oXNm)38vDfWDs{&{qnNlbWREcy_zKNGj>Av5SwBxd{Q5)5wI_iC85b9)H0m?n zy3VzF)QQUN^#Ap$4y>g`H%+G*p{Xf2k1+R&`t_t!xP>SBxoPE#2%aTsNAq{Uc?_rW zJ3!72d2}aKWNy(Jd*FW@dwMEOfcS=vQN!C^+1NUEA`W}A+BP24HQmaU%RH98g*wX9 z-G{Yp2maXa(oOo8HYz!mIFY!)~CDK zI~htP%bI}G7hO7n?8Qjk`Gc2SDC#T~oRA!La9uN{_ZL0Wg_0_Wl#CO4qT0Uc>C{f2 z)2eg-RQ2_~>v2_j+*ecuc*Vj9Q97-G1xqm4<|fDQGW4R(=Mero$!+R#o>sVPt-8lA zYA+P{lt)%AQ^WIW2&Vy5Ve=h2-jw6$X`=2=bF`0H1yn1>!R5dsbNx8>Yndk2Z#rD8 z8ujJfNnOq7ud&NQQ`O7ANz>Z6h3MyCQtEO3(?%Crr`AV{INnp~Utt7c^79;yR;5&SJ!Xm zA8_C!*}W`z`e(Fe<2~33&9zP+8p5YCy7y-y!WQ4Z=98KY-dWFT(=*PMgT<`&H|0GX z86CZ%;SU|?1cBd`qpI-N!L0k-7k{wc#1!?1b*SzKS-dHYqMv-XsFq+=ms)*TqQ%;g z*ivt0XOJlyBBla>qcT?6Dk*ojpY>TgYC(!7@6AOH1_%kSAz!ymMbkz?qqa()yH8l| zJPdtuF!vE&Zp_ZgDyadB?il}eXZ{5vJ5ZeeVh@A=a&;3MpOmDGjUue1tZXUAQO$3b zBrUR|6nInNKnUpjrt>7>i{@H)t@JsI%}YS#mcDW{cT1j3zR-lhwS3|s_wDrBw4u_S z|LWh#4#qBsgjAd;#C`dHc*5 zkf2yfp6MT6C{ zNHqgq13m!UU*xd9#ombCsYr^1i=`n)

s+ju?QKrYKLe^%@Gad{$V&RuSkUoS+NM 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

+

Standalone · filled / outline / border

+
+ + Filled + Outline + Border + + Primary + + + + + Alarm + + + + + Critical + + + + + Warning + + + + + Info + + + + + Success + + + + + Neutral + + + + + Custom + + + +
+
+ +
+

Counts · overflow · max-width

+
+ + + + + + + + +
+
+ +
+

Attached · anchors · position · offset

+
+ + Review + + + + + + + + + Bottom after + + + Offset + +
+
+ + + + diff --git a/testing/visual-testing/tests/badge/dot/index.html b/testing/visual-testing/tests/badge/dot/index.html new file mode 100644 index 00000000000..ed60bf7b76b --- /dev/null +++ b/testing/visual-testing/tests/badge/dot/index.html @@ -0,0 +1,163 @@ + + + + + + + + Badge dot + + + + +
+

Standalone · filled / outline / border

+
+ + Filled + Outline + Border + + Primary + + + + + Alarm + + + + + Critical + + + + + Warning + + + + + Info + + + + + Success + + + + + Neutral + + + + + Custom + + + +
+
+ +
+

Attached · anchors · position · offset

+
+ + Notifications + + + + + + + + + Bottom after + + + Offset + +
+
+ + + + diff --git a/testing/visual-testing/tests/badge/label/index.html b/testing/visual-testing/tests/badge/label/index.html new file mode 100644 index 00000000000..4a2be72226e --- /dev/null +++ b/testing/visual-testing/tests/badge/label/index.html @@ -0,0 +1,210 @@ + + + + + + + + Badge label + + + + +
+

Standalone · filled / outline / border

+
+ + Filled + Outline + Border + + Primary + + + + + Alarm + + + + + Critical + + + + + Warning + + + + + Info + + + + + Success + + + + + Neutral + + + + + Custom + + + +
+
+ +
+

Icon · align-left · max-width

+
+ + + + + +
+
+ +
+

Attached · anchors · position · offset

+
+ + What's new + + + + + + + + + Bottom after + + + Offset + +
+
+ + + + diff --git a/testing/visual-testing/tests/badge/status-icon/index.html b/testing/visual-testing/tests/badge/status-icon/index.html new file mode 100644 index 00000000000..1f6924822e9 --- /dev/null +++ b/testing/visual-testing/tests/badge/status-icon/index.html @@ -0,0 +1,160 @@ + + + + + + + + Badge status-icon + + + + +
+

Standalone · filled / outline

+
+ + Filled + Outline + + Alarm + + + + Error + + + + Critical + + + + Warning + + + + Success + + + + Info + + +
+
+ +
+

Attached · anchors · position · offset

+
+ + Alarm + + + + + + + + + Bottom after + + + Offset + +
+
+ + + + From bbd0b22af22b8c571cac8f0d6d34d40271b45336 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Fri, 24 Jul 2026 18:38:37 +0300 Subject: [PATCH 02/12] feat(badge): address coderabbitai bot comments IX-3943 --- packages/core/src/components/badge/badge.scss | 1 + .../src/components/badge/badge.status-icon.ts | 2 +- .../core/src/components/badge/badge.utils.ts | 10 +-- .../src/components/badge/test/badge.ct.ts | 72 +++++++++---------- .../visual-testing/tests/badge/badge.page.ts | 3 +- 5 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/core/src/components/badge/badge.scss b/packages/core/src/components/badge/badge.scss index 0a3fe453670..ba28adfda1e 100644 --- a/packages/core/src/components/badge/badge.scss +++ b/packages/core/src/components/badge/badge.scss @@ -298,6 +298,7 @@ $border-radius: 100px; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); + clip-path: inset(50%); white-space: nowrap; border: 0; } diff --git a/packages/core/src/components/badge/badge.status-icon.ts b/packages/core/src/components/badge/badge.status-icon.ts index 055f1e03a07..0d9c1b17997 100644 --- a/packages/core/src/components/badge/badge.status-icon.ts +++ b/packages/core/src/components/badge/badge.status-icon.ts @@ -86,7 +86,7 @@ export const BADGE_STATUS_ICON_BY_VARIANT: Record< export function isBadgeStatusIconVariant( variant: string ): variant is BadgeStatusIconVariant { - return variant in BADGE_STATUS_ICON_BY_VARIANT; + return Object.hasOwn(BADGE_STATUS_ICON_BY_VARIANT, variant); } function resolveStatusIconVariant( diff --git a/packages/core/src/components/badge/badge.utils.ts b/packages/core/src/components/badge/badge.utils.ts index e43ef16c4c9..d829057e4ba 100644 --- a/packages/core/src/components/badge/badge.utils.ts +++ b/packages/core/src/components/badge/badge.utils.ts @@ -14,6 +14,8 @@ export const BADGE_OVERFLOW_THRESHOLD = 99; const INTEGER_LABEL_PATTERN = /^-?\d+(\.\d+)?$/; const OVERFLOW_LABEL = `${BADGE_OVERFLOW_THRESHOLD}+`; +type BadgeLabelInput = string | number | null; + /** * Formats badge label text for supported anatomy types. * Returns `null` when the type has no text or the value is invalid. @@ -21,7 +23,7 @@ const OVERFLOW_LABEL = `${BADGE_OVERFLOW_THRESHOLD}+`; */ export function formatBadgeLabel( type: BadgeAnatomyType, - label?: string | number | null + label?: BadgeLabelInput ): string | null { switch (type) { case 'counter': @@ -34,7 +36,7 @@ export function formatBadgeLabel( } } -function coerceLabelText(label?: string | number | null): string { +function coerceLabelText(label?: BadgeLabelInput): string { if (label === undefined || label === null) { return ''; } @@ -42,7 +44,7 @@ function coerceLabelText(label?: string | number | null): string { return String(label).trim(); } -function formatTextLabel(label?: string | number | null): string | null { +function formatTextLabel(label?: BadgeLabelInput): string | null { const trimmed = coerceLabelText(label); if (!trimmed) { @@ -52,7 +54,7 @@ function formatTextLabel(label?: string | number | null): string | null { return trimmed; } -function formatCounterLabel(label?: string | number | null): string | null { +function formatCounterLabel(label?: BadgeLabelInput): string | null { const trimmed = coerceLabelText(label); if (!trimmed) { diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts index ccbf086fbd9..da226428e83 100644 --- a/packages/core/src/components/badge/test/badge.ct.ts +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -19,6 +19,41 @@ import { BadgePage } from './badge.page'; const html = String.raw; +async function expectVisibleTooltipText(tooltip: Locator, text: string) { + await expect(tooltip).toHaveClass(/visible/); + + const metrics = await tooltip.evaluate((el) => { + const slot = el.shadowRoot?.querySelector( + 'slot:not([name])' + ) as HTMLSlotElement | null; + const assigned = slot?.assignedNodes({ flatten: true }) ?? []; + const slottedText = assigned.map((node) => node.textContent ?? '').join(''); + let width = 0; + let height = 0; + + if (assigned[0]) { + const range = document.createRange(); + range.selectNodeContents(assigned[0]); + const rect = range.getBoundingClientRect(); + width = rect.width; + height = rect.height; + } + + return { + slottedText, + width, + height, + fontSize: getComputedStyle(el).fontSize, + }; + }); + + expect(metrics.slottedText).toBe(text); + expect(metrics.fontSize).toBe('14px'); + // Guard against host font-size:0 collapsing tooltip glyphs (empty bubble). + expect(metrics.width).toBeGreaterThan(8); + expect(metrics.height).toBeGreaterThan(8); +} + regressionTest.describe('ix-badge', () => { regressionTest.describe('rendering', () => { regressionTest('hydrates standalone badge', async ({ mount, page }) => { @@ -572,43 +607,6 @@ regressionTest.describe('ix-badge', () => { }); regressionTest.describe('tooltip', () => { - async function expectVisibleTooltipText(tooltip: Locator, text: string) { - await expect(tooltip).toHaveClass(/visible/); - - const metrics = await tooltip.evaluate((el) => { - const slot = el.shadowRoot?.querySelector( - 'slot:not([name])' - ) as HTMLSlotElement | null; - const assigned = slot?.assignedNodes({ flatten: true }) ?? []; - const slottedText = assigned - .map((node) => node.textContent ?? '') - .join(''); - let width = 0; - let height = 0; - - if (assigned[0]) { - const range = document.createRange(); - range.selectNodeContents(assigned[0]); - const rect = range.getBoundingClientRect(); - width = rect.width; - height = rect.height; - } - - return { - slottedText, - width, - height, - fontSize: getComputedStyle(el).fontSize, - }; - }); - - expect(metrics.slottedText).toBe(text); - expect(metrics.fontSize).toBe('14px'); - // Guard against host font-size:0 collapsing tooltip glyphs (empty bubble). - expect(metrics.width).toBeGreaterThan(8); - expect(metrics.height).toBeGreaterThan(8); - } - regressionTest( 'does not render tooltip when tooltip-text is absent', async ({ mount, page }) => { diff --git a/testing/visual-testing/tests/badge/badge.page.ts b/testing/visual-testing/tests/badge/badge.page.ts index e4432db73a8..733f082ed7a 100644 --- a/testing/visual-testing/tests/badge/badge.page.ts +++ b/testing/visual-testing/tests/badge/badge.page.ts @@ -45,9 +45,8 @@ export class BadgeVisualPage { } async waitForReady(): Promise { - await this.badges.first().waitFor(); await expect(this.badges).not.toHaveCount(0); - await expect(this.page.locator('ix-badge.hydrated').first()).toBeVisible(); + await expect(this.page.locator('ix-badge:not(.hydrated)')).toHaveCount(0); } async expectSnapshot(): Promise { From 916336f4e847c7152748c07d0c3440dce8e76641 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Sat, 25 Jul 2026 09:21:47 +0300 Subject: [PATCH 03/12] feat(badge): migrate badge stories from Lit to Stencil TSX IX-3943 --- ...adge.stories.ts => a11y-badge.stories.tsx} | 45 ++-- ...iew.shared.ts => badge-preview.shared.tsx} | 205 +++++++------- ...counter.stories.ts => counter.stories.tsx} | 251 +++++++++--------- .../badge/{dot.stories.ts => dot.stories.tsx} | 149 +++++------ .../{label.stories.ts => label.stories.tsx} | 164 ++++++------ ...con.stories.ts => status-icon.stories.tsx} | 166 ++++++------ 6 files changed, 486 insertions(+), 494 deletions(-) rename packages/storybook-docs/src/stories/badge/accessibility/{a11y-badge.stories.ts => a11y-badge.stories.tsx} (76%) rename packages/storybook-docs/src/stories/badge/{badge-preview.shared.ts => badge-preview.shared.tsx} (61%) rename packages/storybook-docs/src/stories/badge/{counter.stories.ts => counter.stories.tsx} (66%) rename packages/storybook-docs/src/stories/badge/{dot.stories.ts => dot.stories.tsx} (62%) rename packages/storybook-docs/src/stories/badge/{label.stories.ts => label.stories.tsx} (68%) rename packages/storybook-docs/src/stories/badge/{status-icon.stories.ts => status-icon.stories.tsx} (62%) diff --git a/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx similarity index 76% rename from packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts rename to packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx index c260d59e49e..30bbf91b749 100644 --- a/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.ts +++ b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx @@ -6,17 +6,18 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -import type { ArgTypes, Meta, StoryObj } from '@storybook/web-components-vite'; import type { Components } from '@siemens/ix/components'; -import { genericRender, makeArgTypes } from '@utils/generic-render'; -import { html } from 'lit'; +import { h } from '@stencil/core'; +import type { ArgTypes, Meta, StoryObj } from '@storybook/web-components-vite'; +import { stencil } from '@utils/stencil-render'; +import { makeArgTypes } from '@utils/generic-render'; type Element = Components.IxBadge; const meta = { title: 'Example/Badge/Accessibility', tags: [], - render: (args) => genericRender('ix-badge', args), + render: stencil((args: Partial) => ), argTypes: makeArgTypes>>('ix-badge', {}), parameters: { a11y: { @@ -44,57 +45,61 @@ export const BasicUsage: Story = { * (e.g. `role="img"`) because `aria-label` alone is not valid on a role-less host. */ export const DotWithAriaLabel: Story = { - render: () => - html` ( + `, + > + )), }; /** * Standalone badge with optional live region: author sets `role` / `aria-label` on the host. */ export const CustomAriaLabel: Story = { - render: () => - html``, + render: stencil(() => ( + + )), }; /** * Attached badge with a count: the anchor keeps its role; count text is exposed via `aria-describedby`. */ export const AttachedWithCount: Story = { - render: () => html` + render: stencil(() => ( Review changes - `, + )), }; /** * Attached dot badge: the anchor must be named; the indicator is decorative (`aria-hidden`). */ export const AttachedDot: Story = { - render: () => html` + render: stencil(() => ( - `, + )), }; /** * Attached badge merges `aria-describedby` with existing ids on the anchor. */ export const MergedAriaDescribedby: Story = { - render: () => html` -
+ render: stencil(() => ( +
-

Unread messages in your primary folder.

+

+ Unread messages in your primary folder. +

- `, + )), }; /** @@ -111,10 +116,10 @@ export const OverflowLabel: Story = { * Standalone badge hidden from screen readers when the count is redundant with surrounding text. */ export const DecorativeBadge: Story = { - render: () => html` + render: stencil(() => (
Notifications: 3 unread - +
- `, + )), }; diff --git a/packages/storybook-docs/src/stories/badge/badge-preview.shared.ts b/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx similarity index 61% rename from packages/storybook-docs/src/stories/badge/badge-preview.shared.ts rename to packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx index dcacceeaf8a..4fbe82b9bca 100644 --- a/packages/storybook-docs/src/stories/badge/badge-preview.shared.ts +++ b/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx @@ -7,8 +7,7 @@ * LICENSE file in the root directory of this source tree. */ -import { html, nothing, type TemplateResult } from 'lit'; -import { styleMap } from 'lit/directives/style-map.js'; +import { h, type VNode } from '@stencil/core'; import './badge-preview.css'; /** Aligned with chip / react badge preview custom tokens. */ @@ -50,58 +49,56 @@ export const showcaseParameters = { export function cell( label: string, - content: TemplateResult | typeof nothing, + content: VNode | null | undefined, attached = false -): TemplateResult { - return html` -
- ${label} - ${content} +): VNode { + return ( +
+ {label} + {content}
- `; + ); } export function themePanel( colorSchema: 'dark' | 'light', title: string, - content: TemplateResult -): TemplateResult { - return html` + content: VNode +): VNode { + return (
-

${title}

- ${content} +

{title}

+ {content}
- `; + ); } -export function variantGridHeaders(): TemplateResult { - return html` - - Filled - Outline - Border - Pulse - `; +export function variantGridHeaders(): VNode[] { + return [ + , + Filled, + Outline, + Border, + Pulse, + ]; } /** Attached grids omit Outline — not recommended on anchors. */ -export function attachedVariantGridHeaders(): TemplateResult { - return html` - - Filled - Border - Pulse - `; +export function attachedVariantGridHeaders(): VNode[] { + return [ + , + Filled, + Border, + Pulse, + ]; } -export function iconButtonAnchor(ariaLabel: string): TemplateResult { - return html` - - `; +export function iconButtonAnchor(ariaLabel: string): VNode { + return ; } type CustomColors = { @@ -144,8 +141,8 @@ export function counterBadge(options: { offsetY?: number; hostStyle?: Record; custom?: CustomColors; - children?: TemplateResult | typeof nothing; -}): TemplateResult { + children?: VNode | null; +}): VNode { const { variant, label = '1', @@ -163,24 +160,25 @@ export function counterBadge(options: { const background = resolveCustomBackground(variant, custom); const badgeColor = resolveCustomBadgeColor(variant, outline, custom); - return html` + return ( ${children ?? nothing} - `; + {children} + + ); } export function labelBadge(options: { @@ -199,8 +197,8 @@ export function labelBadge(options: { ariaLabel?: string; role?: string; custom?: CustomColors; - children?: TemplateResult | typeof nothing; -}): TemplateResult { + children?: VNode | null; +}): VNode { const { variant, label = 'NEW', @@ -223,29 +221,30 @@ export function labelBadge(options: { const background = resolveCustomBackground(variant, custom); const badgeColor = resolveCustomBadgeColor(variant, outline, custom); - return html` + return ( ${children ?? nothing} - `; + {children} + + ); } export function dotBadge(options: { @@ -259,8 +258,8 @@ export function dotBadge(options: { ariaLabel?: string; role?: string; custom?: CustomColors; - children?: TemplateResult | typeof nothing; -}): TemplateResult { + children?: VNode | null; +}): VNode { const { variant, outline = false, @@ -278,24 +277,25 @@ export function dotBadge(options: { const background = resolveCustomBackground(variant, custom); const badgeColor = resolveCustomBadgeColor(variant, outline, custom); - return html` + return ( ${children ?? nothing} - `; + {children} + + ); } export function statusIconBadge(options: { @@ -308,8 +308,8 @@ export function statusIconBadge(options: { offsetY?: number; ariaLabel?: string; role?: string; - children?: TemplateResult | typeof nothing; -}): TemplateResult { + children?: VNode | null; +}): VNode { const { variant, outline = false, @@ -323,20 +323,21 @@ export function statusIconBadge(options: { children, } = options; - return html` + return ( ${children ?? nothing} - `; + {children} + + ); } diff --git a/packages/storybook-docs/src/stories/badge/counter.stories.ts b/packages/storybook-docs/src/stories/badge/counter.stories.tsx similarity index 66% rename from packages/storybook-docs/src/stories/badge/counter.stories.ts rename to packages/storybook-docs/src/stories/badge/counter.stories.tsx index 3617d8317a9..767a838ac08 100644 --- a/packages/storybook-docs/src/stories/badge/counter.stories.ts +++ b/packages/storybook-docs/src/stories/badge/counter.stories.tsx @@ -7,9 +7,11 @@ * LICENSE file in the root directory of this source tree. */ +import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html, type TemplateResult } from 'lit'; +import { stencil } from '@utils/stencil-render'; import { + attachedVariantGridHeaders, cell, counterBadge, iconButtonAnchor, @@ -17,77 +19,72 @@ import { themePanel, VARIANT_ROWS, variantGridHeaders, - attachedVariantGridHeaders, } from './badge-preview.shared'; /** * Mirrors `packages/react-test-app/src/preview-examples/badge.tsx` * (`/preview/badge`). */ -function standaloneVariantGrid(): TemplateResult { - return html` +function standaloneVariantGrid(): VNode { + return (
- ${variantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell(`${variant} · filled`, counterBadge({ variant }))} - ${cell(`${variant} · outline`, counterBadge({ variant, outline: true }))} - ${cell(`${variant} · border`, counterBadge({ variant, border: true }))} - ${cell( - `${variant} · pulse`, - html`
- ${counterBadge({ variant, enableAnimation: true })} - ${counterBadge({ variant, outline: true, enableAnimation: true })} -
` - )} - ` - )} + {variantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell(`${variant} · filled`, counterBadge({ variant })), + cell(`${variant} · outline`, counterBadge({ variant, outline: true })), + cell(`${variant} · border`, counterBadge({ variant, border: true })), + cell( + `${variant} · pulse`, +
+ {counterBadge({ variant, enableAnimation: true })} + {counterBadge({ variant, outline: true, enableAnimation: true })} +
+ ), + ])}
- `; + ); } -function attachedVariantGrid(): TemplateResult { - return html` +function attachedVariantGrid(): VNode { + return (
- ${attachedVariantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell( - `${variant} · filled · attached`, - counterBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · border · attached`, - counterBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · pulse · attached`, - counterBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ` - )} + {attachedVariantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell( + `${variant} · filled · attached`, + counterBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · border · attached`, + counterBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · pulse · attached`, + counterBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + ])}
- `; + ); } -function badgeCounterPreview(): TemplateResult { - return html` +function badgeCounterPreview(): VNode { + return (

type="counter"

@@ -100,8 +97,8 @@ function badgeCounterPreview(): TemplateResult {

Variants — standalone

No default slot → standalone counter.

- ${themePanel('dark', 'Dark', standaloneVariantGrid())} - ${themePanel('light', 'Light', standaloneVariantGrid())} + {themePanel('dark', 'Dark', standaloneVariantGrid())} + {themePanel('light', 'Light', standaloneVariantGrid())}
@@ -110,46 +107,46 @@ function badgeCounterPreview(): TemplateResult { Default slot wraps anchor; counter overlays top-trailing (−10px / −10px default offset).

- ${themePanel('dark', 'Dark', attachedVariantGrid())} - ${themePanel('light', 'Light', attachedVariantGrid())} + {themePanel('dark', 'Dark', attachedVariantGrid())} + {themePanel('light', 'Light', attachedVariantGrid())}

Standalone counts

- ${cell( + {cell( 'type="counter" label="1"', counterBadge({ variant: 'primary', label: '1' }) )} - ${cell( + {cell( 'type="counter" label="12"', counterBadge({ variant: 'alarm', label: '12' }) )} - ${cell( + {cell( 'type="counter" label="99"', counterBadge({ variant: 'warning', label: '99' }) )} - ${cell( + {cell( 'type="counter" label="100" → 99+', counterBadge({ variant: 'info', label: '100' }) )} - ${cell( + {cell( 'type="counter" label="142" → 99+', counterBadge({ variant: 'critical', label: '142' }) )} - ${cell( + {cell( 'type="counter" label="0"', counterBadge({ variant: 'neutral', label: '0' }) )} - ${cell( + {cell( 'type="counter" label="-1"', counterBadge({ variant: 'success', label: '-1' }) )} - ${cell( + {cell( 'type="counter" label="-99"', counterBadge({ variant: 'primary', label: '-99' }) )} - ${cell( + {cell( 'type="counter" label="-100" (literal)', counterBadge({ variant: 'alarm', label: '-100' }) )} @@ -159,16 +156,16 @@ function badgeCounterPreview(): TemplateResult {

Attached anchors

- ${cell( + {cell( 'IxButton anchor', counterBadge({ variant: 'alarm', label: '3', - children: html`Notifications`, + children: Notifications, }), true )} - ${cell( + {cell( 'IxIconButton anchor', counterBadge({ variant: 'info', @@ -177,12 +174,12 @@ function badgeCounterPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'IxAvatar anchor', counterBadge({ variant: 'primary', label: '12', - children: html``, + children: , }), true )} @@ -192,40 +189,36 @@ function badgeCounterPreview(): TemplateResult {

Formatting

- ${cell('label="1"', counterBadge({ variant: 'alarm', label: '1' }))} - ${cell('label="99"', counterBadge({ variant: 'alarm', label: '99' }))} - ${cell( + {cell('label="1"', counterBadge({ variant: 'alarm', label: '1' }))} + {cell('label="99"', counterBadge({ variant: 'alarm', label: '99' }))} + {cell( 'label="100" → 99+', counterBadge({ variant: 'alarm', label: '100' }) )} - ${cell( + {cell( 'label="3.7" → 3', counterBadge({ variant: 'alarm', label: '3.7' }) )} - ${cell( + {cell( 'label="99.9" → 99', counterBadge({ variant: 'alarm', label: '99.9' }) )} - ${cell( + {cell( 'label="007" → 7', counterBadge({ variant: 'alarm', label: '007' }) )} - ${cell('label="-1"', counterBadge({ variant: 'alarm', label: '-1' }))} - ${cell( + {cell('label="-1"', counterBadge({ variant: 'alarm', label: '-1' }))} + {cell( 'label="new" → no indicator', counterBadge({ variant: 'alarm', label: 'new' }) )} - ${cell( + {cell( 'label="99+" → 99+', counterBadge({ variant: 'alarm', label: '99+' }) )} - ${cell( + {cell( 'no label → no indicator', - html`` + )}
@@ -233,44 +226,44 @@ function badgeCounterPreview(): TemplateResult {

Position and offset

- ${cell( + {cell( 'position="top-after" (default)', counterBadge({ variant: 'warning', label: '5', - children: html`Top after`, + children: Top after, }), true )} - ${cell( + {cell( 'position="bottom-after"', counterBadge({ variant: 'warning', label: '99', position: 'bottom-after', - children: html``, + children: , }), true )} - ${cell( + {cell( 'offsetX={6} offsetY={-4}', counterBadge({ variant: 'info', label: '2', offsetX: 6, offsetY: -4, - children: html`Offset`, + children: Offset, }), true )} - ${cell( + {cell( 'Custom offset', counterBadge({ variant: 'alarm', label: '1', offsetX: -4, offsetY: 2, - children: html`Custom offset`, + children: Custom offset, }), true )} @@ -283,8 +276,8 @@ function badgeCounterPreview(): TemplateResult {

Pulsing (bool)

warning · counter

- ${cell('filled', counterBadge({ variant: 'warning', label: '1' }))} - ${cell( + {cell('filled', counterBadge({ variant: 'warning', label: '1' }))} + {cell( 'filled · pulse', counterBadge({ variant: 'warning', @@ -292,11 +285,11 @@ function badgeCounterPreview(): TemplateResult { enableAnimation: true, }) )} - ${cell( + {cell( 'outline', counterBadge({ variant: 'warning', label: '1', outline: true }) )} - ${cell( + {cell( 'outline · pulse', counterBadge({ variant: 'warning', @@ -309,7 +302,7 @@ function badgeCounterPreview(): TemplateResult {

Live pulse

- ${cell( + {cell( 'standalone · 2s', counterBadge({ variant: 'primary', @@ -317,7 +310,7 @@ function badgeCounterPreview(): TemplateResult { enableAnimation: true, }) )} - ${cell( + {cell( 'attached · 2s', counterBadge({ variant: 'primary', @@ -327,7 +320,7 @@ function badgeCounterPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'standalone · 6s', counterBadge({ variant: 'warning', @@ -343,20 +336,20 @@ function badgeCounterPreview(): TemplateResult {

Width

- ${cell('label="1"', counterBadge({ variant: 'primary', label: '1' }))} - ${cell( + {cell('label="1"', counterBadge({ variant: 'primary', label: '1' }))} + {cell( 'label="12"', counterBadge({ variant: 'primary', label: '12' }) )} - ${cell( + {cell( 'label="99"', counterBadge({ variant: 'primary', label: '99' }) )} - ${cell( + {cell( 'label="142" → 99+', counterBadge({ variant: 'primary', label: '142' }) )} - ${cell( + {cell( '--ix-badge-max-width: 2rem', counterBadge({ variant: 'primary', @@ -370,28 +363,32 @@ function badgeCounterPreview(): TemplateResult {

Container bounds

- ${cell( + {cell( '32px IxIconButton', counterBadge({ variant: 'alarm', label: '1', - children: html``, + children: ( + + ), }), true )} - ${cell( + {cell( '24px IxIcon size="24"', counterBadge({ variant: 'alarm', label: '12', - children: html``, + children: ( + + ), }), true )} @@ -401,20 +398,20 @@ function badgeCounterPreview(): TemplateResult {

Accessibility

- ${cell( + {cell( 'role="alert" · standalone', - html`` + > )}
- `; + ); } const meta = { @@ -428,5 +425,5 @@ type Story = StoryObj; export const Counter: Story = { name: 'Counter', - render: () => badgeCounterPreview(), + render: stencil(() => badgeCounterPreview()), }; diff --git a/packages/storybook-docs/src/stories/badge/dot.stories.ts b/packages/storybook-docs/src/stories/badge/dot.stories.tsx similarity index 62% rename from packages/storybook-docs/src/stories/badge/dot.stories.ts rename to packages/storybook-docs/src/stories/badge/dot.stories.tsx index 6541bc3c759..14fd09912e7 100644 --- a/packages/storybook-docs/src/stories/badge/dot.stories.ts +++ b/packages/storybook-docs/src/stories/badge/dot.stories.tsx @@ -7,9 +7,11 @@ * LICENSE file in the root directory of this source tree. */ +import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html, type TemplateResult } from 'lit'; +import { stencil } from '@utils/stencil-render'; import { + attachedVariantGridHeaders, cell, dotBadge, iconButtonAnchor, @@ -17,77 +19,72 @@ import { themePanel, VARIANT_ROWS, variantGridHeaders, - attachedVariantGridHeaders, } from './badge-preview.shared'; /** * Mirrors `packages/react-test-app/src/preview-examples/badge-dot.tsx` * (`/preview/badge-dot`). */ -function standaloneVariantGrid(): TemplateResult { - return html` +function standaloneVariantGrid(): VNode { + return (
- ${variantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell(`${variant} · filled`, dotBadge({ variant }))} - ${cell(`${variant} · outline`, dotBadge({ variant, outline: true }))} - ${cell(`${variant} · border`, dotBadge({ variant, border: true }))} - ${cell( - `${variant} · pulse`, - html`
- ${dotBadge({ variant, enableAnimation: true })} - ${dotBadge({ variant, outline: true, enableAnimation: true })} -
` - )} - ` - )} + {variantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell(`${variant} · filled`, dotBadge({ variant })), + cell(`${variant} · outline`, dotBadge({ variant, outline: true })), + cell(`${variant} · border`, dotBadge({ variant, border: true })), + cell( + `${variant} · pulse`, +
+ {dotBadge({ variant, enableAnimation: true })} + {dotBadge({ variant, outline: true, enableAnimation: true })} +
+ ), + ])}
- `; + ); } -function attachedVariantGrid(): TemplateResult { - return html` +function attachedVariantGrid(): VNode { + return (
- ${attachedVariantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell( - `${variant} · filled · attached`, - dotBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · border · attached`, - dotBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · pulse · attached`, - dotBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ` - )} + {attachedVariantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell( + `${variant} · filled · attached`, + dotBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · border · attached`, + dotBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · pulse · attached`, + dotBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + ])}
- `; + ); } -function badgeDotPreview(): TemplateResult { - return html` +function badgeDotPreview(): VNode { + return (

Dot badge

@@ -100,8 +97,8 @@ function badgeDotPreview(): TemplateResult {
- ${themePanel('dark', 'Dark', standaloneVariantGrid())} - ${themePanel('light', 'Light', standaloneVariantGrid())} + {themePanel('dark', 'Dark', standaloneVariantGrid())} + {themePanel('light', 'Light', standaloneVariantGrid())}
@@ -110,14 +107,14 @@ function badgeDotPreview(): TemplateResult { Icon button anchor; dot overlays top-trailing (−0.375rem default offset).

- ${themePanel('dark', 'Dark', attachedVariantGrid())} - ${themePanel('light', 'Light', attachedVariantGrid())} + {themePanel('dark', 'Dark', attachedVariantGrid())} + {themePanel('light', 'Light', attachedVariantGrid())}

Attached anchors

- ${cell( + {cell( 'IxIconButton · alarm', dotBadge({ variant: 'alarm', @@ -125,19 +122,19 @@ function badgeDotPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'IxButton · primary', dotBadge({ variant: 'primary', - children: html`Messages`, + children: Messages, }), true )} - ${cell( + {cell( 'IxAvatar · success', dotBadge({ variant: 'success', - children: html``, + children: , }), true )} @@ -147,7 +144,7 @@ function badgeDotPreview(): TemplateResult {

Placement

- ${cell( + {cell( 'position="top-after" (default)', dotBadge({ variant: 'alarm', @@ -155,7 +152,7 @@ function badgeDotPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'position="bottom-after"', dotBadge({ variant: 'info', @@ -164,7 +161,7 @@ function badgeDotPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'offsetX={6} offsetY={-4}', dotBadge({ variant: 'warning', @@ -184,14 +181,14 @@ function badgeDotPreview(): TemplateResult { aria-describedby on anchor when attached).

- ${cell( + {cell( 'aria-label="Unread messages"', dotBadge({ variant: 'alarm', ariaLabel: 'Unread messages', }) )} - ${cell( + {cell( 'role="alert" · aria-label="Action required"', dotBadge({ variant: 'critical', @@ -205,11 +202,11 @@ function badgeDotPreview(): TemplateResult {

Pulse

- ${cell( + {cell( 'filled · pulse · standalone', dotBadge({ variant: 'warning', enableAnimation: true }) )} - ${cell( + {cell( 'filled · pulse · attached', dotBadge({ variant: 'warning', @@ -221,7 +218,7 @@ function badgeDotPreview(): TemplateResult {
- `; + ); } const meta = { @@ -235,5 +232,5 @@ type Story = StoryObj; export const Dot: Story = { name: 'Dot', - render: () => badgeDotPreview(), + render: stencil(() => badgeDotPreview()), }; diff --git a/packages/storybook-docs/src/stories/badge/label.stories.ts b/packages/storybook-docs/src/stories/badge/label.stories.tsx similarity index 68% rename from packages/storybook-docs/src/stories/badge/label.stories.ts rename to packages/storybook-docs/src/stories/badge/label.stories.tsx index 6f89f6e568a..02a14ed1f19 100644 --- a/packages/storybook-docs/src/stories/badge/label.stories.ts +++ b/packages/storybook-docs/src/stories/badge/label.stories.tsx @@ -7,9 +7,11 @@ * LICENSE file in the root directory of this source tree. */ +import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html, type TemplateResult } from 'lit'; +import { stencil } from '@utils/stencil-render'; import { + attachedVariantGridHeaders, cell, iconButtonAnchor, labelBadge, @@ -17,77 +19,72 @@ import { themePanel, VARIANT_ROWS, variantGridHeaders, - attachedVariantGridHeaders, } from './badge-preview.shared'; /** * Mirrors `packages/react-test-app/src/preview-examples/badge-label.tsx` * (`/preview/badge-label`). */ -function standaloneVariantGrid(): TemplateResult { - return html` +function standaloneVariantGrid(): VNode { + return (
- ${variantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell(`${variant} · filled`, labelBadge({ variant }))} - ${cell(`${variant} · outline`, labelBadge({ variant, outline: true }))} - ${cell(`${variant} · border`, labelBadge({ variant, border: true }))} - ${cell( - `${variant} · pulse`, - html`
- ${labelBadge({ variant, enableAnimation: true })} - ${labelBadge({ variant, outline: true, enableAnimation: true })} -
` - )} - ` - )} + {variantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell(`${variant} · filled`, labelBadge({ variant })), + cell(`${variant} · outline`, labelBadge({ variant, outline: true })), + cell(`${variant} · border`, labelBadge({ variant, border: true })), + cell( + `${variant} · pulse`, +
+ {labelBadge({ variant, enableAnimation: true })} + {labelBadge({ variant, outline: true, enableAnimation: true })} +
+ ), + ])}
- `; + ); } -function attachedVariantGrid(): TemplateResult { - return html` +function attachedVariantGrid(): VNode { + return (
- ${attachedVariantGridHeaders()} - ${VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell( - `${variant} · filled · attached`, - labelBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · border · attached`, - labelBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · pulse · attached`, - labelBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ` - )} + {attachedVariantGridHeaders()} + {VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell( + `${variant} · filled · attached`, + labelBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · border · attached`, + labelBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · pulse · attached`, + labelBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + ])}
- `; + ); } -function badgeLabelPreview(): TemplateResult { - return html` +function badgeLabelPreview(): VNode { + return (

Label badge

@@ -101,8 +98,8 @@ function badgeLabelPreview(): TemplateResult {
- ${themePanel('dark', 'Dark', standaloneVariantGrid())} - ${themePanel('light', 'Light', standaloneVariantGrid())} + {themePanel('dark', 'Dark', standaloneVariantGrid())} + {themePanel('light', 'Light', standaloneVariantGrid())}
@@ -111,22 +108,22 @@ function badgeLabelPreview(): TemplateResult { Icon button anchor; label overlays top-trailing (−0.625rem default offset).

- ${themePanel('dark', 'Dark', attachedVariantGrid())} - ${themePanel('light', 'Light', attachedVariantGrid())} + {themePanel('dark', 'Dark', attachedVariantGrid())} + {themePanel('light', 'Light', attachedVariantGrid())}

Icon

- ${cell( + {cell( 'icon={star} · decorative (default)', labelBadge({ variant: 'primary' }) )} - ${cell( + {cell( 'icon={star} · decorative · warning', labelBadge({ variant: 'warning' }) )} - ${cell( + {cell( 'icon={star} · aria-label-icon="Featured"', labelBadge({ variant: 'success', @@ -140,11 +137,11 @@ function badgeLabelPreview(): TemplateResult {

Align left

- ${cell( + {cell( 'default · icon + text', labelBadge({ variant: 'info', label: "What's new" }) )} - ${cell( + {cell( 'alignLeft · icon + text', labelBadge({ variant: 'primary', @@ -152,7 +149,7 @@ function badgeLabelPreview(): TemplateResult { alignLeft: true, }) )} - ${cell( + {cell( 'alignLeft · --ix-badge-max-width: 2.5rem', labelBadge({ variant: 'alarm', @@ -167,7 +164,7 @@ function badgeLabelPreview(): TemplateResult {

Attached anchors

- ${cell( + {cell( 'IxIconButton · alarm', labelBadge({ variant: 'alarm', @@ -175,19 +172,19 @@ function badgeLabelPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'IxButton · primary · warning badge', labelBadge({ variant: 'warning', - children: html`Messages`, + children: Messages, }), true )} - ${cell( + {cell( 'IxAvatar · success', labelBadge({ variant: 'success', - children: html``, + children: , }), true )} @@ -197,7 +194,7 @@ function badgeLabelPreview(): TemplateResult {

Placement

- ${cell( + {cell( 'position="top-after" (default)', labelBadge({ variant: 'alarm', @@ -205,7 +202,7 @@ function badgeLabelPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'position="bottom-after"', labelBadge({ variant: 'info', @@ -214,7 +211,7 @@ function badgeLabelPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'offsetX={6} offsetY={-4}', labelBadge({ variant: 'warning', @@ -231,10 +228,11 @@ function badgeLabelPreview(): TemplateResult {

Standalone a11y

Attached: label text via aria-describedby on anchor. - Standalone: author ARIA stays on the host (pill-like; opt-in live region). + Standalone: author ARIA stays on the host (pill-like; opt-in live + region).

- ${cell( + {cell( 'aria-label="New content available"', labelBadge({ variant: 'primary', @@ -242,7 +240,7 @@ function badgeLabelPreview(): TemplateResult { ariaLabel: 'New content available', }) )} - ${cell( + {cell( 'role="alert" · aria-label="Action required"', labelBadge({ variant: 'critical', @@ -257,11 +255,11 @@ function badgeLabelPreview(): TemplateResult {

Pulse

- ${cell( + {cell( 'filled · pulse · standalone', labelBadge({ variant: 'warning', enableAnimation: true }) )} - ${cell( + {cell( 'filled · pulse · attached', labelBadge({ variant: 'warning', @@ -273,7 +271,7 @@ function badgeLabelPreview(): TemplateResult {
- `; + ); } const meta = { @@ -287,5 +285,5 @@ type Story = StoryObj; export const Label: Story = { name: 'Label', - render: () => badgeLabelPreview(), + render: stencil(() => badgeLabelPreview()), }; diff --git a/packages/storybook-docs/src/stories/badge/status-icon.stories.ts b/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx similarity index 62% rename from packages/storybook-docs/src/stories/badge/status-icon.stories.ts rename to packages/storybook-docs/src/stories/badge/status-icon.stories.tsx index 3c96cd50aae..d676b90e89e 100644 --- a/packages/storybook-docs/src/stories/badge/status-icon.stories.ts +++ b/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx @@ -7,9 +7,11 @@ * LICENSE file in the root directory of this source tree. */ +import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html, type TemplateResult } from 'lit'; +import { stencil } from '@utils/stencil-render'; import { + attachedVariantGridHeaders, cell, iconButtonAnchor, showcaseParameters, @@ -17,87 +19,79 @@ import { statusIconBadge, themePanel, variantGridHeaders, - attachedVariantGridHeaders, } from './badge-preview.shared'; /** * Mirrors `packages/react-test-app/src/preview-examples/badge-status-icon.tsx` * (`/preview/badge-status-icon`). */ -function standaloneVariantGrid(): TemplateResult { - return html` +function standaloneVariantGrid(): VNode { + return (
- ${variantGridHeaders()} - ${STATUS_ICON_VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell(`${variant} · filled`, statusIconBadge({ variant }))} - ${cell( - `${variant} · outline`, - statusIconBadge({ variant, outline: true }) - )} - ${cell( - `${variant} · border`, - statusIconBadge({ variant, border: true }) - )} - ${cell( - `${variant} · pulse`, - html`
- ${statusIconBadge({ variant, enableAnimation: true })} - ${statusIconBadge({ - variant, - outline: true, - enableAnimation: true, - })} -
` - )} - ` - )} + {variantGridHeaders()} + {STATUS_ICON_VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell(`${variant} · filled`, statusIconBadge({ variant })), + cell( + `${variant} · outline`, + statusIconBadge({ variant, outline: true }) + ), + cell(`${variant} · border`, statusIconBadge({ variant, border: true })), + cell( + `${variant} · pulse`, +
+ {statusIconBadge({ variant, enableAnimation: true })} + {statusIconBadge({ + variant, + outline: true, + enableAnimation: true, + })} +
+ ), + ])}
- `; + ); } -function attachedVariantGrid(): TemplateResult { - return html` +function attachedVariantGrid(): VNode { + return (
- ${attachedVariantGridHeaders()} - ${STATUS_ICON_VARIANT_ROWS.map( - ({ label, variant }) => html` - ${label} - ${cell( - `${variant} · filled · attached`, - statusIconBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · border · attached`, - statusIconBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ${cell( - `${variant} · pulse · attached`, - statusIconBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - )} - ` - )} + {attachedVariantGridHeaders()} + {STATUS_ICON_VARIANT_ROWS.flatMap(({ label, variant }) => [ + {label}, + cell( + `${variant} · filled · attached`, + statusIconBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · border · attached`, + statusIconBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + cell( + `${variant} · pulse · attached`, + statusIconBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + }), + true + ), + ])}
- `; + ); } -function badgeStatusIconPreview(): TemplateResult { - return html` +function badgeStatusIconPreview(): VNode { + return (

Status-icon badge

@@ -110,8 +104,8 @@ function badgeStatusIconPreview(): TemplateResult {
- ${themePanel('dark', 'Dark', standaloneVariantGrid())} - ${themePanel('light', 'Light', standaloneVariantGrid())} + {themePanel('dark', 'Dark', standaloneVariantGrid())} + {themePanel('light', 'Light', standaloneVariantGrid())}
@@ -120,14 +114,14 @@ function badgeStatusIconPreview(): TemplateResult { Icon button anchor; status icon overlays top-trailing (−0.625rem default offset).

- ${themePanel('dark', 'Dark', attachedVariantGrid())} - ${themePanel('light', 'Light', attachedVariantGrid())} + {themePanel('dark', 'Dark', attachedVariantGrid())} + {themePanel('light', 'Light', attachedVariantGrid())}

Attached anchors

- ${cell( + {cell( 'IxIconButton · alarm', statusIconBadge({ variant: 'alarm', @@ -135,19 +129,19 @@ function badgeStatusIconPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'IxButton · primary · warning badge', statusIconBadge({ variant: 'warning', - children: html`Messages`, + children: Messages, }), true )} - ${cell( + {cell( 'IxAvatar · success', statusIconBadge({ variant: 'success', - children: html``, + children: , }), true )} @@ -157,7 +151,7 @@ function badgeStatusIconPreview(): TemplateResult {

Placement

- ${cell( + {cell( 'position="top-after" (default)', statusIconBadge({ variant: 'alarm', @@ -165,7 +159,7 @@ function badgeStatusIconPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'position="bottom-after"', statusIconBadge({ variant: 'info', @@ -174,7 +168,7 @@ function badgeStatusIconPreview(): TemplateResult { }), true )} - ${cell( + {cell( 'offsetX={6} offsetY={-4}', statusIconBadge({ variant: 'warning', @@ -194,14 +188,14 @@ function badgeStatusIconPreview(): TemplateResult { aria-describedby on anchor when attached).

- ${cell( + {cell( 'aria-label="Action required"', statusIconBadge({ variant: 'alarm', ariaLabel: 'Action required', }) )} - ${cell( + {cell( 'role="alert" · aria-label="Critical failure"', statusIconBadge({ variant: 'critical', @@ -215,11 +209,11 @@ function badgeStatusIconPreview(): TemplateResult {

Pulse

- ${cell( + {cell( 'filled · pulse · standalone', statusIconBadge({ variant: 'warning', enableAnimation: true }) )} - ${cell( + {cell( 'filled · pulse · attached', statusIconBadge({ variant: 'warning', @@ -231,7 +225,7 @@ function badgeStatusIconPreview(): TemplateResult {
- `; + ); } const meta = { @@ -245,5 +239,5 @@ type Story = StoryObj; export const StatusIcon: Story = { name: 'Status icon', - render: () => badgeStatusIconPreview(), + render: stencil(() => badgeStatusIconPreview()), }; From 67d6787178ead3435a2d267280fc98b671ef8e6d Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Sat, 25 Jul 2026 09:52:33 +0300 Subject: [PATCH 04/12] feat(badge): address review comments IX-3943 --- AGENTS.md | 4 +- .../src/preview-examples/badge-counter.html | 42 +++++++ .../src/preview-examples/badge-counter.ts | 45 +------ .../src/preview-examples/badge-dot.html | 42 +++++++ .../src/preview-examples/badge-dot.ts | 45 +------ .../src/preview-examples/badge-label.html | 34 ++++++ .../src/preview-examples/badge-label.ts | 47 ++----- .../preview-examples/badge-status-icon.html | 32 +++++ .../src/preview-examples/badge-status-icon.ts | 35 +----- .../src/preview-examples/badge.html | 31 +++++ .../src/preview-examples/badge.ts | 44 ++----- packages/core/src/components.d.ts | 4 + packages/core/src/components/badge/badge.scss | 7 +- packages/core/src/components/badge/badge.tsx | 16 +-- .../core/src/components/badge/badge.vars.scss | 16 +++ .../src/components/badge/test/badge.ct.ts | 115 +++++++++++------- .../src/components/badge/test/badge.page.ts | 112 +++++++++-------- .../accessibility/a11y-badge.stories.tsx | 2 +- 18 files changed, 360 insertions(+), 313 deletions(-) create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-counter.html create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-dot.html create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-label.html create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.html create mode 100644 packages/angular-standalone-test-app/src/preview-examples/badge.html create mode 100644 packages/core/src/components/badge/badge.vars.scss diff --git a/AGENTS.md b/AGENTS.md index ba2a89afd6f..b73b408e2a3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,7 +89,8 @@ Targeted commands: - Use core component tests for component behavior, interaction, keyboard handling, accessibility, slots, events, and state changes. - Include accessibility coverage (`makeAxeBuilder`) and a basic hydration/render test in component test files. - Add or update unit tests for pure logic changes, component tests for interaction/accessibility changes, and visual tests only for meaningful UI or theme changes. -- Prefer Playwright locators, user-visible assertions, and deterministic waits over implementation-detail selectors and timeouts. +- Prefer Playwright **accessibility locators** (`getByRole`, `getByLabel`, `getByText`, accessible name/description assertions) for user-facing contracts. Fall back to tag/CSS selectors for custom elements without roles and for decorative chrome outside the a11y tree. +- Prefer deterministic waits over implementation-detail selectors and timeouts. ## Visual regression testing @@ -130,6 +131,7 @@ Targeted commands: ## Component-test conventions (core) - Use `regressionTest` from `@utils/test` (not plain Playwright `test`). +- Prefer accessibility locators (`getByRole`, `getByLabel`, `getByText`) when elements expose roles/names; use tag/CSS selectors for host state and decorative/`aria-hidden` chrome. See `.github/instructions/component-tests.instructions.md`. - Use Playwright locators (including for Shadow DOM assertions). - Avoid arbitrary timeouts (`waitForTimeout`). - Register icons via mount config; do not fetch static SVG files directly in tests. diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-counter.html b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.html new file mode 100644 index 00000000000..29149a2d264 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.html @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts index 5b3873fc590..a8b4197470d 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-counter.ts @@ -13,50 +13,7 @@ import { IxBadge } from '@siemens/ix-angular/standalone'; @Component({ selector: 'app-example', imports: [IxBadge], + templateUrl: './badge-counter.html', styleUrls: ['./badge-counter.css'], - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, }) export default class BadgeCounter {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-dot.html b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.html new file mode 100644 index 00000000000..a6196e151f4 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.html @@ -0,0 +1,42 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts index b338105838b..b3d3296736d 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-dot.ts @@ -13,50 +13,7 @@ import { IxBadge } from '@siemens/ix-angular/standalone'; @Component({ selector: 'app-example', imports: [IxBadge], + templateUrl: './badge-dot.html', styleUrls: ['./badge-dot.css'], - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, }) export default class BadgeDot {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-label.html b/packages/angular-standalone-test-app/src/preview-examples/badge-label.html new file mode 100644 index 00000000000..179187e989a --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-label.html @@ -0,0 +1,34 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts index 75572a6582f..ad0087fd265 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-label.ts @@ -8,51 +8,18 @@ */ import { Component } from '@angular/core'; +import { IxBadge } from '@siemens/ix-angular/standalone'; import { addIcons } from '@siemens/ix-icons'; import { iconInfo } from '@siemens/ix-icons/icons'; -import { IxBadge } from '@siemens/ix-angular/standalone'; - -addIcons({ iconInfo }); @Component({ selector: 'app-example', imports: [IxBadge], + templateUrl: './badge-label.html', styleUrls: ['./badge-label.css'], - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, }) -export default class BadgeLabel {} +export default class BadgeLabel { + constructor() { + addIcons({ iconInfo }); + } +} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.html b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.html new file mode 100644 index 00000000000..ebfacbd6941 --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.html @@ -0,0 +1,32 @@ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts index 2e48ac92442..43256c57650 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts +++ b/packages/angular-standalone-test-app/src/preview-examples/badge-status-icon.ts @@ -13,40 +13,7 @@ import { IxBadge } from '@siemens/ix-angular/standalone'; @Component({ selector: 'app-example', imports: [IxBadge], + templateUrl: './badge-status-icon.html', styleUrls: ['./badge-status-icon.css'], - template: ` -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- `, }) export default class BadgeStatusIcon {} diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.html b/packages/angular-standalone-test-app/src/preview-examples/badge.html new file mode 100644 index 00000000000..68b161a507c --- /dev/null +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.html @@ -0,0 +1,31 @@ +
+ Review + + Bottom after + Messages + Device +
+ +
+ + + + + + + + + + +
+ +
+ + + + + + + + +
diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.ts b/packages/angular-standalone-test-app/src/preview-examples/badge.ts index 9bbd289cfe8..033f3960c34 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge.ts +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.ts @@ -8,48 +8,18 @@ */ import { Component } from '@angular/core'; +import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-angular/standalone'; import { addIcons } from '@siemens/ix-icons'; import { iconInfo, iconStar } from '@siemens/ix-icons/icons'; -import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-angular/standalone'; - -addIcons({ iconInfo, iconStar }); @Component({ selector: 'app-example', imports: [IxBadge, IxButton, IxIconButton], + templateUrl: './badge.html', styleUrls: ['./badge.css'], - template: ` -
- Review - - Bottom after - Messages - Device -
- -
- - - - - - - - - - -
- -
- - - - - - - - -
- `, }) -export default class Badge {} +export default class Badge { + constructor() { + addIcons({ iconInfo, iconStar }); + } +} diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 811f51857c0..5b8a529625f 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -284,6 +284,7 @@ export namespace Components { * Overlay indicator for counts, labels, dots, and status icons. * **Attached** (default slot has content): the indicator is decorative. * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * Host `role` / `aria-*` are discarded so the anchor owns the accessible name. * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. * For `dot` and `status-icon`, provide a host `aria-label` and a naming role * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). @@ -5275,6 +5276,7 @@ declare global { * Overlay indicator for counts, labels, dots, and status icons. * **Attached** (default slot has content): the indicator is decorative. * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * Host `role` / `aria-*` are discarded so the anchor owns the accessible name. * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. * For `dot` and `status-icon`, provide a host `aria-label` and a naming role * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). @@ -7164,6 +7166,7 @@ declare namespace LocalJSX { * Overlay indicator for counts, labels, dots, and status icons. * **Attached** (default slot has content): the indicator is decorative. * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * Host `role` / `aria-*` are discarded so the anchor owns the accessible name. * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. * For `dot` and `status-icon`, provide a host `aria-label` and a naming role * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). @@ -13408,6 +13411,7 @@ declare module "@stencil/core" { * Overlay indicator for counts, labels, dots, and status icons. * **Attached** (default slot has content): the indicator is decorative. * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * Host `role` / `aria-*` are discarded so the anchor owns the accessible name. * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. * For `dot` and `status-icon`, provide a host `aria-label` and a naming role * (for example `role="img"`, or `role="status"` / `role="alert"` for a live region). diff --git a/packages/core/src/components/badge/badge.scss b/packages/core/src/components/badge/badge.scss index ba28adfda1e..5c21bbd6d7f 100644 --- a/packages/core/src/components/badge/badge.scss +++ b/packages/core/src/components/badge/badge.scss @@ -8,6 +8,7 @@ */ @use 'mixins/shadow-dom/component'; +@use './badge.vars' as *; $predefined-variants: primary, alarm, critical, warning, info, neutral, success; $status-icon-variants: alarm, critical, warning, info, success; @@ -20,12 +21,6 @@ $border-radius: 100px; max-width: 100%; vertical-align: top; - --ix-badge-offset-x: 0rem; - --ix-badge-offset-y: 0rem; - --ix-badge-max-width: none; - --ix-badge-pulse-color: var(--theme-color-primary); - --ix-badge-animation-duration: 2s; - @include component.ix-component; } diff --git a/packages/core/src/components/badge/badge.tsx b/packages/core/src/components/badge/badge.tsx index e41fa5a2bd0..3164c80143e 100644 --- a/packages/core/src/components/badge/badge.tsx +++ b/packages/core/src/components/badge/badge.tsx @@ -55,6 +55,7 @@ const BADGE_DESCRIPTION_SLOT = 'description'; * * **Attached** (default slot has content): the indicator is decorative. * When `label` is set, that text is exposed on the anchor via `aria-describedby`. + * Host `role` / `aria-*` are discarded so the anchor owns the accessible name. * * **Standalone** (empty default slot): author `role` / `aria-*` stay on the host. * For `dot` and `status-icon`, provide a host `aria-label` and a naming role @@ -214,19 +215,21 @@ export class Badge private hasDisconnected = false; override componentWillLoad() { + // Mixin strips host ARIA into `inheritAriaAttributes` and removes them from the host. super.componentWillLoad(); this.descriptionId = `${this.getHostElementId()}-description`; const hasAnchor = this.detectHasAnchor(); if (hasAnchor) { this.hasAnchor = true; - a11yHostAttributes(this.hostElement); + // Attached: discard host ARIA — the anchor owns naming; the indicator is decorative + // (`aria-hidden`) and count/label text is exposed via `aria-describedby` on the anchor. this.inheritAriaAttributes = {}; return; } this.hasAnchor = false; - // Preserve author ARIA for standalone mode. + // Standalone: keep mixin-captured ARIA and re-apply on `` in `render()`. } override componentDidLoad() { @@ -302,6 +305,8 @@ export class Badge if (hasAnchor) { this.hasAnchor = true; + // Strip any ARIA still on the host (e.g. re-applied while standalone) and discard — + // attached mode must not keep role / aria-* on the wrapper. a11yHostAttributes(this.hostElement); this.inheritAriaAttributes = {}; this.descriptionId = `${this.getHostElementId()}-description`; @@ -309,7 +314,7 @@ export class Badge } this.hasAnchor = false; - // Re-apply author ARIA after leaving attached mode. + // Leaving attached: capture any author ARIA set on the host for standalone ``. this.inheritAriaAttributes = a11yHostAttributes(this.hostElement); } @@ -405,10 +410,7 @@ export class Badge } return ( - + {text} ); diff --git a/packages/core/src/components/badge/badge.vars.scss b/packages/core/src/components/badge/badge.vars.scss new file mode 100644 index 00000000000..3e5aa6eacd1 --- /dev/null +++ b/packages/core/src/components/badge/badge.vars.scss @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2026 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. + */ + +:host { + --ix-badge-offset-x: 0rem; + --ix-badge-offset-y: 0rem; + --ix-badge-max-width: none; + --ix-badge-pulse-color: var(--theme-color-primary); + --ix-badge-animation-duration: 2s; +} diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts index da226428e83..2dad0733ab7 100644 --- a/packages/core/src/components/badge/test/badge.ct.ts +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -63,7 +63,7 @@ regressionTest.describe('ix-badge', () => { await badge.expectHydrated(); await badge.expectStandalone(); await expect(badge.host).toHaveAttribute('variant', 'info'); - await badge.expectLabelText('12'); + await badge.expectVisibleLabel('12'); }); regressionTest( @@ -84,7 +84,7 @@ regressionTest.describe('ix-badge', () => { regressionTest('formats overflow label as 99+', async ({ mount, page }) => { await mount(``); const badge = new BadgePage(page); - await badge.expectLabelText('99+'); + await badge.expectVisibleLabel('99+'); }); regressionTest( @@ -92,7 +92,7 @@ regressionTest.describe('ix-badge', () => { async ({ mount, page }) => { await mount(``); const badge = new BadgePage(page); - await badge.expectLabelText('99+'); + await badge.expectVisibleLabel('99+'); } ); @@ -151,16 +151,16 @@ regressionTest.describe('ix-badge', () => { await mount( html` `, @@ -168,22 +168,30 @@ regressionTest.describe('ix-badge', () => { ); const badge = new BadgePage(page); - const filled = badge.locator('#filled'); - const outline = badge.locator('#outline'); + const filled = badge.getByRole('img', 'Info filled'); + const outline = badge.getByRole('img', 'Info outline'); await expect(filled).toHaveClass(/\binfo\b/); await expect(outline).toHaveClass(/\boutline\b/); - await expect(filled.locator('ix-icon.status-icon-glyph')).toBeVisible(); - await expect(filled.locator('ix-icon.status-icon-plate')).toBeVisible(); - await expect(outline.locator('ix-icon.status-icon')).toBeVisible(); - await expect(outline.locator('ix-icon.status-icon-plate')).toHaveCount( - 0 - ); - - const filledName = await filled + await expect( + badge.indicatorOf(filled).locator('ix-icon.status-icon-glyph') + ).toBeVisible(); + await expect( + badge.indicatorOf(filled).locator('ix-icon.status-icon-plate') + ).toBeVisible(); + await expect( + badge.indicatorOf(outline).locator('ix-icon.status-icon') + ).toBeVisible(); + await expect( + badge.indicatorOf(outline).locator('ix-icon.status-icon-plate') + ).toHaveCount(0); + + const filledName = await badge + .indicatorOf(filled) .locator('ix-icon.status-icon-glyph') .evaluate((el: HTMLIxIconElement) => el.name); - const outlineName = await outline + const outlineName = await badge + .indicatorOf(outline) .locator('ix-icon.status-icon') .evaluate((el: HTMLIxIconElement) => el.name); @@ -330,6 +338,28 @@ regressionTest.describe('ix-badge', () => { }); regressionTest.describe('attached accessibility', () => { + regressionTest( + 'discards host ARIA when attached (anchor owns naming)', + async ({ mount, page }) => { + await mount(html` + + + + `); + + const badge = new BadgePage(page); + await badge.expectAttached(); + await expect(badge.host).not.toHaveAttribute('role'); + await expect(badge.host).not.toHaveAttribute('aria-label'); + await badge.expectAttachedTextLabelA11y('Messages', '3'); + } + ); + regressionTest( 'sets aria-describedby for text label on anchor', async ({ mount, page }) => { @@ -380,7 +410,7 @@ regressionTest.describe('ix-badge', () => { ); regressionTest( - 'updates hidden description when label changes', + 'updates accessible description when label changes', async ({ mount, page }) => { await mount(html` @@ -389,47 +419,46 @@ regressionTest.describe('ix-badge', () => { `); const badge = new BadgePage(page); - await expect(badge.description).toHaveText('3'); + await badge.expectAttachedTextLabelA11y('Messages', '3'); await badge.setLabel('8'); - await expect(badge.description).toHaveText('8'); + await badge.expectAttachedTextLabelA11y('Messages', '8'); } ); regressionTest( - 'removes aria-describedby from anchor on disconnect', + 'removes accessible description from anchor on disconnect', async ({ mount, page }) => { await mount(html` - + `); const badge = new BadgePage(page); - const button = badge.locator('#anchor'); - await expect(button).toHaveAttribute('aria-describedby', /.+/); + const button = badge.getButton('Messages'); + await badge.expectAttachedTextLabelA11y('Messages', '3'); - await badge.disconnectKeepingAnchor('#anchor'); + await badge.disconnectKeepingAnchor('Messages'); await expect(button).not.toHaveAttribute('aria-describedby'); } ); regressionTest( - 'restores aria-describedby after reconnect', + 'restores accessible description after reconnect', async ({ mount, page }) => { await mount(html`
- +
`); const badge = new BadgePage(page); - const button = badge.locator('#anchor'); - await expect(button).toHaveAttribute('aria-describedby', /.+/); + await badge.expectAttachedTextLabelA11y('Messages', '3'); await page.evaluate(() => { const host = document.querySelector('ix-badge'); @@ -440,7 +469,6 @@ regressionTest.describe('ix-badge', () => { } }); - await expect(button).toHaveAttribute('aria-describedby', /.+/); await badge.expectAttachedTextLabelA11y('Messages', '3'); } ); @@ -454,7 +482,7 @@ regressionTest.describe('ix-badge', () => { const badge = new BadgePage(page); await expect(badge.host).toHaveAttribute('type', 'label'); - await badge.expectLabelText('NEW'); + await badge.expectVisibleLabel('NEW'); }); regressionTest( @@ -501,7 +529,7 @@ regressionTest.describe('ix-badge', () => { const badge = new BadgePage(page); await badge.expectLeadingIconNamed('Featured'); - await badge.expectLabelText('NEW'); + await badge.expectVisibleLabel('NEW'); } ); @@ -587,6 +615,7 @@ regressionTest.describe('ix-badge', () => { role: 'alert', ariaLabel: 'Urgent update', }); + await expect(badge.getByRole('alert', 'Urgent update')).toBeVisible(); } ); @@ -616,7 +645,7 @@ regressionTest.describe('ix-badge', () => { await badge.host.hover(); await expect(badge.host).not.toHaveAttribute('tooltip-text'); - await expect(badge.host.locator('ix-tooltip')).not.toBeAttached(); + await expect(badge.tooltip()).not.toBeAttached(); } ); @@ -630,10 +659,7 @@ regressionTest.describe('ix-badge', () => { await badge.expectHydrated(); await badge.indicator.hover(); - await expectVisibleTooltipText( - badge.host.locator('ix-tooltip'), - 'Label' - ); + await expectVisibleTooltipText(badge.tooltip(), 'Label'); } ); @@ -647,10 +673,7 @@ regressionTest.describe('ix-badge', () => { await badge.expectHydrated(); await badge.indicator.hover(); - await expectVisibleTooltipText( - badge.host.locator('ix-tooltip'), - 'Twelve items' - ); + await expectVisibleTooltipText(badge.tooltip(), 'Twelve items'); } ); @@ -661,13 +684,11 @@ regressionTest.describe('ix-badge', () => { `` ); const badge = new BadgePage(page); - await badge.expectHydrated(); - await badge.indicator.hover(); + const named = badge.getByRole('img', 'Unread'); + await badge.expectHydrated(named); + await badge.indicatorOf(named).hover(); - await expectVisibleTooltipText( - badge.host.locator('ix-tooltip'), - 'Unread' - ); + await expectVisibleTooltipText(badge.tooltip(named), 'Unread'); } ); @@ -684,7 +705,7 @@ regressionTest.describe('ix-badge', () => { await badge.expectAttached(); await badge.indicator.hover(); - await expect(badge.host.locator('ix-tooltip')).not.toBeAttached(); + await expect(badge.tooltip()).not.toBeAttached(); } ); }); diff --git a/packages/core/src/components/badge/test/badge.page.ts b/packages/core/src/components/badge/test/badge.page.ts index 9395fb33c85..872e3f26f64 100644 --- a/packages/core/src/components/badge/test/badge.page.ts +++ b/packages/core/src/components/badge/test/badge.page.ts @@ -12,11 +12,16 @@ import { expect, Locator, Page } from '@playwright/test'; /** * Page Object Model for ix-badge component testing. * + * Prefer accessibility locators (`getByRole`, `getByText`, accessible name / + * description) for author-facing contracts. Fall back to tag / CSS selectors + * for custom-element host state and decorative chrome (e.g. attached + * `aria-hidden` indicator) that is intentionally outside the a11y tree. + * * Usage: * ```ts * const badge = new BadgePage(page); * await badge.expectHydrated(); - * await badge.expectLabelText('12'); + * await badge.expectVisibleLabel('12'); * ``` */ export class BadgePage { @@ -26,15 +31,35 @@ export class BadgePage { this.page = page; } - /** First badge on the page (single-badge fixtures). */ + /** First badge on the page (single-badge fixtures without a naming role). */ get host(): Locator { return this.page.locator('ix-badge').first(); } + /** + * Named standalone badge via host `role` + accessible name. + * Prefer this over `host` when the fixture sets `role` / `aria-label`. + */ + getByRole(role: 'img' | 'alert' | 'status', name: string | RegExp): Locator { + return this.page.getByRole(role, { name }); + } + + getButton(name: string | RegExp): Locator { + return this.page.getByRole('button', { name }); + } + + /** + * Decorative indicator chrome (often `aria-hidden` when attached). + * Structural on purpose — not exposed in the accessibility tree. + */ get indicator(): Locator { return this.host.locator('.indicator'); } + indicatorOf(badge: Locator): Locator { + return badge.locator('.indicator'); + } + get label(): Locator { return this.host.locator('.label'); } @@ -43,12 +68,16 @@ export class BadgePage { return this.host.locator(`> .description, > [slot="description"]`).first(); } - getButton(name: string): Locator { - return this.page.getByRole('button', { name }); + get leadingIcon(): Locator { + return this.indicator.locator('ix-icon.icon'); } - locator(selector: string): Locator { - return this.page.locator(selector); + get statusIconPlate(): Locator { + return this.indicator.locator('ix-icon.status-icon-plate'); + } + + get statusIconGlyph(): Locator { + return this.indicator.locator('ix-icon.status-icon-glyph'); } async expectHydrated(badge: Locator = this.host): Promise { @@ -77,31 +106,19 @@ export class BadgePage { await expect(badge).not.toHaveClass(pattern); } - async expectLabelText( + async expectVisibleLabel( text: string, badge: Locator = this.host ): Promise { - await expect(badge.locator('.label')).toHaveText(text); + await expect(badge.getByText(text, { exact: true })).toBeVisible(); } async expectNoIndicator(badge: Locator = this.host): Promise { - await expect(badge.locator('.indicator')).toHaveCount(0); + await expect(this.indicatorOf(badge)).toHaveCount(0); } async expectIndicatorVisible(badge: Locator = this.host): Promise { - await expect(badge.locator('.indicator')).toBeVisible(); - } - - get leadingIcon(): Locator { - return this.indicator.locator('ix-icon.icon'); - } - - get statusIconPlate(): Locator { - return this.indicator.locator('ix-icon.status-icon-plate'); - } - - get statusIconGlyph(): Locator { - return this.indicator.locator('ix-icon.status-icon-glyph'); + await expect(this.indicatorOf(badge)).toBeVisible(); } async expectLeadingIconDecorative(): Promise { @@ -110,8 +127,7 @@ export class BadgePage { } async expectLeadingIconNamed(ariaLabel: string): Promise { - await expect(this.leadingIcon).toBeVisible(); - await expect(this.leadingIcon).toHaveAttribute('aria-label', ariaLabel); + await expect(this.indicator.getByLabel(ariaLabel)).toBeVisible(); await expect(this.leadingIcon).toHaveAttribute('aria-hidden', 'false'); } @@ -162,7 +178,8 @@ export class BadgePage { expect(descriptionId).toBeTruthy(); expect(describedBy!.split(/\s+/)).toContain(descriptionId); - // Description stays in light DOM for aria-describedby. + // Description stays in light DOM for aria-describedby (SR-only chrome is + // not always exposed via Playwright's accessible description API). await expect .poll(async () => this.page.evaluate( @@ -171,14 +188,6 @@ export class BadgePage { ) ) .toBe(descriptionText); - await expect - .poll(async () => - this.host.evaluate((host, id) => { - const description = host.querySelector(`:scope > #${CSS.escape(id)}`); - return description?.getAttribute('slot') ?? null; - }, descriptionId!) - ) - .toBe('description'); await expect(this.indicator).toHaveAttribute('aria-hidden', 'true'); } @@ -215,7 +224,7 @@ export class BadgePage { await expect(this.indicator).not.toHaveAttribute('aria-label'); if (options.visibleLabel !== undefined) { - await this.expectLabelText(options.visibleLabel); + await this.expectVisibleLabel(options.visibleLabel); } if (options.hostRole === null) { @@ -233,21 +242,17 @@ export class BadgePage { } async expectStandaloneHostAria(options: { - role?: string; - ariaLabel?: string; + role: 'img' | 'alert' | 'status'; + ariaLabel: string; ariaLive?: string; }): Promise { - await this.expectStandalone(); - await expect(this.indicator).not.toHaveAttribute('role'); + const named = this.getByRole(options.role, options.ariaLabel); + await expect(named).toBeVisible(); + await this.expectStandalone(named); + await expect(this.indicatorOf(named)).not.toHaveAttribute('role'); - if (options.role !== undefined) { - await expect(this.host).toHaveAttribute('role', options.role); - } - if (options.ariaLabel !== undefined) { - await expect(this.host).toHaveAttribute('aria-label', options.ariaLabel); - } if (options.ariaLive !== undefined) { - await expect(this.host).toHaveAttribute('aria-live', options.ariaLive); + await expect(named).toHaveAttribute('aria-live', options.ariaLive); } } @@ -260,15 +265,18 @@ export class BadgePage { ); } - async disconnectKeepingAnchor(anchorSelector: string): Promise { - await this.page.evaluate((selector) => { - const badge = document.querySelector('ix-badge'); - const anchor = document.querySelector(selector); - - if (badge && anchor) { + async disconnectKeepingAnchor(buttonName: string): Promise { + const button = this.getButton(buttonName); + await button.evaluate((anchor) => { + const badge = anchor.closest('ix-badge'); + if (badge) { document.body.appendChild(anchor); badge.remove(); } - }, anchorSelector); + }); + } + + tooltip(badge: Locator = this.host): Locator { + return badge.locator('ix-tooltip'); } } diff --git a/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx index 30bbf91b749..c50ba44f36b 100644 --- a/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx +++ b/packages/storybook-docs/src/stories/badge/accessibility/a11y-badge.stories.tsx @@ -80,7 +80,7 @@ export const AttachedWithCount: Story = { */ export const AttachedDot: Story = { render: stencil(() => ( - + )), From 22b0709de24f01da83b329968fddf7d58264ccc1 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Sat, 25 Jul 2026 10:05:29 +0300 Subject: [PATCH 05/12] feat(badge): address review comments IX-3943 --- packages/core/src/components/badge/badge.tsx | 5 ++++- packages/core/src/components/badge/test/badge.ct.ts | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/core/src/components/badge/badge.tsx b/packages/core/src/components/badge/badge.tsx index 3164c80143e..51508b142de 100644 --- a/packages/core/src/components/badge/badge.tsx +++ b/packages/core/src/components/badge/badge.tsx @@ -410,7 +410,10 @@ export class Badge } return ( - + {text} ); diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts index 2dad0733ab7..1d704593201 100644 --- a/packages/core/src/components/badge/test/badge.ct.ts +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -710,7 +710,7 @@ regressionTest.describe('ix-badge', () => { ); }); - regressionTest('accessibility', async ({ mount, makeAxeBuilder }) => { + regressionTest('accessibility', async ({ mount, makeAxeBuilder, page }) => { await mount(html`
@@ -741,6 +741,10 @@ regressionTest.describe('ix-badge', () => {
`); + // Nested tooltips must hydrate (`role="tooltip"`) before axe; otherwise + // `aria-label` on `ix-tooltip` trips aria-prohibited-attr. + await expect(page.locator('ix-tooltip.hydrated')).toHaveCount(2); + const accessibilityScanResults = await makeAxeBuilder().analyze(); expect(accessibilityScanResults.violations).toEqual([]); }); From 47dc5c8a1e70db6c9a848d53befd3c40b8ae5b29 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Sat, 25 Jul 2026 10:16:06 +0300 Subject: [PATCH 06/12] feat(badge): address review comments IX-3943 --- .../src/preview-examples/badge.html | 2 +- .../src/preview-examples/badge.html | 2 +- .../src/preview-examples/badge.html | 2 +- .../src/preview-examples/badge.tsx | 2 +- .../stories/badge/badge-preview.shared.tsx | 123 ++++++++++++++++-- .../src/stories/badge/counter.stories.tsx | 60 +-------- .../src/stories/badge/dot.stories.tsx | 76 +++-------- .../src/stories/badge/label.stories.tsx | 80 +++--------- .../src/stories/badge/status-icon.stories.tsx | 85 +++--------- .../src/preview-examples/badge.vue | 2 +- 10 files changed, 176 insertions(+), 258 deletions(-) diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.html b/packages/angular-standalone-test-app/src/preview-examples/badge.html index 68b161a507c..0bdaeccb6cc 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge.html +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.html @@ -10,7 +10,7 @@ - + diff --git a/packages/angular-test-app/src/preview-examples/badge.html b/packages/angular-test-app/src/preview-examples/badge.html index 68b161a507c..0bdaeccb6cc 100644 --- a/packages/angular-test-app/src/preview-examples/badge.html +++ b/packages/angular-test-app/src/preview-examples/badge.html @@ -10,7 +10,7 @@ - + diff --git a/packages/html-test-app/src/preview-examples/badge.html b/packages/html-test-app/src/preview-examples/badge.html index a60075aceea..a1f00b27c25 100644 --- a/packages/html-test-app/src/preview-examples/badge.html +++ b/packages/html-test-app/src/preview-examples/badge.html @@ -33,7 +33,7 @@ - + diff --git a/packages/react-test-app/src/preview-examples/badge.tsx b/packages/react-test-app/src/preview-examples/badge.tsx index ef68b643ad7..451e86119f8 100644 --- a/packages/react-test-app/src/preview-examples/badge.tsx +++ b/packages/react-test-app/src/preview-examples/badge.tsx @@ -46,7 +46,7 @@ export default () => { - + diff --git a/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx b/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx index 4fbe82b9bca..4d59b7b5d21 100644 --- a/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx +++ b/packages/storybook-docs/src/stories/badge/badge-preview.shared.tsx @@ -79,21 +79,39 @@ export function themePanel( export function variantGridHeaders(): VNode[] { return [ - , - Filled, - Outline, - Border, - Pulse, + , + + Filled + , + + Outline + , + + Border + , + + Pulse + , ]; } /** Attached grids omit Outline — not recommended on anchors. */ export function attachedVariantGridHeaders(): VNode[] { return [ - , - Filled, - Border, - Pulse, + , + + Filled + , + + Border + , + + Pulse + , ]; } @@ -101,6 +119,93 @@ export function iconButtonAnchor(ariaLabel: string): VNode { return ; } +type VariantRow = { + label: string; + variant: V; +}; + +type VariantGridBadgeFactory = (options: { + variant: V; + outline?: boolean; + border?: boolean; + enableAnimation?: boolean; + children?: VNode | null; +}) => VNode; + +export function buildStandaloneVariantGrid( + rows: readonly VariantRow[], + createBadge: VariantGridBadgeFactory +): VNode { + return ( +
+ {variantGridHeaders()} + {rows.flatMap(({ label, variant }) => [ + + {label} + , +
+ {`${variant} · filled`} + {createBadge({ variant })} +
, +
+ {`${variant} · outline`} + {createBadge({ variant, outline: true })} +
, +
+ {`${variant} · border`} + {createBadge({ variant, border: true })} +
, +
+ {`${variant} · pulse`} +
+ {createBadge({ variant, enableAnimation: true })} + {createBadge({ variant, outline: true, enableAnimation: true })} +
+
, + ])} +
+ ); +} + +export function buildAttachedVariantGrid( + rows: readonly VariantRow[], + createBadge: VariantGridBadgeFactory +): VNode { + return ( +
+ {attachedVariantGridHeaders()} + {rows.flatMap(({ label, variant }) => [ + + {label} + , +
+ {`${variant} · filled · attached`} + {createBadge({ + variant, + children: iconButtonAnchor(`${label} anchor`), + })} +
, +
+ {`${variant} · border · attached`} + {createBadge({ + variant, + border: true, + children: iconButtonAnchor(`${label} anchor`), + })} +
, +
+ {`${variant} · pulse · attached`} + {createBadge({ + variant, + enableAnimation: true, + children: iconButtonAnchor(`${label} anchor`), + })} +
, + ])} +
+ ); +} + type CustomColors = { background?: string; badgeColor?: string; diff --git a/packages/storybook-docs/src/stories/badge/counter.stories.tsx b/packages/storybook-docs/src/stories/badge/counter.stories.tsx index 767a838ac08..72bdb327f28 100644 --- a/packages/storybook-docs/src/stories/badge/counter.stories.tsx +++ b/packages/storybook-docs/src/stories/badge/counter.stories.tsx @@ -11,14 +11,14 @@ import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { stencil } from '@utils/stencil-render'; import { - attachedVariantGridHeaders, + buildAttachedVariantGrid, + buildStandaloneVariantGrid, cell, counterBadge, iconButtonAnchor, showcaseParameters, themePanel, VARIANT_ROWS, - variantGridHeaders, } from './badge-preview.shared'; /** @@ -26,61 +26,11 @@ import { * (`/preview/badge`). */ function standaloneVariantGrid(): VNode { - return ( -
- {variantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell(`${variant} · filled`, counterBadge({ variant })), - cell(`${variant} · outline`, counterBadge({ variant, outline: true })), - cell(`${variant} · border`, counterBadge({ variant, border: true })), - cell( - `${variant} · pulse`, -
- {counterBadge({ variant, enableAnimation: true })} - {counterBadge({ variant, outline: true, enableAnimation: true })} -
- ), - ])} -
- ); + return buildStandaloneVariantGrid(VARIANT_ROWS, counterBadge); } function attachedVariantGrid(): VNode { - return ( -
- {attachedVariantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell( - `${variant} · filled · attached`, - counterBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · border · attached`, - counterBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · pulse · attached`, - counterBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - ])} -
- ); + return buildAttachedVariantGrid(VARIANT_ROWS, counterBadge); } function badgeCounterPreview(): VNode { @@ -89,7 +39,7 @@ function badgeCounterPreview(): VNode {

type="counter"

- Solid cell border = alignment grid; dashed outline = + Solid cell border = alignment grid; dashed outline ={' '} ix-badge host bounds.

diff --git a/packages/storybook-docs/src/stories/badge/dot.stories.tsx b/packages/storybook-docs/src/stories/badge/dot.stories.tsx index 14fd09912e7..ecf00812150 100644 --- a/packages/storybook-docs/src/stories/badge/dot.stories.tsx +++ b/packages/storybook-docs/src/stories/badge/dot.stories.tsx @@ -11,14 +11,14 @@ import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { stencil } from '@utils/stencil-render'; import { - attachedVariantGridHeaders, + buildAttachedVariantGrid, + buildStandaloneVariantGrid, cell, dotBadge, iconButtonAnchor, showcaseParameters, themePanel, VARIANT_ROWS, - variantGridHeaders, } from './badge-preview.shared'; /** @@ -26,61 +26,11 @@ import { * (`/preview/badge-dot`). */ function standaloneVariantGrid(): VNode { - return ( -
- {variantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell(`${variant} · filled`, dotBadge({ variant })), - cell(`${variant} · outline`, dotBadge({ variant, outline: true })), - cell(`${variant} · border`, dotBadge({ variant, border: true })), - cell( - `${variant} · pulse`, -
- {dotBadge({ variant, enableAnimation: true })} - {dotBadge({ variant, outline: true, enableAnimation: true })} -
- ), - ])} -
- ); + return buildStandaloneVariantGrid(VARIANT_ROWS, dotBadge); } function attachedVariantGrid(): VNode { - return ( -
- {attachedVariantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell( - `${variant} · filled · attached`, - dotBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · border · attached`, - dotBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · pulse · attached`, - dotBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - ])} -
- ); + return buildAttachedVariantGrid(VARIANT_ROWS, dotBadge); } function badgeDotPreview(): VNode { @@ -89,10 +39,14 @@ function badgeDotPreview(): VNode {

Dot badge

- type="dot" · 12×12px circle · no label. - Attached default offset −6px / −6px (top-trailing). Standalone dots - need aria-label on the host; attached dots are decorative - (anchor carries meaning). + type="dot" + {' · 12×12px circle · no '} + label + { + '. Attached default offset −6px / −6px (top-trailing). Standalone dots need ' + } + aria-label + {' on the host; attached dots are decorative (anchor carries meaning).'}

@@ -177,8 +131,10 @@ function badgeDotPreview(): VNode {

Standalone a11y

- Set aria-label on ix-badge (no - aria-describedby on anchor when attached). + Set aria-label on ix-badge + {' (no '} + aria-describedby + {' on anchor when attached).'}

{cell( diff --git a/packages/storybook-docs/src/stories/badge/label.stories.tsx b/packages/storybook-docs/src/stories/badge/label.stories.tsx index 02a14ed1f19..13481d2b2f9 100644 --- a/packages/storybook-docs/src/stories/badge/label.stories.tsx +++ b/packages/storybook-docs/src/stories/badge/label.stories.tsx @@ -11,14 +11,14 @@ import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { stencil } from '@utils/stencil-render'; import { - attachedVariantGridHeaders, + buildAttachedVariantGrid, + buildStandaloneVariantGrid, cell, iconButtonAnchor, labelBadge, showcaseParameters, themePanel, VARIANT_ROWS, - variantGridHeaders, } from './badge-preview.shared'; /** @@ -26,61 +26,11 @@ import { * (`/preview/badge-label`). */ function standaloneVariantGrid(): VNode { - return ( -
- {variantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell(`${variant} · filled`, labelBadge({ variant })), - cell(`${variant} · outline`, labelBadge({ variant, outline: true })), - cell(`${variant} · border`, labelBadge({ variant, border: true })), - cell( - `${variant} · pulse`, -
- {labelBadge({ variant, enableAnimation: true })} - {labelBadge({ variant, outline: true, enableAnimation: true })} -
- ), - ])} -
- ); + return buildStandaloneVariantGrid(VARIANT_ROWS, labelBadge); } function attachedVariantGrid(): VNode { - return ( -
- {attachedVariantGridHeaders()} - {VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell( - `${variant} · filled · attached`, - labelBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · border · attached`, - labelBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · pulse · attached`, - labelBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - ])} -
- ); + return buildAttachedVariantGrid(VARIANT_ROWS, labelBadge); } function badgeLabelPreview(): VNode { @@ -89,11 +39,16 @@ function badgeLabelPreview(): VNode {

Label badge

- type="label" · text pill (20px height) · - label required · body-regular typography · leading - icon in examples. Optional - aria-label-icon and align-left. Attached - default offset −10px / −10px. + type="label" + {' · text pill (20px height) · '} + label + {' required · body-regular typography · leading '} + icon + {' in examples. Optional '} + aria-label-icon + {' and '} + align-left + {'. Attached default offset −10px / −10px.'}

@@ -227,9 +182,10 @@ function badgeLabelPreview(): VNode {

Standalone a11y

- Attached: label text via aria-describedby on anchor. - Standalone: author ARIA stays on the host (pill-like; opt-in live - region). + Attached: label text via aria-describedby + { + ' on anchor. Standalone: author ARIA stays on the host (pill-like; opt-in live region).' + }

{cell( diff --git a/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx b/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx index d676b90e89e..8e8d9634c96 100644 --- a/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx +++ b/packages/storybook-docs/src/stories/badge/status-icon.stories.tsx @@ -11,14 +11,14 @@ import { h, type VNode } from '@stencil/core'; import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { stencil } from '@utils/stencil-render'; import { - attachedVariantGridHeaders, + buildAttachedVariantGrid, + buildStandaloneVariantGrid, cell, iconButtonAnchor, showcaseParameters, STATUS_ICON_VARIANT_ROWS, statusIconBadge, themePanel, - variantGridHeaders, } from './badge-preview.shared'; /** @@ -26,68 +26,11 @@ import { * (`/preview/badge-status-icon`). */ function standaloneVariantGrid(): VNode { - return ( -
- {variantGridHeaders()} - {STATUS_ICON_VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell(`${variant} · filled`, statusIconBadge({ variant })), - cell( - `${variant} · outline`, - statusIconBadge({ variant, outline: true }) - ), - cell(`${variant} · border`, statusIconBadge({ variant, border: true })), - cell( - `${variant} · pulse`, -
- {statusIconBadge({ variant, enableAnimation: true })} - {statusIconBadge({ - variant, - outline: true, - enableAnimation: true, - })} -
- ), - ])} -
- ); + return buildStandaloneVariantGrid(STATUS_ICON_VARIANT_ROWS, statusIconBadge); } function attachedVariantGrid(): VNode { - return ( -
- {attachedVariantGridHeaders()} - {STATUS_ICON_VARIANT_ROWS.flatMap(({ label, variant }) => [ - {label}, - cell( - `${variant} · filled · attached`, - statusIconBadge({ - variant, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · border · attached`, - statusIconBadge({ - variant, - border: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - cell( - `${variant} · pulse · attached`, - statusIconBadge({ - variant, - enableAnimation: true, - children: iconButtonAnchor(`${label} anchor`), - }), - true - ), - ])} -
- ); + return buildAttachedVariantGrid(STATUS_ICON_VARIANT_ROWS, statusIconBadge); } function badgeStatusIconPreview(): VNode { @@ -96,10 +39,16 @@ function badgeStatusIconPreview(): VNode {

Status-icon badge

- type="status-icon" · 20×20px circle · icon from - variant · no label. Attached default offset - −10px / −10px. Same a11y as dot: attached = decorative; standalone - needs aria-label on the host. + type="status-icon" + {' · 20×20px circle · icon from '} + variant + {' · no '} + label + { + '. Attached default offset −10px / −10px. Same a11y as dot: attached = decorative; standalone needs ' + } + aria-label + {' on the host.'}

@@ -184,8 +133,10 @@ function badgeStatusIconPreview(): VNode {

Standalone a11y

- Set aria-label on ix-badge (no - aria-describedby on anchor when attached). + Set aria-label on ix-badge + {' (no '} + aria-describedby + {' on anchor when attached).'}

{cell( diff --git a/packages/vue-test-app/src/preview-examples/badge.vue b/packages/vue-test-app/src/preview-examples/badge.vue index 57edb99cc57..a55f25d1e48 100644 --- a/packages/vue-test-app/src/preview-examples/badge.vue +++ b/packages/vue-test-app/src/preview-examples/badge.vue @@ -27,7 +27,7 @@ import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-vue'; - + From 640a799a362b3657e49a18ebc2e2bdaedca31d04 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Sat, 25 Jul 2026 10:24:28 +0300 Subject: [PATCH 07/12] feat(badge): address review comments IX-3943 --- packages/core/src/components/badge/test/badge.ct.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts index 1d704593201..8c20d30a640 100644 --- a/packages/core/src/components/badge/test/badge.ct.ts +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -741,9 +741,10 @@ regressionTest.describe('ix-badge', () => {
`); - // Nested tooltips must hydrate (`role="tooltip"`) before axe; otherwise - // `aria-label` on `ix-tooltip` trips aria-prohibited-attr. - await expect(page.locator('ix-tooltip.hydrated')).toHaveCount(2); + // Nested tooltips must expose `role="tooltip"` before axe; otherwise + // `aria-label` on `ix-tooltip` trips aria-prohibited-attr. Slot text alone is + // not enough: content is projected into an inert dialog until shown. + await expect(page.getByRole('tooltip')).toHaveCount(2); const accessibilityScanResults = await makeAxeBuilder().analyze(); expect(accessibilityScanResults.violations).toEqual([]); From 59920649cf7ed1ca78d5735739c3894e9e772649 Mon Sep 17 00:00:00 2001 From: Alex Kaduk Date: Mon, 27 Jul 2026 20:35:26 +0300 Subject: [PATCH 08/12] feat(badge): address review comments IX-3943 --- .../src/preview-examples/badge.html | 10 +++---- .../src/preview-examples/badge.html | 10 +++---- packages/core/src/components/badge/badge.scss | 8 ++++++ .../src/components/badge/test/badge.ct.ts | 28 +++++++++++++++++++ .../src/preview-examples/badge.html | 10 +++---- .../src/preview-examples/badge.tsx | 13 +++++---- .../src/preview-examples/badge.vue | 10 +++---- .../__snapshots__/badge-aria-snapshot.yaml | 26 +++++++++++++---- 8 files changed, 85 insertions(+), 30 deletions(-) diff --git a/packages/angular-standalone-test-app/src/preview-examples/badge.html b/packages/angular-standalone-test-app/src/preview-examples/badge.html index 0bdaeccb6cc..5abda16314f 100644 --- a/packages/angular-standalone-test-app/src/preview-examples/badge.html +++ b/packages/angular-standalone-test-app/src/preview-examples/badge.html @@ -1,9 +1,9 @@
- Review - - Bottom after - Messages - Device + Review + + Bottom after + Messages + Device
diff --git a/packages/angular-test-app/src/preview-examples/badge.html b/packages/angular-test-app/src/preview-examples/badge.html index 0bdaeccb6cc..5abda16314f 100644 --- a/packages/angular-test-app/src/preview-examples/badge.html +++ b/packages/angular-test-app/src/preview-examples/badge.html @@ -1,9 +1,9 @@
- Review - - Bottom after - Messages - Device + Review + + Bottom after + Messages + Device
diff --git a/packages/core/src/components/badge/badge.scss b/packages/core/src/components/badge/badge.scss index 5c21bbd6d7f..4f894a111be 100644 --- a/packages/core/src/components/badge/badge.scss +++ b/packages/core/src/components/badge/badge.scss @@ -55,6 +55,13 @@ $border-radius: 100px; isolation: isolate; } +/* Standalone text badges: allow selecting label/count text (usage guide). */ +:host([type='label']:not(.attached)) .indicator, +:host([type='counter']:not(.attached)) .indicator { + pointer-events: auto; + user-select: text; +} + :host(.with-tooltip:not(.attached)) .indicator { pointer-events: auto; } @@ -72,6 +79,7 @@ $border-radius: 100px; position: absolute; z-index: 1; pointer-events: auto; + user-select: none; cursor: default; } diff --git a/packages/core/src/components/badge/test/badge.ct.ts b/packages/core/src/components/badge/test/badge.ct.ts index 8c20d30a640..e04e1753a11 100644 --- a/packages/core/src/components/badge/test/badge.ct.ts +++ b/packages/core/src/components/badge/test/badge.ct.ts @@ -485,6 +485,34 @@ regressionTest.describe('ix-badge', () => { await badge.expectVisibleLabel('NEW'); }); + regressionTest( + 'allows selecting standalone label text', + async ({ mount, page }) => { + await mount( + `` + ); + const badge = new BadgePage(page); + await badge.expectHydrated(); + + await expect(badge.indicator).toHaveCSS('user-select', 'text'); + } + ); + + regressionTest( + 'keeps attached label text non-selectable', + async ({ mount, page }) => { + await mount(html` + + + + `); + const badge = new BadgePage(page); + await badge.expectAttached(); + + await expect(badge.indicator).toHaveCSS('user-select', 'none'); + } + ); + regressionTest( 'renders no indicator for empty label text', async ({ mount, page }) => { diff --git a/packages/html-test-app/src/preview-examples/badge.html b/packages/html-test-app/src/preview-examples/badge.html index a1f00b27c25..fcf38c17d0c 100644 --- a/packages/html-test-app/src/preview-examples/badge.html +++ b/packages/html-test-app/src/preview-examples/badge.html @@ -22,11 +22,11 @@
- Review - - Bottom after - Messages - Device + Review + + Bottom after + Messages + Device
diff --git a/packages/react-test-app/src/preview-examples/badge.tsx b/packages/react-test-app/src/preview-examples/badge.tsx index 451e86119f8..f35999bedf3 100644 --- a/packages/react-test-app/src/preview-examples/badge.tsx +++ b/packages/react-test-app/src/preview-examples/badge.tsx @@ -17,11 +17,14 @@ export default () => { <>
- Review + Review - + { variant="success" position="bottom-after" > - Bottom after + Bottom after - Messages + Messages - Device + Device
diff --git a/packages/vue-test-app/src/preview-examples/badge.vue b/packages/vue-test-app/src/preview-examples/badge.vue index a55f25d1e48..e12a17fc477 100644 --- a/packages/vue-test-app/src/preview-examples/badge.vue +++ b/packages/vue-test-app/src/preview-examples/badge.vue @@ -16,11 +16,11 @@ import { IxBadge, IxButton, IxIconButton } from '@siemens/ix-vue';

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 Ms;&y`*{gT|4VK9T0{{R3 literal 0 HcmV?d00001 diff --git a/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-status-icon-1-chromium---classic-light-linux.png b/testing/visual-testing/__screenshots__/tests/badge/badge.e2e.ts/badge-status-icon-1-chromium---classic-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..3f8974a3da0d01a9e3a0e41c1eab5c074d895342 GIT binary patch literal 35291 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 { + regressionTest('counter', async ({ page }) => { + const badge = new BadgeVisualPage(page); + await badge.gotoCounter(); + await badge.waitForReady(); + await badge.expectSnapshot(); + }); + + regressionTest('label', async ({ page }) => { + const badge = new BadgeVisualPage(page); + await badge.gotoLabel(); + await badge.waitForReady(); + await badge.expectSnapshot(); + }); + + regressionTest('dot', async ({ page }) => { + const badge = new BadgeVisualPage(page); + await badge.gotoDot(); + await badge.waitForReady(); + await badge.expectSnapshot(); + }); + + regressionTest('status-icon', async ({ page }) => { + const badge = new BadgeVisualPage(page); + await badge.gotoStatusIcon(); + await badge.waitForReady(); + await badge.expectSnapshot(); + }); +}); diff --git a/testing/visual-testing/tests/badge/badge.page.ts b/testing/visual-testing/tests/badge/badge.page.ts new file mode 100644 index 00000000000..e4432db73a8 --- /dev/null +++ b/testing/visual-testing/tests/badge/badge.page.ts @@ -0,0 +1,56 @@ +/* + * SPDX-FileCopyrightText: 2026 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, Locator, Page } from '@playwright/test'; + +export const BADGE_COUNTER_ROUTE = 'badge/counter'; +export const BADGE_LABEL_ROUTE = 'badge/label'; +export const BADGE_DOT_ROUTE = 'badge/dot'; +export const BADGE_STATUS_ICON_ROUTE = 'badge/status-icon'; + +/** + * Page Object Model for ix-badge visual regression tests. + */ +export class BadgeVisualPage { + readonly page: Page; + + constructor(page: Page) { + this.page = page; + } + + get badges(): Locator { + return this.page.locator('ix-badge'); + } + + async gotoCounter(): Promise { + await this.page.goto(BADGE_COUNTER_ROUTE); + } + + async gotoLabel(): Promise { + await this.page.goto(BADGE_LABEL_ROUTE); + } + + async gotoDot(): Promise { + await this.page.goto(BADGE_DOT_ROUTE); + } + + async gotoStatusIcon(): Promise { + await this.page.goto(BADGE_STATUS_ICON_ROUTE); + } + + async waitForReady(): Promise { + await this.badges.first().waitFor(); + await expect(this.badges).not.toHaveCount(0); + await expect(this.page.locator('ix-badge.hydrated').first()).toBeVisible(); + } + + async expectSnapshot(): Promise { + expect(await this.page.screenshot({ fullPage: true })).toMatchSnapshot(); + } +} diff --git a/testing/visual-testing/tests/badge/counter/index.html b/testing/visual-testing/tests/badge/counter/index.html new file mode 100644 index 00000000000..6e830d94013 --- /dev/null +++ b/testing/visual-testing/tests/badge/counter/index.html @@ -0,0 +1,189 @@ + + + + + + + + Badge counter + + + + +