@repobit/dex-system-design 0.23.63 → 0.23.65

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.23.65](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.64...@repobit/dex-system-design@0.23.65) (2026-07-03)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **DEX-1014:** css adjustments for cards component
11
+ * **DEX-1014:** css adjustments for cards component
12
+
13
+
14
+ ## [0.23.64](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.63...@repobit/dex-system-design@0.23.64) (2026-07-03)
15
+
16
+ ### Bug Fixes
17
+
18
+ * **DEX-1014:** css adjustments for cards component
19
+
20
+
6
21
  ## [0.23.63](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.62...@repobit/dex-system-design@0.23.63) (2026-07-02)
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.63",
3
+ "version": "0.23.65",
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",
@@ -70,8 +70,8 @@
70
70
  "url": "https://github.com/bitdefender/dex-core/issues"
71
71
  },
72
72
  "dependencies": {
73
- "@repobit/dex-store": "1.3.59",
74
- "@repobit/dex-store-elements": "1.4.51",
73
+ "@repobit/dex-store": "1.3.61",
74
+ "@repobit/dex-store-elements": "1.4.53",
75
75
  "lit": "^3.3.2"
76
76
  },
77
77
  "devDependencies": {
@@ -88,5 +88,5 @@
88
88
  "volta": {
89
89
  "node": "24.14.0"
90
90
  },
91
- "gitHead": "0bc5274bdbaef4a05431b2df49170b11d375aa59"
91
+ "gitHead": "798ae4c67c57d8932da4962aea6c451315865638"
92
92
  }
@@ -8,12 +8,16 @@ export default css`
8
8
  padding-top: var(--spacing-64);
9
9
  padding-bottom: var(--spacing-64);
10
10
  max-width: 1290px;
11
+ margin: 0 auto;
11
12
  }
12
13
 
13
14
  ::slotted([slot="icon"]) {
14
- width: 48px !important;
15
- height: 48px !important;
16
- flex-shrink: 0;
15
+ max-width: 120px !important;
16
+ max-height: 120px !important;
17
+ width: auto !important;
18
+ height: auto !important;
19
+ object-fit: contain !important;
20
+ display: block !important;
17
21
  }
18
22
 
19
23
  .bd-section-title-s {
@@ -33,11 +37,7 @@ export default css`
33
37
  justify-content: center;
34
38
  position: relative;
35
39
  width: 100%;
36
- margin: var(--spacing-0) auto;
37
- overflow: hidden;
38
40
  flex-direction: column;
39
- padding-left: var(--spacing-14);
40
- padding-right: var(--spacing-14);
41
41
  max-width: 1400px;
42
42
  margin: 0 auto;
43
43
  }
@@ -65,7 +65,6 @@ export default css`
65
65
  scroll-snap-type: x mandatory;
66
66
  display: grid;
67
67
  gap: 1.5rem;
68
- grid-template-columns: repeat(4, 1fr);
69
68
  }
70
69
 
71
70
  .bd-light-carousel-track-s::-webkit-scrollbar {
@@ -73,13 +72,12 @@ export default css`
73
72
  }
74
73
 
