diff --git a/dev/breadcrumb.html b/dev/breadcrumb.html new file mode 100644 index 00000000000..92aa76bb7d5 --- /dev/null +++ b/dev/breadcrumb.html @@ -0,0 +1,88 @@ + + + + + + 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..4e601fd7ad9 --- /dev/null +++ b/packages/breadcrumb/package.json @@ -0,0 +1,54 @@ +{ + "name": "@vaadin/breadcrumb", + "version": "25.0.0-alpha20", + "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", + "web-types.lit.json" + ], + "keywords": [ + "Vaadin", + "breadcrumb", + "navigation", + "web-components", + "web-component" + ], + "dependencies": { + "@open-wc/dedupe-mixin": "^1.3.0", + "@vaadin/a11y-base": "25.0.0-alpha20", + "@vaadin/component-base": "25.0.0-alpha20", + "@vaadin/vaadin-themable-mixin": "25.0.0-alpha20", + "lit": "^3.0.0" + }, + "devDependencies": { + "@vaadin/chai-plugins": "25.0.0-alpha20", + "@vaadin/test-runner-commands": "25.0.0-alpha20", + "@vaadin/testing-helpers": "^2.0.0", + "@vaadin/vaadin-lumo-styles": "25.0.0-alpha20", + "sinon": "^21.0.0" + }, + "web-types": [ + "web-types.json", + "web-types.lit.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..4fdffec621f --- /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/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..f6147be5a91 --- /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/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.d.ts b/packages/breadcrumb/src/vaadin-breadcrumb-item.d.ts new file mode 100644 index 00000000000..cd908d7368e --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb-item.d.ts @@ -0,0 +1,67 @@ +/** + * @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. + * + * ⚠️ **This component is experimental** and the API may change. In order to use it, enable the feature flag by setting `window.Vaadin.featureFlags.breadcrumbComponent = true`. + * + * ```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/src/vaadin-breadcrumb-item.js b/packages/breadcrumb/src/vaadin-breadcrumb-item.js new file mode 100644 index 00000000000..cafc46efa19 --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb-item.js @@ -0,0 +1,206 @@ +/** + * @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. + * + * ⚠️ **This component is experimental** and the API may change. In order to use it, enable the feature flag by setting `window.Vaadin.featureFlags.breadcrumbComponent = true`. + * + * ```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 experimental() { + return 'breadcrumbComponent'; + } + + 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.d.ts b/packages/breadcrumb/src/vaadin-breadcrumb.d.ts new file mode 100644 index 00000000000..61a1f64cbe3 --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb.d.ts @@ -0,0 +1,45 @@ +/** + * @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. + * + * ⚠️ **This component is experimental** and the API may change. In order to use it, enable the feature flag by setting `window.Vaadin.featureFlags.breadcrumbComponent = true`. + * + * ```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)) { + /** + * The aria-label attribute for the breadcrumb navigation + */ + ariaLabel: string; +} + +declare global { + interface HTMLElementTagNameMap { + 'vaadin-breadcrumb': Breadcrumb; + } +} + +export { Breadcrumb }; diff --git a/packages/breadcrumb/src/vaadin-breadcrumb.js b/packages/breadcrumb/src/vaadin-breadcrumb.js new file mode 100644 index 00000000000..b7510bd8bad --- /dev/null +++ b/packages/breadcrumb/src/vaadin-breadcrumb.js @@ -0,0 +1,119 @@ +/** + * @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. + * + * ⚠️ **This component is experimental** and the API may change. In order to use it, enable the feature flag by setting `window.Vaadin.featureFlags.breadcrumbComponent = true`. + * + * ```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 experimental() { + return true; + } + + static get styles() { + return breadcrumbStyles; + } + + static get properties() { + return { + /** + * The aria-label attribute for the breadcrumb navigation + */ + ariaLabel: { + type: String, + value: 'Breadcrumb', + reflectToAttribute: true, + sync: true, + }, + + /** + * 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'); + } + } + + /** @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..31adfc5016d --- /dev/null +++ b/packages/breadcrumb/test/breadcrumb.test.js @@ -0,0 +1,165 @@ +import { expect } from '@vaadin/chai-plugins'; +import { fixtureSync, nextFrame } from '@vaadin/testing-helpers'; + +// Enable experimental breadcrumb component +window.Vaadin ??= {}; +window.Vaadin.featureFlags ??= {}; +window.Vaadin.featureFlags.breadcrumbComponent = true; + +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/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..c0c8a02f591 --- /dev/null +++ b/packages/breadcrumb/test/dom/breadcrumb.test.js @@ -0,0 +1,150 @@ +import { expect } from '@vaadin/chai-plugins'; +import { sendKeys } from '@vaadin/test-runner-commands'; +import { fixtureSync } from '@vaadin/testing-helpers'; + +// Enable experimental breadcrumb component +window.Vaadin ??= {}; +window.Vaadin.featureFlags ??= {}; +window.Vaadin.featureFlags.breadcrumbComponent = true; + +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 00000000000..17f049bf7ea Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/default.png differ 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 00000000000..0871cc70ecc Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled-hover.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled.png new file mode 100644 index 00000000000..0871cc70ecc Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/disabled.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-first.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-first.png new file mode 100644 index 00000000000..0871cc70ecc Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-first.png differ 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 00000000000..0871cc70ecc Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/focus-ring-second.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/hover.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/hover.png new file mode 100644 index 00000000000..0871cc70ecc Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/hover.png differ 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 00000000000..1be32b3501a Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/long-trail.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/router-ignore.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/router-ignore.png new file mode 100644 index 00000000000..f8f24302645 Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/router-ignore.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/rtl.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/rtl.png new file mode 100644 index 00000000000..7fde199bb15 Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/rtl.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/short.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/short.png new file mode 100644 index 00000000000..67ee48d1aec Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/short.png differ diff --git a/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/single-item.png b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/single-item.png new file mode 100644 index 00000000000..be6bd69fea0 Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/single-item.png differ 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 00000000000..2a100f8e191 Binary files /dev/null and b/packages/breadcrumb/test/visual/base/screenshots/breadcrumb/baseline/with-target.png differ diff --git a/packages/breadcrumb/test/visual/lumo/breadcrumb.test.js b/packages/breadcrumb/test/visual/lumo/breadcrumb.test.js new file mode 100644 index 00000000000..c6ee7d1a280 --- /dev/null +++ b/packages/breadcrumb/test/visual/lumo/breadcrumb.test.js @@ -0,0 +1,217 @@ +import { resetMouse, sendKeys, sendMouseToElement } from '@vaadin/test-runner-commands'; +import { fixtureSync } from '@vaadin/testing-helpers'; +import { visualDiff } from '@web/test-runner-visual-regression'; +import '@vaadin/vaadin-lumo-styles/props.css'; + +// Enable experimental breadcrumb component +window.Vaadin ??= {}; +window.Vaadin.featureFlags ??= {}; +window.Vaadin.featureFlags.breadcrumbComponent = true; + +import '../../../vaadin-breadcrumb.js'; +import '../../../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/lumo/screenshots/breadcrumb/baseline/default.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/default.png new file mode 100644 index 00000000000..68ee49bdb7e Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/default.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled-hover.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled-hover.png new file mode 100644 index 00000000000..434bef30911 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled-hover.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled.png new file mode 100644 index 00000000000..434bef30911 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/disabled.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-first.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-first.png new file mode 100644 index 00000000000..434bef30911 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-first.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-second.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-second.png new file mode 100644 index 00000000000..434bef30911 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/focus-ring-second.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/hover.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/hover.png new file mode 100644 index 00000000000..c9e3e86ce0c Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/hover.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/long-trail.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/long-trail.png new file mode 100644 index 00000000000..fb32a1f5eae Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/long-trail.png differ 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 00000000000..ad43bad9f19 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/router-ignore.png differ diff --git a/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/rtl.png b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/rtl.png new file mode 100644 index 00000000000..d351e526fb1 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/rtl.png differ 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 00000000000..4c9fcf76013 Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/short.png differ 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 00000000000..6007c6d26ce Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/single-item.png differ 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 00000000000..1b41aed6dde Binary files /dev/null and b/packages/breadcrumb/test/visual/lumo/screenshots/breadcrumb/baseline/with-target.png differ diff --git a/packages/breadcrumb/vaadin-breadcrumb-item.d.ts b/packages/breadcrumb/vaadin-breadcrumb-item.d.ts new file mode 100644 index 00000000000..5af55d239ca --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb-item.d.ts @@ -0,0 +1 @@ +export * from './src/vaadin-breadcrumb-item.js'; 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..c6198ecdd2f --- /dev/null +++ b/packages/breadcrumb/vaadin-breadcrumb.d.ts @@ -0,0 +1 @@ +export * from './src/vaadin-breadcrumb.js'; 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';