@repobit/dex-system-design 0.23.15 → 0.23.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/package.json +2 -2
- package/src/components/Button/Button.js +61 -33
- package/src/components/Button/button.css.js +63 -79
- package/src/components/anchor/anchor-nav.css.js +105 -91
- package/src/components/anchor/anchor-nav.js +209 -123
- package/src/components/anchor/anchor.stories.js +190 -83
- package/src/components/badge/badge.css.js +15 -38
- package/src/components/badge/badge.js +15 -35
- package/src/components/compare/compare.stories.js +6 -3
- package/src/components/link/link.css.js +38 -2
- package/src/components/link/link.js +20 -14
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { LitElement, html, nothing } from "lit";
|
|
1
|
+
import { LitElement, html, nothing } from "lit";
|
|
2
2
|
import { tokens } from "../../tokens/tokens.js";
|
|
3
|
+
import "../Button/Button.js";
|
|
4
|
+
import "../link/link.js";
|
|
3
5
|
import { anchorNavStyles } from "./anchor-nav.css.js";
|
|
4
6
|
|
|
5
|
-
/** Parse token length from computed style (e.g. `8rem` → px). */
|
|
6
7
|
function parseLengthToPx(value) {
|
|
7
8
|
const s = (value || "").trim();
|
|
8
9
|
if (!s) return 0;
|
|
9
10
|
if (s.endsWith("px")) return parseFloat(s);
|
|
10
11
|
if (s.endsWith("rem")) {
|
|
11
|
-
const root =
|
|
12
|
-
parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
12
|
+
const root = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
13
13
|
return parseFloat(s) * root;
|
|
14
14
|
}
|
|
15
15
|
return parseFloat(s) || 0;
|
|
@@ -20,54 +20,58 @@ class BdAnchorNavItem extends HTMLElement {
|
|
|
20
20
|
super();
|
|
21
21
|
this.attachShadow({ mode: "open" });
|
|
22
22
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.render();
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
render() {
|
|
29
|
-
this.shadowRoot.innerHTML = `<slot></slot>`;
|
|
30
|
-
}
|
|
23
|
+
connectedCallback() { this.render(); }
|
|
24
|
+
render() { this.shadowRoot.innerHTML = `<slot></slot>`; }
|
|
31
25
|
}
|
|
32
26
|
|
|
33
27
|
class BdAnchorNav extends LitElement {
|
|
34
28
|
static properties = {
|
|
35
29
|
activeId : { type: String, state: true },
|
|
36
|
-
/** Landmark label for the outer `<nav>` (screen readers). */
|
|
37
30
|
navLabel : { type: String, attribute: "aria-label" },
|
|
38
|
-
/** Mobile dropdown open state */
|
|
39
31
|
_dropdownOpen : { type: Boolean, state: true },
|
|
40
|
-
|
|
41
|
-
|
|
32
|
+
_mobileCtaRevealed: { type: Boolean, state: true },
|
|
33
|
+
ctaLabel : { type: String, attribute: "cta-label" },
|
|
34
|
+
ctaHref : { type: String, attribute: "cta-href" },
|
|
35
|
+
items : { type: Array },
|
|
36
|
+
maxWidth : { type: String, attribute: "max-width" }
|
|
42
37
|
};
|
|
43
38
|
|
|
44
39
|
static styles = [tokens, anchorNavStyles];
|
|
45
40
|
|
|
46
41
|
constructor() {
|
|
47
42
|
super();
|
|
48
|
-
this.activeId
|
|
49
|
-
this.navLabel
|
|
50
|
-
this._dropdownOpen
|
|
51
|
-
this._mobileCtaRevealed
|
|
52
|
-
this.
|
|
43
|
+
this.activeId = "";
|
|
44
|
+
this.navLabel = "Section navigation";
|
|
45
|
+
this._dropdownOpen = false;
|
|
46
|
+
this._mobileCtaRevealed = false;
|
|
47
|
+
this.ctaLabel = "Buy now";
|
|
48
|
+
this.ctaHref = "";
|
|
49
|
+
this.items = null;
|
|
50
|
+
this.maxWidth = "";
|
|
51
|
+
this._panelId = `bd-anchor-nav-panel-${Math.random().toString(36)
|
|
53
52
|
.slice(2, 11)}`;
|
|
54
|
-
this._onScrollSpy
|
|
55
|
-
this._onDocumentPointerDown
|
|
56
|
-
this._onKeydown
|
|
57
|
-
this._scrollPending
|
|
58
|
-
/** While set, scrollspy must not overwrite activeId during smooth scroll to a clicked section */
|
|
53
|
+
this._onScrollSpy = this._onScrollSpy.bind(this);
|
|
54
|
+
this._onDocumentPointerDown = this._onDocumentPointerDown.bind(this);
|
|
55
|
+
this._onKeydown = this._onKeydown.bind(this);
|
|
56
|
+
this._scrollPending = false;
|
|
59
57
|
this._programmaticScrollTargetId = null;
|
|
60
|
-
this._unlockScrollSpyTimer
|
|
61
|
-
this._scrollEndUnlockHandler
|
|
58
|
+
this._unlockScrollSpyTimer = null;
|
|
59
|
+
this._scrollEndUnlockHandler = null;
|
|
60
|
+
this._stickyOriginalTop = null;
|
|
61
|
+
this._stickyPlaceholder = null;
|
|
62
|
+
this._onStickyScroll = null;
|
|
63
|
+
this._handleResize = this._handleResize.bind(this);
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
connectedCallback() {
|
|
65
67
|
super.connectedCallback();
|
|
66
68
|
window.addEventListener("scroll", this._onScrollSpy, { passive: true });
|
|
67
69
|
window.addEventListener("resize", this._onScrollSpy, { passive: true });
|
|
70
|
+
window.addEventListener("resize", this._handleResize);
|
|
68
71
|
document.addEventListener("pointerdown", this._onDocumentPointerDown, true);
|
|
69
72
|
document.addEventListener("keydown", this._onKeydown, true);
|
|
70
73
|
queueMicrotask(() => this._runScrollSpy());
|
|
74
|
+
this._initSticky();
|
|
71
75
|
}
|
|
72
76
|
|
|
73
77
|
disconnectedCallback() {
|
|
@@ -75,8 +79,111 @@ class BdAnchorNav extends LitElement {
|
|
|
75
79
|
this._cancelScrollSpyUnlock();
|
|
76
80
|
window.removeEventListener("scroll", this._onScrollSpy);
|
|
77
81
|
window.removeEventListener("resize", this._onScrollSpy);
|
|
82
|
+
window.removeEventListener("resize", this._handleResize);
|
|
78
83
|
document.removeEventListener("pointerdown", this._onDocumentPointerDown, true);
|
|
79
84
|
document.removeEventListener("keydown", this._onKeydown, true);
|
|
85
|
+
this._destroySticky();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_handleResize() {
|
|
89
|
+
this._handleMobileFullWidth();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
_handleMobileFullWidth() {
|
|
93
|
+
const isMobile = window.matchMedia("(max-width: 768px)").matches;
|
|
94
|
+
const ctaSlot = this.shadowRoot?.querySelector('slot[name="cta"]');
|
|
95
|
+
|
|
96
|
+
if (!ctaSlot) return;
|
|
97
|
+
|
|
98
|
+
const assignedElements = ctaSlot.assignedElements();
|
|
99
|
+
const buttonLink = assignedElements.find(el => el.tagName === 'BD-BUTTON-LINK');
|
|
100
|
+
|
|
101
|
+
if (buttonLink) {
|
|
102
|
+
if (isMobile) {
|
|
103
|
+
buttonLink.setAttribute('fullwidth', '');
|
|
104
|
+
} else {
|
|
105
|
+
buttonLink.removeAttribute('fullwidth');
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
_initSticky() {
|
|
111
|
+
this._stickyOriginalTop = null;
|
|
112
|
+
|
|
113
|
+
this._onStickyScroll = () => {
|
|
114
|
+
const parent = this.parentElement;
|
|
115
|
+
if (!parent) return;
|
|
116
|
+
|
|
117
|
+
const parentRect = parent.getBoundingClientRect();
|
|
118
|
+
const navHeight = this._stickyPlaceholder
|
|
119
|
+
? this._stickyPlaceholder.offsetHeight
|
|
120
|
+
: this.offsetHeight;
|
|
121
|
+
|
|
122
|
+
if (this._stickyOriginalTop === null) {
|
|
123
|
+
const rect = this.getBoundingClientRect();
|
|
124
|
+
this._stickyOriginalTop = rect.top + window.scrollY;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const passedTop = window.scrollY >= this._stickyOriginalTop;
|
|
128
|
+
const parentExited = parentRect.bottom <= navHeight;
|
|
129
|
+
|
|
130
|
+
if (passedTop && !parentExited) {
|
|
131
|
+
if (!this.classList.contains("is-sticky")) {
|
|
132
|
+
if (!this._stickyPlaceholder) {
|
|
133
|
+
this._stickyPlaceholder = document.createElement("div");
|
|
134
|
+
this._stickyPlaceholder.style.height = `${this.offsetHeight}px`;
|
|
135
|
+
this._stickyPlaceholder.style.display = "block";
|
|
136
|
+
this.parentNode.insertBefore(this._stickyPlaceholder, this);
|
|
137
|
+
}
|
|
138
|
+
this.classList.add("is-sticky");
|
|
139
|
+
}
|
|
140
|
+
this.style.setProperty("--sticky-left", `${parentRect.left}px`);
|
|
141
|
+
this.style.setProperty("--sticky-width", `${parentRect.width}px`);
|
|
142
|
+
} else {
|
|
143
|
+
if (this.classList.contains("is-sticky")) {
|
|
144
|
+
this.classList.remove("is-sticky");
|
|
145
|
+
this.style.removeProperty("--sticky-left");
|
|
146
|
+
this.style.removeProperty("--sticky-width");
|
|
147
|
+
if (this._stickyPlaceholder) {
|
|
148
|
+
this._stickyPlaceholder.remove();
|
|
149
|
+
this._stickyPlaceholder = null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
this._onStickyResize = () => {
|
|
156
|
+
this._stickyOriginalTop = null;
|
|
157
|
+
if (this.classList.contains("is-sticky")) {
|
|
158
|
+
const parent = this.parentElement;
|
|
159
|
+
const parentRect = parent.getBoundingClientRect();
|
|
160
|
+
this.style.setProperty("--sticky-left", `${parentRect.left}px`);
|
|
161
|
+
this.style.setProperty("--sticky-width", `${parentRect.width}px`);
|
|
162
|
+
}
|
|
163
|
+
this._onStickyScroll();
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
window.addEventListener("scroll", this._onStickyScroll, { passive: true });
|
|
167
|
+
window.addEventListener("resize", this._onStickyResize, { passive: true });
|
|
168
|
+
requestAnimationFrame(() => this._onStickyScroll());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
_destroySticky() {
|
|
172
|
+
if (this._onStickyScroll) {
|
|
173
|
+
window.removeEventListener("scroll", this._onStickyScroll);
|
|
174
|
+
this._onStickyScroll = null;
|
|
175
|
+
}
|
|
176
|
+
if (this._onStickyResize) {
|
|
177
|
+
window.removeEventListener("resize", this._onStickyResize);
|
|
178
|
+
this._onStickyResize = null;
|
|
179
|
+
}
|
|
180
|
+
if (this._stickyPlaceholder) {
|
|
181
|
+
this._stickyPlaceholder.remove();
|
|
182
|
+
this._stickyPlaceholder = null;
|
|
183
|
+
}
|
|
184
|
+
this.style.removeProperty("--sticky-left");
|
|
185
|
+
this.style.removeProperty("--sticky-width");
|
|
186
|
+
this.classList.remove("is-sticky");
|
|
80
187
|
}
|
|
81
188
|
|
|
82
189
|
_cancelScrollSpyUnlock() {
|
|
@@ -90,7 +197,6 @@ class BdAnchorNav extends LitElement {
|
|
|
90
197
|
}
|
|
91
198
|
}
|
|
92
199
|
|
|
93
|
-
/** After in-nav navigation, ignore scrollspy until scroll finishes (avoids flashing 2→3→4). */
|
|
94
200
|
_scheduleScrollSpyUnlock() {
|
|
95
201
|
this._cancelScrollSpyUnlock();
|
|
96
202
|
const onScrollEnd = () => {
|
|
@@ -99,7 +205,7 @@ class BdAnchorNav extends LitElement {
|
|
|
99
205
|
this._unlockScrollSpyTimer = null;
|
|
100
206
|
}
|
|
101
207
|
window.removeEventListener("scrollend", onScrollEnd);
|
|
102
|
-
this._scrollEndUnlockHandler
|
|
208
|
+
this._scrollEndUnlockHandler = null;
|
|
103
209
|
this._programmaticScrollTargetId = null;
|
|
104
210
|
this._runScrollSpy();
|
|
105
211
|
};
|
|
@@ -142,52 +248,63 @@ class BdAnchorNav extends LitElement {
|
|
|
142
248
|
});
|
|
143
249
|
}
|
|
144
250
|
|
|
251
|
+
_resolvedItems() {
|
|
252
|
+
if (this.items && this.items.length) {
|
|
253
|
+
return this.items.map((item, i) => ({
|
|
254
|
+
title: item.title,
|
|
255
|
+
href : item.href || `#anchor-${i + 1}-section`,
|
|
256
|
+
id : `anchor-${i + 1}`
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
return Array.from(this.children)
|
|
260
|
+
.filter((el) => el.tagName === "BD-ANCHOR-NAV-ITEM")
|
|
261
|
+
.map((el, i) => ({
|
|
262
|
+
title: el.getAttribute("title"),
|
|
263
|
+
href : el.getAttribute("href") || `#anchor-${i + 1}-section`,
|
|
264
|
+
id : `anchor-${i + 1}`
|
|
265
|
+
}));
|
|
266
|
+
}
|
|
267
|
+
|
|
145
268
|
_runScrollSpy() {
|
|
146
|
-
const
|
|
147
|
-
|
|
269
|
+
const resolved = this._resolvedItems();
|
|
270
|
+
const count = resolved.length;
|
|
271
|
+
let next = this.activeId;
|
|
272
|
+
|
|
148
273
|
if (count && !this._programmaticScrollTargetId) {
|
|
149
274
|
const y = window.scrollY + this._stickyOffsetPx() + 2;
|
|
150
275
|
next = "anchor-1";
|
|
151
276
|
for (let i = 0; i < count; i++) {
|
|
152
|
-
const
|
|
277
|
+
const sectionId = resolved[i].href.replace(/^#/, "") || `anchor-${i + 1}-section`;
|
|
278
|
+
const el = document.getElementById(sectionId);
|
|
153
279
|
if (!el) continue;
|
|
154
280
|
const top = el.getBoundingClientRect().top + window.scrollY;
|
|
155
281
|
if (top <= y) next = `anchor-${i + 1}`;
|
|
156
282
|
}
|
|
157
283
|
}
|
|
158
284
|
|
|
159
|
-
const isMobile
|
|
160
|
-
const
|
|
285
|
+
const isMobile = window.matchMedia("(max-width: 768px)").matches;
|
|
286
|
+
const firstHref = resolved[0]?.href.replace(/^#/, "") || "anchor-1-section";
|
|
287
|
+
const first = document.getElementById(firstHref);
|
|
161
288
|
let nextCta;
|
|
162
|
-
if (!isMobile)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
nextCta = true;
|
|
166
|
-
} else {
|
|
167
|
-
/* Show only while first section is fully scrolled past; hide again when it scrolls back into view */
|
|
168
|
-
nextCta = first.getBoundingClientRect().bottom <= 0;
|
|
169
|
-
}
|
|
289
|
+
if (!isMobile) nextCta = true;
|
|
290
|
+
else if (!first) nextCta = true;
|
|
291
|
+
else nextCta = first.getBoundingClientRect().bottom <= 0;
|
|
170
292
|
|
|
171
293
|
if (this.activeId !== next || this._mobileCtaRevealed !== nextCta) {
|
|
172
|
-
this.activeId
|
|
294
|
+
this.activeId = next;
|
|
173
295
|
this._mobileCtaRevealed = nextCta;
|
|
174
296
|
this.requestUpdate();
|
|
175
297
|
}
|
|
176
298
|
}
|
|
177
299
|
|
|
178
|
-
_navItemCount() {
|
|
179
|
-
return Array.from(this.children).filter(
|
|
180
|
-
(el) => el.tagName === "BD-ANCHOR-NAV-ITEM"
|
|
181
|
-
).length;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
300
|
firstUpdated() {
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
301
|
+
const resolved = this._resolvedItems();
|
|
302
|
+
if (resolved.length) {
|
|
187
303
|
this.activeId = "anchor-1";
|
|
188
304
|
this.requestUpdate();
|
|
189
305
|
}
|
|
190
306
|
queueMicrotask(() => this._runScrollSpy());
|
|
307
|
+
this._handleMobileFullWidth();
|
|
191
308
|
}
|
|
192
309
|
|
|
193
310
|
updated(changedProperties) {
|
|
@@ -199,7 +316,6 @@ class BdAnchorNav extends LitElement {
|
|
|
199
316
|
queueMicrotask(() => this._playMobileDropdownLabelSwap());
|
|
200
317
|
}
|
|
201
318
|
|
|
202
|
-
/** Mobile dropdown title: subtle fade + slide when scrollspy (or tap) changes section. */
|
|
203
319
|
_playMobileDropdownLabelSwap() {
|
|
204
320
|
if (typeof window === "undefined") return;
|
|
205
321
|
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
|
|
@@ -216,15 +332,11 @@ class BdAnchorNav extends LitElement {
|
|
|
216
332
|
);
|
|
217
333
|
}
|
|
218
334
|
|
|
219
|
-
/**
|
|
220
|
-
* Scroll clearance = actual sticky bar height + small inset (not a fixed 128px token).
|
|
221
|
-
* Matches best practice: target headings sit just under the bar, not with extra dead space.
|
|
222
|
-
*/
|
|
223
335
|
_stickyOffsetPx() {
|
|
224
|
-
const barPx
|
|
336
|
+
const barPx = this.offsetHeight;
|
|
225
337
|
const insetRaw = getComputedStyle(this).getPropertyValue("--spacing-8")
|
|
226
338
|
.trim();
|
|
227
|
-
const insetPx
|
|
339
|
+
const insetPx = parseLengthToPx(insetRaw) || 8;
|
|
228
340
|
if (barPx > 0) return barPx + insetPx;
|
|
229
341
|
const fallback = getComputedStyle(this).getPropertyValue("--spacing-128")
|
|
230
342
|
.trim();
|
|
@@ -235,33 +347,28 @@ class BdAnchorNav extends LitElement {
|
|
|
235
347
|
if (event?.preventDefault) event.preventDefault();
|
|
236
348
|
const el = getTarget();
|
|
237
349
|
if (!el) return;
|
|
238
|
-
const offset
|
|
239
|
-
const rect
|
|
240
|
-
const scrollTop
|
|
241
|
-
const elementY
|
|
242
|
-
const prefersReduced =
|
|
243
|
-
typeof window !== "undefined" &&
|
|
350
|
+
const offset = this._stickyOffsetPx();
|
|
351
|
+
const rect = el.getBoundingClientRect();
|
|
352
|
+
const scrollTop = window.scrollY ?? window.pageYOffset;
|
|
353
|
+
const elementY = rect.top + scrollTop;
|
|
354
|
+
const prefersReduced = typeof window !== "undefined" &&
|
|
244
355
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
245
|
-
window.scrollTo({
|
|
246
|
-
top : elementY - offset,
|
|
247
|
-
behavior: prefersReduced ? "auto" : "smooth"
|
|
248
|
-
});
|
|
356
|
+
window.scrollTo({ top: elementY - offset, behavior: prefersReduced ? "auto" : "smooth" });
|
|
249
357
|
}
|
|
250
358
|
|
|
251
|
-
handleClick(event, id) {
|
|
359
|
+
handleClick(event, id, href) {
|
|
252
360
|
event.preventDefault();
|
|
253
361
|
this._cancelScrollSpyUnlock();
|
|
254
362
|
this._programmaticScrollTargetId = id;
|
|
255
|
-
this.activeId
|
|
256
|
-
|
|
257
|
-
const sectionEl = document.getElementById(
|
|
363
|
+
this.activeId = id;
|
|
364
|
+
const sectionId = (href || "").replace(/^#/, "") || `${id}-section`;
|
|
365
|
+
const sectionEl = document.getElementById(sectionId);
|
|
258
366
|
if (sectionEl) {
|
|
259
367
|
this._scrollToY(event, () => sectionEl);
|
|
260
368
|
this._scheduleScrollSpyUnlock();
|
|
261
369
|
} else {
|
|
262
370
|
this._programmaticScrollTargetId = null;
|
|
263
371
|
}
|
|
264
|
-
|
|
265
372
|
this.requestUpdate();
|
|
266
373
|
}
|
|
267
374
|
|
|
@@ -272,54 +379,51 @@ class BdAnchorNav extends LitElement {
|
|
|
272
379
|
this.requestUpdate();
|
|
273
380
|
}
|
|
274
381
|
|
|
275
|
-
_selectFromDropdown(e, id) {
|
|
276
|
-
this.handleClick(e, id);
|
|
382
|
+
_selectFromDropdown(e, id, href) {
|
|
383
|
+
this.handleClick(e, id, href);
|
|
277
384
|
this._dropdownOpen = false;
|
|
278
385
|
this.requestUpdate();
|
|
279
386
|
}
|
|
280
387
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const m = /^anchor-(\d+)$/.exec(this.activeId || "");
|
|
287
|
-
const n = m ? parseInt(m[1], 10) : 1;
|
|
288
|
-
const idx = Math.min(Math.max(n - 1, 0), Math.max(0, items.length - 1));
|
|
289
|
-
return items[idx]?.getAttribute("title") || items[0]?.getAttribute("title") || "Section";
|
|
388
|
+
_activeLabel(resolved) {
|
|
389
|
+
const m = /^anchor-(\d+)$/.exec(this.activeId || "");
|
|
390
|
+
const n = m ? parseInt(m[1], 10) : 1;
|
|
391
|
+
const idx = Math.min(Math.max(n - 1, 0), Math.max(0, resolved.length - 1));
|
|
392
|
+
return resolved[idx]?.title || resolved[0]?.title || "Section";
|
|
290
393
|
}
|
|
291
394
|
|
|
292
395
|
render() {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
);
|
|
396
|
+
const resolved = this._resolvedItems();
|
|
397
|
+
const dropdownLabel = this._activeLabel(resolved);
|
|
296
398
|
|
|
297
399
|
const linkRow = (cls) => html`
|
|
298
400
|
<div class="${cls}">
|
|
299
|
-
${
|
|
300
|
-
const id = `anchor-${index + 1}`;
|
|
401
|
+
${resolved.map(({ id, title, href }) => {
|
|
301
402
|
const isActive = this.activeId === id;
|
|
302
403
|
return html`
|
|
303
|
-
<
|
|
304
|
-
href="
|
|
305
|
-
|
|
404
|
+
<bd-link
|
|
405
|
+
href="${href}"
|
|
406
|
+
kind="${isActive ? "primary" : "secondary"}"
|
|
407
|
+
no-underline
|
|
408
|
+
class="anchor-link ${isActive ? "active" : ""}"
|
|
409
|
+
color="var(--color-neutral-900)"
|
|
410
|
+
?active=${isActive}
|
|
306
411
|
aria-current=${isActive ? "true" : nothing}
|
|
307
|
-
@click=${(e) => this.handleClick(e, id)}
|
|
308
|
-
>
|
|
309
|
-
${item.getAttribute("title")}
|
|
310
|
-
</a>
|
|
412
|
+
@click=${(e) => this.handleClick(e, id, href)}
|
|
413
|
+
>${title}</bd-link>
|
|
311
414
|
`;
|
|
312
415
|
})}
|
|
313
416
|
</div>
|
|
314
417
|
`;
|
|
315
418
|
|
|
316
|
-
const
|
|
419
|
+
const innerStyle = this.maxWidth ? `max-width: ${this.maxWidth};` : '';
|
|
317
420
|
|
|
318
421
|
return html`
|
|
319
422
|
<nav aria-label=${this.navLabel}>
|
|
320
423
|
<div
|
|
321
424
|
class="bd-anchor-nav__inner"
|
|
322
425
|
part="inner"
|
|
426
|
+
style="${innerStyle}"
|
|
323
427
|
?data-mobile-cta-visible=${this._mobileCtaRevealed}
|
|
324
428
|
>
|
|
325
429
|
${linkRow("anchor-links anchor-links--desktop")}
|
|
@@ -336,13 +440,7 @@ class BdAnchorNav extends LitElement {
|
|
|
336
440
|
<span class="bd-anchor-nav__dropdown-label">${dropdownLabel}</span>
|
|
337
441
|
<span class="bd-anchor-nav__dropdown-chevron" aria-hidden="true">
|
|
338
442
|
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
339
|
-
<path
|
|
340
|
-
d="M5 8l5 5 5-5"
|
|
341
|
-
stroke="currentColor"
|
|
342
|
-
stroke-width="2"
|
|
343
|
-
stroke-linecap="round"
|
|
344
|
-
stroke-linejoin="round"
|
|
345
|
-
/>
|
|
443
|
+
<path d="M5 8l5 5 5-5" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
346
444
|
</svg>
|
|
347
445
|
</span>
|
|
348
446
|
</button>
|
|
@@ -354,22 +452,17 @@ class BdAnchorNav extends LitElement {
|
|
|
354
452
|
?hidden=${!this._dropdownOpen}
|
|
355
453
|
>
|
|
356
454
|
<ul class="bd-anchor-nav__dropdown-list" role="presentation">
|
|
357
|
-
${
|
|
358
|
-
const id = `anchor-${index + 1}`;
|
|
455
|
+
${resolved.map(({ id, title, href }) => {
|
|
359
456
|
const isActive = this.activeId === id;
|
|
360
457
|
return html`
|
|
361
458
|
<li role="presentation">
|
|
362
459
|
<button
|
|
363
460
|
type="button"
|
|
364
461
|
role="option"
|
|
365
|
-
class="bd-anchor-nav__dropdown-option ${isActive
|
|
366
|
-
? "bd-anchor-nav__dropdown-option--active"
|
|
367
|
-
: ""}"
|
|
462
|
+
class="bd-anchor-nav__dropdown-option ${isActive ? "bd-anchor-nav__dropdown-option--active" : ""}"
|
|
368
463
|
aria-selected=${isActive ? "true" : "false"}
|
|
369
|
-
@click=${(e) => this._selectFromDropdown(e, id)}
|
|
370
|
-
>
|
|
371
|
-
${item.getAttribute("title")}
|
|
372
|
-
</button>
|
|
464
|
+
@click=${(e) => this._selectFromDropdown(e, id, href)}
|
|
465
|
+
>${title}</button>
|
|
373
466
|
</li>
|
|
374
467
|
`;
|
|
375
468
|
})}
|
|
@@ -378,14 +471,7 @@ class BdAnchorNav extends LitElement {
|
|
|
378
471
|
</div>
|
|
379
472
|
|
|
380
473
|
<div class="bd-cta">
|
|
381
|
-
<
|
|
382
|
-
type="button"
|
|
383
|
-
class="bd-anchor-nav__cta"
|
|
384
|
-
part="buy-button"
|
|
385
|
-
@click=${(e) => this.scrollToPricing(e)}
|
|
386
|
-
>
|
|
387
|
-
Buy now
|
|
388
|
-
</button>
|
|
474
|
+
<slot name="cta"></slot>
|
|
389
475
|
</div>
|
|
390
476
|
</div>
|
|
391
477
|
</nav>
|
|
@@ -394,4 +480,4 @@ class BdAnchorNav extends LitElement {
|
|
|
394
480
|
}
|
|
395
481
|
|
|
396
482
|
customElements.define("bd-anchor-nav-item", BdAnchorNavItem);
|
|
397
|
-
customElements.define("bd-anchor-nav", BdAnchorNav);
|
|
483
|
+
customElements.define("bd-anchor-nav", BdAnchorNav);
|