75
74
  .bd-light-box-s {
76
- flex: var(--spacing-0) var(--spacing-0) auto;
77
75
  background: var(--background-card-grey);
78
76
  border-radius: var(--spacing-20);
79
77
  padding: var(--spacing-32);
80
78
  display: flex;
81
79
  flex-direction: column;
82
- align-items: start;
80
+ align-items: flex-start;
83
81
  justify-content: flex-start;
84
82
  text-align: start;
85
83
  transition: transform 0.2s ease-in-out;
@@ -133,30 +131,32 @@ export default css`
133
131
  text-align: center !important;
134
132
  }
135
133
 
136
- .bd-light-icon-s {
137
- position: relative;
138
- max-width: 100%;
139
- height: var(--spacing-44);
140
- width: var(--spacing-44);
141
- }
134
+ .bd-light-icon-s {
135
+ max-width: 120px;
136
+ max-height: 120px;
137
+ width: auto;
138
+ height: auto;
139
+ object-fit: contain;
140
+ display: block;
141
+ }
142
142
 
143
143
  .bd-light-box-no-content .bd-light-icon-s {
144
144
  margin: 0 !important;
145
- bottom: 0;
146
145
  }
147
146
 
148
147
  .bd-light-box-header-s {
149
148
  display: flex;
150
149
  flex-direction: column;
151
150
  align-items: flex-start;
151
+ justify-content: flex-start;
152
152
  gap: var(--spacing-8);
153
153
  padding-bottom: var(--spacing-8);
154
- left: -5px;
155
154
  position: relative;
156
155
  }
157
156
 
158
157
  .bd-light-box-no-content .bd-light-box-header-s {
159
158
  align-items: center !important;
159
+ justify-content: center !important;
160
160
  margin: 0 !important;
161
161
  }
162
162
 
@@ -167,8 +167,9 @@ export default css`
167
167
 
168
168
  .bd-light-title-badge-wrapper-s {
169
169
  display: flex;
170
- align-items: center;
170
+ align-items: flex-start;
171
171
  gap: var(--spacing-4, 4px);
172
+ overflow: hidden;
172
173
  }
173
174
 
174
175
  .bd-light-title-no-content {
@@ -177,9 +178,26 @@ export default css`
177
178
  justify-content: center;
178
179
  }
179
180
 
181
+ .bd-card-content-wrapper {
182
+ flex: 1;
183
+ display: flex;
184
+ flex-direction: column;
185
+ width: 100%;
186
+ }
187
+
188
+ .bd-card-cta-wrapper {
189
+ margin-top: var(--spacing-16);
190
+ padding-top: var(--spacing-8);
191
+ display: flex;
192
+ align-items: flex-start;
193
+ }
194
+
195
+ .bd-card-cta-wrapper:empty {
196
+ display: none;
197
+ }
198
+
180
199
  @media (max-width: 1024px) {
181
200
  .bd-light-box-s {
182
- width: 380px;
183
201
  padding: 1.5em;
184
202
  }
185
203
 
@@ -192,7 +210,7 @@ export default css`
192
210
  }
193
211
 
194
212
  .bd-light-carousel-track-s {
195
- grid-template-columns: repeat(2, 1fr);
213
+ grid-template-columns: repeat(2, 1fr) !important;
196
214
  }
197
215
  }
198
216
 
@@ -230,15 +248,11 @@ export default css`
230
248
  .bd-light-box-s p {
231
249
  font-size: 0.9em;
232
250
  }
233
-
234
- .bd-light-icon-s {
235
- bottom: var(--spacing-10);
236
- }
237
251
  }
238
252
 
239
253
  @media (max-width: 600px) {
240
254
  .bd-light-carousel-track-s {
241
- grid-template-columns: 1fr;
255
+ grid-template-columns: 1fr !important;
242
256
  }
243
257
  }
244
258
  `;
@@ -1,5 +1,6 @@
1
1
  import { LitElement, html } from "lit";
2
2
  import { tokens } from "../../tokens/tokens.js";
3
+ import "../button/button.js";
3
4
  import "../heading/heading.js";
4
5
  import carouselCSS from "./card.css.js";
5
6
 
