From 74764226f9334bed68c81c852e65c9f3974e13a2 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 25 Aug 2025 14:18:34 +0300 Subject: [PATCH 01/14] feat: add breadcrumb component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new breadcrumb navigation component with the following features: - Main `` container component with semantic HTML - `` sub-component for individual items - Support for href, target, and router-ignore attributes - Automatic detection and styling of the last/current item - Disabled state support - Full accessibility with ARIA attributes - Lumo theme integration with customizable CSS properties - TypeScript definitions - Demo page and test suite 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- dev/breadcrumb.html | 83 ++++++++ packages/breadcrumb/package.json | 51 +++++ .../styles/vaadin-breadcrumb-item-styles.js | 69 ++++++ .../src/styles/vaadin-breadcrumb-styles.js | 29 +++ .../breadcrumb/src/vaadin-breadcrumb-item.js | 200 ++++++++++++++++++ packages/breadcrumb/src/vaadin-breadcrumb.js | 105 +++++++++ packages/breadcrumb/test/breadcrumb.test.js | 159 ++++++++++++++ .../breadcrumb/vaadin-breadcrumb-item.d.ts | 65 ++++++ packages/breadcrumb/vaadin-breadcrumb-item.js | 6 + packages/breadcrumb/vaadin-breadcrumb.d.ts | 38 ++++ packages/breadcrumb/vaadin-breadcrumb.js | 6 + 11 files changed, 811 insertions(+) create mode 100644 dev/breadcrumb.html create mode 100644 packages/breadcrumb/package.json create mode 100644 packages/breadcrumb/src/styles/vaadin-breadcrumb-item-styles.js create mode 100644 packages/breadcrumb/src/styles/vaadin-breadcrumb-styles.js create mode 100644 packages/breadcrumb/src/vaadin-breadcrumb-item.js create mode 100644 packages/breadcrumb/src/vaadin-breadcrumb.js create mode 100644 packages/breadcrumb/test/breadcrumb.test.js create mode 100644 packages/breadcrumb/vaadin-breadcrumb-item.d.ts create mode 100644 packages/breadcrumb/vaadin-breadcrumb-item.js create mode 100644 packages/breadcrumb/vaadin-breadcrumb.d.ts create mode 100644 packages/breadcrumb/vaadin-breadcrumb.js diff --git a/dev/breadcrumb.html b/dev/breadcrumb.html new file mode 100644 index 00000000000..5ff9f673664 --- /dev/null +++ b/dev/breadcrumb.html @@ -0,0 +1,83 @@ + + + + + + vaadin-breadcrumb + + + + + + +

Breadcrumb Examples

+ +
+

Basic Breadcrumb

+ + Home + Products + Laptops + MacBook Pro + +
+ +
+

Short Breadcrumb

+ + Home + Settings + +
+ +
+

Breadcrumb with Target

+ + Home + Vaadin (opens in new tab) + Current Page + +
+ +
+

Disabled Items

+ + Home + Products (disabled) + Current Page + +
+ +
+

Long Breadcrumb Trail

+ + Home + Documentation + Components + Navigation + Breadcrumb + Examples + +
+ +
+

Router Ignore Example

