@repobit/dex-system-design 0.25.4 → 0.25.5

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,14 @@
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.25.5](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.25.4...@repobit/dex-system-design@0.25.5) (2026-10-05)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **DEX-1014:** button component - rounded variant
11
+ * **DEX-1014:** button component - rounded variant
12
+
13
+
6
14
  ## [0.25.4](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.25.3...@repobit/dex-system-design@0.25.4) (2026-10-02)
7
15
 
8
16
  **Note:** Version bump only for package @repobit/dex-system-design
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobit/dex-system-design",
3
- "version": "0.25.4",
3
+ "version": "0.25.5",
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",
@@ -76,8 +76,8 @@
76
76
  "url": "https://github.com/bitdefender/dex-core/issues"
77
77
  },
78
78
  "dependencies": {
79
- "@repobit/dex-store": "1.6.41",
80
- "@repobit/dex-store-elements": "2.1.11",
79
+ "@repobit/dex-store": "1.6.42",
80
+ "@repobit/dex-store-elements": "2.1.12",
81
81
  "lit": "^3.3.2"
82
82
  },
83
83
  "devDependencies": {
@@ -94,5 +94,5 @@
94
94
  "volta": {
95
95
  "node": "24.14.0"
96
96
  },
97
- "gitHead": "7fa90da5e767feac5859b40aeaeedebf9a5ee6c9"
97
+ "gitHead": "63acb7bfc214afa83b52f12193d91ed28782f0ff"
98
98
  }
@@ -32,6 +32,8 @@ export default css`
32
32
  --button-arrow-shift: 0.65em;
33
33
  --button-arrow-inset: 0.65em;
34
34
  --button-arrow-offset: -0.4em;
35
+
36
+ --button-radius-rounded: var(--spacing-30);
35
37
  }
36
38
 
37
39
  /* ============================================
@@ -76,6 +78,10 @@ export default css`
76
78
  border-radius: var(--radius-md);
77
79
  }
78
80
 
81
+ :host([shape="rounded"][data-bd-button-focus]) {
82
+ border-radius: var(--button-radius-rounded);
83
+ }
84
+
79
85
  button:focus,
80
86
  button:focus-visible,
81
87
  a:focus,
@@ -143,9 +149,9 @@ export default css`
143
149
  color: var(--color-neutral-0);
144
150
  }
145
151
 
146
- .button--danger:hover {
147
- background-color: var(--button-background-danger-hover);
148
- }
152
+ // .button--danger:hover {
153
+ // background-color: var(--button-background-danger-hover);
154
+ // }
149
155
 
150
156
  .button--danger:active {
151
157
  background-color: var(--button-background-danger-focus);
@@ -180,12 +186,6 @@ export default css`
180
186
  pointer-events: none;
181
187
  }
182
188
 
183
- .button--with-arrow .button__arrow svg {
184
- width: 100%;
185
- height: 100%;
186
- display: block;
187
- }
188
-
189
189
  .button--with-arrow:hover .button__label,