@@ -25,20 +26,68 @@ class Card extends LitElement {
25
26
  if (!items.length) return;
26
27
 
27
28
  items.forEach(item => {
28
- const box = item.renderRoot?.querySelector(".bd-light-box-s");
29
- if (box) {
30
- box.style.height = "auto";
31
- box.style.minHeight = "0";
32
- }
29
+ const box = item.renderRoot?.querySelector(".bd-light-box-s");
30
+ const iconW = item.renderRoot?.querySelector(".bd-light-box-header-s");
31
+ const titleW = item.renderRoot?.querySelector(".bd-light-title-badge-wrapper-s");
32
+ const contentW = item.renderRoot?.querySelector(".bd-card-content-wrapper");
33
+
34
+ if (box) { box.style.height = "auto"; box.style.minHeight = "0"; box.style.width = "auto"; }
35
+ if (iconW) { iconW.style.height = "auto"; }
36
+ if (titleW) { titleW.style.height = "auto"; }
37
+ if (contentW) { contentW.style.height = "auto"; }
33
38
  });
34
39
 
35
40
  requestAnimationFrame(() => {
41
+ let maxIcon = 0;
42
+ items.forEach(item => {
43
+ const el = item.renderRoot?.querySelector(".bd-light-box-header-s");
44
+ if (!el) return;
45
+ const h = el.getBoundingClientRect().height;
46
+ if (h > maxIcon) maxIcon = h;
47
+ });
48
+ if (maxIcon > 0) {
49
+ items.forEach(item => {
50
+ const el = item.renderRoot?.querySelector(".bd-light-box-header-s");
51
+ if (el) el.style.height = `${maxIcon}px`;
52
+ });
53
+ }
54
+
55
+ let maxTitle = 0;
56
+ items.forEach(item => {
57
+ const el = item.renderRoot?.querySelector(".bd-light-title-badge-wrapper-s");
58
+ if (!el) return;
59
+ const h = el.getBoundingClientRect().height;
60
+ if (h > maxTitle) maxTitle = h;
61
+ });
62
+ if (maxTitle > 0) {
63
+ items.forEach(item => {
64
+ const el = item.renderRoot?.querySelector(".bd-light-title-badge-wrapper-s");
65
+ if (el) el.style.height = `${maxTitle}px`;
66
+ });
67
+ }
68
+
69
+ let maxContent = 0;
70
+ items.forEach(item => {
71
+ const el = item.renderRoot?.querySelector(".bd-card-content-wrapper");
72
+ if (!el) return;
73
+ const h = el.getBoundingClientRect().height;
74
+ if (h > maxContent) maxContent = h;
75
+ });
76
+ if (maxContent > 0) {
77
+ items.forEach(item => {
78
+ const el = item.renderRoot?.querySelector(".bd-card-content-wrapper");
79
+ if (el) el.style.height = `${maxContent}px`;
80
+ });
81
+ }
82
+
83
+ let maxW = 0;
36
84
  let maxH = 0;
37
85
  items.forEach(item => {
38
86
  const box = item.renderRoot?.querySelector(".bd-light-box-s");
39
87
  if (!box) return;
40
- const h = box.getBoundingClientRect().height;
41
- if (h > maxH) maxH = h;
88
+ const rect = box.getBoundingClientRect();
89
+ if (rect.height > maxH) maxH = rect.height;
90
+ if (rect.width > maxW) maxW = rect.width;
42
91
  });
43
92
 
44
93
  if (maxH > 0) {
@@ -50,6 +99,16 @@ class Card extends LitElement {
50
99
  }
51
100
  });
52
101
  }
102
+
103
+ if (maxW > 0) {
104
+ items.forEach(item => {
105
+ const box = item.renderRoot?.querySelector(".bd-light-box-s");
106
+ if (box) {
107
+ box.style.width = `${maxW}px`;
108
+ box.style.minWidth = `${maxW}px`;
109
+ }
110
+ });
111
+ }
53
112
  });
54
113
  }
55
114
 
@@ -76,6 +135,8 @@ class Card extends LitElement {
76
135
  }
77
136
 
78
137
  render() {
138
+ const itemCount = this.querySelectorAll("bd-card-item").length;
139
+
79
140
  return html`
80
141
  <section class="bd-light-carousel-s">
81
142
  ${this.title
@@ -85,7 +146,10 @@ class Card extends LitElement {
85
146
  </div>
86
147
  `
87
148
  : null}
88
- <div class="bd-light-carousel-track-s">
149
+ <div
150
+ class="bd-light-carousel-track-s"
151
+ style="grid-template-columns: repeat(${itemCount}, 1fr);"
152
+ >
89
153
  <slot @slotchange=${() => this._equalizeHeights()}></slot>
90
154
  </div>
91
155
  </section>
