diff --git a/screenshot/builds/master.json b/screenshot/builds/master.json
index 70533c0865..569f697e3a 100644
--- a/screenshot/builds/master.json
+++ b/screenshot/builds/master.json
@@ -381,6 +381,58 @@
"isLandscape": false,
"isMobile": false
},
+ {
+ "id": "eff4f911",
+ "image": "a37d4364febc6a1c279bb675ea0eb056.png",
+ "userAgent": "default",
+ "desc": "ld-breadcrumbs renders as CSS Component",
+ "testPath": "./src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts",
+ "width": 600,
+ "height": 600,
+ "deviceScaleFactor": 1,
+ "hasTouch": false,
+ "isLandscape": false,
+ "isMobile": false
+ },
+ {
+ "id": "f91c2718",
+ "image": "a37d4364febc6a1c279bb675ea0eb056.png",
+ "userAgent": "default",
+ "desc": "ld-breadcrumbs renders as Web Component",
+ "testPath": "./src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts",
+ "width": 600,
+ "height": 600,
+ "deviceScaleFactor": 1,
+ "hasTouch": false,
+ "isLandscape": false,
+ "isMobile": false
+ },
+ {
+ "id": "94e3f635",
+ "image": "053c6df29d132a360ae66ba7abd42795.png",
+ "userAgent": "default",
+ "desc": "ld-breadcrumbs renders with icons as CSS component",
+ "testPath": "./src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts",
+ "width": 600,
+ "height": 600,
+ "deviceScaleFactor": 1,
+ "hasTouch": false,
+ "isLandscape": false,
+ "isMobile": false
+ },
+ {
+ "id": "cdf7649b",
+ "image": "053c6df29d132a360ae66ba7abd42795.png",
+ "userAgent": "default",
+ "desc": "ld-breadcrumbs renders with icons as Web Component",
+ "testPath": "./src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts",
+ "width": 600,
+ "height": 600,
+ "deviceScaleFactor": 1,
+ "hasTouch": false,
+ "isLandscape": false,
+ "isMobile": false
+ },
{
"id": "c5c7582a",
"image": "e0193ce006e37fabf36900daaadd0712.png",
@@ -7377,7 +7429,7 @@
},
{
"id": "11c3a598",
- "image": "f63a4918e6f270256c006b1df8b99d6c.png",
+ "image": "796d9b032fbdbcef50000743d0889bc8.png",
"userAgent": "default",
"desc": "ld-link css component with chevron end",
"testPath": "./src/liquid/components/ld-link/test/ld-link.e2e.ts",
@@ -7390,7 +7442,7 @@
},
{
"id": "ebcd4fea",
- "image": "f9c3e4ef4d16627a54a6ec0640ca4c50.png",
+ "image": "2507876c594192cb4fb29e004ae599df.png",
"userAgent": "default",
"desc": "ld-link css component with chevron start",
"testPath": "./src/liquid/components/ld-link/test/ld-link.e2e.ts",
@@ -7429,7 +7481,7 @@
},
{
"id": "a51ed960",
- "image": "025b40f6e717937da79d23075f94454a.png",
+ "image": "6f0fe7041f6573b8a71a8622b40e7c22.png",
"userAgent": "default",
"desc": "ld-link web component with chevron end",
"testPath": "./src/liquid/components/ld-link/test/ld-link.e2e.ts",
@@ -7442,7 +7494,7 @@
},
{
"id": "235718a5",
- "image": "db0056903ab347b75e15880aeed38984.png",
+ "image": "e180cf4b6a412aedb2a005aa9df45864.png",
"userAgent": "default",
"desc": "ld-link web component with chevron start",
"testPath": "./src/liquid/components/ld-link/test/ld-link.e2e.ts",
diff --git a/screenshot/images/025b40f6e717937da79d23075f94454a.png b/screenshot/images/025b40f6e717937da79d23075f94454a.png
deleted file mode 100644
index 5327a0f1f1..0000000000
Binary files a/screenshot/images/025b40f6e717937da79d23075f94454a.png and /dev/null differ
diff --git a/screenshot/images/053c6df29d132a360ae66ba7abd42795.png b/screenshot/images/053c6df29d132a360ae66ba7abd42795.png
new file mode 100644
index 0000000000..0a9d07ecb8
Binary files /dev/null and b/screenshot/images/053c6df29d132a360ae66ba7abd42795.png differ
diff --git a/screenshot/images/2507876c594192cb4fb29e004ae599df.png b/screenshot/images/2507876c594192cb4fb29e004ae599df.png
new file mode 100644
index 0000000000..ac1b9a1277
Binary files /dev/null and b/screenshot/images/2507876c594192cb4fb29e004ae599df.png differ
diff --git a/screenshot/images/6f0fe7041f6573b8a71a8622b40e7c22.png b/screenshot/images/6f0fe7041f6573b8a71a8622b40e7c22.png
new file mode 100644
index 0000000000..b772b4f0aa
Binary files /dev/null and b/screenshot/images/6f0fe7041f6573b8a71a8622b40e7c22.png differ
diff --git a/screenshot/images/796d9b032fbdbcef50000743d0889bc8.png b/screenshot/images/796d9b032fbdbcef50000743d0889bc8.png
new file mode 100644
index 0000000000..66a29fbddc
Binary files /dev/null and b/screenshot/images/796d9b032fbdbcef50000743d0889bc8.png differ
diff --git a/screenshot/images/a37d4364febc6a1c279bb675ea0eb056.png b/screenshot/images/a37d4364febc6a1c279bb675ea0eb056.png
new file mode 100644
index 0000000000..1bac149e15
Binary files /dev/null and b/screenshot/images/a37d4364febc6a1c279bb675ea0eb056.png differ
diff --git a/screenshot/images/db0056903ab347b75e15880aeed38984.png b/screenshot/images/db0056903ab347b75e15880aeed38984.png
deleted file mode 100644
index 1bc1ebd3bb..0000000000
Binary files a/screenshot/images/db0056903ab347b75e15880aeed38984.png and /dev/null differ
diff --git a/screenshot/images/e180cf4b6a412aedb2a005aa9df45864.png b/screenshot/images/e180cf4b6a412aedb2a005aa9df45864.png
new file mode 100644
index 0000000000..0510e22830
Binary files /dev/null and b/screenshot/images/e180cf4b6a412aedb2a005aa9df45864.png differ
diff --git a/screenshot/images/f63a4918e6f270256c006b1df8b99d6c.png b/screenshot/images/f63a4918e6f270256c006b1df8b99d6c.png
deleted file mode 100644
index a86cbcdc52..0000000000
Binary files a/screenshot/images/f63a4918e6f270256c006b1df8b99d6c.png and /dev/null differ
diff --git a/screenshot/images/f9c3e4ef4d16627a54a6ec0640ca4c50.png b/screenshot/images/f9c3e4ef4d16627a54a6ec0640ca4c50.png
deleted file mode 100644
index ecfd307704..0000000000
Binary files a/screenshot/images/f9c3e4ef4d16627a54a6ec0640ca4c50.png and /dev/null differ
diff --git a/src/docs/components/docs-breadcrumbs/assets/chevron-dark.svg b/src/docs/components/docs-breadcrumbs/assets/chevron-dark.svg
deleted file mode 100644
index 15c1c0de09..0000000000
--- a/src/docs/components/docs-breadcrumbs/assets/chevron-dark.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/docs/components/docs-breadcrumbs/assets/chevron-light.svg b/src/docs/components/docs-breadcrumbs/assets/chevron-light.svg
deleted file mode 100644
index db9943731c..0000000000
--- a/src/docs/components/docs-breadcrumbs/assets/chevron-light.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.css b/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.css
deleted file mode 100644
index cce6ca085f..0000000000
--- a/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.css
+++ /dev/null
@@ -1,57 +0,0 @@
-@define-mixin docs-breadcrumbs-ui-light {
- .docs-breadcrumbs__list li::after {
- background-image: url('dist/build/assets/chevron-dark.svg');
- }
-}
-
-@define-mixin docs-breadcrumbs-ui-dark {
- .docs-breadcrumbs__list li::after {
- background-image: url('dist/build/assets/chevron-light.svg');
- }
-}
-
-@mixin docs-breadcrumbs-ui-light;
-
-@media (prefers-color-scheme: dark) {
- @mixin docs-breadcrumbs-ui-dark;
-}
-.docs-ui-dark {
- @mixin docs-breadcrumbs-ui-dark;
-}
-.docs-ui-light {
- @mixin docs-breadcrumbs-ui-light;
-}
-
-docs-breadcrumbs,
-.docs-breadcrumbs {
- min-height: 1.75rem;
- width: 100%;
-}
-
-.docs-breadcrumbs__list {
- display: flex;
- flex-wrap: wrap;
- list-style: none;
- font: var(--ld-typo-body-s);
-
- li:not(:last-of-type) {
- margin-right: var(--ld-sp-8);
-
- &::after {
- content: '';
- background-repeat: no-repeat;
- width: 0.8rem;
- height: 1.375rem;
- margin-left: var(--ld-sp-12);
- display: inline-flex;
- align-items: center;
- justify-content: center;
- }
- }
-
- a:not([href]),
- a[href='.'] {
- cursor: default;
- pointer-events: none;
- }
-}
diff --git a/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.tsx b/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.tsx
deleted file mode 100644
index 9eb8fadbed..0000000000
--- a/src/docs/components/docs-breadcrumbs/docs-breadcrumbs.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Component, h, Host } from '@stencil/core'
-
-/** @internal **/
-@Component({
- tag: 'docs-breadcrumbs',
- styleUrl: 'docs-breadcrumbs.css',
- shadow: false,
- assetsDirs: ['assets'],
-})
-export class DocsBreadcrumbs {
- render() {
- return (
-
-
-
- )
- }
-}
diff --git a/src/docs/components/docs-main/docs-main.css b/src/docs/components/docs-main/docs-main.css
index 4c3ef5fe79..58851fd3f7 100644
--- a/src/docs/components/docs-main/docs-main.css
+++ b/src/docs/components/docs-main/docs-main.css
@@ -5,6 +5,12 @@
}
main {
+ > header {
+ ld-breadcrumbs {
+ filter: none;
+ }
+ }
+
> p,
> ol,
> ul,
@@ -77,6 +83,12 @@
}
main {
+ > header {
+ ld-breadcrumbs {
+ filter: invert(1) hue-rotate(180deg);
+ }
+ }
+
> p,
> ol,
> ul,
@@ -179,9 +191,14 @@
display: flex;
justify-content: flex-end;
flex-wrap: wrap;
+ align-items: center;
+ }
- > * + *:not(.docs-breadcrumbs) {
- margin-top: var(--ld-sp-16);
+ > header {
+ ld-breadcrumbs {
+ flex-grow: 1;
+ margin-inline: 0 var(--ld-sp-24);
+ margin-block: var(--ld-sp-16);
}
}
diff --git a/src/docs/includes/layout.njk b/src/docs/includes/layout.njk
index 61c83798a8..b8f572aea8 100644
--- a/src/docs/includes/layout.njk
+++ b/src/docs/includes/layout.njk
@@ -112,18 +112,14 @@ title: Introduction
{% if 'Introduction' not in title and not '404' in title and not 'legal' in page.url %}
-
+
{% set navPages = collections.all | eleventyNavigationBreadcrumb(title) %}
{% macro renderBreadcrumb(entry) %}
-
- {{ entry.title }}
-
+ {{ entry.title }}
{% endmacro %}
{% for entry in navPages %}{{ renderBreadcrumb(entry) }}{% endfor %}
-
- {{ title }}
-
-
+ {{ title }}
+
{% endif %}
diff --git a/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.css b/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.css
new file mode 100644
index 0000000000..61ef751565
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.css
@@ -0,0 +1,15 @@
+:host,
+.ld-breadcrumbs {
+ --ld-crumb-icon-gap: 0.5em;
+ --ld-crumb-gap: 0.6em;
+
+ line-height: 1.5;
+}
+
+.ld-breadcrumbs > ol {
+ display: flex;
+ flex-wrap: wrap;
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
diff --git a/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.tsx b/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.tsx
new file mode 100644
index 0000000000..6637d869fd
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/ld-breadcrumbs.tsx
@@ -0,0 +1,52 @@
+import '../../components' // type definitions for type checks and intelliSense
+import { Component, h, Element } from '@stencil/core'
+
+/**
+ * @part list - Breadcrumbs list
+ * @virtualProp ref - reference to component
+ * @virtualProp {string | number} key - for tracking the node's identity when working with lists
+ */
+
+@Component({
+ tag: 'ld-breadcrumbs',
+ styleUrl: 'ld-breadcrumbs.css',
+ shadow: true,
+})
+export class LdBreadcrumbs {
+ @Element() el: HTMLElement
+
+ private observer: MutationObserver
+
+ private updateCurrent = () => {
+ const crumbs = this.el.querySelectorAll('ld-crumb')
+ crumbs.forEach((crumb) => {
+ crumb.current = undefined
+ })
+ crumbs[crumbs.length - 1].current = true
+ }
+
+ componentDidLoad() {
+ this.observer = new MutationObserver(this.updateCurrent)
+ this.observer.observe(this.el, {
+ subtree: true,
+ childList: true,
+ attributes: false,
+ })
+
+ this.updateCurrent()
+ }
+
+ disconnectedCallback() {
+ if (this.observer) this.observer.disconnect()
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
diff --git a/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.css b/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.css
new file mode 100644
index 0000000000..2347fe05d2
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.css
@@ -0,0 +1,32 @@
+.ld-breadcrumbs .ld-link,
+.ld-crumb__link::part(anchor) {
+ --ld-link-gap: var(--ld-crumb-icon-gap);
+ --ld-link-chevron-gap: var(--ld-crumb-gap);
+ display: inline-flex;
+}
+
+.ld-breadcrumbs li:not(:last-of-type) .ld-link,
+.ld-crumb__link:not(.ld-crumb__link--current)::part(anchor) {
+ --ld-link-col: var(--ld-col-neutral-600);
+
+ font-weight: normal;
+ margin-right: calc(var(--ld-crumb-gap) + 0.5em);
+
+ &:hover {
+ --ld-link-col: var(--ld-thm-primary-hover);
+ }
+
+ &:focus:focus-visible {
+ --ld-link-col: var(--ld-thm-primary-focus);
+ }
+
+ &:active {
+ --ld-link-col: var(--ld-thm-primary-active);
+ }
+}
+
+.ld-breadcrumbs li:last-of-type .ld-link,
+.ld-crumb__link--current {
+ cursor: default;
+ pointer-events: none;
+}
diff --git a/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.tsx b/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.tsx
new file mode 100644
index 0000000000..b76f5d48d4
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/ld-crumb/ld-crumb.tsx
@@ -0,0 +1,40 @@
+import '../../../components' // type definitions for type checks and intelliSense
+import { Component, h, Prop } from '@stencil/core'
+import { getClassNames } from '../../../utils/getClassNames'
+
+/**
+ * @part link - Breadcrumb link
+ * @virtualProp ref - reference to component
+ * @virtualProp {string | number} key - for tracking the node's identity when working with lists
+ */
+@Component({
+ tag: 'ld-crumb',
+ styleUrl: 'ld-crumb.css',
+ shadow: true,
+})
+export class LdCrumb {
+ /** @internal */
+ @Prop() current?: boolean
+
+ /** The URL that the hyperlink points to. */
+ @Prop() href?: string
+
+ render() {
+ return (
+
+
+
+
+
+ )
+ }
+}
diff --git a/src/liquid/components/ld-breadcrumbs/ld-crumb/readme.md b/src/liquid/components/ld-breadcrumbs/ld-crumb/readme.md
new file mode 100644
index 0000000000..8a3175594c
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/ld-crumb/readme.md
@@ -0,0 +1,50 @@
+---
+eleventyNavigation:
+ key: Crumb
+ parent: Breadcrumbs
+layout: layout.njk
+title: Crumb
+permalink: components/ld-breadcrumbs/ld-crumb/
+---
+
+# ld-crumb
+
+The `ld-crumb` component is a subcomponent for `ld-breadcrumbs`.
+
+Please refer to the [`ld-breadcrumbs` documentation](components/ld-breadcrumbs/) for usage examples.
+
+
+
+
+## Properties
+
+| Property | Attribute | Description | Type | Default |
+| -------- | --------- | -------------------------------------------------------- | ------------------ | ----------- |
+| `href` | `href` | The URL that the hyperlink points to. | `string` | `undefined` |
+| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
+| `ref` | `ref` | reference to component | `any` | `undefined` |
+
+
+## Shadow Parts
+
+| Part | Description |
+| -------- | --------------- |
+| `"link"` | Breadcrumb link |
+
+
+## Dependencies
+
+### Depends on
+
+- [ld-link](../../ld-link)
+
+### Graph
+```mermaid
+graph TD;
+ ld-crumb --> ld-link
+ style ld-crumb fill:#f9f,stroke:#333,stroke-width:4px
+```
+
+----------------------------------------------
+
+
diff --git a/src/liquid/components/ld-breadcrumbs/readme.md b/src/liquid/components/ld-breadcrumbs/readme.md
new file mode 100644
index 0000000000..707f6a1cfc
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/readme.md
@@ -0,0 +1,109 @@
+---
+eleventyNavigation:
+ key: Breadcrumbs
+ parent: Components
+layout: layout.njk
+title: Breadcrumbs
+permalink: components/ld-breadcrumbs/
+---
+
+
+
+
+
+
+# ld-breadcrumbs
+
+A breadcrumb trail consists of a list of links to the parent pages of the current page in hierarchical order. It helps users find their place within a website or web application. Breadcrumbs are often placed horizontally before a page's main content.
+
+This component is meant to be used in conjunction with the [`ld-crumb`](./ld-crumb/) component.
+
+## Examples
+
+### Basic
+
+{% example %}
+
+ Components
+ Breadcrumbs
+
+
+
+
+
+{% endexample %}
+
+### With icons
+
+{% example %}
+
+
+
+ Components
+
+
+
+ Breadcrumbs
+
+
+
+
+
+
+{% endexample %}
+
+
+
+
+## Properties
+
+| Property | Attribute | Description | Type | Default |
+| -------- | --------- | -------------------------------------------------------- | ------------------ | ----------- |
+| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
+| `ref` | `ref` | reference to component | `any` | `undefined` |
+
+
+## Shadow Parts
+
+| Part | Description |
+| -------- | ---------------- |
+| `"list"` | Breadcrumbs list |
+
+
+----------------------------------------------
+
+
diff --git a/src/liquid/components/ld-breadcrumbs/test/__snapshots__/ld-breadcrumbs.spec.tsx.snap b/src/liquid/components/ld-breadcrumbs/test/__snapshots__/ld-breadcrumbs.spec.tsx.snap
new file mode 100644
index 0000000000..70fa919090
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/test/__snapshots__/ld-breadcrumbs.spec.tsx.snap
@@ -0,0 +1,127 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ld-breadcrumbs renders 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ foo
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+
+
+
+ qux
+
+
+`;
+
+exports[`ld-breadcrumbs updates current after addition of a crumb 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ foo
+
+
+
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+
+
+
+ qux
+
+
+
+
+
+
+
+
+
+ baz
+
+
+`;
+
+exports[`ld-breadcrumbs updates current after removal of current crumb 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ foo
+
+
+
+
+
+
+
+
+
+ bar
+
+
+`;
diff --git a/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts b/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts
new file mode 100644
index 0000000000..7bd76fe2d6
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.e2e.ts
@@ -0,0 +1,171 @@
+import {
+ analyzeAccessibility,
+ getPageWithContent,
+} from 'src/liquid/utils/e2e-tests'
+import { LdIcon } from '../../ld-icon/ld-icon'
+import { LdBreadcrumbs } from '../ld-breadcrumbs'
+import { LdCrumb } from '../ld-crumb/ld-crumb'
+import { LdLink } from '../../ld-link/ld-link'
+
+const components = [LdBreadcrumbs, LdCrumb, LdLink, LdIcon]
+
+describe('ld-breadcrumbs', () => {
+ it('renders as Web Component', async () => {
+ const page = await getPageWithContent(
+ `
+ foo
+ bar
+ qux
+ `
+ )
+
+ const results = await page.compareScreenshot()
+ expect(results).toMatchScreenshot()
+ })
+
+ it('renders as CSS Component', async () => {
+ const page = await getPageWithContent(
+ ``,
+ {
+ components,
+ }
+ )
+
+ const results = await page.compareScreenshot()
+ expect(results).toMatchScreenshot()
+ })
+
+ describe('accessibility', () => {
+ it('is accessible as a Web Component', async () => {
+ const page = await getPageWithContent(
+ `
+ foo
+ bar
+ qux
+ `
+ )
+ page.waitForChanges()
+
+ const accessibilityReport = await analyzeAccessibility(page, {
+ rules: {
+ // Disabling list rules here, because manual tests with screenreader
+ // resulted in expected behavior: The screenreader reads number of list items
+ // in breadcrumb trail list.
+ list: { enabled: false },
+ listitem: { enabled: false },
+ },
+ })
+ expect(accessibilityReport).toHaveNoAccessibilityIssues()
+ })
+
+ it('is accessible as a CSS Component', async () => {
+ const page = await getPageWithContent(
+ ``,
+ {
+ components,
+ }
+ )
+
+ page.waitForChanges()
+ const accessibilityReport = await analyzeAccessibility(page)
+ expect(accessibilityReport).toHaveNoAccessibilityIssues()
+ })
+ })
+
+ it('renders with icons as Web Component', async () => {
+ const page = await getPageWithContent(
+ `
+
+
+ foo
+
+
+
+ bar
+
+
+
+ qux
+
+ `,
+ {
+ components,
+ }
+ )
+
+ const results = await page.compareScreenshot()
+ expect(results).toMatchScreenshot()
+ })
+
+ it('renders with icons as CSS component', async () => {
+ const page = await getPageWithContent(
+ ``,
+ {
+ components,
+ }
+ )
+
+ const results = await page.compareScreenshot()
+ expect(results).toMatchScreenshot()
+ })
+})
diff --git a/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.spec.tsx b/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.spec.tsx
new file mode 100644
index 0000000000..b9a711d206
--- /dev/null
+++ b/src/liquid/components/ld-breadcrumbs/test/ld-breadcrumbs.spec.tsx
@@ -0,0 +1,61 @@
+import { newSpecPage } from '@stencil/core/testing'
+import { LdBreadcrumbs } from '../ld-breadcrumbs'
+import { LdCrumb } from '../ld-crumb/ld-crumb'
+import { getTriggerableMutationObserver } from '../../../utils/mutationObserver'
+
+describe('ld-breadcrumbs', () => {
+ it('renders', async () => {
+ const page = await newSpecPage({
+ components: [LdBreadcrumbs, LdCrumb],
+ html: `
+ foo
+ bar
+ qux
+ `,
+ })
+ await page.waitForChanges()
+ jest.advanceTimersByTime(0)
+
+ expect(page.root).toMatchSnapshot()
+ })
+
+ it('updates current after addition of a crumb', async () => {
+ const page = await newSpecPage({
+ components: [LdBreadcrumbs, LdCrumb],
+ html: `
+ foo
+ bar
+ qux
+ `,
+ })
+ await page.waitForChanges()
+ jest.advanceTimersByTime(0)
+
+ const crumb = page.doc.createElement('ld-crumb')
+ crumb.innerHTML = 'baz'
+
+ page.root.appendChild(crumb)
+ getTriggerableMutationObserver().trigger([])
+ await page.waitForChanges()
+
+ expect(page.root).toMatchSnapshot()
+ })
+
+ it('updates current after removal of current crumb', async () => {
+ const page = await newSpecPage({
+ components: [LdBreadcrumbs, LdCrumb],
+ html: `
+ foo
+ bar
+ qux
+ `,
+ })
+ await page.waitForChanges()
+
+ page.root.removeChild(page.root.querySelector('ld-crumb:last-of-type'))
+ getTriggerableMutationObserver().trigger([])
+ await page.waitForChanges()
+
+ expect(page.root).toMatchSnapshot()
+ })
+})
diff --git a/src/liquid/components/ld-checkbox/ld-checkbox.tsx b/src/liquid/components/ld-checkbox/ld-checkbox.tsx
index fe39bbe60e..a22b1c3e48 100644
--- a/src/liquid/components/ld-checkbox/ld-checkbox.tsx
+++ b/src/liquid/components/ld-checkbox/ld-checkbox.tsx
@@ -222,6 +222,7 @@ export class LdCheckbox implements InnerFocusable, ClonesAttributes {
type="checkbox"
value={this.value}
/>
+ {/* custom icon check */}
');
transform: translateY(4%);
}
+ /* custom icon calendar-picker */
&[type='time'] {
min-width: var(--ld-input-time-min-width-md);
diff --git a/src/liquid/components/ld-link/ld-link.css b/src/liquid/components/ld-link/ld-link.css
index 48587404c5..9273c4c9e0 100644
--- a/src/liquid/components/ld-link/ld-link.css
+++ b/src/liquid/components/ld-link/ld-link.css
@@ -1,11 +1,13 @@
.ld-link {
--ld-link-col: var(--ld-thm-primary);
- --ld-link-chevron-width: 0.15em;
+ --ld-link-gap: 0.3em;
+ --ld-link-chevron-gap: 0em;
+ --ld-link-chevron-width: 0.135em;
align-items: baseline;
color: var(--ld-link-col);
cursor: pointer;
- gap: 0.3em;
+ gap: var(--ld-link-gap);
font-family: var(--ld-font-body);
font-size: inherit;
font-weight: 700;
@@ -32,8 +34,16 @@
cursor: default;
opacity: 0.3;
}
+
+ > ld-icon,
+ > .ld-icon,
+ > ::slotted(ld-icon),
+ > ::slotted(.ld-icon) {
+ transform: translateY(10%);
+ }
}
+/* custom icon arrow-right */
.ld-link--chevron-start,
.ld-link--chevron-end {
display: inline-flex;
@@ -42,31 +52,54 @@
&::after {
content: '';
background-color: var(--ld-link-col);
- border-radius: var(--ld-link-chevron-width);
+ border-radius: 99rem;
display: block;
flex-shrink: 0;
height: 0.5em;
transform-origin: right;
width: var(--ld-link-chevron-width);
}
-
- &::before {
- transform: translateX(calc(0.15em + 50%)) translateY(-60%) rotate(-40deg);
- }
- &::after {
- transform: translateX(calc(-0.15em - 50%)) translateY(20%) rotate(40deg);
- }
}
.ld-link--chevron-start {
+ margin-left: calc(0.5 * var(--ld-link-chevron-gap));
+
&::before,
&::after {
order: -1;
}
+
+ &::before {
+ transform: translateX(
+ calc(0.5 * (var(--ld-link-gap) - var(--ld-link-chevron-gap)) + 50%)
+ )
+ translateY(-65%) rotate(-40deg);
+ }
+ &::after {
+ transform: translateX(
+ calc(-0.5 * var(--ld-link-gap) - 0.5 * var(--ld-link-chevron-gap) - 50%)
+ )
+ translateY(20%) rotate(40deg);
+ }
}
.ld-link--chevron-end {
+ margin-right: calc(0.5 * var(--ld-link-chevron-gap));
+
&::before,
&::after {
order: 1;
}
+
+ &::before {
+ transform: translateX(
+ calc(0.5 * (var(--ld-link-gap) + var(--ld-link-chevron-gap)) + 50%)
+ )
+ translateY(-65%) rotate(-40deg);
+ }
+ &::after {
+ transform: translateX(
+ calc(-0.5 * var(--ld-link-gap) + 0.5 * var(--ld-link-chevron-gap) - 50%)
+ )
+ translateY(20%) rotate(40deg);
+ }
}
diff --git a/src/liquid/components/ld-link/ld-link.tsx b/src/liquid/components/ld-link/ld-link.tsx
index 225fe22466..96b42a9f3f 100644
--- a/src/liquid/components/ld-link/ld-link.tsx
+++ b/src/liquid/components/ld-link/ld-link.tsx
@@ -1,9 +1,11 @@
import '../../components' // type definitions for type checks and intelliSense
-import { Component, Element, h, Prop, State } from '@stencil/core'
+import { Component, Element, h, Method, Prop, State } from '@stencil/core'
import { getClassNames } from 'src/liquid/utils/getClassNames'
import { cloneAttributes } from '../../utils/cloneAttributes'
/**
+ * @part anchor - the link anchor
+ * @virtualProp href - the URL that the hyperlink points to
* @virtualProp ref - reference to component
* @virtualProp {string | number} key - for tracking the node's identity when working with lists
*/
@@ -13,18 +15,22 @@ import { cloneAttributes } from '../../utils/cloneAttributes'
styleUrl: 'ld-link.css',
shadow: true,
})
-export class LdLink implements ClonesAttributes {
+export class LdLink implements ClonesAttributes, InnerFocusable {
@Element() el: HTMLElement
+ private anchor: HTMLAnchorElement
private attributesObserver: MutationObserver
+ /** Displays chevron icon. */
+ @Prop() chevron?: 'start' | 'end'
+
/**
* The disabled attribute sets `aria-disabled="true"`
* on the rendered anchor element.
*/
@Prop() disabled?: boolean
- /** Displays chevron icon. */
- @Prop() chevron?: 'start' | 'end'
+ /** Tab index of the input. */
+ @Prop() ldTabindex: number | undefined
/**
* The `target` attributed can be used in conjunction with the `href` attribute.
@@ -35,6 +41,12 @@ export class LdLink implements ClonesAttributes {
@State() clonedAttributes
+ /** Sets focus on the anchor. */
+ @Method()
+ async focusInner() {
+ this.anchor.focus()
+ }
+
componentWillLoad() {
this.attributesObserver = cloneAttributes.call(this, [
'iconStart',
@@ -77,8 +89,11 @@ export class LdLink implements ClonesAttributes {
aria-disabled={
this.disabled || this.el.ariaDisabled ? 'true' : undefined
}
+ ref={(ref) => (this.anchor = ref)}
rel={this.target === '_blank' ? 'noreferrer noopener' : undefined}
disabled={this.disabled}
+ part="anchor focusable"
+ tabIndex={this.ldTabindex}
>
diff --git a/src/liquid/components/ld-link/readme.md b/src/liquid/components/ld-link/readme.md
index 12d371bbaa..69b89534df 100644
--- a/src/liquid/components/ld-link/readme.md
+++ b/src/liquid/components/ld-link/readme.md
@@ -112,15 +112,50 @@ There are several ways to disable a link. The simplest one is by not using a `hr
## Properties
-| Property | Attribute | Description | Type | Default |
-| ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------- |
-| `chevron` | `chevron` | Displays chevron icon. | `"end" \| "start"` | `undefined` |
-| `disabled` | `disabled` | The disabled attribute sets `aria-disabled="true"` on the rendered anchor element. | `boolean` | `undefined` |
-| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
-| `ref` | `ref` | reference to component | `any` | `undefined` |
-| `target` | `target` | The `target` attributed can be used in conjunction with the `href` attribute. See [mdn docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target) for more information on the `target` attribute. | `"_blank" \| "_parent" \| "_self" \| "_top"` | `undefined` |
+| Property | Attribute | Description | Type | Default |
+| ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ----------- |
+| `chevron` | `chevron` | Displays chevron icon. | `"end" \| "start"` | `undefined` |
+| `disabled` | `disabled` | The disabled attribute sets `aria-disabled="true"` on the rendered anchor element. | `boolean` | `undefined` |
+| `href` | `href` | the URL that the hyperlink points to | `any` | `undefined` |
+| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
+| `ldTabindex` | `ld-tabindex` | Tab index of the input. | `number` | `undefined` |
+| `ref` | `ref` | reference to component | `any` | `undefined` |
+| `target` | `target` | The `target` attributed can be used in conjunction with the `href` attribute. See [mdn docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-target) for more information on the `target` attribute. | `"_blank" \| "_parent" \| "_self" \| "_top"` | `undefined` |
+## Methods
+
+### `focusInner() => Promise`
+
+Sets focus on the anchor.
+
+#### Returns
+
+Type: `Promise`
+
+
+
+
+## Shadow Parts
+
+| Part | Description |
+| ---------- | --------------- |
+| `"anchor"` | the link anchor |
+
+
+## Dependencies
+
+### Used by
+
+ - [ld-crumb](../ld-breadcrumbs/ld-crumb)
+
+### Graph
+```mermaid
+graph TD;
+ ld-crumb --> ld-link
+ style ld-link fill:#f9f,stroke:#333,stroke-width:4px
+```
+
----------------------------------------------
diff --git a/src/liquid/components/ld-link/test/__snapshots__/ld-link.spec.tsx.snap b/src/liquid/components/ld-link/test/__snapshots__/ld-link.spec.tsx.snap
index 039c67cd82..d3e9400e43 100644
--- a/src/liquid/components/ld-link/test/__snapshots__/ld-link.spec.tsx.snap
+++ b/src/liquid/components/ld-link/test/__snapshots__/ld-link.spec.tsx.snap
@@ -3,7 +3,7 @@
exports[`ld-link renders as disabled 1`] = `
-
+
@@ -14,7 +14,7 @@ exports[`ld-link renders as disabled 1`] = `
exports[`ld-link renders default 1`] = `
-
+
@@ -25,7 +25,7 @@ exports[`ld-link renders default 1`] = `
exports[`ld-link renders with href 1`] = `
-
+
@@ -36,7 +36,7 @@ exports[`ld-link renders with href 1`] = `
exports[`ld-link renders with target _blank and rel 1`] = `
-
+
diff --git a/src/liquid/components/ld-link/test/ld-link.spec.tsx b/src/liquid/components/ld-link/test/ld-link.spec.tsx
index a230bfaf99..277c01b918 100644
--- a/src/liquid/components/ld-link/test/ld-link.spec.tsx
+++ b/src/liquid/components/ld-link/test/ld-link.spec.tsx
@@ -35,4 +35,18 @@ describe('ld-link', () => {
})
expect(page.root).toMatchSnapshot()
})
+
+ it('allows to set inner focus', async () => {
+ const page = await newSpecPage({
+ components: [LdLink],
+ html: 'Link',
+ })
+ const ldLink = page.root
+ const anchor = ldLink.shadowRoot.children[0] as HTMLAnchorElement
+
+ anchor.focus = jest.fn()
+ await ldLink.focusInner()
+
+ expect(anchor.focus).toHaveBeenCalled()
+ })
})
diff --git a/src/liquid/components/ld-modal/ld-modal.css b/src/liquid/components/ld-modal/ld-modal.css
index 1d8b0c139a..c553016f16 100644
--- a/src/liquid/components/ld-modal/ld-modal.css
+++ b/src/liquid/components/ld-modal/ld-modal.css
@@ -130,6 +130,7 @@ dialog.ld-modal--blurry-backdrop,
}
}
+/* custom icon cross */
.ld-modal__x {
align-self: flex-start;
appearance: none;
diff --git a/src/liquid/components/ld-notification/ld-notification.tsx b/src/liquid/components/ld-notification/ld-notification.tsx
index 78b01cc4a6..65debfbbd7 100644
--- a/src/liquid/components/ld-notification/ld-notification.tsx
+++ b/src/liquid/components/ld-notification/ld-notification.tsx
@@ -137,6 +137,7 @@ export class LdNotification {
}
part="btn-dismiss focusable"
>
+ {/* custom icon cross */}