@repobit/dex-system-design 0.23.116 → 0.24.0

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,21 @@
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.24.0](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.117...@repobit/dex-system-design@0.24.0) (2026-08-13)
7
+
8
+ ### Features
9
+
10
+ * **DEX-28239:** add horizontal layout variation to compare card component
11
+
12
+
13
+ ## [0.23.117](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.116...@repobit/dex-system-design@0.23.117) (2026-08-11)
14
+
15
+ **Note:** Version bump only for package @repobit/dex-system-design
16
+
17
+
18
+
19
+
20
+
6
21
  ## [0.23.116](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.115...@repobit/dex-system-design@0.23.116) (2026-08-07)
7
22
 
8
23
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobit/dex-system-design",
3
- "version": "0.23.116",
3
+ "version": "0.24.0",
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",
@@ -74,8 +74,8 @@
74
74
  "url": "https://github.com/bitdefender/dex-core/issues"
75
75
  },
76
76
  "dependencies": {
77
- "@repobit/dex-store": "1.6.14",
78
- "@repobit/dex-store-elements": "2.0.19",
77
+ "@repobit/dex-store": "1.6.16",
78
+ "@repobit/dex-store-elements": "2.0.21",
79
79
  "lit": "^3.3.2"
80
80
  },
81
81
  "devDependencies": {
@@ -92,5 +92,5 @@
92
92
  "volta": {
93
93
  "node": "24.14.0"
94
94
  },
95
- "gitHead": "7af92630a57f9ae948eb1eb3630085d3566d233c"
95
+ "gitHead": "c08cf4f44c57f9a84693f94fa894e97034624867"
96
96
  }
@@ -68,6 +68,10 @@ export default css`
68
68
  }
69
69
  }
70
70
 
71
+ .cs-grid > ::slotted(compare-card[layout="horizontal"]) {
72
+ grid-column: 1 / -1;
73
+ }
74
+
71
75
  .card {
72
76
  background: var(--color-neutral-25);
73
77
  border-radius: var(--radius-3xl);
@@ -124,6 +128,59 @@ export default css`
124
128
  flex: 0 0 auto;
125
129
  }
126
130
 
