@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 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.16",
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": "0d063cda634ce56449d0dd9501bc86fc6d3d818e"
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
- /* Double rAF focus pattern */
33
- :host([data-bd-button-focus]) {
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
- .max--width {
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
- a:focus-visible,
21
- .bd-anchor-nav__cta:focus-visible,
22
- .bd-anchor-nav__dropdown-toggle:focus-visible,
23
- .bd-anchor-nav__dropdown-option:focus-visible {
24
- outline: var(--spacing-2) solid var(--bd-accesibility-focus);
25
- outline-offset: var(--spacing-2);
26
- border-radius: var(--space-2xs);
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(--layout-compare-grid-max);
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
- display: flex;
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
- /* ── Desktop links ── */
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
- /* ── Animations ── */
292
+ .bd-anchor-nav__cta::after {
293
+ display: none;
294
+ }
266
295
 
267
296
  @keyframes bd-anchor-nav-dropdown-label-swap {
268
- from {
269
- opacity: 0.35;
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
- a::after,
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
- <a
404
+ <bd-link
291
405
  href="${href}"
292
- class="${isActive ? "active" : ""}"
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}</a>
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
- <a
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 : { type: String },
8
- target : { type: String },
9
- kind : { type: String, reflect: true },
10
- underline: { type: Boolean, reflect: true },
11
- disabled : { type: Boolean, reflect: true },
12
- fontSize : { type: String, attribute: "font-size" },
13
- color : { type: String }
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 = "_self";
20
- this.kind = "primary";
21
- this.underline = false;
22
- this.disabled = false;
23
- this.fontSize = "";
24
- this.color = "";
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
  }