190
190
  .button--with-arrow:focus-visible .button__label {
191
191
  transform: translateX(calc(var(--button-arrow-shift) * -1));
@@ -269,8 +269,12 @@ export default css`
269
269
  min-width: 150px;
270
270
  }
271
271
 
272
- .button--bold {
273
- font-weight: var(--typography-fontWeight-semibold);
272
+ .button--rounded {
273
+ border-radius: var(--radius-3xl);
274
+ }
275
+
276
+ .button--bold {
277
+ font: normal normal var(--typography-fontWeight-medium) var(--typography-fontSize-lg) / var(--dimension-24px) Roboto, sans-serif;
274
278
  }
275
279
 
276
280
  /* slot-ul nu mai e copil direct al .button (e în .button__label) */
@@ -1,23 +1,10 @@
1
1
  import { LitElement, html } from "lit";
2
2
  import { tokens } from "../../tokens/tokens.js";
3
+ import "../icons/arrow-right-icon.js";
3
4
  import buttonsCSS from "./button.css.js";
4
5
 
5
- /**
6
- * Săgeata afișată pe hover / focus pentru butoanele cu kind="danger".
7
- * Folosește currentColor, deci preia culoarea textului butonului.
8
- */
9
6
  const arrowIcon = html`
10
- <span class="button__arrow" aria-hidden="true">
11
- <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
12
- <path
13
- d="M2.5 8h11M9 3.5 13.5 8 9 12.5"
14
- stroke="currentColor"
15
- stroke-width="1.5"
16
- stroke-linecap="round"
17
- stroke-linejoin="round"
18
- />
19
- </svg>
20
- </span>
7
+ <bd-arrow-right-icon class="button__arrow" width="100%" height="100%" aria-hidden="true"></bd-arrow-right-icon>
21
8
  `;
22
9
 
23
10
  class Button extends LitElement {
@@ -32,7 +19,8 @@ class Button extends LitElement {
32
19
  fontSize : { type: String, attribute: "font-size" },
33
20
  fontWeight : { type: String, attribute: "font-weight" },
34
21
  align : { type: String },
35
- noArrow : { type: Boolean, attribute: "no-arrow" }
22
+ noArrow : { type: Boolean, attribute: "no-arrow" },
23
+ shape : { type: String, reflect: true }
36
24
  };
37
25
 
38
26
  constructor() {
@@ -44,6 +32,7 @@ class Button extends LitElement {
44
32
  this.fontWeight = "";
45
33
  this.align = "left";
46
34
  this.noArrow = false;
35
+ this.shape = "default";
47
36
  }
48
37
 
49
38
  _onFocusin(e) {
@@ -99,6 +88,10 @@ class Button extends LitElement {
99
88
  }
100
89
  }
101
90
 
91
+ get shapeClass() {
92
+ return this.shape === "rounded" ? "button--rounded" : "";
93
+ }
94
+
102
95
  get fullWidthClass() {
103
96
  return this.fullWidth ? "max--width" : "";
104
97
  }
@@ -107,7 +100,6 @@ class Button extends LitElement {
107
100
  return this.strong ? "button--bold" : "";
108
101
  }
109
102
 
110
- /** Săgeata pe hover e activă implicit pentru danger; se poate dezactiva cu no-arrow. */
111
103
  get hasArrow() {
112
104
  return this.kind === "danger" && !this.noArrow;
113
105
  }
@@ -122,7 +114,7 @@ class Button extends LitElement {
122
114
  @click=${this._handleClick}
123
115
  @focusin=${this._onFocusin}
124
116
  @focusout=${this._onFocusout}
125
- class="button ${this.kindClass} ${this.sizeClass} ${this.fullWidthClass} ${this.strongClass} ${this.arrowClass}"
117
+ class="button ${this.kindClass} ${this.sizeClass} ${this.shapeClass} ${this.fullWidthClass} ${this.strongClass} ${this.arrowClass}"
126
118
  aria-label="${this.label}"
127
119
  style="
128
120
  ${this.fontSize ? `font-size: ${this.fontSize};` : ""}
@@ -150,7 +142,8 @@ class ButtonLink extends LitElement {
150
142
  buyLink : { type: Boolean },
151
143
  shadow : { type: Boolean, reflect: true },
152
144
  align : { type: String },
153
- noArrow : { type: Boolean, attribute: "no-arrow" }
145
+ noArrow : { type: Boolean, attribute: "no-arrow" },
146
+ shape : { type: String, reflect: true }
154
147
  };
155
148
 
156
149
  constructor() {
@@ -167,6 +160,7 @@ class ButtonLink extends LitElement {
167
160
  this.shadow = true;
168
161
  this.align = "left";
169
162
  this.noArrow = false;
163
+ this.shape = "default";
170
164
  }
171
165
 
172
166
  _onFocusin(e) {
@@ -218,6 +212,10 @@ class ButtonLink extends LitElement {
218
212
  }
219
213
  }
220
214
 
215
+ get shapeClass() {
216
+ return this.shape === "rounded" ? "button--rounded" : "";
217
+ }
218
+
221
219
  get fullWidthClass() {
222
220
  return this.fullWidth ? "max--width" : "";
223
221
  }
@@ -238,7 +236,7 @@ class ButtonLink extends LitElement {
238
236
  return html`
239
237
  <a
240
238
  href="${this.href}"
241
- class="button ${this.kindClass} ${this.sizeClass} ${this.fullWidthClass} ${this.strongClass} ${this.arrowClass}"
239
+ class="button ${this.kindClass} ${this.sizeClass} ${this.shapeClass} ${this.fullWidthClass} ${this.strongClass} ${this.arrowClass}"
242
240
  aria-label="${this.label}"
243
241
  @click=${this._handleClick}
244
242
  @focusin=${this._onFocusin}
@@ -265,7 +263,8 @@ class ContactButton extends LitElement {
265
263
  static properties = {
266
264
  label: { type: String },
267
265
  href : { type: String },
268
- align: { type: String }
266
+ align: { type: String },
267
+ shape: { type: String, reflect: true }
269
268
  };
270
269
 
271
270
  constructor() {
@@ -273,6 +272,7 @@ class ContactButton extends LitElement {
273
272
  this.label = "Contact us";
274
273
  this.href = "https://www.google.com";
275
274
  this.align = "left";
275
+ this.shape = "default";
276
276
  }
277
277
 
278
278
  _onFocusin(e) {
@@ -290,10 +290,14 @@ class ContactButton extends LitElement {
290
290
  this.removeAttribute('data-bd-button-focus');
291
291
  }
292
292
 
293
+ get shapeClass() {
294
+ return this.shape === "rounded" ? "button--rounded" : "";
295
+ }
296
+
293
297
  render() {
294
298
  return html`
295
299
  <a
296
- class="button bd-contact-btn"
300
+ class="button bd-contact-btn ${this.shapeClass}"
297
301
  href="${this.href}"
298
302
  aria-label="${this.label}"
299
303
  @click=${this._handleClick}
@@ -18,6 +18,7 @@ Three button components are available:
18
18
  \`\`\`html
19
19
  <bd-button kind="primary" size="md">Click me</bd-button>
20
20
  <bd-button kind="danger" size="md">Activez votre protection</bd-button>
21
+ <bd-button kind="primary" size="md" shape="rounded">Rounded</bd-button>
21
22
  <bd-button-link kind="danger" size="lg" href="/buy">Buy now</bd-button-link>
22
23
  <bd-contact-button label="Contact us" href="/contact"></bd-contact-button>
23
24
  \`\`\`
@@ -53,6 +54,14 @@ The effect can be tuned from outside via CSS custom properties:
53
54
  | \`md\` | \`button--medium\` |
54
55
  | \`lg\` | \`button--large\` |
55
56
 
57
+ ### Shape Values
58
+ | Shape | Effect |
59
+ |---|---|
60
+ | \`default\` | Border radius from the size (\`--radius-md\` / \`--radius-lg\`) |
61
+ | \`rounded\` | \`button--rounded\` — border radius \`--spacing-30\` |
62
+
63
+ The rounded radius can be overridden via the \`--button-radius-rounded\` CSS custom property.
64
+
56
65
  ### Alignment Values
57
66
  | Align | Effect |
58
67
  |---|---|
@@ -84,6 +93,12 @@ The effect can be tuned from outside via CSS custom properties:
84
93
  description: 'Size of the button',
85
94
  table : { type: { summary: "'sm' | 'md' | 'lg'" }, defaultValue: { summary: 'md' }, category: 'Appearance' }
86
95
  },
96
+ shape: {
97
+ control : { type: 'select' },
98
+ options : ['default', 'rounded'],
99
+ description: 'Shape of the button. `rounded` applies `--spacing-30` border radius.',
100
+ table : { type: { summary: "'default' | 'rounded'" }, defaultValue: { summary: 'default' }, category: 'Appearance' }
101
+ },
87
102
  noArrow: {
88
103
  control : 'boolean',
89
104
  description: '(kind="danger" only) Disables the hover arrow. Attribute: `no-arrow`',
@@ -137,6 +152,7 @@ const defaultArgs = {
137
152
  label : 'Buy now',
138
153
  kind : 'primary',
139
154
  size : 'md',
155
+ shape : 'default',
140
156
  noArrow : false,
141
157
  fullWidth : false,
142
158
  strong : false,
@@ -167,6 +183,38 @@ export const ButtonAllKinds = {
167
183
  parameters: { docs: { description: { story: 'All five `kind` variants side by side. Hover the danger button to see the arrow.' } } }
168
184
  };
169
185
 
186
+ export const ButtonRounded = {
187
+ name : 'Button — Rounded',
188
+ render: () => html`
189
+ <div style="display:flex; flex-direction:column; gap:16px; align-items:flex-start;">
190
+ <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
191
+ <bd-button kind="primary" size="md" shape="rounded">Primary</bd-button>
192
+ <bd-button kind="primary-outline" size="md" shape="rounded">Primary Outline</bd-button>
193
+ <bd-button kind="outline" size="md" shape="rounded">Outline</bd-button>
194
+ <bd-button kind="secondary" size="md" shape="rounded">Secondary</bd-button>
195
+ <bd-button kind="danger" size="md" shape="rounded" strong>Danger</bd-button>
196
+ </div>
197
+ <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
198
+ <bd-button kind="primary" size="sm" shape="rounded">Small</bd-button>
199
+ <bd-button kind="primary" size="md" shape="rounded">Medium</bd-button>
200
+ <bd-button kind="primary" size="lg" shape="rounded">Large</bd-button>
201
+ </div>
202
+ </div>
203
+ `,
204
+ parameters: { docs: { description: { story: '`shape="rounded"` applies `--spacing-30` border radius across all kinds and sizes.' } } }
205
+ };
206
+
207
+ export const ButtonShapeComparison = {
208
+ name : 'Button — Default vs Rounded',
209
+ render: () => html`
210
+ <div style="display:flex; gap:12px; align-items:center; flex-wrap:wrap;">
211
+ <bd-button kind="primary" size="md">Default</bd-button>
212
+ <bd-button kind="primary" size="md" shape="rounded">Rounded</bd-button>
213
+ </div>
214
+ `,
215
+ parameters: { docs: { description: { story: 'Side-by-side comparison of the `default` and `rounded` shapes.' } } }
216
+ };
217
+
170
218
  export const ButtonDangerArrow = {
171
219
  name : 'Button — Danger (Hover Arrow)',
172
220
  render: () => html`
@@ -218,9 +266,10 @@ export const ButtonFullWidth = {
218
266
  <div style="width:400px; display:flex; flex-direction:column; gap:12px;">
219
267
  <bd-button kind="primary" size="md" .fullWidth="${true}">Full Width Button</bd-button>
220
268
  <bd-button kind="danger" size="md" strong .fullWidth="${true}">Full Width Danger</bd-button>
269
+ <bd-button kind="primary" size="md" shape="rounded" .fullWidth="${true}">Full Width Rounded</bd-button>
221
270
  </div>
222
271
  `,
223
- parameters: { docs: { description: { story: '`fullWidth` set to true — applies `max--width` class. The danger arrow also works at full width.' } } }
272
+ parameters: { docs: { description: { story: '`fullWidth` set to true — applies `max--width` class. The danger arrow and rounded shape also work at full width.' } } }
224
273
  };
225
274
 
226
275
  export const ButtonStrong = {
@@ -315,6 +364,18 @@ export const ButtonLinkAllKinds = {
315
364
  parameters: { docs: { description: { story: 'All `kind` variants for `bd-button-link`.' } } }
316
365
  };
317
366
 
367
+ export const ButtonLinkRounded = {
368
+ name : 'ButtonLink — Rounded',
369
+ render: () => html`
370
+ <div style="display:flex; gap:12px; flex-wrap:wrap; align-items:center;">
371
+ <bd-button-link kind="primary" size="md" href="#" shape="rounded">Primary</bd-button-link>
372
+ <bd-button-link kind="primary-outline" size="md" href="#" shape="rounded">Primary Outline</bd-button-link>
373
+ <bd-button-link kind="danger" size="md" href="#" shape="rounded" strong>Danger</bd-button-link>
374
+ </div>
375
+ `,
376
+ parameters: { docs: { description: { story: '`shape="rounded"` on `bd-button-link`.' } } }
377
+ };
378
+
318
379
  export const ButtonLinkAllSizes = {
319
380
  name : 'ButtonLink — All Sizes',
320
381
  render: () => html`
@@ -420,6 +481,14 @@ export const ContactButtonCustomHref = {
420
481
  parameters: { docs: { description: { story: 'Contact button linking to an external support URL.' } } }
421
482
  };
422
483
 
484
+ export const ContactButtonRounded = {
485
+ name : 'ContactButton — Rounded',
486
+ render: () => html`
487
+ <bd-contact-button label="Contact us" href="#" shape="rounded"></bd-contact-button>
488
+ `,
489
+ parameters: { docs: { description: { story: '`shape="rounded"` on `bd-contact-button`.' } } }
490
+ };
491
+
423
492
  export const ContactButtonAlignCenter = {
424
493
  name : 'ContactButton — Align Center',
425
494
  render: () => html`
@@ -462,6 +531,7 @@ export const Playground = {
462
531
  <bd-button
463
532
  kind="${args.kind}"
464
533
  size="${args.size}"
534
+ shape="${args.shape}"
465
535
  label="${args.label}"
466
536
  align="${args.align}"
467
537
  ?fullwidth="${args.fullWidth}"
@@ -472,7 +542,7 @@ export const Playground = {
472
542
  >${args.label}</bd-button>
473
543
  </div>
474
544
  `,
475
- parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props including alignment and the danger hover arrow.' } } }
545
+ parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props including shape, alignment and the danger hover arrow.' } } }
476
546
  };
477
547
 
478
548
  // ─── White / Outline-White (on dark background) ───────────────────────────
@@ -483,7 +553,9 @@ export const ButtonWhiteOnDark = {
483
553
  <div style="background: linear-gradient(120deg, #0038e0 0%, #061a5c 100%); padding: 48px; border-radius: 12px; display:flex; gap:16px; flex-wrap:wrap; align-items:center; justify-content:center;">
484
554
  <bd-button-link kind="white" size="md" strong href="#">Download BETA Today</bd-button-link>
485
555
  <bd-button-link kind="outline-white" size="md" strong href="#">Read the docs</bd-button-link>
556
+ <bd-button-link kind="white" size="md" strong href="#" shape="rounded">Rounded White</bd-button-link>
557
+ <bd-button-link kind="outline-white" size="md" strong href="#" shape="rounded">Rounded Outline</bd-button-link>
486
558
  </div>
487
559
  `,
488
- parameters: { docs: { description: { story: '`white` and `outline-white` kinds, meant for use on colored/dark backgrounds like `bd-cta-banner` or hero sections.' } } }
560
+ parameters: { docs: { description: { story: '`white` and `outline-white` kinds, meant for use on colored/dark backgrounds like `bd-cta-banner` or hero sections. Also shown with `shape="rounded"`.' } } }
489
561
  };
@@ -0,0 +1,31 @@
1
+ import { LitElement, css, html } from "lit";
2
+
3
+ class ArrowRightIcon extends LitElement {
4
+ static properties = {
5
+ width : { type: String },
6
+ height: { type: String },
7
+ color : { type: String }
8
+ };
9
+
10
+ constructor() {
11
+ super();
12
+ this.width = "20";
13
+ this.height = "20";
14
+ this.color = "currentColor";
15
+ }
16
+
17
+ static styles = css`
18
+ :host { display: inline-flex; }
19
+ svg { display: block; }
20
+ `;
21
+
22
+ render() {
23
+ return html`
24
+ <svg xmlns="http://www.w3.org/2000/svg" width="${this.width}" height="${this.height}" viewBox="0 0 16 16" fill="none" aria-hidden="true">
25
+ <path d="M2.5 8h11M9 3.5 13.5 8 9 12.5" stroke="${this.color}" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
26
+ </svg>
27
+ `;
28
+ }
29
+ }
30
+
31
+ customElements.define("bd-arrow-right-icon", ArrowRightIcon);