@@ -111,15 +175,22 @@ class CardItem extends LitElement {
111
175
  const iconEl = this.querySelector("[slot='icon']");
112
176
 
113
177
  if (iconEl) {
114
- return iconEl.cloneNode(true);
178
+ const clone = iconEl.cloneNode(true);
179
+ clone.style.maxWidth = "120px";
180
+ clone.style.maxHeight = "120px";
181
+ clone.style.width = "auto";
182
+ clone.style.height = "auto";
183
+ clone.style.objectFit = "contain";
184
+ clone.style.display = "block";
185
+ return clone;
115
186
  }
116
187
 
117
188
  if (this.icon) {
118
189
  return html`<img
119
- src="${this.icon}"
120
- alt="icon"
121
- class="bd-light-icon-s"
122
- />`;
190
+ src="${this.icon}"
191
+ alt="icon"
192
+ class="bd-light-icon-s"
193
+ />`;
123
194
  }
124
195
 
125
196
  return "";
@@ -128,7 +199,8 @@ class CardItem extends LitElement {
128
199
  _hasContent() {
129
200
  const slottedNodes = [...this.childNodes].filter((node) => {
130
201
  if (node.nodeType === Node.ELEMENT_NODE) {
131
- return node.getAttribute("slot") !== "icon";
202
+ const slot = node.getAttribute("slot");
203
+ return slot !== "icon" && slot !== "cta";
132
204
  }
133
205
  return node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== "";
134
206
  });
@@ -142,9 +214,13 @@ class CardItem extends LitElement {
142
214
 
143
215
  return html`
144
216
  <div class="bd-light-box-s ${isCentered ? "bd-light-box-center" : ""} ${!hasContent ? "bd-light-box-no-content" : ""}">
217
+
218
+ <!-- Icon -->
145
219
  <div class="bd-light-box-header-s ${isCentered ? "bd-light-box-header-center" : ""}">
146
220
  ${this._renderIcon()}
147
221
  </div>
222
+
223
+ <!-- Titlu -->
148
224
  ${this.title
149
225
  ? html`
150
226
  <div class="bd-light-title-badge-wrapper-s ${!hasContent ? "bd-light-title-no-content" : ""}">
@@ -152,7 +228,17 @@ class CardItem extends LitElement {
152
228
  </div>
153
229
  `
154
230
  : ""}
155
- <slot></slot>
231
+
232
+ <!-- Content -->
233
+ <div class="bd-card-content-wrapper">
234
+ <slot></slot>
235
+ </div>
236
+
237
+ <!-- CTA Button -->
238
+ <div class="bd-card-cta-wrapper">
239
+ <slot name="cta"></slot>
240
+ </div>
241
+
156
242
  </div>
157
243
  `;
158
244
  }
@@ -1,9 +1,8 @@
1
1
  import { html } from 'lit';
2
+ import '../button/button.js';
2
3
  import '../heading/heading.js';
3
4
  import '../icons/analysis-icon.js';
4
- import '../icons/arrow-down-icon.js';
5
5
  import '../icons/arrow-up-icon.js';
6
- import '../icons/close-icon.js';
7
6
  import '../icons/family-icon.js';
8
7
  import '../icons/globe-icon.js';
9
8
  import '../icons/individual-icon.js';
@@ -20,25 +19,33 @@ export default {
20
19
  component: `
21
20
  **Card** and **CardItem** are Lit components for a static card grid layout.
22
21
 
23
- - \`<bd-card-section>\` — a section wrapper with an optional title and a flex/grid track
24
- - \`<bd-card-item>\` — individual card with optional icon, title, alignment, and slotted content
22
+ - \`<bd-card-section>\` — a section wrapper with an optional title and a grid track
23
+ - \`<bd-card-item>\` — individual card with optional icon, title, alignment, slotted content, and CTA button
25
24
 
26
25
  ### Usage
27
26
  \`\`\`html
28
27
  <bd-card-section title="Why Bitdefender">
29
- <bd-card-item title="AI Protectionn" align="center">
28
+ <bd-card-item title="AI Protection" align="center">
30
29
  <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
31
30
  <bd-p>Powered by machine learning.</bd-p>
32
- <bd-p>Powered by machine learning.</bd-p>
31
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
33
32
  </bd-card-item>
34
33
  </bd-card-section>
35
34
  \`\`\`
36
35
 
37
- ### CardItem Behavior
38
- - If \`align="center"\` applies \`bd-light-box-center\` and \`bd-light-box-header-center\` classes
39
- - If no slotted content (besides icon) — applies \`bd-light-box-no-content\` and \`bd-light-title-no-content\` classes
40
- - Icon is rendered from a \`slot="icon"\` element if present, otherwise falls back to the \`icon\` prop as an image path
41
- - Title uses \`<bd-h as="h4">\` with 10px vertical padding
36
+ ### CardItem Slots
37
+ | Slot | Descriere |
38
+ |---|---|
39
+ | \`icon\` | Iconiță sau imagine (max 120x120px automat) |
40
+ | default | Conținut text — \`bd-p\`, liste, etc. |
41
+ | \`cta\` | Buton CTA jos stânga — \`bd-button-link\` sau \`bd-button\` |
42
+
43
+ ### CardItem Props
44
+ | Prop | Valori | Default |
45
+ |---|---|---|
46
+ | \`title\` | String | \`''\` |
47
+ | \`align\` | \`start\`, \`center\` | \`start\` |
48
+ | \`icon\` | String (path) | \`''\` |
42
49
  `
43
50
  }
44
51
  }
