@repobit/dex-system-design 0.23.16 → 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 +7 -0
- package/package.json +2 -2
- package/src/components/Button/Button.js +1 -1
- package/src/components/Button/button.css.js +11 -11
- package/src/components/anchor/anchor-nav.css.js +105 -93
- package/src/components/anchor/anchor-nav.js +127 -10
- package/src/components/link/link.css.js +38 -2
- package/src/components/link/link.js +20 -14
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [0.23.17](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.16...@repobit/dex-system-design@0.23.17) (2026-04-29)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **DEX-1014:** adjustments for anchor-nav. Modified structure
|
|
11
|
+
|
|
12
|
+
|
|
6
13
|
## [0.23.16](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.15...@repobit/dex-system-design@0.23.16) (2026-04-23)
|
|
7
14
|
|
|
8
15
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@repobit/dex-system-design",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.17",
|
|
4
4
|
"description": "Design system based on Web Components.",
|
|
5
5
|
"author": "Iordache Matei Cezar <miordache@bitdefender.com>",
|
|
6
6
|
"homepage": "https://github.com/bitdefender/dex-core#readme",
|
|
@@ -89,5 +89,5 @@
|
|
|
89
89
|
"volta": {
|
|
90
90
|
"node": "24.14.0"
|
|
91
91
|
},
|
|
92
|
-
"gitHead": "
|
|
92
|
+
"gitHead": "7e0f9b42767c23f33e6b6b79665bec599b432a69"
|
|
93
93
|
}
|
|
@@ -107,7 +107,7 @@ class ButtonLink extends LitElement {
|
|
|
107
107
|
size : { type: String },
|
|
108
108
|
customClass: { type: String },
|
|
109
109
|
kind : { type: String },
|
|
110
|
-
fullWidth : { type: Boolean },
|
|
110
|
+
fullWidth : { type: Boolean, attribute: "fullwidth" },
|
|
111
111
|
strong : { type: Boolean },
|
|
112
112
|
fontSize : { type: String, attribute: "font-size" },
|
|
113
113
|
fontWeight : { type: String, attribute: "font-weight" },
|
|
@@ -29,8 +29,16 @@ export default css`
|
|
|
29
29
|
--bd-accesibility-focus: var(--color-blue-500);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
:host([fullwidth]) {
|
|
33
|
+
display: block;
|
|
34
|
+
width: 100%;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.max--width {
|
|
38
|
+
width: 100%;
|
|
39
|
+
display: flex;
|
|
40
|
+
}
|
|
41
|
+
:host([data-bd-button-focus]) {
|
|
34
42
|
outline: var(--spacing-2) solid var(--bd-accesibility-focus);
|
|
35
43
|
outline-offset: var(--spacing-2);
|
|
36
44
|
border-radius: var(--radius-md);
|
|
@@ -167,15 +175,7 @@ export default css`
|
|
|
167
175
|
font-weight: var(--typography-fontWeight-semibold);
|
|
168
176
|
}
|
|
169
177
|
|
|
170
|
-
|
|
171
|
-
width: 100%;
|
|
172
|
-
display: block;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
.button.max--width {
|
|
176
|
-
width: 100%;
|
|
177
|
-
}
|
|
178
|
-
|
|
178
|
+
|
|
179
179
|
/* Asigură-te că slot-ul ocupă întreg spațiul */
|
|
180
180
|
.button > ::slotted(*) {
|
|
181
181
|
display: inline-block;
|
|
@@ -3,35 +3,35 @@ import { css } from "lit";
|
|
|
3
3
|
export const anchorNavStyles = css`
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
6
|
-
position: sticky;
|
|
7
|
-
top: var(--spacing-0);
|
|
8
|
-
z-index: 1000;
|
|
9
|
-
border-top: var(--border-width-1) solid var(--color-neutral-100);
|
|
10
|
-
border-bottom: var(--border-width-1) solid var(--color-neutral-100);
|
|
11
|
-
padding-block: var(--spacing-10);
|
|
12
|
-
padding-inline: var(--layout-ensemble-inline-padding);
|
|
13
6
|
width: 100%;
|
|
14
|
-
box-sizing: border-box;
|
|
15
7
|
background: var(--color-neutral-0);
|
|
16
|
-
margin-bottom: var(--spacing-0);
|
|
17
8
|
--bd-accesibility-focus: var(--color-blue-500);
|
|
9
|
+
--anchor-nav-max-width: var(--layout-compare-grid-max, 100%);
|
|
18
10
|
}
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
12
|
+
:host(.is-sticky) {
|
|
13
|
+
position: fixed;
|
|
14
|
+
top: 0;
|
|
15
|
+
left: var(--sticky-left, 0);
|
|
16
|
+
width: var(--sticky-width, 100%);
|
|
17
|
+
box-shadow: var(--shadow-sm);
|
|
18
|
+
z-index: 1000;
|
|
27
19
|
}
|
|
28
20
|
|
|
21
|
+
/* Border-urile sunt pe nav - full width */
|
|
29
22
|
nav {
|
|
30
23
|
display: block;
|
|
31
24
|
margin: var(--spacing-0);
|
|
32
25
|
padding: var(--spacing-0);
|
|
33
26
|
width: 100%;
|
|
34
27
|
box-sizing: border-box;
|
|
28
|
+
border-top: var(--border-width-1) solid var(--color-neutral-100);
|
|
29
|
+
border-bottom: var(--border-width-1) solid var(--color-neutral-100);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Când e sticky, păstrăm aceleași border-uri */
|
|
33
|
+
:host(.is-sticky) nav {
|
|
34
|
+
background: var(--color-neutral-0);
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
.bd-anchor-nav__inner {
|
|
@@ -41,11 +41,24 @@ export const anchorNavStyles = css`
|
|
|
41
41
|
align-items: center;
|
|
42
42
|
gap: var(--spacing-32);
|
|
43
43
|
width: 100%;
|
|
44
|
-
max-width: var(--
|
|
44
|
+
max-width: var(--anchor-nav-max-width);
|
|
45
|
+
padding-block: var(--spacing-10);
|
|
46
|
+
padding-inline: var(--layout-ensemble-inline-padding, var(--spacing-24));
|
|
45
47
|
margin-inline: auto;
|
|
46
48
|
box-sizing: border-box;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
/* Restul codului tău CSS rămâne identic de aici în jos */
|
|
52
|
+
|
|
53
|
+
.anchor-link:focus-visible,
|
|
54
|
+
.bd-anchor-nav__cta:focus-visible,
|
|
55
|
+
.bd-anchor-nav__dropdown-toggle:focus-visible,
|
|
56
|
+
.bd-anchor-nav__dropdown-option:focus-visible {
|
|
57
|
+
outline: var(--spacing-2) solid var(--bd-accesibility-focus);
|
|
58
|
+
outline-offset: var(--spacing-2);
|
|
59
|
+
border-radius: var(--space-2xs);
|
|
60
|
+
}
|
|
61
|
+
|
|
49
62
|
.anchor-links {
|
|
50
63
|
position: relative;
|
|
51
64
|
display: flex;
|
|
@@ -57,8 +70,67 @@ export const anchorNavStyles = css`
|
|
|
57
70
|
min-width: 0;
|
|
58
71
|
}
|
|
59
72
|
|
|
60
|
-
.anchor-links--desktop {
|
|
61
|
-
|
|
73
|
+
.anchor-links--desktop { display: flex; }
|
|
74
|
+
|
|
75
|
+
.anchor-link {
|
|
76
|
+
position: relative;
|
|
77
|
+
text-decoration: none;
|
|
78
|
+
color: var(--color-neutral-900);
|
|
79
|
+
font-weight: var(--typography-fontWeight-normal);
|
|
80
|
+
padding: var(--spacing-10) var(--spacing-0);
|
|
81
|
+
display: inline-block;
|
|
82
|
+
font-size: var(--typography-body-regular-fontSize);
|
|
83
|
+
font-family: var(--typography-body-regular-fontFamily);
|
|
84
|
+
transition: color var(--transition-duration-fast) var(--transition-easing-smooth);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.anchor-link.active {
|
|
88
|
+
font-weight: var(--typography-fontWeight-semibold);
|
|
89
|
+
color: var(--color-neutral-900);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.anchor-link,
|
|
93
|
+
.anchor-link.bd-link,
|
|
94
|
+
.anchor-link.bd-link--primary,
|
|
95
|
+
.anchor-link.bd-link--secondary {
|
|
96
|
+
text-decoration: none !important;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.anchor-link:hover,
|
|
100
|
+
.anchor-link.bd-link:hover,
|
|
101
|
+
.anchor-link.bd-link--primary:hover,
|
|
102
|
+
.anchor-link.bd-link--secondary:hover {
|
|
103
|
+
text-decoration: none !important;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.anchor-link.bd-link--primary:hover {
|
|
107
|
+
color: var(--color-blue-500) !important;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.anchor-link.bd-link--secondary:hover {
|
|
111
|
+
color: var(--color-neutral-900) !important;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.anchor-link.active:hover,
|
|
115
|
+
.anchor-link.active.bd-link--primary:hover,
|
|
116
|
+
.anchor-link.active.bd-link--secondary:hover {
|
|
117
|
+
color: var(--color-neutral-900) !important;
|
|
118
|
+
text-decoration: none !important;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.anchor-link::after {
|
|
122
|
+
content: "";
|
|
123
|
+
position: absolute;
|
|
124
|
+
left: var(--spacing-0);
|
|
125
|
+
bottom: calc(-1 * var(--spacing-14));
|
|
126
|
+
width: 0%;
|
|
127
|
+
height: var(--border-width-3);
|
|
128
|
+
background-color: var(--color-blue-500);
|
|
129
|
+
transition: width var(--transition-duration-slow) var(--transition-easing-ease-out);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.anchor-link.active::after {
|
|
133
|
+
width: 100%;
|
|
62
134
|
}
|
|
63
135
|
|
|
64
136
|
.bd-anchor-nav__dropdown {
|
|
@@ -69,8 +141,6 @@ export const anchorNavStyles = css`
|
|
|
69
141
|
width: 100%;
|
|
70
142
|
}
|
|
71
143
|
|
|
72
|
-
/* ── Dropdown toggle ── */
|
|
73
|
-
|
|
74
144
|
.bd-anchor-nav__dropdown-toggle {
|
|
75
145
|
display: flex;
|
|
76
146
|
align-items: center;
|
|
@@ -104,7 +174,6 @@ export const anchorNavStyles = css`
|
|
|
104
174
|
.bd-anchor-nav__dropdown-toggle[aria-expanded="true"] {
|
|
105
175
|
background: var(--color-neutral-50);
|
|
106
176
|
border-color: var(--color-blue-200);
|
|
107
|
-
border-radius: var(--radius-lg) var(--radius-lg) var(--spacing-0) var(--spacing-0);
|
|
108
177
|
}
|
|
109
178
|
|
|
110
179
|
.bd-anchor-nav__dropdown-label {
|
|
@@ -128,8 +197,6 @@ export const anchorNavStyles = css`
|
|
|
128
197
|
color: var(--color-blue-500);
|
|
129
198
|
}
|
|
130
199
|
|
|
131
|
-
/* ── Dropdown panel ── */
|
|
132
|
-
|
|
133
200
|
.bd-anchor-nav__dropdown-panel {
|
|
134
201
|
position: absolute;
|
|
135
202
|
left: var(--spacing-0);
|
|
@@ -154,8 +221,6 @@ export const anchorNavStyles = css`
|
|
|
154
221
|
gap: var(--spacing-2);
|
|
155
222
|
}
|
|
156
223
|
|
|
157
|
-
/* ── Dropdown options ── */
|
|
158
|
-
|
|
159
224
|
.bd-anchor-nav__dropdown-option {
|
|
160
225
|
display: flex;
|
|
161
226
|
align-items: center;
|
|
@@ -194,52 +259,10 @@ export const anchorNavStyles = css`
|
|
|
194
259
|
background: var(--color-blue-50);
|
|
195
260
|
}
|
|
196
261
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
a {
|
|
200
|
-
position: relative;
|
|
201
|
-
text-decoration: none;
|
|
202
|
-
color: var(--color-neutral-900);
|
|
203
|
-
font-weight: var(--typography-fontWeight-normal);
|
|
204
|
-
padding: var(--spacing-10) var(--spacing-0);
|
|
205
|
-
display: inline-block;
|
|
206
|
-
font-size: var(--typography-body-regular-fontSize);
|
|
207
|
-
font-family: var(--typography-body-regular-fontFamily);
|
|
208
|
-
transition: color var(--transition-duration-fast) var(--transition-easing-smooth);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
a.active {
|
|
212
|
-
font-weight: var(--typography-fontWeight-semibold);
|
|
213
|
-
color: var(--color-neutral-900);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
a:hover:not(.active) {
|
|
217
|
-
color: var(--color-blue-500);
|
|
218
|
-
}
|
|
219
|
-
.bd-anchor-nav__cta:hover {
|
|
220
|
-
color: var(--color-neutral-0) !important;
|
|
221
|
-
}
|
|
222
|
-
a.active:hover {
|
|
223
|
-
color: var(--color-neutral-900);
|
|
262
|
+
::slotted([slot="cta"]) {
|
|
263
|
+
flex-shrink: 0;
|
|
224
264
|
}
|
|
225
265
|
|
|
226
|
-
a::after {
|
|
227
|
-
content: "";
|
|
228
|
-
position: absolute;
|
|
229
|
-
left: var(--spacing-0);
|
|
230
|
-
bottom: calc(-1 * var(--spacing-14));
|
|
231
|
-
width: 0%;
|
|
232
|
-
height: var(--border-width-3);
|
|
233
|
-
background-color: var(--color-blue-500);
|
|
234
|
-
transition: width var(--transition-duration-slow) var(--transition-easing-ease-out);
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
a.active::after {
|
|
238
|
-
width: 100%;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/* ── CTA button ── */
|
|
242
|
-
|
|
243
266
|
.bd-anchor-nav__cta {
|
|
244
267
|
font-family: var(--typography-fontFamily-sans);
|
|
245
268
|
font-size: var(--typography-fontSize-lg);
|
|
@@ -251,32 +274,32 @@ export const anchorNavStyles = css`
|
|
|
251
274
|
cursor: pointer;
|
|
252
275
|
background: var(--color-red-500);
|
|
253
276
|
color: var(--color-neutral-0);
|
|
277
|
+
text-decoration: none !important;
|
|
254
278
|
transition: background var(--transition-duration-fast) var(--transition-easing-smooth);
|
|
255
279
|
}
|
|
256
280
|
|
|
257
281
|
.bd-anchor-nav__cta:hover {
|
|
258
282
|
background: var(--color-red-600);
|
|
283
|
+
color: var(--color-neutral-0);
|
|
284
|
+
text-decoration: none !important;
|
|
259
285
|
}
|
|
260
286
|
|
|
261
287
|
.bd-anchor-nav__cta:active {
|
|
262
288
|
background: var(--color-red-700);
|
|
289
|
+
color: var(--color-neutral-0);
|
|
263
290
|
}
|
|
264
291
|
|
|
265
|
-
|
|
292
|
+
.bd-anchor-nav__cta::after {
|
|
293
|
+
display: none;
|
|
294
|
+
}
|
|
266
295
|
|
|
267
296
|
@keyframes bd-anchor-nav-dropdown-label-swap {
|
|
268
|
-
from {
|
|
269
|
-
|
|
270
|
-
transform: translateY(var(--spacing-4));
|
|
271
|
-
}
|
|
272
|
-
to {
|
|
273
|
-
opacity: 1;
|
|
274
|
-
transform: translateY(var(--spacing-0));
|
|
275
|
-
}
|
|
297
|
+
from { opacity: 0.35; transform: translateY(var(--spacing-4)); }
|
|
298
|
+
to { opacity: 1; transform: translateY(var(--spacing-0)); }
|
|
276
299
|
}
|
|
277
300
|
|
|
278
301
|
@media (prefers-reduced-motion: reduce) {
|
|
279
|
-
|
|
302
|
+
.anchor-link::after,
|
|
280
303
|
.bd-anchor-nav__dropdown-chevron,
|
|
281
304
|
.bd-cta,
|
|
282
305
|
.bd-anchor-nav__dropdown-label--swap {
|
|
@@ -284,27 +307,16 @@ export const anchorNavStyles = css`
|
|
|
284
307
|
}
|
|
285
308
|
}
|
|
286
309
|
|
|
287
|
-
/* ── Mobile ── */
|
|
288
|
-
|
|
289
310
|
@media (max-width: 768px) {
|
|
290
|
-
:host {
|
|
291
|
-
padding-block: var(--spacing-10);
|
|
292
|
-
padding-inline: var(--layout-ensemble-inline-padding);
|
|
293
|
-
}
|
|
294
|
-
|
|
295
311
|
.bd-anchor-nav__inner {
|
|
296
312
|
flex-direction: column;
|
|
297
313
|
align-items: stretch;
|
|
298
314
|
gap: var(--spacing-16);
|
|
299
315
|
}
|
|
300
316
|
|
|
301
|
-
.anchor-links--desktop {
|
|
302
|
-
display: none !important;
|
|
303
|
-
}
|
|
317
|
+
.anchor-links--desktop { display: none !important; }
|
|
304
318
|
|
|
305
|
-
.bd-anchor-nav__dropdown {
|
|
306
|
-
display: block;
|
|
307
|
-
}
|
|
319
|
+
.bd-anchor-nav__dropdown { display: block; }
|
|
308
320
|
|
|
309
321
|
.bd-anchor-nav__dropdown-label.bd-anchor-nav__dropdown-label--swap {
|
|
310
322
|
animation: bd-anchor-nav-dropdown-label-swap var(--transition-duration-normal)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
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
7
|
function parseLengthToPx(value) {
|
|
@@ -30,7 +32,8 @@ class BdAnchorNav extends LitElement {
|
|
|
30
32
|
_mobileCtaRevealed: { type: Boolean, state: true },
|
|
31
33
|
ctaLabel : { type: String, attribute: "cta-label" },
|
|
32
34
|
ctaHref : { type: String, attribute: "cta-href" },
|
|
33
|
-
items : { type: Array }
|
|
35
|
+
items : { type: Array },
|
|
36
|
+
maxWidth : { type: String, attribute: "max-width" }
|
|
34
37
|
};
|
|
35
38
|
|
|
36
39
|
static styles = [tokens, anchorNavStyles];
|
|
@@ -44,6 +47,7 @@ class BdAnchorNav extends LitElement {
|
|
|
44
47
|
this.ctaLabel = "Buy now";
|
|
45
48
|
this.ctaHref = "";
|
|
46
49
|
this.items = null;
|
|
50
|
+
this.maxWidth = "";
|
|
47
51
|
this._panelId = `bd-anchor-nav-panel-${Math.random().toString(36)
|
|
48
52
|
.slice(2, 11)}`;
|
|
49
53
|
this._onScrollSpy = this._onScrollSpy.bind(this);
|
|
@@ -53,15 +57,21 @@ class BdAnchorNav extends LitElement {
|
|
|
53
57
|
this._programmaticScrollTargetId = null;
|
|
54
58
|
this._unlockScrollSpyTimer = null;
|
|
55
59
|
this._scrollEndUnlockHandler = null;
|
|
60
|
+
this._stickyOriginalTop = null;
|
|
61
|
+
this._stickyPlaceholder = null;
|
|
62
|
+
this._onStickyScroll = null;
|
|
63
|
+
this._handleResize = this._handleResize.bind(this);
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
connectedCallback() {
|
|
59
67
|
super.connectedCallback();
|
|
60
68
|
window.addEventListener("scroll", this._onScrollSpy, { passive: true });
|
|
61
69
|
window.addEventListener("resize", this._onScrollSpy, { passive: true });
|
|
70
|
+
window.addEventListener("resize", this._handleResize);
|
|
62
71
|
document.addEventListener("pointerdown", this._onDocumentPointerDown, true);
|
|
63
72
|
document.addEventListener("keydown", this._onKeydown, true);
|
|
64
73
|
queueMicrotask(() => this._runScrollSpy());
|
|
74
|
+
this._initSticky();
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
disconnectedCallback() {
|
|
@@ -69,8 +79,111 @@ class BdAnchorNav extends LitElement {
|
|
|
69
79
|
this._cancelScrollSpyUnlock();
|
|
70
80
|
window.removeEventListener("scroll", this._onScrollSpy);
|
|
71
81
|
window.removeEventListener("resize", this._onScrollSpy);
|
|
82
|
+
window.removeEventListener("resize", this._handleResize);
|
|
72
83
|
document.removeEventListener("pointerdown", this._onDocumentPointerDown, true);
|
|
73
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");
|
|
74
187
|
}
|
|
75
188
|
|
|
76
189
|
_cancelScrollSpyUnlock() {
|
|
@@ -191,6 +304,7 @@ class BdAnchorNav extends LitElement {
|
|
|
191
304
|
this.requestUpdate();
|
|
192
305
|
}
|
|
193
306
|
queueMicrotask(() => this._runScrollSpy());
|
|
307
|
+
this._handleMobileFullWidth();
|
|
194
308
|
}
|
|
195
309
|
|
|
196
310
|
updated(changedProperties) {
|
|
@@ -287,22 +401,29 @@ class BdAnchorNav extends LitElement {
|
|
|
287
401
|
${resolved.map(({ id, title, href }) => {
|
|
288
402
|
const isActive = this.activeId === id;
|
|
289
403
|
return html`
|
|
290
|
-
<
|
|
404
|
+
<bd-link
|
|
291
405
|
href="${href}"
|
|
292
|
-
|
|
406
|
+
kind="${isActive ? "primary" : "secondary"}"
|
|
407
|
+
no-underline
|
|
408
|
+
class="anchor-link ${isActive ? "active" : ""}"
|
|
409
|
+
color="var(--color-neutral-900)"
|
|
410
|
+
?active=${isActive}
|
|
293
411
|
aria-current=${isActive ? "true" : nothing}
|
|
294
412
|
@click=${(e) => this.handleClick(e, id, href)}
|
|
295
|
-
>${title}</
|
|
413
|
+
>${title}</bd-link>
|
|
296
414
|
`;
|
|
297
415
|
})}
|
|
298
416
|
</div>
|
|
299
417
|
`;
|
|
300
418
|
|
|
419
|
+
const innerStyle = this.maxWidth ? `max-width: ${this.maxWidth};` : '';
|
|
420
|
+
|
|
301
421
|
return html`
|
|
302
422
|
<nav aria-label=${this.navLabel}>
|
|
303
423
|
<div
|
|
304
424
|
class="bd-anchor-nav__inner"
|
|
305
425
|
part="inner"
|
|
426
|
+
style="${innerStyle}"
|
|
306
427
|
?data-mobile-cta-visible=${this._mobileCtaRevealed}
|
|
307
428
|
>
|
|
308
429
|
${linkRow("anchor-links anchor-links--desktop")}
|
|
@@ -350,11 +471,7 @@ class BdAnchorNav extends LitElement {
|
|
|
350
471
|
</div>
|
|
351
472
|
|
|
352
473
|
<div class="bd-cta">
|
|
353
|
-
<
|
|
354
|
-
class="bd-anchor-nav__cta"
|
|
355
|
-
href="${this.ctaHref || "#section-pricing"}"
|
|
356
|
-
part="buy-button"
|
|
357
|
-
>${this.ctaLabel}</a>
|
|
474
|
+
<slot name="cta"></slot>
|
|
358
475
|
</div>
|
|
359
476
|
</div>
|
|
360
477
|
</nav>
|
|
@@ -363,4 +480,4 @@ class BdAnchorNav extends LitElement {
|
|
|
363
480
|
}
|
|
364
481
|
|
|
365
482
|
customElements.define("bd-anchor-nav-item", BdAnchorNavItem);
|
|
366
|
-
customElements.define("bd-anchor-nav", BdAnchorNav);
|
|
483
|
+
customElements.define("bd-anchor-nav", BdAnchorNav);
|
|
@@ -37,6 +37,39 @@ export default css`
|
|
|
37
37
|
text-underline-offset: 2px;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/* ============================================
|
|
41
|
+
ACTIVE STATE - FONT WEIGHT 700
|
|
42
|
+
============================================ */
|
|
43
|
+
|
|
44
|
+
.bd-link--active {
|
|
45
|
+
font-weight: 700 !important;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Poți adăuga și alte stiluri pentru active dacă dorești */
|
|
49
|
+
.bd-link--active.bd-link--primary {
|
|
50
|
+
color: var(--color-neutral-900);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.bd-link--active.bd-link--secondary {
|
|
54
|
+
color: var(--color-neutral-900);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
.bd-link--no-underline:hover,
|
|
59
|
+
.bd-link--no-underline.bd-link--primary:hover,
|
|
60
|
+
.bd-link--no-underline.bd-link--secondary:hover,
|
|
61
|
+
.bd-link--no-underline.bd-link--danger:hover,
|
|
62
|
+
.bd-link--no-underline.bd-link--bold:hover,
|
|
63
|
+
.bd-link--no-underline.bd-link--subtle:hover {
|
|
64
|
+
text-decoration: none !important;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
.bd-link--no-underline.bd-link--secondary:hover {
|
|
70
|
+
color: var(--color-neutral-800) !important;
|
|
71
|
+
}
|
|
72
|
+
|
|
40
73
|
/* Light variant for dark backgrounds */
|
|
41
74
|
.bd-link--light {
|
|
42
75
|
color: var(--color-neutral-0);
|
|
@@ -101,9 +134,12 @@ export default css`
|
|
|
101
134
|
pointer-events: none;
|
|
102
135
|
}
|
|
103
136
|
|
|
104
|
-
|
|
105
|
-
/* Focus styles for all variants */
|
|
137
|
+
/* Focus styles */
|
|
106
138
|
.bd-link:focus {
|
|
139
|
+
outline: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.bd-link:focus-visible {
|
|
107
143
|
outline: 2px solid var(--color-blue-300);
|
|
108
144
|
outline-offset: 2px;
|
|
109
145
|
border-radius: 2px;
|
|
@@ -4,24 +4,28 @@ import linkCSS from "./link.css.js";
|
|
|
4
4
|
|
|
5
5
|
class BdLink extends LitElement {
|
|
6
6
|
static properties = {
|
|
7
|
-
href
|
|
8
|
-
target
|
|
9
|
-
kind
|
|
10
|
-
underline: { type: Boolean, reflect: true },
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
href : { type: String },
|
|
8
|
+
target : { type: String },
|
|
9
|
+
kind : { type: String, reflect: true },
|
|
10
|
+
underline : { type: Boolean, reflect: true },
|
|
11
|
+
noUnderline: { type: Boolean, attribute: "no-underline" },
|
|
12
|
+
disabled : { type: Boolean, reflect: true },
|
|
13
|
+
fontSize : { type: String, attribute: "font-size" },
|
|
14
|
+
color : { type: String },
|
|
15
|
+
active : { type: Boolean, reflect: true }
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
constructor() {
|
|
17
19
|
super();
|
|
18
|
-
this.href
|
|
19
|
-
this.target
|
|
20
|
-
this.kind
|
|
21
|
-
this.underline
|
|
22
|
-
this.
|
|
23
|
-
this.
|
|
24
|
-
this.
|
|
20
|
+
this.href = "#";
|
|
21
|
+
this.target = "_self";
|
|
22
|
+
this.kind = "primary";
|
|
23
|
+
this.underline = false;
|
|
24
|
+
this.noUnderline = false;
|
|
25
|
+
this.disabled = false;
|
|
26
|
+
this.fontSize = "";
|
|
27
|
+
this.color = "";
|
|
28
|
+
this.active = false;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
static styles = [tokens, linkCSS];
|
|
@@ -31,6 +35,8 @@ class BdLink extends LitElement {
|
|
|
31
35
|
"bd-link",
|
|
32
36
|
`bd-link--${this.kind}`,
|
|
33
37
|
this.underline ? "bd-link--underline" : "",
|
|
38
|
+
this.noUnderline ? "bd-link--no-underline" : "",
|
|
39
|
+
this.active ? "bd-link--active" : "",
|
|
34
40
|
this.disabled ? "bd-link--disabled" : ""
|
|
35
41
|
].filter(Boolean).join(" ");
|
|
36
42
|
}
|