11/*-
22 * #%L
3- *
3+ *
44 * Copyright (C) 2018 - 2025 Vaadin Ltd
5- *
5+ *
66 * Licensed under the Apache License, Version 2.0 (the "License");
77 * you may not use this file except in compliance with the License.
88 * You may obtain a copy of the License at
9- *
9+ *
1010 * http://www.apache.org/licenses/LICENSE-2.0
11- *
11+ *
1212 * Unless required by applicable law or agreed to in writing, software
1313 * distributed under the License is distributed on an "AS IS" BASIS,
1414 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1818 */
1919import { html , LitElement , css } from "lit" ;
2020import { customElement , property } from 'lit/decorators.js' ;
21- import { ThemableMixin } from "@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js" ;
2221import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js' ;
2322import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js' ;
24- import { typography } from "@vaadin/vaadin-lumo-styles" ;
2523
2624/**
2725 * A Web Component for individual breadcrumb items in a breadcrumb navigation system.
28- *
26+ *
2927 * - Built using LitElement with theming support via Vaadin's ThemableMixin.
3028 * - Represents a single navigation step, optionally linking to a specific URL via the `href` property.
3129 * - Can be marked as collapsible using the `collapse` attribute to allow responsive shrinking (When this attribute is added,
32- * the breadcrumb label will show ellipsis if the available space is not enough to fit the whole label).
30+ * the breadcrumb label will show ellipsis if the available space is not enough to fit the whole label).
3331 * - Supports an ellipsis mode (`part="ellipsis"`) to indicate hidden breadcrumbs when space is limited.
3432 * - Displays a separator unless it is the last breadcrumb in the sequence.
35- *
33+ *
3634 * Example usage:
3735 * ```html
3836 * <vcf-breadcrumb href="/home">Home</vcf-breadcrumb>
3937 * <vcf-breadcrumb href="/products">Products</vcf-breadcrumb>
4038 * <vcf-breadcrumb>Current Page</vcf-breadcrumb>
4139 * ```
42- *
40+ *
4341 * @memberof Vaadin
4442 * @name vcf-breadcrumb
4543 * @mixes ElementMixin
46- * @mixes ThemableMixin
4744 * @mixes PolylitMixin
4845 * @demo demo/index.html
4946 */
5047@customElement ( "vcf-breadcrumb" )
51- class VcfBreadcrumb extends ElementMixin ( ThemableMixin ( PolylitMixin ( LitElement ) ) ) {
48+ class VcfBreadcrumb extends ElementMixin ( PolylitMixin ( LitElement ) ) {
5249
53- @property ( { type : String , reflect : true } )
50+ @property ( { type : String , reflect : true } )
5451 href = '' ;
5552
56- @property ( { type : Boolean , reflect : true } )
53+ @property ( { type : Boolean , reflect : true } )
5754 collapse = false ;
5855
5956 static get is ( ) {
@@ -75,16 +72,67 @@ class VcfBreadcrumb extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))
7572 }
7673
7774 static get styles ( ) {
78- return [ typography , css `
79- : host (: last- of- type) [part = 'separator' ] {
80- display : none;
81- }
82-
75+ return [ css `
8376 : host {
8477 display : flex;
8578 align-items : center;
8679 min-width : 40px ;
87- }
80+ --vcf-breadcrumb-separator-font-family : 'inherit' ;
81+ --vcf-breadcrumb-separator-symbol : '/' ;
82+ --vcf-breadcrumb-separator-color : var (--vaadin-text-color-secondary , # 666 );
83+ --vcf-breadcrumb-separator-size : var (--vaadin-icon-size , 1lh );
84+ --vcf-breadcrumb-separator-margin : 0 ;
85+ --vcf-breadcrumb-separator-padding : 0 var (--vaadin-padding-xs , 6px );
86+ --vcf-breadcrumb-mobile-back-symbol : '←' ;
87+ --vcf-breadcrumb-link-focus-ring-color : var (--vaadin-focus-ring-color , Highlight);
88+ }
89+
90+ : host [part = 'separator' ] {
91+ margin : var (--vcf-breadcrumb-separator-margin );
92+ padding : var (--vcf-breadcrumb-separator-padding );
93+ }
94+
95+ : host [part = 'separator' ]::after {
96+ font-family : var (--vcf-breadcrumb-separator-font-family );
97+ content : var (--vcf-breadcrumb-separator-symbol );
98+ color : var (--vcf-breadcrumb-separator-color );
99+ font-size : var (--vcf-breadcrumb-separator-size );
100+ speak : none;
101+ }
102+
103+ : host (: last- of- type) [part = 'separator' ] {
104+ display : none;
105+ }
106+
107+ [part = 'link' ] {
108+ overflow : hidden;
109+ white-space : nowrap;
110+ text-overflow : ellipsis;
111+ }
112+
113+ /* Focus ring */
114+ : host (: focus-within ) [part = "link" ] {
115+ outline : var (--vcf-breadcrumb-link-focus-ring-color ) auto 1px ;
116+ outline-offset : 1px ;
117+ }
118+
119+ ::slotted (a:focus) {
120+ outline : none;
121+ }
122+
123+ /* mobile back mode */
124+ : host (.mobile-back ) {
125+ display : none;
126+ }
127+
128+ : host (.mobile-back ) [part = 'separator' ] {
129+ display : none;
130+ }
131+
132+ : host (.mobile-back .is-last-not-current ),
133+ : host (.mobile-back .is-before-current ) {
134+ display : inline-block;
135+ }
88136 ` ] ;
89137 }
90138
@@ -115,14 +163,14 @@ class VcfBreadcrumb extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))
115163 // @ts -ignore
116164 popover . opened = ! popover . opened ;
117165 }
118- } ) ;
166+ } ) ;
119167 popover . addEventListener ( "opened-changed" , ( event ) => {
120168 if ( ! ( ( event as CustomEvent ) . detail . value ) ) {
121169 anchor . focus ( ) ; // Return focus to the ellipsis element
122170 }
123- } ) ;
171+ } ) ;
124172 anchor . appendChild ( popover ) ;
125- }
173+ }
126174 this . removeAttribute ( "id" ) ;
127175 }
128176
@@ -142,7 +190,7 @@ class VcfBreadcrumb extends ElementMixin(ThemableMixin(PolylitMixin(LitElement))
142190 _isEllipsisElement ( ) {
143191 return this . getAttribute ( "part" ) === "ellipsis" ;
144192 }
145-
193+
146194}
147195
148196export { VcfBreadcrumb } ;
0 commit comments