@@ -46,25 +53,23 @@ export default {
46
53
  argTypes: {
47
54
  sectionTitle: {
48
55
  control : 'text',
49
- description: 'Optional title for the card section, rendered as `<h1>`',
56
+ description: 'Optional title for the card section',
50
57
  table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CardSection' }
51
58
  },
52
59
  itemTitle: {
53
60
  control : 'text',
54
- description: 'Title of the card item, rendered using `<bd-h as="h4">`',
61
+ description: 'Title of the card item',
55
62
  table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CardItem' }
56
63
  },
57
64
  align: {
58
65
  control : { type: 'select' },
59
66
  options : ['start', 'center'],
60
- description: 'Alignment of card content. `"center"` applies centering CSS classes.',
67
+ description: 'Alignment of card content.',
61
68
  table : { type: { summary: "'start' | 'center'" }, defaultValue: { summary: 'start' }, category: 'CardItem' }
62
69
  }
63
70
  }
64
71
  };
65
72
 
66
- // ─── Stories ───────────────────────────────────────────────────────────────
67
-
68
73
  export const Default = {
69
74
  name : 'Default (4 items)',
70
75
  render: () => html`
@@ -87,7 +92,65 @@ export const Default = {
87
92
  </bd-card-item>
88
93
  </bd-card-section>
89
94
  `,
90
- parameters: { docs: { description: { story: 'Four card items with icons, titles, and slotted `bd-p` content inside a section with a title.' } } }
95
+ parameters: { docs: { description: { story: 'Four card items with icons, titles, and content.' } } }
96
+ };
97
+
98
+ export const WithCTA = {
99
+ name : 'With CTA Button',
100
+ render: () => html`
101
+ <bd-card-section title="Why Bitdefender">
102
+ <bd-card-item title="AI Protection">
103
+ <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
104
+ <bd-p>Powered by machine learning and behavioral analysis to stop threats before they reach you.</bd-p>
105
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
106
+ </bd-card-item>
107
+ <bd-card-item title="Multi-layer Security">
108
+ <bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
109
+ <bd-p>Multiple independent protection layers stop any attack.</bd-p>
110
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
111
+ </bd-card-item>
112
+ <bd-card-item title="VPN Included">
113
+ <bd-machine-learning-icon slot="icon" width="32" height="32" color="#006DFF"></bd-machine-learning-icon>
114
+ <bd-p>Unlimited encrypted VPN traffic for all your devices, anywhere.</bd-p>
115
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
116
+ </bd-card-item>
117
+ <bd-card-item title="Parental Controls">
118
+ <bd-analysis-icon slot="icon" width="32" height="32" color="#006DFF"></bd-analysis-icon>
119
+ <bd-p>Advanced controls to protect your children online.</bd-p>
120
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
121
+ </bd-card-item>
122
+ </bd-card-section>
123
+ `,
124
+ parameters: { docs: { description: { story: 'Cards with CTA button in the bottom-left via `slot="cta"`.' } } }
125
+ };
126
+
127
+ export const WithCTAUnevenContent = {
128
+ name : 'With CTA — Uneven Content (alignment test)',
129
+ render: () => html`
130
+ <bd-card-section title="Features">
131
+ <bd-card-item title="AI Protection">
132
+ <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
133
+ <bd-p>Powered by machine learning and behavioral analysis to stop threats before they reach you. Our AI engine learns from billions of threat signals every day.</bd-p>
134
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
135
+ </bd-card-item>
136
+ <bd-card-item title="Multi-layer Security — Advanced Protection Suite">
137
+ <bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
138
+ <bd-p>Stop any attack.</bd-p>
139
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
140
+ </bd-card-item>
141
+ <bd-card-item title="VPN">
142
+ <bd-machine-learning-icon slot="icon" width="32" height="32" color="#006DFF"></bd-machine-learning-icon>
143
+ <bd-p>Unlimited encrypted VPN traffic for all your devices, anywhere in the world, at any time.</bd-p>
144
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
145
+ </bd-card-item>
146
+ <bd-card-item title="Parental Controls">
147
+ <bd-analysis-icon slot="icon" width="32" height="32" color="#006DFF"></bd-analysis-icon>
148
+ <bd-p>Advanced controls to protect your children online and monitor their activity.</bd-p>
149
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
150
+ </bd-card-item>
151
+ </bd-card-section>
152
+ `,
153
+ parameters: { docs: { description: { story: 'Cards with uneven title and content lengths — tests row alignment equalization. CTA buttons should always align at the same vertical position.' } } }
91
154
  };