131
+ /* ── Horizontal layout ──────────────────────────────────────────────────────── */
132
+
133
+ .card--horizontal {
134
+ display: grid;
135
+ grid-template-columns: 1fr 1fr;
136
+ align-items: stretch;
137
+ gap: var(--spacing-40);
138
+ }
139
+
140
+ .card-left {
141
+ display: flex;
142
+ flex-direction: column;
143
+ gap: var(--spacing-16);
144
+ }
145
+
146
+ /* slot is transparent so fallback children are direct flex items of .card-left */
147
+ slot[name="header"] { display: contents; }
148
+
149
+ ::slotted([slot="header"]) {
150
+ display: flex;
151
+ flex-direction: column;
152
+ }
153
+
154
+ .card-left-top {
155
+ display: flex;
156
+ align-items: center;
157
+ gap: var(--spacing-12);
158
+ }
159
+
160
+ .card--horizontal .card-icon-wrap {
161
+ width: var(--dimension-40px);
162
+ height: var(--dimension-40px);
163
+ }
164
+
165
+ .card--horizontal .card-description { margin: 0; }
166
+
167
+ /* footnote sits at the bottom of the left column */
168
+ .card--horizontal .card-footnote { margin-top: auto; }
169
+
170
+ .card-right {
171
+ display: flex;
172
+ flex-direction: column;
173
+ justify-content: center;
174
+ }
175
+
176
+ @media (max-width: 768px) {
177
+ .card--horizontal {
178
+ grid-template-columns: 1fr;
179
+ }
180
+
181
+ .card--horizontal .card-footnote { margin-top: 0; }
182
+ }
183
+
127
184
  .bar-track {
128
185
  position: relative;
129
186
  height: var(--cs-bar-height);
@@ -223,6 +223,7 @@ class CompareCard extends LitElement {
223
223
  footnote : { type: String },
224
224
  footnoteHref : { type: String, attribute: "footnote-href" },
225
225
  iconSrc : { type: String, attribute: "icon-src" },
226
+ layout : { type: String },
226
227
  barStretch : { type: Boolean, attribute: "bar-stretch" },
227
228
  barFillMin : { type: Number, attribute: "bar-fill-min" },
228
229
  barStretchGamma: { type: Number, attribute: "bar-stretch-gamma" },
@@ -241,6 +242,7 @@ class CompareCard extends LitElement {
241
242
  this.footnote = "";
242
243
  this.footnoteHref = "";
243
244
  this.iconSrc = "";
245
+ this.layout = "";
244
246
  this.barStretch = true;
245
247
  this.barFillMin = 50;
246
248
  this.barStretchGamma = 1;
@@ -365,7 +367,56 @@ class CompareCard extends LitElement {
365
367
  `;
366
368
  }
367
369
 
370
+ _renderHorizontal() {
371
+ return html`
372
+ <div
373
+ class="card card--horizontal"
374
+ role="article"
375
+ aria-labelledby="${this._headingId}"
376
+ aria-describedby="${this._chartHelpId}"
377
+ >
378
+ <p class="cs-sr-only" id="${this._chartHelpId}">
379
+ Bar lengths are scaled for visibility between brands. Use the announced scores for exact values; scale is out of ${this.chartScale}.
380
+ </p>
381
+
382
+ <div class="card-left">
383
+ <slot name="header">
384
+ <div class="card-left-top">
385
+ ${this.iconSrc ? html`
386
+ <div class="card-icon-wrap" aria-hidden="true">
387
+ <bd-img
388
+ src="${this.iconSrc}"
389
+ alt=""
390
+ width="40"
391
+ height="40"
392
+ fit="contain"
393
+ radius="none"
394
+ shadow="none"
395
+ loading="eager"
396
+ ></bd-img>
397
+ </div>
398
+ ` : ""}
399
+ <bd-h as="h3" class="card-title" heading-id="${this._headingId}">${this.title}</bd-h>
400
+ </div>
401
+ ${this.description ? html`
402
+ <bd-p kind="regular" class="card-description">${this.description}</bd-p>
403
+ ` : ""}
404
+ ${this._renderFootnote()}
405
+ </slot>
406
+ </div>
407
+
408
+ <div class="card-right">
409
+ <div class="card-bars" role="group" aria-label="Scores by brand">
410
+ <slot @slotchange=${this._syncBarStretch}></slot>
411
+ </div>
412
+ </div>
413
+ </div>
414
+ `;
415
+ }
416
+
368
417
  render() {
418
+ if (this.layout === "horizontal") return this._renderHorizontal();
419
+
369
420
  const isMobile = window.matchMedia("(max-width: 767px)").matches;
370
421
 
371
422
  return html`
@@ -484,7 +535,7 @@ class CompareSection extends LitElement {
484
535
 
485
536
  const cards = slot
486
537
  .assignedElements({ flatten: true })
487
- .filter((el) => el.localName === "compare-card");
538
+ .filter((el) => el.localName === "compare-card" && el.getAttribute("layout") !== "horizontal");
488
539
 
489
540
  if (!cards.length) return;
490
541
 
@@ -626,4 +626,54 @@ export const ThemeDark = {
626
626
  </bd-compare-section>
627
627
  </div>
628
628
  `
629
+ };
630
+
631
+
632
+ // ─── Horizontal layout ────────────────────────────────────────────────────────
633
+
634
+ export const HorizontalLayout = {
635
+ name : "Horizontal Layout (attribute-driven)",
636
+ render: () => html`
637
+ <bd-compare-section
638
+ title="Award-Winning Security, Independently Verified"
639
+ gap="32px"
640
+ >
641
+ <compare-card
642
+ layout="horizontal"
643
+ title="Best Protection"
644
+ description="Best Protection against e-Threats (On a scale of 0 to 6, with 6 as the highest level of protection)"
645
+ footnote="Overall Score. July 2011 – February 2025. Source AV TEST.org"
646
+ footnote-href="${AV_TEST_URL}"
647
+ icon-src="${SHIELD_ICON}"
648
+ bar-stretch="false"
649
+ >
650
+ <compare-bar label="Bitdefender" score="5.95" max-score="6" variant="primary"></compare-bar>
651
+ <compare-bar label="Norton" score="5.89" max-score="6" variant="secondary" scale="0.93"></compare-bar>
652
+ <compare-bar label="McAfee" score="5.45" max-score="6" variant="secondary" scale="0.47"></compare-bar>
653
+ <compare-bar label="Kaspersky" score="5.20" max-score="6" variant="secondary" scale="0.40"></compare-bar>
654
+ </compare-card>
655
+ </bd-compare-section>
656
+ `
657
+ };
658
+
659
+ export const HorizontalLayoutCustomSlot = {
660
+ name : "Horizontal Layout (custom slot=\"header\")",
661
+ render: () => html`
662
+ <bd-compare-section gap="32px">
663
+ <compare-card layout="horizontal" bar-stretch="false">
664
+ <div slot="header" style="display:flex;flex-direction:column;gap:var(--spacing-16)">
665
+ <div style="display:flex;align-items:center;gap:var(--spacing-12)">
666
+ <bd-img src="${SHIELD_ICON}" alt="" width="40" height="40" fit="contain" radius="none" shadow="none" loading="eager"></bd-img>
667
+ <bd-h as="h3">Award-Winning Protection</bd-h>
668
+ </div>
669
+ <bd-p kind="regular">Scale of 0–6. Higher is better. Independently tested since 2011.</bd-p>
670
+ <bd-p kind="xsmall" style="margin-top:auto">Overall Score. July 2011 – February 2025. Source AV TEST.org</bd-p>
671
+ </div>
672
+ <compare-bar label="Bitdefender" score="5.95" max-score="6" variant="primary"></compare-bar>
673
+ <compare-bar label="Norton" score="5.89" max-score="6" variant="secondary" scale="0.93"></compare-bar>
674
+ <compare-bar label="McAfee" score="5.45" max-score="6" variant="secondary" scale="0.47"></compare-bar>
675
+ <compare-bar label="Kaspersky" score="5.20" max-score="6" variant="secondary" scale="0.40"></compare-bar>
676
+ </compare-card>
677
+ </bd-compare-section>
678
+ `
629
679
  };