+ + Home + API (full page reload) + Current + +
+ + \ No newline at end of file diff --git a/packages/breadcrumb/package.json b/packages/breadcrumb/package.json new file mode 100644 index 00000000000..739f5721d8d --- /dev/null +++ b/packages/breadcrumb/package.json @@ -0,0 +1,51 @@ +{ + "name": "@vaadin/breadcrumb", + "version": "25.0.0-alpha16", + "publishConfig": { + "access": "public" + }, + "description": "vaadin-breadcrumb", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/vaadin/web-components.git", + "directory": "packages/breadcrumb" + }, + "author": "Vaadin Ltd", + "homepage": "https://vaadin.com/components", + "bugs": { + "url": "https://github.com/vaadin/web-components/issues" + }, + "main": "vaadin-breadcrumb.js", + "module": "vaadin-breadcrumb.js", + "type": "module", + "files": [ + "src", + "vaadin-*.d.ts", + "vaadin-*.js", + "web-types.json" + ], + "keywords": [ + "Vaadin", + "breadcrumb", + "navigation", + "web-components", + "web-component" + ], + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@vaadin/a11y-base": "25.0.0-alpha16", + "@vaadin/component-base": "25.0.0-alpha16", + "@vaadin/vaadin-themable-mixin": "25.0.0-alpha16", + "lit": "^3.0.0" + }, + "devDependencies": { + "@vaadin/chai-plugins": "25.0.0-alpha16", + "@vaadin/testing-helpers": "^2.0.0", + "@vaadin/vaadin-lumo-styles": "25.0.0-alpha16", + "sinon": "^21.0.0" + }, + "web-types": [ + "web-types.json" + ] +} \ No newline at end of file diff --git a/packages/breadcrumb/src/styles/vaadin-breadcrumb-item-styles.js b/packages/breadcrumb/src/styles/vaadin-breadcrumb-item-styles.js new file mode 100644 index 00000000000..ec57edfa93e --- /dev/null +++ b/packages/breadcrumb/src/styles/vaadin-breadcrumb-item-styles.js @@ -0,0 +1,69 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import '@vaadin/component-base/src/styles/style-props.js'; +import '@vaadin/vaadin-lumo-styles/font-icons.js'; +import { css } from 'lit'; + +export const breadcrumbItemStyles = css` + :host { + display: inline-flex; + align-items: center; + white-space: nowrap; + } + + :host([hidden]) { + display: none !important; + } + + [part='link'] { + display: inline-flex; + align-items: center; + text-decoration: var(--vaadin-breadcrumb-link-text-decoration, none); + color: var(--vaadin-breadcrumb-link-color, var(--vaadin-secondary-text-color)); + transition: color 0.2s; + outline: none; + cursor: var(--vaadin-clickable-cursor); + } + + a[part='link']:hover { + text-decoration: var(--vaadin-breadcrumb-link-hover-text-decoration, underline); + color: var(--vaadin-breadcrumb-link-hover-color, var(--vaadin-primary-text-color)); + } + + a[part='link']:focus-visible { + border-radius: var(--vaadin-radius-s); + box-shadow: 0 0 0 2px var(--vaadin-focus-ring-color); + } + + span[part='link'] { + color: var(--vaadin-breadcrumb-current-color, var(--vaadin-primary-text-color)); + cursor: default; + } + + :host([disabled]) [part='link'] { + color: var(--vaadin-disabled-text-color); + cursor: default; + pointer-events: none; + } + + :host([last]) [part='link'] { + color: var(--vaadin-breadcrumb-current-color, var(--vaadin-primary-text-color)); + font-weight: var(--vaadin-breadcrumb-current-font-weight, 500); + } + + [part='separator'] { + display: inline-flex; + align-items: center; + margin: 0 var(--vaadin-breadcrumb-separator-spacing, var(--vaadin-space-xs)); + color: var(--vaadin-breadcrumb-separator-color, var(--vaadin-tertiary-text-color)); + } + + [part='separator']::after { + content: var(--vaadin-breadcrumb-separator, var(--lumo-icons-angle-right)); + font-family: var(--vaadin-breadcrumb-separator-font-family, 'lumo-icons'); + font-size: var(--vaadin-breadcrumb-separator-size, var(--vaadin-icon-size-s)); + } +`; diff --git a/packages/breadcrumb/src/styles/vaadin-breadcrumb-styles.js b/packages/breadcrumb/src/styles/vaadin-breadcrumb-styles.js new file mode 100644 index 00000000000..f24b50042cd --- /dev/null +++ b/packages/breadcrumb/src/styles/vaadin-breadcrumb-styles.js @@ -0,0 +1,29 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import '@vaadin/component-base/src/styles/style-props.js'; +import '@vaadin/vaadin-lumo-styles/font-icons.js'; +import { css } from 'lit'; + +export const breadcrumbStyles = css` + :host { + display: block; + font-size: var(--vaadin-breadcrumb-font-size, var(--vaadin-font-size-s)); + line-height: var(--vaadin-breadcrumb-line-height, var(--vaadin-line-height-xs)); + } + + :host([hidden]) { + display: none !important; + } + + [part='list'] { + display: flex; + flex-wrap: wrap; + align-items: center; + list-style: none; + margin: 0; + padding: 0; + } +`; diff --git a/packages/breadcrumb/src/vaadin-breadcrumb-item.js b/packages/breadcrumb/src/vaadin-breadcrumb-item.js new file mode 100644 index 00000000000..026ca290b0b --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb-item.js @@ -0,0 +1,200 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { html, LitElement } from 'lit'; +import { ifDefined } from 'lit/directives/if-defined.js'; +import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js'; +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { matchPaths } from '@vaadin/component-base/src/url-utils.js'; +import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; +import { breadcrumbItemStyles } from './styles/vaadin-breadcrumb-item-styles.js'; + +/** + * `` is a Web Component for displaying a single item in a breadcrumb trail. + * + * ```html + * Products + * ``` + * + * ### Styling + * + * The following shadow DOM parts are available for styling: + * + * Part name | Description + * -------------|---------------- + * `link` | The link element + * `separator` | The separator element + * + * The following state attributes are available for styling: + * + * Attribute | Description + * ------------|------------- + * `disabled` | Set when the element is disabled + * `last` | Set when this is the last item in the breadcrumb + * `current` | Set when the item's href matches the current page + * + * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation. + * + * @customElement + * @extends HTMLElement + * @mixes DisabledMixin + * @mixes DirMixin + * @mixes ElementMixin + * @mixes ThemableMixin + */ +class BreadcrumbItem extends DisabledMixin( + DirMixin(ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement))))), +) { + static get is() { + return 'vaadin-breadcrumb-item'; + } + + static get styles() { + return breadcrumbItemStyles; + } + + static get properties() { + return { + /** + * The URL to navigate to + */ + href: { + type: String, + }, + + /** + * The target of the link + */ + target: { + type: String, + }, + + /** + * Whether to exclude the item from client-side routing + * @type {boolean} + * @attr {boolean} router-ignore + */ + routerIgnore: { + type: Boolean, + value: false, + }, + + /** + * Whether this is the last item in the breadcrumb + * @type {boolean} + * @private + */ + _last: { + type: Boolean, + value: false, + reflectToAttribute: true, + attribute: 'last', + }, + + /** + * Whether the item's href matches the current page + * @type {boolean} + */ + current: { + type: Boolean, + value: false, + readOnly: true, + reflectToAttribute: true, + }, + }; + } + + constructor() { + super(); + this.__boundUpdateCurrent = this.__updateCurrent.bind(this); + } + + /** @protected */ + render() { + return html` + ${this.href && !this._last + ? html` + + + + ` + : html` + + + + `} + ${!this._last ? html`` : ''} + `; + } + + /** @protected */ + firstUpdated() { + super.firstUpdated(); + + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'listitem'); + } + } + + /** @protected */ + updated(props) { + super.updated(props); + + if (props.has('href')) { + this.__updateCurrent(); + } + } + + /** @protected */ + connectedCallback() { + super.connectedCallback(); + this.__updateCurrent(); + + window.addEventListener('popstate', this.__boundUpdateCurrent); + window.addEventListener('vaadin-navigated', this.__boundUpdateCurrent); + } + + /** @protected */ + disconnectedCallback() { + super.disconnectedCallback(); + + window.removeEventListener('popstate', this.__boundUpdateCurrent); + window.removeEventListener('vaadin-navigated', this.__boundUpdateCurrent); + } + + /** + * @param {boolean} last + * @private + */ + _setLast(last) { + this._last = last; + } + + /** @private */ + __updateCurrent() { + if (!this.href) { + this._setCurrent(false); + return; + } + + const browserPath = `${location.pathname}${location.search}`; + this._setCurrent(matchPaths(browserPath, this.href)); + } +} + +defineCustomElement(BreadcrumbItem); + +export { BreadcrumbItem }; diff --git a/packages/breadcrumb/src/vaadin-breadcrumb.js b/packages/breadcrumb/src/vaadin-breadcrumb.js new file mode 100644 index 00000000000..6ab98d181b7 --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb.js @@ -0,0 +1,105 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import './vaadin-breadcrumb-item.js'; +import { html, LitElement } from 'lit'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { LumoInjectionMixin } from '@vaadin/vaadin-themable-mixin/lumo-injection-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; +import { breadcrumbStyles } from './styles/vaadin-breadcrumb-styles.js'; + +/** + * `` is a Web Component for displaying hierarchical navigation. + * + * ```html + * + * Home + * Products + * Details + * + * ``` + * + * ### Styling + * + * The following shadow DOM parts are available for styling: + * + * Part name | Description + * -----------|---------------- + * `list` | The ordered list element + * + * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation. + * + * @customElement + * @extends HTMLElement + * @mixes ElementMixin + * @mixes ThemableMixin + */ +class Breadcrumb extends ElementMixin(ThemableMixin(PolylitMixin(LumoInjectionMixin(LitElement)))) { + static get is() { + return 'vaadin-breadcrumb'; + } + + static get styles() { + return breadcrumbStyles; + } + + static get properties() { + return { + /** + * The list of breadcrumb items + * @type {!Array} + * @private + */ + _items: { + type: Array, + }, + }; + } + + constructor() { + super(); + this._items = []; + } + + /** @protected */ + render() { + return html` +
    + +
+ `; + } + + /** @protected */ + firstUpdated() { + super.firstUpdated(); + + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'navigation'); + } + + this.setAttribute('aria-label', 'Breadcrumb'); + } + + /** @private */ + _onSlotChange() { + const slot = this.shadowRoot.querySelector('slot'); + const items = slot.assignedElements().filter((el) => el.localName === 'vaadin-breadcrumb-item'); + + this._items = items; + + // Update aria-current for the last item + items.forEach((item, index) => { + const isLast = index === items.length - 1; + item._setLast(isLast); + }); + } +} + +defineCustomElement(Breadcrumb); + +export { Breadcrumb }; diff --git a/packages/breadcrumb/test/breadcrumb.test.js b/packages/breadcrumb/test/breadcrumb.test.js new file mode 100644 index 00000000000..eac25bfdbfc --- /dev/null +++ b/packages/breadcrumb/test/breadcrumb.test.js @@ -0,0 +1,159 @@ +import { expect } from '@vaadin/chai-plugins'; +import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; +import '../vaadin-breadcrumb.js'; +import '../vaadin-breadcrumb-item.js'; + +describe('vaadin-breadcrumb', () => { + let breadcrumb; + + beforeEach(async () => { + breadcrumb = fixtureSync(` + + Home + Products + Current + + `); + await nextFrame(); + }); + + describe('basic functionality', () => { + it('should have proper tag name', () => { + expect(breadcrumb.localName).to.equal('vaadin-breadcrumb'); + }); + + it('should have navigation role', () => { + expect(breadcrumb.getAttribute('role')).to.equal('navigation'); + }); + + it('should have aria-label', () => { + expect(breadcrumb.getAttribute('aria-label')).to.equal('Breadcrumb'); + }); + + it('should contain breadcrumb items', () => { + const items = breadcrumb.querySelectorAll('vaadin-breadcrumb-item'); + expect(items).to.have.length(3); + }); + }); + + describe('item management', () => { + it('should mark last item as last', () => { + const items = breadcrumb.querySelectorAll('vaadin-breadcrumb-item'); + expect(items[0].hasAttribute('last')).to.be.false; + expect(items[1].hasAttribute('last')).to.be.false; + expect(items[2].hasAttribute('last')).to.be.true; + }); + + it('should update last attribute when items change', async () => { + const newItem = document.createElement('vaadin-breadcrumb-item'); + newItem.textContent = 'New Item'; + breadcrumb.appendChild(newItem); + await nextFrame(); + + const items = breadcrumb.querySelectorAll('vaadin-breadcrumb-item'); + expect(items[2].hasAttribute('last')).to.be.false; + expect(items[3].hasAttribute('last')).to.be.true; + }); + }); +}); + +describe('vaadin-breadcrumb-item', () => { + let item; + + beforeEach(async () => { + item = fixtureSync('Test Item'); + await nextFrame(); + }); + + describe('basic functionality', () => { + it('should have proper tag name', () => { + expect(item.localName).to.equal('vaadin-breadcrumb-item'); + }); + + it('should have listitem role', () => { + expect(item.getAttribute('role')).to.equal('listitem'); + }); + + it('should render link when href is set', () => { + const link = item.shadowRoot.querySelector('a[part="link"]'); + expect(link).to.exist; + expect(link.getAttribute('href')).to.equal('/test'); + }); + + it('should render span when href is not set', async () => { + const noHrefItem = fixtureSync('No Link'); + await nextFrame(); + + const span = noHrefItem.shadowRoot.querySelector('span[part="link"]'); + const link = noHrefItem.shadowRoot.querySelector('a[part="link"]'); + expect(span).to.exist; + expect(link).to.not.exist; + }); + }); + + describe('separator', () => { + it('should render separator by default', () => { + const separator = item.shadowRoot.querySelector('[part="separator"]'); + expect(separator).to.exist; + }); + + it('should not render separator for last item', async () => { + item._setLast(true); + await nextFrame(); + + const separator = item.shadowRoot.querySelector('[part="separator"]'); + expect(separator).to.not.exist; + }); + }); + + describe('disabled state', () => { + it('should handle disabled state', async () => { + item.disabled = true; + await nextFrame(); + + const link = item.shadowRoot.querySelector('[part="link"]'); + expect(link.getAttribute('href')).to.be.null; + expect(link.getAttribute('tabindex')).to.equal('-1'); + }); + }); + + describe('target attribute', () => { + it('should set target on link', async () => { + item.target = '_blank'; + await nextFrame(); + + const link = item.shadowRoot.querySelector('[part="link"]'); + expect(link.getAttribute('target')).to.equal('_blank'); + }); + }); + + describe('router-ignore attribute', () => { + it('should set router-ignore on link', async () => { + item.routerIgnore = true; + await nextFrame(); + + const link = item.shadowRoot.querySelector('[part="link"]'); + expect(link.hasAttribute('router-ignore')).to.be.true; + }); + }); + + describe('last item behavior', () => { + it('should render span instead of link when last', async () => { + item._setLast(true); + await nextFrame(); + + const span = item.shadowRoot.querySelector('span[part="link"]'); + const link = item.shadowRoot.querySelector('a[part="link"]'); + expect(span).to.exist; + expect(link).to.not.exist; + }); + + it('should set aria-current="page" for last item', async () => { + item._setLast(true); + await nextFrame(); + + const span = item.shadowRoot.querySelector('[part="link"]'); + expect(span.getAttribute('aria-current')).to.equal('page'); + }); + }); +}); diff --git a/packages/breadcrumb/vaadin-breadcrumb-item.d.ts b/packages/breadcrumb/vaadin-breadcrumb-item.d.ts new file mode 100644 index 00000000000..4294b581556 --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb-item.d.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js'; +import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js'; +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +/** + * `` is a Web Component for displaying a single item in a breadcrumb trail. + * + * ```html + * Products + * ``` + * + * ### Styling + * + * The following shadow DOM parts are available for styling: + * + * Part name | Description + * -------------|---------------- + * `link` | The link element + * `separator` | The separator element + * + * The following state attributes are available for styling: + * + * Attribute | Description + * ------------|------------- + * `disabled` | Set when the element is disabled + * `last` | Set when this is the last item in the breadcrumb + * `current` | Set when the item's href matches the current page + * + * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation. + */ +declare class BreadcrumbItem extends DisabledMixin(DirMixin(ElementMixin(ThemableMixin(HTMLElement)))) { + /** + * The URL to navigate to + */ + href: string | null | undefined; + + /** + * The target of the link + */ + target: string | null | undefined; + + /** + * Whether to exclude the item from client-side routing + */ + routerIgnore: boolean; + + /** + * Whether the item's href matches the current page + */ + readonly current: boolean; +} + +declare global { + interface HTMLElementTagNameMap { + 'vaadin-breadcrumb-item': BreadcrumbItem; + } +} + +export { BreadcrumbItem }; diff --git a/packages/breadcrumb/vaadin-breadcrumb-item.js b/packages/breadcrumb/vaadin-breadcrumb-item.js new file mode 100644 index 00000000000..26b3617b7b2 --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb-item.js @@ -0,0 +1,6 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +export { BreadcrumbItem } from './src/vaadin-breadcrumb-item.js'; diff --git a/packages/breadcrumb/vaadin-breadcrumb.d.ts b/packages/breadcrumb/vaadin-breadcrumb.d.ts new file mode 100644 index 00000000000..fe7da1d4a93 --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb.d.ts @@ -0,0 +1,38 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; + +/** + * `` is a Web Component for displaying hierarchical navigation. + * + * ```html + * + * Home + * Products + * Details + * + * ``` + * + * ### Styling + * + * The following shadow DOM parts are available for styling: + * + * Part name | Description + * -----------|---------------- + * `list` | The ordered list element + * + * See [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation. + */ +declare class Breadcrumb extends ElementMixin(ThemableMixin(HTMLElement)) {} + +declare global { + interface HTMLElementTagNameMap { + 'vaadin-breadcrumb': Breadcrumb; + } +} + +export { Breadcrumb }; diff --git a/packages/breadcrumb/vaadin-breadcrumb.js b/packages/breadcrumb/vaadin-breadcrumb.js new file mode 100644 index 00000000000..1aca182f729 --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb.js @@ -0,0 +1,6 @@ +/** + * @license + * Copyright (c) 2017 - 2025 Vaadin Ltd. + * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ + */ +export { Breadcrumb } from './src/vaadin-breadcrumb.js'; From 486eb00ffa4695f9df75cbac0261e3252de5f085 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 25 Aug 2025 15:25:33 +0300 Subject: [PATCH 02/14] test: add screenshot and DOM snapshot tests for breadcrumb component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add comprehensive test coverage including: - Visual regression tests for base and Lumo themes - DOM snapshot tests for component structure - Tests for various states (hover, focus, disabled) - RTL support tests - Tests for different breadcrumb configurations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../dom/__snapshots__/breadcrumb.test.snap.js | 273 ++++++++++++++++++ .../breadcrumb/test/dom/breadcrumb.test.js | 144 +++++++++ .../test/visual/base/breadcrumb.test.js | 210 ++++++++++++++ .../breadcrumb/baseline/default.png | Bin 0 -> 1609 bytes .../breadcrumb/baseline/disabled-hover.png | Bin 0 -> 1234 bytes .../breadcrumb/baseline/disabled.png | Bin 0 -> 1234 bytes .../breadcrumb/baseline/focus-ring-first.png | Bin 0 -> 1613 bytes .../breadcrumb/baseline/focus-ring-second.png | Bin 0 -> 1614 bytes .../screenshots/breadcrumb/baseline/hover.png | Bin 0 -> 1254 bytes .../breadcrumb/baseline/long-trail.png | Bin 0 -> 2220 bytes .../breadcrumb/baseline/router-ignore.png | Bin 0 -> 1504 bytes .../screenshots/breadcrumb/baseline/rtl.png | Bin 0 -> 1496 bytes .../screenshots/breadcrumb/baseline/short.png | Bin 0 -> 860 bytes .../breadcrumb/baseline/single-item.png | Bin 0 -> 652 bytes .../breadcrumb/baseline/with-target.png | Bin 0 -> 1700 bytes .../test/visual/lumo/breadcrumb.test.js | 211 ++++++++++++++ .../breadcrumb/baseline/default.png | Bin 0 -> 1599 bytes .../breadcrumb/baseline/disabled-hover.png | Bin 0 -> 1273 bytes .../breadcrumb/baseline/disabled.png | Bin 0 -> 1273 bytes .../breadcrumb/baseline/focus-ring-first.png | Bin 0 -> 1273 bytes .../breadcrumb/baseline/focus-ring-second.png | Bin 0 -> 1273 bytes .../screenshots/breadcrumb/baseline/hover.png | Bin 0 -> 1293 bytes .../breadcrumb/baseline/long-trail.png | Bin 0 -> 2249 bytes .../breadcrumb/baseline/router-ignore.png | Bin 0 -> 1528 bytes .../screenshots/breadcrumb/baseline/rtl.png | Bin 0 -> 1482 bytes .../screenshots/breadcrumb/baseline/short.png | Bin 0 -> 852 bytes .../breadcrumb/baseline/single-item.png | Bin 0 -> 652 bytes .../breadcrumb/baseline/with-target.png | Bin 0 -> 1696 bytes 28 files changed, 838 insertions(+) create mode 100644 packages/breadcrumb/test/dom/__snapshots__/breadcrumb.test.snap.js create mode 100644 packages/breadcrumb/test/dom/breadcrumb.test.js create mode 100644 packages/breadcrumb/test/visual/base/breadcrumb.test.js create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/default.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled-hover.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-first.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-second.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/hover.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/long-trail.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/router-ignore.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/rtl.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/short.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/single-item.png create mode 100644 packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/with-target.png create mode 100644 packages/breadcrumb/test/visual/lumo/breadcrumb.test.js create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/default.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled-hover.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-first.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-second.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/hover.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/long-trail.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/router-ignore.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/rtl.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/short.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/single-item.png create mode 100644 packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/with-target.png diff --git a/packages/breadcrumb/test/dom/__snapshots__/breadcrumb.test.snap.js b/packages/breadcrumb/test/dom/__snapshots__/breadcrumb.test.snap.js new file mode 100644 index 00000000000..4bf48ce9c70 --- /dev/null +++ b/packages/breadcrumb/test/dom/__snapshots__/breadcrumb.test.snap.js @@ -0,0 +1,273 @@ +/* @web/test-runner snapshot v1 */ +export const snapshots = {}; + +snapshots["vaadin-breadcrumb breadcrumb host default"] = +` + + Home + + + Products + + + Current Page + + +`; +/* end snapshot vaadin-breadcrumb breadcrumb host default */ + +snapshots["vaadin-breadcrumb breadcrumb host focused"] = +` + + Home + + + Products + + + Current Page + + +`; +/* end snapshot vaadin-breadcrumb breadcrumb host focused */ + +snapshots["vaadin-breadcrumb breadcrumb host focus-ring"] = +` + + Home + + + Products + + + Current Page + + +`; +/* end snapshot vaadin-breadcrumb breadcrumb host focus-ring */ + +snapshots["vaadin-breadcrumb breadcrumb shadow default"] = +`
    + + +
+`; +/* end snapshot vaadin-breadcrumb breadcrumb shadow default */ + +snapshots["vaadin-breadcrumb-item item host default with href"] = +` + Products + +`; +/* end snapshot vaadin-breadcrumb-item item host default with href */ + +snapshots["vaadin-breadcrumb-item item host default without href"] = +` + Current Page + +`; +/* end snapshot vaadin-breadcrumb-item item host default without href */ + +snapshots["vaadin-breadcrumb-item item host disabled"] = +` + Products + +`; +/* end snapshot vaadin-breadcrumb-item item host disabled */ + +snapshots["vaadin-breadcrumb-item item host with target"] = +` + Vaadin + +`; +/* end snapshot vaadin-breadcrumb-item item host with target */ + +snapshots["vaadin-breadcrumb-item item host router-ignore"] = +` + API + +`; +/* end snapshot vaadin-breadcrumb-item item host router-ignore */ + +snapshots["vaadin-breadcrumb-item item host focused"] = +` + Products + +`; +/* end snapshot vaadin-breadcrumb-item item host focused */ + +snapshots["vaadin-breadcrumb-item item host focus-ring"] = +` + Products + +`; +/* end snapshot vaadin-breadcrumb-item item host focus-ring */ + +snapshots["vaadin-breadcrumb-item item host last item with href"] = +` + Products + +`; +/* end snapshot vaadin-breadcrumb-item item host last item with href */ + +snapshots["vaadin-breadcrumb-item item host last item without href"] = +` + Current Page + +`; +/* end snapshot vaadin-breadcrumb-item item host last item without href */ + +snapshots["vaadin-breadcrumb-item item host current"] = +` + Home + +`; +/* end snapshot vaadin-breadcrumb-item item host current */ + +snapshots["vaadin-breadcrumb-item item shadow default with href"] = +` + + + + +`; +/* end snapshot vaadin-breadcrumb-item item shadow default with href */ + +snapshots["vaadin-breadcrumb-item item shadow default without href"] = +` + + + + +`; +/* end snapshot vaadin-breadcrumb-item item shadow default without href */ + +snapshots["vaadin-breadcrumb-item item shadow disabled"] = +` + + + + +`; +/* end snapshot vaadin-breadcrumb-item item shadow disabled */ + +snapshots["vaadin-breadcrumb-item item shadow last item with href"] = +` + + + + +`; +/* end snapshot vaadin-breadcrumb-item item shadow last item with href */ + +snapshots["vaadin-breadcrumb-item item shadow last item without href"] = +` + + + + +`; +/* end snapshot vaadin-breadcrumb-item item shadow last item without href */ + diff --git a/packages/breadcrumb/test/dom/breadcrumb.test.js b/packages/breadcrumb/test/dom/breadcrumb.test.js new file mode 100644 index 00000000000..1eae8ae8fd0 --- /dev/null +++ b/packages/breadcrumb/test/dom/breadcrumb.test.js @@ -0,0 +1,144 @@ +import { expect } from '@vaadin/chai-plugins'; +import { sendKeys } from '@vaadin/test-runner-commands'; +import { fixtureSync } from '@vaadin/testing-helpers'; +import '../../src/vaadin-breadcrumb.js'; +import '../../src/vaadin-breadcrumb-item.js'; + +describe('vaadin-breadcrumb', () => { + let breadcrumb; + + describe('breadcrumb host', () => { + beforeEach(() => { + breadcrumb = fixtureSync(` + + Home + Products + Current Page + + `); + }); + + it('default', async () => { + await expect(breadcrumb).dom.to.equalSnapshot(); + }); + + it('focused', async () => { + breadcrumb.querySelector('vaadin-breadcrumb-item').focus(); + await expect(breadcrumb).dom.to.equalSnapshot(); + }); + + it('focus-ring', async () => { + await sendKeys({ press: 'Tab' }); + await expect(breadcrumb).dom.to.equalSnapshot(); + }); + }); + + describe('breadcrumb shadow', () => { + beforeEach(() => { + breadcrumb = fixtureSync(` + + Home + Products + Current Page + + `); + }); + + it('default', async () => { + await expect(breadcrumb).shadowDom.to.equalSnapshot(); + }); + }); +}); + +describe('vaadin-breadcrumb-item', () => { + let item; + + describe('item host', () => { + it('default with href', async () => { + item = fixtureSync('Products'); + await expect(item).dom.to.equalSnapshot(); + }); + + it('default without href', async () => { + item = fixtureSync('Current Page'); + await expect(item).dom.to.equalSnapshot(); + }); + + it('disabled', async () => { + item = fixtureSync('Products'); + await expect(item).dom.to.equalSnapshot(); + }); + + it('with target', async () => { + item = fixtureSync( + 'Vaadin', + ); + await expect(item).dom.to.equalSnapshot(); + }); + + it('router-ignore', async () => { + item = fixtureSync('API'); + await expect(item).dom.to.equalSnapshot(); + }); + + it('focused', async () => { + item = fixtureSync('Products'); + item.focus(); + await expect(item).dom.to.equalSnapshot(); + }); + + it('focus-ring', async () => { + item = fixtureSync('Products'); + await sendKeys({ press: 'Tab' }); + await expect(item).dom.to.equalSnapshot(); + }); + + it('last item with href', async () => { + item = fixtureSync('Products'); + item._setLast(true); + await expect(item).dom.to.equalSnapshot(); + }); + + it('last item without href', async () => { + item = fixtureSync('Current Page'); + item._setLast(true); + await expect(item).dom.to.equalSnapshot(); + }); + + it('current', async () => { + item = fixtureSync('Home'); + // Simulate matching current page + item._setCurrent(true); + await expect(item).dom.to.equalSnapshot(); + }); + }); + + describe('item shadow', () => { + it('default with href', async () => { + item = fixtureSync('Products'); + await expect(item).shadowDom.to.equalSnapshot(); + }); + + it('default without href', async () => { + item = fixtureSync('Current Page'); + await expect(item).shadowDom.to.equalSnapshot(); + }); + + it('disabled', async () => { + item = fixtureSync('Products'); + await expect(item).shadowDom.to.equalSnapshot(); + }); + + it('last item with href', async () => { + item = fixtureSync('Products'); + item._setLast(true); + await expect(item).shadowDom.to.equalSnapshot(); + }); + + it('last item without href', async () => { + item = fixtureSync('Current Page'); + item._setLast(true); + await expect(item).shadowDom.to.equalSnapshot(); + }); + }); +}); diff --git a/packages/breadcrumb/test/visual/base/breadcrumb.test.js b/packages/breadcrumb/test/visual/base/breadcrumb.test.js new file mode 100644 index 00000000000..7a3670b2766 --- /dev/null +++ b/packages/breadcrumb/test/visual/base/breadcrumb.test.js @@ -0,0 +1,210 @@ +import { resetMouse, sendKeys, sendMouseToElement } from '@vaadin/test-runner-commands'; +import { fixtureSync } from '@vaadin/testing-helpers'; +import { visualDiff } from '@web/test-runner-visual-regression'; +import '../../../src/vaadin-breadcrumb.js'; +import '../../../src/vaadin-breadcrumb-item.js'; + +describe('breadcrumb', () => { + let div, element; + + afterEach(async () => { + await resetMouse(); + }); + + describe('basic', () => { + it('default', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Laptops + MacBook Pro + `, + div, + ); + await visualDiff(div, 'default'); + }); + + it('short', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Settings + `, + div, + ); + await visualDiff(div, 'short'); + }); + + it('single-item', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Current Page + `, + div, + ); + await visualDiff(div, 'single-item'); + }); + + it('long-trail', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Documentation + Components + Navigation + Breadcrumb + Examples + `, + div, + ); + await visualDiff(div, 'long-trail'); + }); + }); + + describe('states', () => { + it('hover', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + const item = element.querySelector('vaadin-breadcrumb-item[href="/products"]'); + await sendMouseToElement({ type: 'move', element: item }); + await visualDiff(div, 'hover'); + }); + + it('focus-ring', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await sendKeys({ press: 'Tab' }); + await visualDiff(div, 'focus-ring-first'); + }); + + it('focus-ring-second', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await sendKeys({ press: 'Tab' }); + await sendKeys({ press: 'Tab' }); + await visualDiff(div, 'focus-ring-second'); + }); + + it('disabled', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await visualDiff(div, 'disabled'); + }); + + it('disabled-hover', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + const item = element.querySelector('vaadin-breadcrumb-item[disabled]'); + await sendMouseToElement({ type: 'move', element: item }); + await visualDiff(div, 'disabled-hover'); + }); + }); + + describe('attributes', () => { + it('with-target', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Vaadin (opens in new tab) + Current Page + `, + div, + ); + await visualDiff(div, 'with-target'); + }); + + it('router-ignore', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + API (full page reload) + Current + `, + div, + ); + await visualDiff(div, 'router-ignore'); + }); + }); + + describe('RTL', () => { + it('rtl', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + div.setAttribute('dir', 'rtl'); + element = fixtureSync( + ` + الصفحة الرئيسية + المنتجات + الصفحة الحالية + `, + div, + ); + await visualDiff(div, 'rtl'); + }); + }); +}); diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/default.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/default.png new file mode 100644 index 0000000000000000000000000000000000000000..ea8b7b11574ee8993401f6eae2fcf913cb332271 GIT binary patch literal 1609 zcmV-P2DbT$P)Px*14%?dRCt{2oUNbRHW-SQr7T0Sk^VrX$>!;psw?hB`41*tDdI10c za3CN7U_d}X0>FTPfCPX60RagB0|EjP00smEBmfKu2uJ`J5D<_6Fd!fx0boEtKmx#k zfPe&m0bviwGQnO8PD-WCi_+&>soNq?v#c_~jog=`tLw#=a};T0w@iC~51Bff!!n6x44!RZBmig&b4XDIT5jEwCs5-d)Y!;V6A_>mDu{L1?u& z@Xa+^WVMGJLYYL)^E&D})#j(s8S|O-bvV0xpJcW^Q$l==UD8kSl#r9?tWAG=kj`+~ z#H2f;MM`~?$DdBMv)@Dw`F4KC2wKhX+%YC`;3Jf;t=@4K$|Q_8&b{~6bqr}VTb*(E zAX(GNKk;Q?i^@c3Eju&4>koY2@+A&zpZxHec0ZD3ve?k;uwR$5-})U1;~bG>!N0XyotAcavc3|r%r<)F^Dj(7x9_v%Z`pdleJc=FBuV< ztQFcLBNqr=5T=%s1tok@!j3jGG;JDP#{E{Ev%Aq+ojvWXznX-qE`$gZmeM|F^fe2P z0Vxk8_?S3r_g2Rd#ZiQPR-@gv=EuLuD};XjQ#}Zg#_0y2Fs3A?z1uZ_Bu^8NjA&y_ z3P{)U1-q`EF&gRIadk?>c1M%(XZAT-+Wz4qbn)?CxzPlqWPa`klFp7U!+vY++3T8p z`l(^E?j#zI?e3Gw*Q^|$vS#bN^BV{Le&w5_eHj}1J*9K}>*`0s?&fc`9R#u2LVrF` z9iv4;swB~#t@P?LuOh*o=iScDS&UwZtI4YJs7^HV zc-)`CWl3=Pdp@D-BrtaxeYmR9R$aQP*X6R`h#$z+WvWT1U4I_OE0o{dSu<79X$>B0 z@-@4H;{y^0zOwwPd~?Jtdb8yH?DJQ`%4PWafK}Fv@Kim7o8pn%W_8EuUw61{-i)i6 zDJBolRhMyTG>)gt@&-e-Pb#OEt|lw9P2E0PWc52gkH@B%d`hDr{xYH4&BAW}(IO!z zkHhc=U42mAoH|`@`z>SAY1dz6?|D2v@=V&~Ydw$kd_i6Q4k;$#;&<95Wv#A-&pg%T z3YH?vvPfmFot(?dg^76G{1iqO+dGv|n~pUDGD?f4JldHnk^^+{q2z@LDXT6wtqo96 z%Iqf7v@;^wQM=EU;*qbM?}1!WNn-TXxw_vMrZCs)eE92^i=T{Mt6QXcOD#0y?!1{$aq~>=+I0&KQJoE) zNSBB-7ea`T_HWviw-DukLHX;uYO=(q<(85%L183)( z_=f=i@P7dU@_V98@Hozq^B0RagB0|EjP00smE zBmfKu2uJ`J5D<_6Fd!fx0boEtKmx#kfPe&m0RaIC00ZJbqs@@z6_2ui00000NkvXX Hu0mjfsn-R7 literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled-hover.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled-hover.png new file mode 100644 index 0000000000000000000000000000000000000000..a5bd55e3df5aab60fbc5987136d3c575db510b2a GIT binary patch literal 1234 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 LNkvXXu0mjf=&cij literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-second.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-second.png new file mode 100644 index 0000000000000000000000000000000000000000..167400de94e173f35aae8bbf4c8f557d0603d604 GIT binary patch literal 1614 zcmV-U2C?~xP)Px*2uVaiRCt{2nm=sYMij=M>H_WLWbhEc2uKeGSugQmv@Q^!&QxkkCu%XE!9#}t zA%P5Dvw4VdHyIg%+Lz)06h#6!APA|BGU67i6(m57IQtwcPeYbE0G zZQTN{fj4j7ym;~A{QUgt>Z)!n9HytI@87@w?AfzNj~>;nWkP5O{VT(lFJCq{H@CL7 z>K0OoCr_T(wmmg9RkslF>5I(q@v)*POG`_;yStZ{mvzhGb9s5WySuxzw4|!);o)K3 zawY+>UAwxvswm3-{(jv;%GuxFR}^J+b+v9GlYrQ(v9q%?09aXBsar@np~z6MWJHQx z8(_T=qvL=XYqZ>(Qp)4QhYtY%{qf_SMurh(1z0ELUKi8T(?sy#xUKY6a9j2E9T*?n zup7#6$Bqf0A-{BNjC_3S{QaIYt|*G4C`6FyB;t~H1LGqNU>xNoY6*FDF=`Sqk-DL) zyI!ub?SoJ;AuQ_ZI6pci{JZyi^Jl%~eyX;+(Q!8@v6Z=H7#j$@@q2?%xu_d!`!%^X8@%E{9S0-;MTv|}KuJQ%&60PGPT-iIUpH59 zm7aJfJpgT4CzH2uc#80>bRy&F(BpHEk(QghNi#%Glu=SAuiyci@(_{t zeH3RcCfsPqr;gH)AIGt9KObrF(LU0+6Y+S99ss}t^p*@1>$(mNySo2yKJ(CT>eJ>e-J(k>rnmnco5YvQ1VnY1i^TQEAsP z#l%~Eq-FLhcCBM_FJ#8G>1uLa%hW~9HiT-)t5Esz1&NM5ndL{rP^ij@JjRbXVVEf#@!)QMyUECKzAqYp+#LK?j2;Fa@|IU z+*P{GJmVJCrCON3Di5$e>Z8#CiX8&CHD@n6jQvy#n>~B3(P%W9r^rvX4*1cm=-PrB zRSTQYvyG^=?z-J$SG~Cy8%XOmsTCaNg>err{$T&}0G$+Cw#tPtHjoD0X1oTlx*FOr z0E{+Ogu5QDKXe=b?PqG-Xq(A2$)h21lXfu}o8%5YBA^yL!&dKo!O9Z9$*~Fin$llI(G%9!MefKNVF~1%M#9xo4N7AeP!O z5a8C{;|~2j9ANBOR!NFw5#m>dTxMow0O0HVGkAtjWGMJ{!v0th;B|OBuw{jJ?ZUzW z02~|~)Gef(P-H0hcA{D?f^aDoVZg?a&n`+s)z{47;h|Xn3O_zRu3OF|AaPx(ph-kQRCt{2oGq8zI24AJC0n+IC3B90B-XIaqAjb#S|r23g%0aaD3f5>PSGZ) zVfH`hz+qz}o6PC57M6K|ZCRhToS9^*?R`)z%hJ79?^v&rb7s*r4FZ6m_~oes0D#$m zYJuMG>P)7SkBW%s9jo9y5v#8?yBj zE?HxQ%A4Zsk?GVt-railp3EzMw<{6lsrJf<-!oKP&cApkb+NKPl4^D1B^n8@djr%t zGSdMK4$0{ypU3+;qu)PnUU8qA6gMS8cuo4j6W&hI&MG@HTO35p(YGY|a52Ovjg#c< z<#Jb|a<}Yy)%~o_chz`a`SqbsLnTW0Y1G%U4XC^5@@Y%YlkUEy2-1@EHL$IhnUr7I zl_E>eNkUO3_t1dMw25%-N5X3v<_5D$dJ3~j*s-=>#jtp~V%R#6jXU-dA@q{n*@ILK z7G{;0Rr7_?+=CMvMyMFYqEp52FtYTp^f9Ai6xr{K%q9;3uDnDsN7u$EpD2Bwj!}dr zqk2xZ^^z*%h{9fWqfl}r(#KOY&@@fcc&b((M@mGNfqKhYQZ0J(Phu?Oub=3z2>toD zd4kc#(M~VJm|8O8ZpEGk-)_9(`(Nf*Vj(*?rEqQx*MziDgg|&l}YoS}gj=E3{T0~X|-4=Cy z{2*sR))S{OeHs0zbXubCrB!?aue^;Q;T{GQ?dv{u}dh;I9} z_SHbg!&OVx7?mH6iW#waF(-b@Qt(%skKbul@8jnuMA;FM6+(w=RYNNh_3E87&UD=I zzJIG6HZI|gF|;E=8gn(em(|Uw{MoW^%I%VwZLP54=Q75sieWin z+pagAm*N)1VB%7DiUk literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/long-trail.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/long-trail.png new file mode 100644 index 0000000000000000000000000000000000000000..7096af8a34d067e8ce000e633cc5a57c3829733d GIT binary patch literal 2220 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 ZGWA;qmOgpID+x?q44$rjF6*2UngAEWCKmtz literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/with-target.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/with-target.png new file mode 100644 index 0000000000000000000000000000000000000000..7d5e97a5c2a1f44c182b88923d78e1b313cdd7b8 GIT binary patch literal 1700 zcmb8w|3A|S0LSsqgl3oWB^*ce@TK`OL_!H$WJ9zW;mWss$=3+^+LxP)V(3_yZyWQa z%-L*ASFzODu@McqL?>UiGsYud8>Z`DxL=;H_kZwyc*)C65uybF06-Cibin`s$nX0$ z0?T|?sluS{dqBw;Hw4i3R(lZuS)IHjc3Q`F4(05IWqTonS~GlzY$X@hBTkyLjtZO3?3@nM~`u;-c!{ z`q4#MFz#2btwlV5)3Z=;2XL~A|C_>KnV4D^9R*q;>w17gd83BrQxOMaUXeBrZOqKtb(BFJymR8(zSWQ2q z{YhAO{bM1BR!t!T*efTU?|~uae;xTF+0uQ`F1k$etsS|x_ckG2{l$f2vXQ9l^O{<- zB`Y$P4NpSg&oKYY12J8slRpgp2KQF zX#8@Of+~JPW8-3_qeTIX^`CCw>_yF4P%a$Z>+g6LmHA* zVEzG1vb#c^%U5B`{<{);LqB#31=U5OvCGV+K#L}7^iI$lT#5j zobm(b2zit>dtxcC$Z`@}BNPtznMiED73E7sofMDf5wdG}GUQLXf;4g6>K=C?w9&3V zu628R4O=4dU2rD0JLZ=LYk(?I0EwV#oNm7d*s z;dFJ383pQIM-Rv3ESD-jqs-^#Eq#ei?M3n}S%6m;zGLC_TB7Xa<8F=-_RXfsqd|pJ zpb@xW;46spyZgZ1puK$ywM}#Br)krkEN{Kx^y9|P?b*y)g&{Q-$BqbcaCD7;dPQxfesZmTsalr^>+zLs(D@^MV7Vt5jP&rwPEp|`XVsOr8rUAF zJ==zH^aJhNKyRsRp=vBZ5++|^KdgraIxt$;nRSDO1YlTu4)0^vHp*f4MczI|ZS&&8 z^#9nXZ=PXI=oylv^!;7f+4S{bMr6`It005jg1o7Tina#g(W*`5q9xnzcnz}@s}ncV z*u`g({++BE7t1gOQ>v7B@NRH;kZw}~^{o~?pbVu>ny!d?dKEO8m$|!O6x6BXufehL z9#7}1!NV-w`88xwiOiS-s_ySb(Wh2Hz~Q-#4MwMEt8B|Tt*u1!m5nzeBVzeSjv)cJ zT@hj$+JZK!NxT9J%y79L0n76B|2(J5ewit}qec#e_1RE-Vk!-6xJ(K@dchgcTkf^7 zSf6R?Bs#_v=Mn<*|H)MIH$E7n3w?JxrhC$M+vzE*8j zsTC=Og+XHJ6`KjMlGF-|*=BgKL6RTj*_Qzav;2q-An9Vec&T^qK6=PD(RQ)Kgg=3T}9@VOq$24gsU)#a;h{&8gg3><*t { + let div, element; + + afterEach(async () => { + await resetMouse(); + }); + + describe('basic', () => { + it('default', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Laptops + MacBook Pro + `, + div, + ); + await visualDiff(div, 'default'); + }); + + it('short', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Settings + `, + div, + ); + await visualDiff(div, 'short'); + }); + + it('single-item', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Current Page + `, + div, + ); + await visualDiff(div, 'single-item'); + }); + + it('long-trail', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Documentation + Components + Navigation + Breadcrumb + Examples + `, + div, + ); + await visualDiff(div, 'long-trail'); + }); + }); + + describe('states', () => { + it('hover', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + const item = element.querySelector('vaadin-breadcrumb-item[href="/products"]'); + await sendMouseToElement({ type: 'move', element: item }); + await visualDiff(div, 'hover'); + }); + + it('focus-ring', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await sendKeys({ press: 'Tab' }); + await visualDiff(div, 'focus-ring-first'); + }); + + it('focus-ring-second', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await sendKeys({ press: 'Tab' }); + await sendKeys({ press: 'Tab' }); + await visualDiff(div, 'focus-ring-second'); + }); + + it('disabled', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + await visualDiff(div, 'disabled'); + }); + + it('disabled-hover', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Products + Current Page + `, + div, + ); + const item = element.querySelector('vaadin-breadcrumb-item[disabled]'); + await sendMouseToElement({ type: 'move', element: item }); + await visualDiff(div, 'disabled-hover'); + }); + }); + + describe('attributes', () => { + it('with-target', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + Vaadin (opens in new tab) + Current Page + `, + div, + ); + await visualDiff(div, 'with-target'); + }); + + it('router-ignore', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + element = fixtureSync( + ` + Home + API (full page reload) + Current + `, + div, + ); + await visualDiff(div, 'router-ignore'); + }); + }); + + describe('RTL', () => { + it('rtl', async () => { + div = document.createElement('div'); + div.style.display = 'inline-block'; + div.style.padding = '10px'; + div.setAttribute('dir', 'rtl'); + element = fixtureSync( + ` + الصفحة الرئيسية + المنتجات + الصفحة الحالية + `, + div, + ); + await visualDiff(div, 'rtl'); + }); + }); +}); diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/default.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/default.png new file mode 100644 index 0000000000000000000000000000000000000000..68ee49bdb7ebe2451d4bb6e6b314b63e6149957a GIT binary patch literal 1599 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 literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/router-ignore.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/router-ignore.png new file mode 100644 index 0000000000000000000000000000000000000000..ad43bad9f19f6b24b7038fc7cfd9e96f5f51d27c GIT binary patch literal 1528 zcmaLXYdF&j00!_safHfRbykTATP|BDLuxG(W)`Exq{%I@(R9dVv}r97)ycv{N-j%d zZfzBNRK!9qZKYUpW)&*3P>h`8^EuCRzP#`I;r;x}BzU>6*4wNH0KjSw>_J}u(Ac!R zVJkJ4lWCEZy<8e`zU~-6(6eP60JQ5p4muN)iYAH>DM~j`n!D>ciOKGlcUn5(HqmWf z7$mjW6y-M#!Jg1r(VY;0h$rF~4D?JR>a3_-{qPR{FR9ajS#y`zyr0o6>7hhS?0Bk( z1+<)tyS-@$fVH?S7`{DYt4$v0nZZWSl_NUYP%YJpb}(yBBTUzMF|Cfhjq!wp0ipkO zOM%bAbz$Ist6tWn$9ZLfDV*ts8qI=Ir)gM&lNfBsb5_FjP@ZhJYC?Yc*6or2dfuFr z6zkJM2ZG2I2!pKqP@rU??WFZ{rojYyxQIS!q0!eR;)T=q#~0EkEHummK`;JUQ4fUhZW}Ijp{9mVFy(@D=9P+-k3{k*xb1T_Bg28Yc!D%t$AYuLe3pE3bXD z>zl#d%put#PIZNKMXfJcu;?{Xd*o&%m>3z%D3QmQWd?(O$*^QgVbBdaR{I(wJMwDO z=KzJd=!H84xwjy)zEkC0(o~x^!;6e7G?DG%0KXM>F^H)YFrFkVKPcFqFQ&xvYXutB zv(U4=@D#uJj?#Gfkt46Jguy#ReTKf2`pE{R4w6vaMp+oOj{UXZPkw5-8Ec5gXq#Gx zXG1xYL7^ThPHMg_F12x-i+~b(@HctoA4yM|(!*>(;wc%4yPS6hF4F-|QM$(?7!TP|L72K?!(Yb? z(|xLpb`Q9`#iID>ftgVq^H|Pm-l4s_ha96?EBv);{K$eW<*i>RNW|c7QEhLu{Z{t< zdE#2Q*rOvn^7TrkMoCCVHE1+O_lyY4Un+(s#-i`igiD;6Hz3z%<#OpzD;xs(T)Gb9 z6-CF41uga!xAV`>zLq|yVJ@oW!)ikvALB!nr&ITPUK^#7ZnS5vsuU4bYjF~@l${*n zo6amw{dK-lHdk2}jm&*n1qiE4>@4j4Q!4i(bt@cLJ&egy$YiY4yP;OmPn{$OFqH{I zP0Y&^u|KEY7v%OYjV9a@BXX%AHT^Lvd9!tt*i+dwC-@PQIeoU%FYEYDv7PuRPx)gh@m}RCt{2oUeDRI26ZkR#n!OI^=t6R_vbBjKjUUVO1G7va%BX0(kDp$~xk9 z>Q=^)bx+ncj;yO|T~_d8!VG~h?d-gFxF5xwhTO~deiK6AlxVF1L1xJ>r%nJtP6oOk znJ?&mWWJ#Lk@RYCjZ@1zHU2x@ucSy8Bol6N+tvUe*a=E%Byha=A8i3ClhtL&)Tu;kP%I?FSN6Zi z>lR-z=28UhK#>AKT3G(J%u8LQu*^%Bp6X^rYUyw&)(6leV2%F)5!|G3ztl2cR;}Kb z^!t=8^VH$0M&&K@CAjKy08RWdU%CVtnfnzB2_ZbtTF11vh3``Upz9o@93N{{YXI>5 z<@8uxL`KNSWMogECw|S#laO!D{V5g_5}NazixfMTy5C6$Z$Pw~Hz}T8T*DoN7x?UQ zAju{}ySySJgxtct)|<#14>%&qaQs%XVMg5VMH{VkOqCGUG=!AS;p*1)QMXH%SSB<+ zsG4m8yYVZY*m^7{LLx5$31kEBV!8voNR%LBd& z)*DL_ZSnTYGj+vpKF-*K+#G3T^^|wt5NoXGcFkHp)Bt1&K@dxlxc>x5^-2F0@ z)?fD9q=}3BMRvJ*+_QL63sING_kEZ2nnG?5Tw+<$BGYe;ZCp!y0PrIwa{Bk5QJ<9* zlVB~Z?+Y%Rr2qgBtB2NpiPc#~O>Ie^(U=!^Z%JsqZ4Fm(hmOt7B+X-^>vj;0$g5bm zNL*&+X1O+fW!p{^4lZ(8_wzvOf_77;>)d{SuM#H{lkbgX?Mg8j=rRY!k1&z=(ZeQ% zWD)EQ0105XwiiUOBl(~dUKFRz@vfjEn_Bua8nZm$D;n(%0Ea4Wmm~G^NHoHlNt(w- z_W)uso~y{Jg<_c-B8jY)XLlMC9PV|ICj6LNsKf3T535IjWI;$KcIxUigS#DNa@!!d zub=PhQ_a)1OP}uGw8XM^#klaIxT$CF7F(D$vPhbKf!%JS)Ke}G>MqNC*~}u_1iJA%$jv%f ziJP3=e%etafW_FH>?(x?kLLMj?GQ=j3bfu!F=b{&2_OE=%H&pSDfS5ZmP=%XZK zTzT%RH!%0|tnyY*-dbzDxsOCU)GB#^#?1(5w54$@FUjSq{&`S&$1lNoE49p*0Pw4E z>h?G-dK+}`x~+9l*tecXy83MX_%eEl{ps4{zZU5gT-@Z(L&@22k;2U1bVz-|GB5Xo z)cfdm(Vp|03%E*)*NIhhNzy#-+ea_+FTelMm0+m6)vJe26+4*e*;`pps!C842T1Sh@S)bou8)#kLlTmb*Wf5ee+@x zFHb^V|0P&7X}RK5#r=1RiiO+XA|qsxq{Z}&`5%I*!=*?qcR%DO!ljDUBB}R-g~HhR zIo?+($A{p5vqEMIe&3JG7j!=|U(o%?d_ngk^99|H%olV&GGEaB$b3QfBl88_kIWZz kKQdp?{m6Vl_apP=KjIlK*T&{wC;$Ke07*qoM6N<$g5lrx@Bjb+ literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/short.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/short.png new file mode 100644 index 0000000000000000000000000000000000000000..4c9fcf76013d2e93d67a761ac540661f10a78d49 GIT binary patch literal 852 zcmeAS@N?(olHy`uVBq!ia0vp^^+2q~!2~3e;x1PMDaPU;cPEB*=VV?oFfj9Zx;Tbp zG`^jsSbW<+9ElI9PS_M3*X&7vNK=!`99w{ zzs+!Pmfg+Ic=EP0!#L}6(Z49K^cShFTNvlb>#tcDXntKh-J1I_L&ufPx%wwAxBab~ zBc--U5jY(gt(S%#+yH(k;E|V%HT{i6hg`9o_z(gYDAMpR1M`@K{wzFif14 z*nB7b#lEh+Qx?WJED@XMwB+5-fg`czEfG26Q(!P0@zwgUfdPh}Oz_3dpZ_k$CMe}c5=P&s9GVu|coD5TG&EDUy z_S(Oh@XRKn)46Nn<r$0M}J7-ScakwPi zZ{nTLhabr|$S>bf?HF9>@Np|YgTOittx2r`^Zko={dR0vuwdyIJrR~?jAy2;TC`fD z`rn~bCN{w(mxFeg|Fsa^_Qx^$;FJQ_fU>8R^R|09ZOc2Y`{8kEHCtDT;eLj;cb~na zPxJ@#xE9^s*L7e0=)NDub6wX@4xaj?>sVq?obak`atsQ)U+w=RH7mVgy>o7jJ;&|F zDeu3Xe{fg$^WCq{yR~HJtId0VPh=UJss5R(HkXd-J^3m3Q0&rHg`jTx8!w7PTD3O+ zdwlr$>3;jG<+-aT8%*t3t5;{u`LpPN&$PeZ=B-sRA4|TQIH`S&Za=v8wS@6HbxF%d zm;d|L2D<}-g$C2+zi}0rTD&@-sc;56XfLm=YOv~bxO)q R37Ab7JYD@<);T3K0RVdTr`iAj literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/single-item.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/single-item.png new file mode 100644 index 0000000000000000000000000000000000000000..6007c6d26cea2ffeab693d51500aaa3140ee74d3 GIT binary patch literal 652 zcmeAS@N?(olHy`uVBq!ia0vp^89=PY!2~3i>v+BbQjEnx?oJHr&dI!FU|@3dba4#H zXnZ?sf9W9ufn)wNn@Z#km*gl+U${7hWrl-XqtV=uW711DA1hGLb>zAoQJ<62Cn0z8 zua&a*uP>hE>igNP=bv}DbME$L);(G&GD1dtoRaM=JOl$C9gld3!(|!$b2C?Z zVsWc=uk^K7>mMoUZ8+gQC2@VCYjff~Jr(DzVh?hY@7$KWa@tY3XkJpxp0Mj}8*}q- zr}2qt&as&`H4Qk5(E6L3yze_PHP?_)RQ{PH$Dw?5gwbQ1%E zZ*b#{FPHCWsHfg}^;m)7*Gic+TJQE4>CQg1R_j`n)OC-BJjbiw<{BQm7B%bOeCel4 z^bh=8C>D@=pZmD=>Mq+kw>&rZe4iW@D#zIOT5|h^8ug!rwmmCDx0vch9$UY6*>Ua~ z{nycesFTUIp$aiKp!*S08_SdFw+tyKaR8gx(_^IwIk)8+PZxrf#Gd^`K5vWO- zwBf#s;Jk!&h4rmJ%~ovsl3o2%s^Vhp`RkI4_d7iJ5x?+P gH)>=e$8jA)Y;5&fL!%!Oz~sf?>FVdQ&MBb@0A6J&x&QzG literal 0 HcmV?d00001 diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/with-target.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/with-target.png new file mode 100644 index 0000000000000000000000000000000000000000..1b41aed6dde5d167a3fb4ec9d963ae5e863eff20 GIT binary patch literal 1696 zcmb8w`9Bj300!`FjyYn;5g&>|)0-)x+{bG%$FQ2^F5<0C=xvTSM@!0`BO2MVnyXFB zF?v()E5e#9_Rh5z$vN4y39pdXztAt==lSXR^~v-`x+utL$pHWW1%#_J3IG85?sr2O z(7s9~`p@aIwjhTye^9@A`;nykdv6eLye9EH8ev_fkJMH=1AUR* zzwB^{xf*&jSV(SdQ;RKtM6-sCs{!K~PcdsJu)x(LcB@8L<)^<_;m#}4$tnS#W!8vn zhlYSk?X_v=xu!@lkz+1#qrh64>b&9$rgWR>1(`w11^E{>%D6Q;DTPXeU;U=0DrRz1 zZ|qebk<>R3l$9X`oFWEo6$%-%k4oMau98v+ZFwt0+-ITAI>e@kb6bB*O?FI-ojusC z$v0UlJChu&9uS#+d^W|iXXD9awIG+LsfAqGXi}qEXarw-Tb~z!-Yoe21GR`Zh+<1% zcI}qb#c^l2PG!Ft*!Xn3FzG0ga9w+LdMOe@6|AqBp4vKarLMUDKKrlXW@pbcA%sKc>OFgq~3=9Ll90kHcq{vN5&yPA_A`*j6`_Y<1<1=0MX zm$O?xb?)s*2~)P0PkfJ&L&;e`?KqD;VOhgwL~DH7csTQ@z;0PP?6F>74*J%|zlVu_ ztIM+tHw@m$)I*A)MHg7C*xlS3ey?o6(Qhwg(%_2qIXWI^KZ-NB^_!))Vx7p{Lb;}h^s-tQ!N1GXioEdN23iuzzz;ONSnDW>#73s1mN@a zHSOD9p^dWFk8X>=_EDU8VetOAZm+za5rMUeF&YiLg3EcN>R?BpBAZ=l<;=xX3|kCE$E)%iMIGEz0!T^{zOO-Xk73rR{ehmRSeKh(be7~#V+a=}u z0&`ctlN|2N0lDZO?jwC!DG=RplZU1Cr^)VS%57YrB0cd#i%6cV?<^E<`W#mbN^E)^ zba@0mlR0FOwrgTq54q5a{!L+QKD;q!Fse_S8w8w4zr8(g7|hhUq|qJQ;4_QBNM^o+ zB3el_cR6p3Y=xxps^zI#nD{_9pC69n3XBDJg@FcUgfF25$BP@n4iUZOrovKRroA{{ zito6|yf&{~SIk^NU%4M0a%b=BmyiJrP-_GgXl7Meg+Nhltl1^LijshiA94M?Hm|PV zsLGq5>Qz4e+!`$9%f34ScEgwZuUZe>USy-y>8iN4#BH{>I2-f=Kl$Ckeh7=a*lR8q zMs>C|=2fSp04YThp5SkBOTnT)y_0#DHQR$Ey~DWY)_Q% zlyqpFjCjlQPtjRG@0?jetC(zRMpKrW6-Ua+X8Siqd1es@yWvkdt}F zgO;G7k{^qQqgCIon2lR2|40v&Q87(Wa>%DR%KijfkaBsaSGCe>4f~e^K){jCbxxO4 F{|AGjL1X{` literal 0 HcmV?d00001 From aa77adc01bcebd0b59786a31bf7b617180f82c2d Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Tue, 26 Aug 2025 12:13:45 +0300 Subject: [PATCH 03/14] chore: add web-types.lit.json configuration for breadcrumb component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- packages/breadcrumb/package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/breadcrumb/package.json b/packages/breadcrumb/package.json index 739f5721d8d..eaa947d3a96 100644 --- a/packages/breadcrumb/package.json +++ b/packages/breadcrumb/package.json @@ -23,7 +23,8 @@ "src", "vaadin-*.d.ts", "vaadin-*.js", - "web-types.json" + "web-types.json", + "web-types.lit.json" ], "keywords": [ "Vaadin", @@ -46,6 +47,7 @@ "sinon": "^21.0.0" }, "web-types": [ - "web-types.json" + "web-types.json", + "web-types.lit.json" ] } \ No newline at end of file From 42a7c10ad670feacfdc8fc78a49f46f63ef8f765 Mon Sep 17 00:00:00 2001 From: Artur Date: Sun, 28 Sep 2025 09:09:04 +0300 Subject: [PATCH 04/14] Update dev/breadcrumb.html Co-authored-by: Serhii Kulykov --- dev/breadcrumb.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev/breadcrumb.html b/dev/breadcrumb.html index 5ff9f673664..f246f95f891 100644 --- a/dev/breadcrumb.html +++ b/dev/breadcrumb.html @@ -6,8 +6,8 @@ vaadin-breadcrumb