Skip to content

Commit 98ebc02

Browse files
Artur-claude
andcommitted
feat: add breadcrumb component
Add a new breadcrumb navigation component with the following features: - Main `<vaadin-breadcrumb>` container component with semantic HTML - `<vaadin-breadcrumb-item>` 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 <[email protected]>
1 parent d5579d6 commit 98ebc02

11 files changed

+811
-0
lines changed

dev/breadcrumb.html

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>vaadin-breadcrumb</title>
7+
<script type="module" src="./common.js"></script>
8+
<script type="module">
9+
import '../packages/breadcrumb/vaadin-breadcrumb.js';
10+
import '../packages/breadcrumb/vaadin-breadcrumb-item.js';
11+
</script>
12+
<style>
13+
.demo-section {
14+
margin: 2em 0;
15+
}
16+
17+
.demo-section h3 {
18+
margin-bottom: 1em;
19+
}
20+
</style>
21+
</head>
22+
23+
<body>
24+
<h2>Breadcrumb Examples</h2>
25+
26+
<div class="demo-section">
27+
<h3>Basic Breadcrumb</h3>
28+
<vaadin-breadcrumb>
29+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
30+
<vaadin-breadcrumb-item href="/products">Products</vaadin-breadcrumb-item>
31+
<vaadin-breadcrumb-item href="/products/laptops">Laptops</vaadin-breadcrumb-item>
32+
<vaadin-breadcrumb-item>MacBook Pro</vaadin-breadcrumb-item>
33+
</vaadin-breadcrumb>
34+
</div>
35+
36+
<div class="demo-section">
37+
<h3>Short Breadcrumb</h3>
38+
<vaadin-breadcrumb>
39+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
40+
<vaadin-breadcrumb-item>Settings</vaadin-breadcrumb-item>
41+
</vaadin-breadcrumb>
42+
</div>
43+
44+
<div class="demo-section">
45+
<h3>Breadcrumb with Target</h3>
46+
<vaadin-breadcrumb>
47+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
48+
<vaadin-breadcrumb-item href="https://vaadin.com" target="_blank">Vaadin (opens in new tab)</vaadin-breadcrumb-item>
49+
<vaadin-breadcrumb-item>Current Page</vaadin-breadcrumb-item>
50+
</vaadin-breadcrumb>
51+
</div>
52+
53+
<div class="demo-section">
54+
<h3>Disabled Items</h3>
55+
<vaadin-breadcrumb>
56+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
57+
<vaadin-breadcrumb-item href="/products" disabled>Products (disabled)</vaadin-breadcrumb-item>
58+
<vaadin-breadcrumb-item>Current Page</vaadin-breadcrumb-item>
59+
</vaadin-breadcrumb>
60+
</div>
61+
62+
<div class="demo-section">
63+
<h3>Long Breadcrumb Trail</h3>
64+
<vaadin-breadcrumb>
65+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
66+
<vaadin-breadcrumb-item href="/docs">Documentation</vaadin-breadcrumb-item>
67+
<vaadin-breadcrumb-item href="/docs/components">Components</vaadin-breadcrumb-item>
68+
<vaadin-breadcrumb-item href="/docs/components/navigation">Navigation</vaadin-breadcrumb-item>
69+
<vaadin-breadcrumb-item href="/docs/components/navigation/breadcrumb">Breadcrumb</vaadin-breadcrumb-item>
70+
<vaadin-breadcrumb-item>Examples</vaadin-breadcrumb-item>
71+
</vaadin-breadcrumb>
72+
</div>
73+
74+
<div class="demo-section">
75+
<h3>Router Ignore Example</h3>
76+
<vaadin-breadcrumb>
77+
<vaadin-breadcrumb-item href="/">Home</vaadin-breadcrumb-item>
78+
<vaadin-breadcrumb-item href="/api" router-ignore>API (full page reload)</vaadin-breadcrumb-item>
79+
<vaadin-breadcrumb-item>Current</vaadin-breadcrumb-item>
80+
</vaadin-breadcrumb>
81+
</div>
82+
</body>
83+
</html>

