@repobit/dex-system-design 0.23.64 → 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,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.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
+
6
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)
7
15
 
8
16
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobit/dex-system-design",
3
- "version": "0.23.64",
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.60",
74
- "@repobit/dex-store-elements": "1.4.52",
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": "d2ffeffa127085b7c0af844f9965b13afdfd7bd8"
91
+ "gitHead": "798ae4c67c57d8932da4962aea6c451315865638"
92
92
  }
@@ -12,9 +12,12 @@ export default css`
12
12
  }
13
13
 
14
14
  ::slotted([slot="icon"]) {
15
- width: 48px !important;
16
- height: 48px !important;
17
- 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;
18
21
  }
19
22
 
20
23
  .bd-section-title-s {
@@ -35,8 +38,6 @@ export default css`
35
38
  position: relative;
36
39
  width: 100%;
37
40
  flex-direction: column;
38
- padding-left: var(--spacing-14);
39
- padding-right: var(--spacing-14);
40
41
  max-width: 1400px;
41
42
  margin: 0 auto;
42
43
  }
@@ -64,7 +65,6 @@ export default css`
64
65
  scroll-snap-type: x mandatory;
65
66
  display: grid;
66
67
  gap: 1.5rem;
67
- /* grid-template-columns vine din JS */
68
68
  }
69
69
 
70
70
  .bd-light-carousel-track-s::-webkit-scrollbar {
@@ -72,13 +72,12 @@ export default css`
72
72
  }
73
73
 
74
74
  .bd-light-box-s {
75
- flex: var(--spacing-0) var(--spacing-0) auto;
76
75
  background: var(--background-card-grey);
77
76
  border-radius: var(--spacing-20);
78
77
  padding: var(--spacing-32);
79
78
  display: flex;
80
79
  flex-direction: column;
81
- align-items: start;
80
+ align-items: flex-start;
82
81
  justify-content: flex-start;
83
82
  text-align: start;
84
83
  transition: transform 0.2s ease-in-out;
@@ -132,30 +131,32 @@ export default css`
132
131
  text-align: center !important;
133
132
  }
134
133
 
135
- .bd-light-icon-s {
136
- position: relative;
137
- max-width: 100%;
138
- height: var(--spacing-44);
139
- width: var(--spacing-44);
140
- }
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
+ }
141
142
 
142
143
  .bd-light-box-no-content .bd-light-icon-s {
143
144
  margin: 0 !important;
144
- bottom: 0;
145
145
  }
146
146
 
147
147
  .bd-light-box-header-s {
148
148
  display: flex;
149
149
  flex-direction: column;
150
150
  align-items: flex-start;
151
+ justify-content: flex-start;
151
152
  gap: var(--spacing-8);
152
153
  padding-bottom: var(--spacing-8);
153
- left: -5px;
154
154
  position: relative;
155
155
  }
156
156
 
157
157
  .bd-light-box-no-content .bd-light-box-header-s {
158
158
  align-items: center !important;
159
+ justify-content: center !important;
159
160
  margin: 0 !important;
160
161
  }
161
162
 
@@ -166,8 +167,9 @@ export default css`
166
167
 
167
168
  .bd-light-title-badge-wrapper-s {
168
169
  display: flex;
169
- align-items: center;
170
+ align-items: flex-start;
170
171
  gap: var(--spacing-4, 4px);
172
+ overflow: hidden;
171
173
  }
172
174
 
173
175
  .bd-light-title-no-content {
@@ -176,9 +178,26 @@ export default css`
176
178
  justify-content: center;
177
179
  }
178
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
+
179
199
  @media (max-width: 1024px) {
180
200
  .bd-light-box-s {
181
- width: 380px;
182
201
  padding: 1.5em;
183
202
  }
184
203
 
@@ -229,10 +248,6 @@ export default css`
229
248
  .bd-light-box-s p {
230
249
  font-size: 0.9em;
231
250
  }
232
-
233
- .bd-light-icon-s {
234
- bottom: var(--spacing-10);
235
- }
236
251
  }
237
252
 
238
253
  @media (max-width: 600px) {
@@ -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
 
@@ -116,15 +175,22 @@ class CardItem extends LitElement {
116
175
  const iconEl = this.querySelector("[slot='icon']");
117
176
 
118
177
  if (iconEl) {
119
- 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;
120
186
  }
121
187
 
122
188
  if (this.icon) {
123
189
  return html`<img
124
- src="${this.icon}"
125
- alt="icon"
126
- class="bd-light-icon-s"
127
- />`;
190
+ src="${this.icon}"
191
+ alt="icon"
192
+ class="bd-light-icon-s"
193
+ />`;
128
194
  }
129
195
 
130
196
  return "";
@@ -133,7 +199,8 @@ class CardItem extends LitElement {
133
199
  _hasContent() {
134
200
  const slottedNodes = [...this.childNodes].filter((node) => {
135
201
  if (node.nodeType === Node.ELEMENT_NODE) {
136
- return node.getAttribute("slot") !== "icon";
202
+ const slot = node.getAttribute("slot");
203
+ return slot !== "icon" && slot !== "cta";
137
204
  }
138
205
  return node.nodeType === Node.TEXT_NODE && node.textContent.trim() !== "";
139
206
  });
@@ -147,9 +214,13 @@ class CardItem extends LitElement {
147
214
 
148
215
  return html`
149
216
  <div class="bd-light-box-s ${isCentered ? "bd-light-box-center" : ""} ${!hasContent ? "bd-light-box-no-content" : ""}">
217
+
218
+ <!-- Icon -->
150
219
  <div class="bd-light-box-header-s ${isCentered ? "bd-light-box-header-center" : ""}">
151
220
  ${this._renderIcon()}
152
221
  </div>
222
+
223
+ <!-- Titlu -->
153
224
  ${this.title
154
225
  ? html`
155
226
  <div class="bd-light-title-badge-wrapper-s ${!hasContent ? "bd-light-title-no-content" : ""}">
@@ -157,7 +228,17 @@ class CardItem extends LitElement {
157
228
  </div>
158
229
  `
159
230
  : ""}
160
- <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
+
161
242
  </div>
162
243
  `;
163
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
  };