92
155
 
93
156
  export const NoSectionTitle = {
@@ -112,7 +175,7 @@ export const NoSectionTitle = {
112
175
  </bd-card-item>
113
176
  </bd-card-section>
114
177
  `,
115
- parameters: { docs: { description: { story: 'Section without `title` prop — the header div is conditionally omitted.' } } }
178
+ parameters: { docs: { description: { story: 'Section without title prop.' } } }
116
179
  };
117
180
 
118
181
  export const CenteredAlignment = {
@@ -137,7 +200,7 @@ export const CenteredAlignment = {
137
200
  </bd-card-item>
138
201
  </bd-card-section>
139
202
  `,
140
- parameters: { docs: { description: { story: '`align="center"` applied to all items — centers icon, title, and content.' } } }
203
+ parameters: { docs: { description: { story: '`align="center"` applied to all items.' } } }
141
204
  };
142
205
 
143
206
  export const MixedAlignment = {
@@ -154,7 +217,7 @@ export const MixedAlignment = {
154
217
  </bd-card-item>
155
218
  </bd-card-section>
156
219
  `,
157
- parameters: { docs: { description: { story: 'Two items side by side with different alignment values.' } } }
220
+ parameters: { docs: { description: { story: 'Two items with different alignment values.' } } }
158
221
  };
159
222
 
160
223
  export const NoIcon = {
@@ -175,7 +238,7 @@ export const NoIcon = {
175
238
  </bd-card-item>
176
239
  </bd-card-section>
177
240
  `,
178
- parameters: { docs: { description: { story: 'Items without a `slot="icon"` element — the icon wrapper renders empty.' } } }
241
+ parameters: { docs: { description: { story: 'Items without icon.' } } }
179
242
  };
180
243
 
181
244
  export const NoSlottedContent = {
@@ -196,11 +259,11 @@ export const NoSlottedContent = {
196
259
  </bd-card-item>
197
260
  </bd-card-section>
198
261
  `,
199
- parameters: { docs: { description: { story: 'Items with only an icon and title — applies `bd-light-box-no-content` and `bd-light-title-no-content` CSS classes.' } } }
262
+ parameters: { docs: { description: { story: 'Items with only icon and title.' } } }
200
263
  };
201
264
 
202
265
  export const TitleOnly = {
203
- name : 'Title Only (no icon, no content)',
266
+ name : 'Title Only',
204
267
  render: () => html`
205
268
  <bd-card-section title="Features">
206
269
  <bd-card-item title="AI Protection"></bd-card-item>
@@ -208,7 +271,7 @@ export const TitleOnly = {
208
271
  <bd-card-item title="Parental Controls"></bd-card-item>
209
272
  </bd-card-section>
210
273
  `,
211
- parameters: { docs: { description: { story: 'Minimal cards with only a title — no icon, no slotted content.' } } }
274
+ parameters: { docs: { description: { story: 'Minimal cards with only a title.' } } }
212
275
  };
213
276
 
214
277
  export const RichContent = {
@@ -220,15 +283,16 @@ export const RichContent = {
220
283
  <bd-p>Antivirus & Anti-malware</bd-p>
221
284
  <bd-p>VPN (200+ servers)</bd-p>
222
285
  <bd-p>Password Manager</bd-p>
286
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">See all features</bd-button-link>
223
287
  </bd-card-item>
224
288
  <bd-card-item title="Supported Platforms">
225
289
  <bd-arrow-up-icon slot="icon" width="32" height="32" color="#006DFF"></bd-arrow-up-icon>
226
290
  <bd-p>Windows, macOS, Android, iOS</bd-p>
227
- <a href="#">View all platforms</a>
291
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">View all platforms</bd-button-link>
228
292
  </bd-card-item>
229
293
  </bd-card-section>
230
294
  `,
231
- parameters: { docs: { description: { story: 'Rich slotted content using multiple `bd-p` elements and a link.' } } }
295
+ parameters: { docs: { description: { story: 'Rich content with multiple bd-p elements and CTA buttons.' } } }
232
296
  };
233
297
 
234
298
  export const SingleItem = {
@@ -238,12 +302,64 @@ export const SingleItem = {
238
302
  <bd-card-item title="AI Protection">
239
303
  <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
240
304
  <bd-p>Machine learning-powered protection.</bd-p>
305
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
241
306
  </bd-card-item>
242
307
  </bd-card-section>
243
308
  `,
244
- parameters: { docs: { description: { story: 'Edge case: only one card item inside the section.' } } }
309
+ parameters: { docs: { description: { story: 'Edge case: only one card item.' } } }
310
+ };
311
+ export const WithImages = {
312
+ name : 'With Images (large + small)',
313
+ render: () => html`
314
+ <bd-card-section title="Our Products">
315
+ <bd-card-item title="Total Security">
316
+ <img slot="icon" src="/assets/tabs-img1.png" alt="Total Security" />
317
+ <bd-p>Complete protection for all your devices with advanced threat detection and real-time security updates.</bd-p>
318
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
319
+ </bd-card-item>
320
+ <bd-card-item title="Internet Security">
321
+ <img slot="icon" src="/assets/tabs-img2.png" alt="Internet Security" />
322
+ <bd-p>Stay safe online.</bd-p>
323
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
324
+ </bd-card-item>
325
+ <bd-card-item title="Antivirus Plus">
326
+ <img slot="icon" src="/assets/tabs-img3.png" alt="Antivirus Plus" />
327
+ <bd-p>Essential protection for your Windows PC with real-time antivirus and anti-phishing.</bd-p>
328
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
329
+ </bd-card-item>
330
+ </bd-card-section>
331
+ `,
332
+ parameters: { docs: { description: { story: 'Cards with large images via `slot="icon"` — max-width/max-height 120px applied automatically.' } } }
245
333
  };
246
334
 
335
+ export const MixedIconsAndImages = {
336
+ name : 'Mixed — Icons and Images',
337
+ render: () => html`
338
+ <bd-card-section title="Mixed Media">
339
+ <bd-card-item title="AI Protection">
340
+ <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
341
+ <bd-p>Powered by machine learning and behavioral analysis.</bd-p>
342
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
343
+ </bd-card-item>
344
+ <bd-card-item title="Total Security">
345
+ <img slot="icon" src="/assets/tabs-img1.png" alt="Total Security" />
346
+ <bd-p>Complete protection for all your devices.</bd-p>
347
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
348
+ </bd-card-item>
349
+ <bd-card-item title="VPN Included">
350
+ <bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
351
+ <bd-p>Unlimited encrypted VPN traffic for all your devices, anywhere.</bd-p>
352
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
353
+ </bd-card-item>
354
+ <bd-card-item title="Internet Security">
355
+ <img slot="icon" src="/assets/tabs-img2.png" alt="Internet Security" />
356
+ <bd-p>Stay safe online with advanced threat detection.</bd-p>
357
+ <bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
358
+ </bd-card-item>
359
+ </bd-card-section>
360
+ `,
361
+ parameters: { docs: { description: { story: 'Mix of SVG icons and large images in the same grid — tests consistent icon row height equalization.' } } }
362
+ };
247
363
  export const Playground = {
248
364
  name: '🛝 Playground',
249
365
  args: {
@@ -256,12 +372,14 @@ export const Playground = {
256
372
  <bd-card-item title="${args.itemTitle}" align="${args.align}">
257
373
  <bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
258
374
  <bd-p>Powered by machine learning and behavioral analysis.</bd-p>
375
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
259
376
  </bd-card-item>
260
377
  <bd-card-item title="VPN Included" align="${args.align}">
261
378
  <bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
262
379
  <bd-p>Unlimited encrypted VPN traffic.</bd-p>
380
+ <bd-button-link slot="cta" href="#" kind="primary" size="sm">Learn more</bd-button-link>
263
381
  </bd-card-item>
264
382
  </bd-card-section>
265
383
  `,
266
- parameters: { docs: { description: { story: 'Interactive playground. Adjust section title, item title, and alignment via Controls.' } } }
384
+ parameters: { docs: { description: { story: 'Interactive playground.' } } }
267
385
  };