packages/breadcrumb/package.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"name": "@vaadin/breadcrumb",
3+
"version": "25.0.0-alpha16",
4+
"publishConfig": {
5+
"access": "public"
6+
},
7+
"description": "vaadin-breadcrumb",
8+
"license": "Apache-2.0",
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/vaadin/web-components.git",
12+
"directory": "packages/breadcrumb"
13+
},
14+
"author": "Vaadin Ltd",
15+
"homepage": "https://vaadin.com/components",
16+
"bugs": {
17+
"url": "https://github.com/vaadin/web-components/issues"
18+
},
19+
"main": "vaadin-breadcrumb.js",
20+
"module": "vaadin-breadcrumb.js",
21+
"type": "module",
22+
"files": [
23+
"src",
24+
"vaadin-*.d.ts",
25+
"vaadin-*.js",
26+
"web-types.json"
27+
],
28+
"keywords": [
29+
"Vaadin",
30+
"breadcrumb",
31+
"navigation",
32+
"web-components",
33+
"web-component"
34+
],
35+
"dependencies": {
36+
"@open-wc/dedupe-mixin": "^1.3.0",
37+
"@vaadin/a11y-base": "25.0.0-alpha16",
38+
"@vaadin/component-base": "25.0.0-alpha16",
39+
"@vaadin/vaadin-themable-mixin": "25.0.0-alpha16",
40+
"lit": "^3.0.0"
41+
},
42+
"devDependencies": {
43+
"@vaadin/chai-plugins": "25.0.0-alpha16",
44+
"@vaadin/testing-helpers": "^2.0.0",
45+
"@vaadin/vaadin-lumo-styles": "25.0.0-alpha16",
46+
"sinon": "^21.0.0"
47+
},
48+
"web-types": [
49+
"web-types.json"
50+
]
51+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* @license
3+
* Copyright (c) 2017 - 2025 Vaadin Ltd.
4+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5+
*/
6+
import '@vaadin/component-base/src/styles/style-props.js';
7+
import '@vaadin/vaadin-lumo-styles/font-icons.js';
8+
import { css } from 'lit';
9+
10+
export const breadcrumbItemStyles = css`
11+
:host {
12+
display: inline-flex;
13+
align-items: center;
14+
white-space: nowrap;
15+
}
16+
17+
:host([hidden]) {
18+
display: none !important;
19+
}
20+
21+
[part='link'] {
22+
display: inline-flex;
23+
align-items: center;
24+
text-decoration: var(--vaadin-breadcrumb-link-text-decoration, none);
25+
color: var(--vaadin-breadcrumb-link-color, var(--vaadin-secondary-text-color));
26+
transition: color 0.2s;
27+
outline: none;
28+
cursor: var(--vaadin-clickable-cursor);
29+
}
30+
31+
a[part='link']:hover {
32+
text-decoration: var(--vaadin-breadcrumb-link-hover-text-decoration, underline);
33+
color: var(--vaadin-breadcrumb-link-hover-color, var(--vaadin-primary-text-color));
34+
}
35+
36+
a[part='link']:focus-visible {
37+
border-radius: var(--vaadin-radius-s);
38+
box-shadow: 0 0 0 2px var(--vaadin-focus-ring-color);
39+
}
40+
41+
span[part='link'] {
42+
color: var(--vaadin-breadcrumb-current-color, var(--vaadin-primary-text-color));
43+
cursor: default;
44+
}
45+
46+
:host([disabled]) [part='link'] {
47+
color: var(--vaadin-disabled-text-color);
48+
cursor: default;
49+
pointer-events: none;
50+
}
51+
52+
:host([last]) [part='link'] {
53+
color: var(--vaadin-breadcrumb-current-color, var(--vaadin-primary-text-color));
54+
font-weight: var(--vaadin-breadcrumb-current-font-weight, 500);
55+
}
56+
57+
[part='separator'] {
58+
display: inline-flex;
59+
align-items: center;
60+
margin: 0 var(--vaadin-breadcrumb-separator-spacing, var(--vaadin-space-xs));
61+
color: var(--vaadin-breadcrumb-separator-color, var(--vaadin-tertiary-text-color));
62+
}
63+
64+
[part='separator']::after {
65+
content: var(--vaadin-breadcrumb-separator, var(--lumo-icons-angle-right));
66+
font-family: var(--vaadin-breadcrumb-separator-font-family, 'lumo-icons');
67+
font-size: var(--vaadin-breadcrumb-separator-size, var(--vaadin-icon-size-s));
68+
}
69+
`;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @license
3+
* Copyright (c) 2017 - 2025 Vaadin Ltd.
4+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5+
*/
6+
import '@vaadin/component-base/src/styles/style-props.js';
7+
import '@vaadin/vaadin-lumo-styles/font-icons.js';
8+
import { css } from 'lit';
9+
10+
export const breadcrumbStyles = css`
11+
:host {
12+
display: block;
13+
font-size: var(--vaadin-breadcrumb-font-size, var(--vaadin-font-size-s));
14+
line-height: var(--vaadin-breadcrumb-line-height, var(--vaadin-line-height-xs));
15+
}
16+
17+
:host([hidden]) {
18+
display: none !important;
19+
}
20+
21+
[part='list'] {
22+
display: flex;
23+
flex-wrap: wrap;
24+
align-items: center;
25+
list-style: none;
26+
margin: 0;
27+
padding: 0;
28+
}
29+
`;

0 commit comments

Comments
 (0)