@repobit/dex-system-design 0.23.74 → 0.23.76
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 +14 -0
- package/package.json +4 -4
- package/src/components/Button/Button.js +10 -4
- package/src/components/Button/button.css.js +43 -12
- package/src/components/Button/button.stories.js +116 -12
- package/src/components/cards/card.css.js +44 -23
- package/src/components/cards/card.js +32 -14
- package/src/components/cards/card.stories.js +86 -26
- package/src/components/features-tab/features-tab.js +1 -1
- package/src/components/features-tab/features-tab.stories.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
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.76](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.75...@repobit/dex-system-design@0.23.76) (2026-07-13)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **DEX-1014:** card adjustments
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [0.23.75](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.74...@repobit/dex-system-design@0.23.75) (2026-07-13)
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **DEX-1014:** card buttons alignment and button adjustments
|
|
18
|
+
|
|
19
|
+
|
|
6
20
|
## [0.23.74](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.23.73...@repobit/dex-system-design@0.23.74) (2026-07-10)
|
|
7
21
|
|
|
8
22
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@repobit/dex-system-design",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.76",
|
|
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.3.
|
|
78
|
-
"@repobit/dex-store-elements": "1.4.
|
|
77
|
+
"@repobit/dex-store": "1.3.72",
|
|
78
|
+
"@repobit/dex-store-elements": "1.4.64",
|
|
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": "
|
|
95
|
+
"gitHead": "393438b117548f2f4a3cc6541b6f3557dae3af28"
|
|
96
96
|
}
|
|
@@ -12,7 +12,8 @@ class Button extends LitElement {
|
|
|
12
12
|
fullWidth : { type: Boolean },
|
|
13
13
|
strong : { type: Boolean },
|
|
14
14
|
fontSize : { type: String, attribute: "font-size" },
|
|
15
|
-
fontWeight : { type: String, attribute: "font-weight" }
|
|
15
|
+
fontWeight : { type: String, attribute: "font-weight" },
|
|
16
|
+
align : { type: String }
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
constructor() {
|
|
@@ -22,6 +23,7 @@ class Button extends LitElement {
|
|
|
22
23
|
this.size = "md";
|
|
23
24
|
this.fontSize = "";
|
|
24
25
|
this.fontWeight = "";
|
|
26
|
+
this.align = "left";
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
_onFocusin(e) {
|
|
@@ -112,7 +114,8 @@ class ButtonLink extends LitElement {
|
|
|
112
114
|
fontSize : { type: String, attribute: "font-size" },
|
|
113
115
|
fontWeight : { type: String, attribute: "font-weight" },
|
|
114
116
|
buyLink : { type: Boolean },
|
|
115
|
-
shadow : { type: Boolean, reflect: true }
|
|
117
|
+
shadow : { type: Boolean, reflect: true },
|
|
118
|
+
align : { type: String }
|
|
116
119
|
};
|
|
117
120
|
|
|
118
121
|
constructor() {
|
|
@@ -127,6 +130,7 @@ class ButtonLink extends LitElement {
|
|
|
127
130
|
this.fontWeight = "";
|
|
128
131
|
this.buyLink = false;
|
|
129
132
|
this.shadow = true;
|
|
133
|
+
this.align = "left";
|
|
130
134
|
}
|
|
131
135
|
|
|
132
136
|
_onFocusin(e) {
|
|
@@ -211,13 +215,15 @@ class ButtonLink extends LitElement {
|
|
|
211
215
|
class ContactButton extends LitElement {
|
|
212
216
|
static properties = {
|
|
213
217
|
label: { type: String },
|
|
214
|
-
href : { type: String }
|
|
218
|
+
href : { type: String },
|
|
219
|
+
align: { type: String }
|
|
215
220
|
};
|
|
216
221
|
|
|
217
222
|
constructor() {
|
|
218
223
|
super();
|
|
219
224
|
this.label = "Contact us";
|
|
220
225
|
this.href = "https://www.google.com";
|
|
226
|
+
this.align = "left";
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
_onFocusin(e) {
|
|
@@ -266,4 +272,4 @@ ContactButton.styles = [tokens, buttonsCSS];
|
|
|
266
272
|
|
|
267
273
|
customElements.define("bd-button", Button);
|
|
268
274
|
customElements.define("bd-button-link", ButtonLink);
|
|
269
|
-
customElements.define("bd-contact-button", ContactButton);
|
|
275
|
+
customElements.define("bd-contact-button", ContactButton);
|
|
@@ -29,16 +29,43 @@ export default css`
|
|
|
29
29
|
--bd-accesibility-focus: var(--color-blue-500);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
/* ============================================
|
|
33
|
+
ALIGNMENT SUPPORT
|
|
34
|
+
============================================ */
|
|
35
|
+
|
|
36
|
+
:host([align="center"]) {
|
|
37
|
+
display: flex;
|
|
38
|
+
justify-content: center;
|
|
39
|
+
width: 100%;
|
|
40
|
+
}
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
:host([align="right"]) {
|
|
43
|
+
display: flex;
|
|
44
|
+
justify-content: flex-end;
|
|
45
|
+
width: 100%;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
:host([align="left"]) {
|
|
49
|
+
display: inline-flex;
|
|
50
|
+
justify-content: flex-start;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:host([fullwidth]) {
|
|
54
|
+
display: block;
|
|
55
|
+
width: 100%;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
:host([align="center"][fullwidth]) .button,
|
|
59
|
+
:host([align="right"][fullwidth]) .button {
|
|
60
|
+
width: 100%;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.max--width {
|
|
64
|
+
width: 100%;
|
|
65
|
+
display: flex;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:host([data-bd-button-focus]) {
|
|
42
69
|
outline: var(--spacing-2) solid var(--bd-accesibility-focus);
|
|
43
70
|
outline-offset: var(--spacing-2);
|
|
44
71
|
border-radius: var(--radius-md);
|
|
@@ -55,6 +82,7 @@ export default css`
|
|
|
55
82
|
a.button {
|
|
56
83
|
text-decoration: none;
|
|
57
84
|
}
|
|
85
|
+
|
|
58
86
|
.button,
|
|
59
87
|
.bd-contact-btn {
|
|
60
88
|
display: inline-flex;
|
|
@@ -119,23 +147,28 @@ export default css`
|
|
|
119
147
|
border: var(--border-width-2) solid var(--border-button-background-outline);
|
|
120
148
|
color: var(--color-button-background-outline);
|
|
121
149
|
}
|
|
150
|
+
|
|
122
151
|
.button--outline:hover {
|
|
123
152
|
background-color: var(--button-background-outline-hover);
|
|
124
153
|
border: var(--border-width-2) solid var(--border-button-background-outline-hover);
|
|
125
154
|
}
|
|
155
|
+
|
|
126
156
|
.button--outline:active {
|
|
127
157
|
background-color: var(--button-background-outline-focus);
|
|
128
158
|
color: var(--color-neutral-0);
|
|
129
159
|
}
|
|
160
|
+
|
|
130
161
|
.button--primary--outline {
|
|
131
162
|
background-color: transparent;
|
|
132
163
|
border: var(--border-width-2) solid var(--border-button-background-primary-outline);
|
|
133
164
|
color: var(--color-button-background-primary-outline);
|
|
134
165
|
}
|
|
166
|
+
|
|
135
167
|
.button--primary--outline:hover {
|
|
136
168
|
background-color: var(--button-background-primary-outline-hover);
|
|
137
169
|
border: var(--border-width-2) solid var(--border-button-background-primary-outline-hover);
|
|
138
170
|
}
|
|
171
|
+
|
|
139
172
|
.button--primary--outline:active {
|
|
140
173
|
background-color: var(--button-background-primary-outline-focus);
|
|
141
174
|
color: var(--color-neutral-0);
|
|
@@ -175,8 +208,6 @@ export default css`
|
|
|
175
208
|
font-weight: var(--typography-fontWeight-semibold);
|
|
176
209
|
}
|
|
177
210
|
|
|
178
|
-
|
|
179
|
-
/* Asigură-te că slot-ul ocupă întreg spațiul */
|
|
180
211
|
.button > ::slotted(*) {
|
|
181
212
|
display: inline-block;
|
|
182
213
|
width: 100%;
|
|
@@ -188,4 +219,4 @@ export default css`
|
|
|
188
219
|
transition: none !important;
|
|
189
220
|
}
|
|
190
221
|
}
|
|
191
|
-
`;
|
|
222
|
+
`;
|
|
@@ -37,6 +37,13 @@ Three button components are available:
|
|
|
37
37
|
| \`md\` | \`button--medium\` |
|
|
38
38
|
| \`lg\` | \`button--large\` |
|
|
39
39
|
|
|
40
|
+
### Alignment Values
|
|
41
|
+
| Align | Effect |
|
|
42
|
+
|---|---|
|
|
43
|
+
| \`left\` | Aligns button to the left (default) |
|
|
44
|
+
| \`center\` | Centers button horizontally |
|
|
45
|
+
| \`right\` | Aligns button to the right |
|
|
46
|
+
|
|
40
47
|
### Events
|
|
41
48
|
- \`custom-click\` — dispatched on click or Enter/Space keypress
|
|
42
49
|
`
|
|
@@ -71,6 +78,12 @@ Three button components are available:
|
|
|
71
78
|
description: 'Applies bold font weight via `button--bold` class',
|
|
72
79
|
table : { type: { summary: 'boolean' }, defaultValue: { summary: 'false' }, category: 'Appearance' }
|
|
73
80
|
},
|
|
81
|
+
align: {
|
|
82
|
+
control : { type: 'select' },
|
|
83
|
+
options : ['left', 'center', 'right'],
|
|
84
|
+
description: 'Horizontal alignment of the button',
|
|
85
|
+
table : { type: { summary: "'left' | 'center' | 'right'" }, defaultValue: { summary: 'left' }, category: 'Layout' }
|
|
86
|
+
},
|
|
74
87
|
fontSize: {
|
|
75
88
|
control : 'text',
|
|
76
89
|
description: 'Inline font-size override (e.g. "18px")',
|
|
@@ -100,8 +113,14 @@ Three button components are available:
|
|
|
100
113
|
};
|
|
101
114
|
|
|
102
115
|
const defaultArgs = {
|
|
103
|
-
label : 'Buy now',
|
|
104
|
-
|
|
116
|
+
label : 'Buy now',
|
|
117
|
+
kind : 'primary',
|
|
118
|
+
size : 'md',
|
|
119
|
+
fullWidth : false,
|
|
120
|
+
strong : false,
|
|
121
|
+
align : 'left',
|
|
122
|
+
fontSize : '',
|
|
123
|
+
fontWeight: ''
|
|
105
124
|
};
|
|
106
125
|
|
|
107
126
|
// ─── bd-button Stories ─────────────────────────────────────────────────────
|
|
@@ -159,6 +178,44 @@ export const ButtonStrong = {
|
|
|
159
178
|
parameters: { docs: { description: { story: 'Comparison between normal and `strong` (bold) button.' } } }
|
|
160
179
|
};
|
|
161
180
|
|
|
181
|
+
export const ButtonAlignCenter = {
|
|
182
|
+
name : 'Button — Align Center',
|
|
183
|
+
render: () => html`
|
|
184
|
+
<div style="width:100%;">
|
|
185
|
+
<bd-button kind="primary" size="md" align="center">Centered Button</bd-button>
|
|
186
|
+
</div>
|
|
187
|
+
`,
|
|
188
|
+
parameters: { docs: { description: { story: 'Button centered horizontally using `align="center"`.' } } }
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const ButtonAlignRight = {
|
|
192
|
+
name : 'Button — Align Right',
|
|
193
|
+
render: () => html`
|
|
194
|
+
<div style="width:100%;">
|
|
195
|
+
<bd-button kind="danger" size="md" align="right">Right Aligned Button</bd-button>
|
|
196
|
+
</div>
|
|
197
|
+
`,
|
|
198
|
+
parameters: { docs: { description: { story: 'Button aligned to the right using `align="right"`.' } } }
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
export const ButtonAllAlignments = {
|
|
202
|
+
name : 'Button — All Alignments',
|
|
203
|
+
render: () => html`
|
|
204
|
+
<div style="width:100%; max-width:600px; display:flex; flex-direction:column; gap:16px;">
|
|
205
|
+
<div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
|
|
206
|
+
<bd-button kind="primary" size="md" align="left">Left (default)</bd-button>
|
|
207
|
+
</div>
|
|
208
|
+
<div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
|
|
209
|
+
<bd-button kind="primary" size="md" align="center">Center</bd-button>
|
|
210
|
+
</div>
|
|
211
|
+
<div style="border:1px dashed #ccc; padding:12px; border-radius:4px;">
|
|
212
|
+
<bd-button kind="primary" size="md" align="right">Right</bd-button>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
`,
|
|
216
|
+
parameters: { docs: { description: { story: 'All three alignment variants side by side for comparison.' } } }
|
|
217
|
+
};
|
|
218
|
+
|
|
162
219
|
export const ButtonCustomTypography = {
|
|
163
220
|
name : 'Button — Custom Font Size & Weight',
|
|
164
221
|
render: () => html`
|
|
@@ -236,6 +293,30 @@ export const ButtonLinkFullWidth = {
|
|
|
236
293
|
parameters: { docs: { description: { story: 'Full-width `bd-button-link`.' } } }
|
|
237
294
|
};
|
|
238
295
|
|
|
296
|
+
export const ButtonLinkAlignCenter = {
|
|
297
|
+
name : 'ButtonLink — Align Center',
|
|
298
|
+
render: () => html`
|
|
299
|
+
<div style="width:100%;">
|
|
300
|
+
<bd-button-link kind="primary" size="md" href="#" align="center">
|
|
301
|
+
Centered Link Button
|
|
302
|
+
</bd-button-link>
|
|
303
|
+
</div>
|
|
304
|
+
`,
|
|
305
|
+
parameters: { docs: { description: { story: 'ButtonLink centered horizontally using `align="center"`.' } } }
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const ButtonLinkAlignRight = {
|
|
309
|
+
name : 'ButtonLink — Align Right',
|
|
310
|
+
render: () => html`
|
|
311
|
+
<div style="width:100%;">
|
|
312
|
+
<bd-button-link kind="danger" size="md" href="#" align="right">
|
|
313
|
+
Right Aligned Link Button
|
|
314
|
+
</bd-button-link>
|
|
315
|
+
</div>
|
|
316
|
+
`,
|
|
317
|
+
parameters: { docs: { description: { story: 'ButtonLink aligned to the right using `align="right"`.' } } }
|
|
318
|
+
};
|
|
319
|
+
|
|
239
320
|
export const ButtonLinkCustomTypography = {
|
|
240
321
|
name : 'ButtonLink — Custom Typography',
|
|
241
322
|
render: () => html`
|
|
@@ -272,6 +353,26 @@ export const ContactButtonCustomHref = {
|
|
|
272
353
|
parameters: { docs: { description: { story: 'Contact button linking to an external support URL.' } } }
|
|
273
354
|
};
|
|
274
355
|
|
|
356
|
+
export const ContactButtonAlignCenter = {
|
|
357
|
+
name : 'ContactButton — Align Center',
|
|
358
|
+
render: () => html`
|
|
359
|
+
<div style="width:100%;">
|
|
360
|
+
<bd-contact-button label="Contact us" href="#" align="center"></bd-contact-button>
|
|
361
|
+
</div>
|
|
362
|
+
`,
|
|
363
|
+
parameters: { docs: { description: { story: 'Contact button centered horizontally using `align="center"`.' } } }
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
export const ContactButtonAlignRight = {
|
|
367
|
+
name : 'ContactButton — Align Right',
|
|
368
|
+
render: () => html`
|
|
369
|
+
<div style="width:100%;">
|
|
370
|
+
<bd-contact-button label="Contact us" href="#" align="right"></bd-contact-button>
|
|
371
|
+
</div>
|
|
372
|
+
`,
|
|
373
|
+
parameters: { docs: { description: { story: 'Contact button aligned to the right using `align="right"`.' } } }
|
|
374
|
+
};
|
|
375
|
+
|
|
275
376
|
// ─── Combined Story ────────────────────────────────────────────────────────
|
|
276
377
|
|
|
277
378
|
export const AllButtonTypes = {
|
|
@@ -290,15 +391,18 @@ export const Playground = {
|
|
|
290
391
|
name : '🛝 Playground',
|
|
291
392
|
args : { ...defaultArgs },
|
|
292
393
|
render: (args) => html`
|
|
293
|
-
<
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
394
|
+
<div style="width:100%;">
|
|
395
|
+
<bd-button
|
|
396
|
+
kind="${args.kind}"
|
|
397
|
+
size="${args.size}"
|
|
398
|
+
label="${args.label}"
|
|
399
|
+
align="${args.align}"
|
|
400
|
+
?full-width="${args.fullWidth}"
|
|
401
|
+
?strong="${args.strong}"
|
|
402
|
+
font-size="${args.fontSize}"
|
|
403
|
+
font-weight="${args.fontWeight}"
|
|
404
|
+
>${args.label}</bd-button>
|
|
405
|
+
</div>
|
|
302
406
|
`,
|
|
303
|
-
parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props.' } } }
|
|
407
|
+
parameters: { docs: { description: { story: 'Interactive playground for `bd-button`. Use Controls to adjust all props including alignment.' } } }
|
|
304
408
|
};
|
|
@@ -7,27 +7,41 @@ export default css`
|
|
|
7
7
|
--border-card-grey: var(--color-neutral-50);
|
|
8
8
|
max-width: 1290px;
|
|
9
9
|
margin: 0 auto;
|
|
10
|
+
padding-top: var(--spacing-64);
|
|
11
|
+
padding-bottom: var(--spacing-64);
|
|
12
|
+
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
::slotted([slot="icon"]) {
|
|
13
16
|
max-width: 120px !important;
|
|
14
17
|
max-height: 120px !important;
|
|
15
|
-
width: auto !important;
|
|
16
|
-
height: auto !important;
|
|
17
18
|
object-fit: contain !important;
|
|
18
19
|
display: block !important;
|
|
19
|
-
border-radius: var(--spacing-20);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
.bd-section-title-s {
|
|
23
23
|
font-family: var(--typography-fontFamily-sans);
|
|
24
24
|
font-weight: var(--typography-fontWeight-semibold);
|
|
25
25
|
font-size: 2em;
|
|
26
|
+
text-align: center;
|
|
27
|
+
margin: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.bd-section-subtitle-s {
|
|
31
|
+
font-family: var(--typography-fontFamily-sans);
|
|
32
|
+
font-size: var(--typography-body-regular-fontSize);
|
|
33
|
+
color: var(--color-neutral-700);
|
|
34
|
+
text-align: center;
|
|
35
|
+
margin: var(--spacing-8) 0 0 0;
|
|
26
36
|
}
|
|
27
37
|
|
|
28
38
|
.bd-header-light-carousel-s {
|
|
29
|
-
margin-bottom:
|
|
30
|
-
margin-top:
|
|
39
|
+
margin-bottom: var(--spacing-48);
|
|
40
|
+
margin-top: var(--spacing-48);
|
|
41
|
+
display: flex;
|
|
42
|
+
flex-direction: column;
|
|
43
|
+
align-items: center;
|
|
44
|
+
gap: var(--spacing-8);
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
.bd-light-carousel-s {
|
|
@@ -41,16 +55,6 @@ export default css`
|
|
|
41
55
|
margin: 0 auto;
|
|
42
56
|
}
|
|
43
57
|
|
|
44
|
-
.bd-light-carousel-title-s {
|
|
45
|
-
font-size: 28px;
|
|
46
|
-
font-weight: 700;
|
|
47
|
-
text-align: center;
|
|
48
|
-
color: #e4002b;
|
|
49
|
-
margin-bottom: 32px;
|
|
50
|
-
text-transform: uppercase;
|
|
51
|
-
letter-spacing: 0.5px;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
58
|
.bd-light-carousel-track-s {
|
|
55
59
|
scroll-behavior: smooth;
|
|
56
60
|
flex: 1;
|
|
@@ -130,14 +134,14 @@ export default css`
|
|
|
130
134
|
text-align: center !important;
|
|
131
135
|
}
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
137
|
+
.bd-light-icon-s {
|
|
138
|
+
max-width: 120px;
|
|
139
|
+
max-height: 120px;
|
|
140
|
+
width: auto;
|
|
141
|
+
height: auto;
|
|
142
|
+
object-fit: contain;
|
|
143
|
+
display: block;
|
|
144
|
+
}
|
|
141
145
|
|
|
142
146
|
.bd-light-box-no-content .bd-light-icon-s {
|
|
143
147
|
margin: 0 !important;
|
|
@@ -170,6 +174,22 @@ export default css`
|
|
|
170
174
|
gap: var(--spacing-4, 4px);
|
|
171
175
|
overflow: hidden;
|
|
172
176
|
margin-bottom: var(--spacing-8);
|
|
177
|
+
width: 100%;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.bd-card-title-group {
|
|
181
|
+
display: flex;
|
|
182
|
+
flex-direction: column;
|
|
183
|
+
gap: var(--spacing-4);
|
|
184
|
+
width: 100%;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.bd-card-item-subtitle {
|
|
188
|
+
font-family: var(--typography-fontFamily-sans);
|
|
189
|
+
font-size: var(--typography-fontSize-sm);
|
|
190
|
+
color: var(--color-neutral-600);
|
|
191
|
+
margin: 0;
|
|
192
|
+
line-height: var(--typography-lineHeight-normal);
|
|
173
193
|
}
|
|
174
194
|
|
|
175
195
|
.bd-light-title-no-content {
|
|
@@ -190,6 +210,7 @@ export default css`
|
|
|
190
210
|
padding-top: var(--spacing-8);
|
|
191
211
|
display: flex;
|
|
192
212
|
align-items: flex-start;
|
|
213
|
+
width: 100%;
|
|
193
214
|
}
|
|
194
215
|
|
|
195
216
|
.bd-card-cta-wrapper:empty {
|
|
@@ -7,12 +7,14 @@ import carouselCSS from "./card.css.js";
|
|
|
7
7
|
class Card extends LitElement {
|
|
8
8
|
static properties = {
|
|
9
9
|
title : { type: String },
|
|
10
|
+
subtitle : { type: String },
|
|
10
11
|
_itemCount: { state: true }
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
constructor() {
|
|
14
15
|
super();
|
|
15
16
|
this.title = "";
|
|
17
|
+
this.subtitle = "";
|
|
16
18
|
this._itemCount = 0;
|
|
17
19
|
this._resizeObserver = null;
|
|
18
20
|
}
|
|
@@ -144,13 +146,18 @@ class Card extends LitElement {
|
|
|
144
146
|
render() {
|
|
145
147
|
return html`
|
|
146
148
|
<section class="bd-light-carousel-s">
|
|
147
|
-
${this.title
|
|
149
|
+
${this.title || this.subtitle
|
|
148
150
|
? html`
|
|
149
151
|
<div class="bd-header-light-carousel-s">
|
|
150
|
-
|
|
152
|
+
${this.title
|
|
153
|
+
? html`<bd-h as="h1" class="bd-section-title-s">${this.title}</bd-h>`
|
|
154
|
+
: ""}
|
|
155
|
+
${this.subtitle
|
|
156
|
+
? html`<p class="bd-section-subtitle-s">${this.subtitle}</p>`
|
|
157
|
+
: ""}
|
|
151
158
|
</div>
|
|
152
159
|
`
|
|
153
|
-
:
|
|
160
|
+
: ""}
|
|
154
161
|
<div
|
|
155
162
|
class="bd-light-carousel-track-s"
|
|
156
163
|
style="grid-template-columns: repeat(${this._itemCount || 1}, 1fr);"
|
|
@@ -164,16 +171,18 @@ class Card extends LitElement {
|
|
|
164
171
|
|
|
165
172
|
class CardItem extends LitElement {
|
|
166
173
|
static properties = {
|
|
167
|
-
title: { type: String },
|
|
168
|
-
icon
|
|
169
|
-
align: { type: String }
|
|
174
|
+
title : { type: String },
|
|
175
|
+
icon : { type: String },
|
|
176
|
+
align : { type: String },
|
|
177
|
+
ctaAlign: { type: String, attribute: "cta-align" }
|
|
170
178
|
};
|
|
171
179
|
|
|
172
180
|
constructor() {
|
|
173
181
|
super();
|
|
174
|
-
this.title
|
|
175
|
-
this.icon
|
|
176
|
-
this.align
|
|
182
|
+
this.title = "";
|
|
183
|
+
this.icon = "";
|
|
184
|
+
this.align = "start";
|
|
185
|
+
this.ctaAlign = "start";
|
|
177
186
|
}
|
|
178
187
|
|
|
179
188
|
_renderIcon() {
|
|
@@ -211,10 +220,10 @@ class CardItem extends LitElement {
|
|
|
211
220
|
|
|
212
221
|
if (this.icon) {
|
|
213
222
|
return html`<img
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
223
|
+
src="${this.icon}"
|
|
224
|
+
alt="icon"
|
|
225
|
+
class="bd-light-icon-s"
|
|
226
|
+
/>`;
|
|
218
227
|
}
|
|
219
228
|
|
|
220
229
|
return "";
|
|
@@ -235,14 +244,21 @@ class CardItem extends LitElement {
|
|
|
235
244
|
render() {
|
|
236
245
|
const isCentered = this.align === "center";
|
|
237
246
|
const hasContent = this._hasContent();
|
|
247
|
+
const ctaJustify = this.ctaAlign === "center"
|
|
248
|
+
? "justify-content: center;"
|
|
249
|
+
: this.ctaAlign === "end"
|
|
250
|
+
? "justify-content: flex-end;"
|
|
251
|
+
: "justify-content: flex-start;";
|
|
238
252
|
|
|
239
253
|
return html`
|
|
240
254
|
<div class="bd-light-box-s ${isCentered ? "bd-light-box-center" : ""} ${!hasContent ? "bd-light-box-no-content" : ""}">
|
|
241
255
|
|
|
256
|
+
<!-- Icon -->
|
|
242
257
|
<div class="bd-light-box-header-s ${isCentered ? "bd-light-box-header-center" : ""}">
|
|
243
258
|
${this._renderIcon()}
|
|
244
259
|
</div>
|
|
245
260
|
|
|
261
|
+
<!-- Title -->
|
|
246
262
|
${this.title
|
|
247
263
|
? html`
|
|
248
264
|
<div class="bd-light-title-badge-wrapper-s ${!hasContent ? "bd-light-title-no-content" : ""}">
|
|
@@ -251,11 +267,13 @@ class CardItem extends LitElement {
|
|
|
251
267
|
`
|
|
252
268
|
: ""}
|
|
253
269
|
|
|
270
|
+
<!-- Content -->
|
|
254
271
|
<div class="bd-card-content-wrapper">
|
|
255
272
|
<slot></slot>
|
|
256
273
|
</div>
|
|
257
274
|
|
|
258
|
-
|
|
275
|
+
<!-- CTA Button -->
|
|
276
|
+
<div class="bd-card-cta-wrapper" style="${ctaJustify}">
|
|
259
277
|
<slot name="cta"></slot>
|
|
260
278
|
</div>
|
|
261
279
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { html } from 'lit';
|
|
2
|
-
import '../
|
|
2
|
+
import '../Button/Button.js';
|
|
3
3
|
import '../heading/heading.js';
|
|
4
4
|
import '../icons/analysis-icon.js';
|
|
5
5
|
import '../icons/arrow-up-icon.js';
|
|
@@ -19,12 +19,12 @@ export default {
|
|
|
19
19
|
component: `
|
|
20
20
|
**Card** and **CardItem** are Lit components for a static card grid layout.
|
|
21
21
|
|
|
22
|
-
- \`<bd-card-section>\` — a section wrapper with an optional title and
|
|
22
|
+
- \`<bd-card-section>\` — a section wrapper with an optional title and subtitle for the section
|
|
23
23
|
- \`<bd-card-item>\` — individual card with optional icon, title, alignment, slotted content, and CTA button
|
|
24
24
|
|
|
25
25
|
### Usage
|
|
26
26
|
\`\`\`html
|
|
27
|
-
<bd-card-section title="Why Bitdefender">
|
|
27
|
+
<bd-card-section title="Why Bitdefender" subtitle="Discover the benefits">
|
|
28
28
|
<bd-card-item title="AI Protection" align="center">
|
|
29
29
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
30
30
|
<bd-p>Powered by machine learning.</bd-p>
|
|
@@ -33,12 +33,11 @@ export default {
|
|
|
33
33
|
</bd-card-section>
|
|
34
34
|
\`\`\`
|
|
35
35
|
|
|
36
|
-
###
|
|
37
|
-
|
|
|
38
|
-
|
|
39
|
-
| \`
|
|
40
|
-
|
|
|
41
|
-
| \`cta\` | Buton CTA jos stânga — \`bd-button-link\` sau \`bd-button\` |
|
|
36
|
+
### CardSection Props
|
|
37
|
+
| Prop | Valori | Default |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| \`title\` | String | \`''\` |
|
|
40
|
+
| \`subtitle\` | String | \`''\` |
|
|
42
41
|
|
|
43
42
|
### CardItem Props
|
|
44
43
|
| Prop | Valori | Default |
|
|
@@ -46,6 +45,13 @@ export default {
|
|
|
46
45
|
| \`title\` | String | \`''\` |
|
|
47
46
|
| \`align\` | \`start\`, \`center\` | \`start\` |
|
|
48
47
|
| \`icon\` | String (path) | \`''\` |
|
|
48
|
+
|
|
49
|
+
### CardItem Slots
|
|
50
|
+
| Slot | Descriere |
|
|
51
|
+
|---|---|
|
|
52
|
+
| \`icon\` | Iconiță sau imagine (max 120x120px automat) |
|
|
53
|
+
| default | Conținut text — \`bd-p\`, liste, etc. |
|
|
54
|
+
| \`cta\` | Buton CTA jos stânga — \`bd-button-link\` sau \`bd-button\` |
|
|
49
55
|
`
|
|
50
56
|
}
|
|
51
57
|
}
|
|
@@ -56,6 +62,11 @@ export default {
|
|
|
56
62
|
description: 'Optional title for the card section',
|
|
57
63
|
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CardSection' }
|
|
58
64
|
},
|
|
65
|
+
sectionSubtitle: {
|
|
66
|
+
control : 'text',
|
|
67
|
+
description: 'Optional subtitle for the card section (displayed below title)',
|
|
68
|
+
table : { type: { summary: 'string' }, defaultValue: { summary: '' }, category: 'CardSection' }
|
|
69
|
+
},
|
|
59
70
|
itemTitle: {
|
|
60
71
|
control : 'text',
|
|
61
72
|
description: 'Title of the card item',
|
|
@@ -95,10 +106,56 @@ export const Default = {
|
|
|
95
106
|
parameters: { docs: { description: { story: 'Four card items with icons, titles, and content.' } } }
|
|
96
107
|
};
|
|
97
108
|
|
|
109
|
+
export const WithSectionSubtitle = {
|
|
110
|
+
name : 'With Section Subtitle',
|
|
111
|
+
render: () => html`
|
|
112
|
+
<bd-card-section title="Why Bitdefender" subtitle="Discover the benefits of our award-winning security">
|
|
113
|
+
<bd-card-item title="AI Protection">
|
|
114
|
+
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
115
|
+
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
116
|
+
</bd-card-item>
|
|
117
|
+
<bd-card-item title="Multi-layer Security">
|
|
118
|
+
<bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
|
|
119
|
+
<bd-p>Multiple independent protection layers stop any attack.</bd-p>
|
|
120
|
+
</bd-card-item>
|
|
121
|
+
<bd-card-item title="VPN Included">
|
|
122
|
+
<bd-machine-learning-icon slot="icon" width="32" height="32" color="#006DFF"></bd-machine-learning-icon>
|
|
123
|
+
<bd-p>Unlimited encrypted VPN traffic for all your devices.</bd-p>
|
|
124
|
+
</bd-card-item>
|
|
125
|
+
<bd-card-item title="Parental Controls">
|
|
126
|
+
<bd-analysis-icon slot="icon" width="32" height="32" color="#006DFF"></bd-analysis-icon>
|
|
127
|
+
<bd-p>Advanced controls to protect your children online.</bd-p>
|
|
128
|
+
</bd-card-item>
|
|
129
|
+
</bd-card-section>
|
|
130
|
+
`,
|
|
131
|
+
parameters: { docs: { description: { story: 'Section with both title and subtitle above the cards.' } } }
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const SectionSubtitleOnly = {
|
|
135
|
+
name : 'Section Subtitle Only',
|
|
136
|
+
render: () => html`
|
|
137
|
+
<bd-card-section subtitle="Discover the benefits of our award-winning security">
|
|
138
|
+
<bd-card-item title="AI Protection">
|
|
139
|
+
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
140
|
+
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
141
|
+
</bd-card-item>
|
|
142
|
+
<bd-card-item title="Multi-layer Security">
|
|
143
|
+
<bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
|
|
144
|
+
<bd-p>Multiple independent protection layers stop any attack.</bd-p>
|
|
145
|
+
</bd-card-item>
|
|
146
|
+
<bd-card-item title="VPN Included">
|
|
147
|
+
<bd-machine-learning-icon slot="icon" width="32" height="32" color="#006DFF"></bd-machine-learning-icon>
|
|
148
|
+
<bd-p>Unlimited encrypted VPN traffic for all your devices.</bd-p>
|
|
149
|
+
</bd-card-item>
|
|
150
|
+
</bd-card-section>
|
|
151
|
+
`,
|
|
152
|
+
parameters: { docs: { description: { story: 'Section with subtitle only (no title).' } } }
|
|
153
|
+
};
|
|
154
|
+
|
|
98
155
|
export const WithCTA = {
|
|
99
156
|
name : 'With CTA Button',
|
|
100
157
|
render: () => html`
|
|
101
|
-
<bd-card-section title="Why Bitdefender">
|
|
158
|
+
<bd-card-section title="Why Bitdefender" subtitle="Explore our key features">
|
|
102
159
|
<bd-card-item title="AI Protection">
|
|
103
160
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
104
161
|
<bd-p>Powered by machine learning and behavioral analysis to stop threats before they reach you.</bd-p>
|
|
@@ -127,13 +184,13 @@ export const WithCTA = {
|
|
|
127
184
|
export const WithCTAUnevenContent = {
|
|
128
185
|
name : 'With CTA — Uneven Content (alignment test)',
|
|
129
186
|
render: () => html`
|
|
130
|
-
<bd-card-section title="Features">
|
|
187
|
+
<bd-card-section title="Features" subtitle="Compare our security solutions">
|
|
131
188
|
<bd-card-item title="AI Protection">
|
|
132
189
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
133
190
|
<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
191
|
<bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
|
|
135
192
|
</bd-card-item>
|
|
136
|
-
<bd-card-item title="Multi-layer Security
|
|
193
|
+
<bd-card-item title="Multi-layer Security">
|
|
137
194
|
<bd-globe-icon slot="icon" width="32" height="32" color="#006DFF"></bd-globe-icon>
|
|
138
195
|
<bd-p>Stop any attack.</bd-p>
|
|
139
196
|
<bd-button-link slot="cta" href="#" kind="danger" size="sm">Get started</bd-button-link>
|
|
@@ -175,13 +232,13 @@ export const NoSectionTitle = {
|
|
|
175
232
|
</bd-card-item>
|
|
176
233
|
</bd-card-section>
|
|
177
234
|
`,
|
|
178
|
-
parameters: { docs: { description: { story: 'Section without title
|
|
235
|
+
parameters: { docs: { description: { story: 'Section without title or subtitle.' } } }
|
|
179
236
|
};
|
|
180
237
|
|
|
181
238
|
export const CenteredAlignment = {
|
|
182
239
|
name : 'Centered Alignment',
|
|
183
240
|
render: () => html`
|
|
184
|
-
<bd-card-section title="Features">
|
|
241
|
+
<bd-card-section title="Features" subtitle="All features are centered">
|
|
185
242
|
<bd-card-item title="AI Protection" align="center">
|
|
186
243
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
187
244
|
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
@@ -206,7 +263,7 @@ export const CenteredAlignment = {
|
|
|
206
263
|
export const MixedAlignment = {
|
|
207
264
|
name : 'Mixed Alignment',
|
|
208
265
|
render: () => html`
|
|
209
|
-
<bd-card-section title="Mixed Layout">
|
|
266
|
+
<bd-card-section title="Mixed Layout" subtitle="Different alignment styles">
|
|
210
267
|
<bd-card-item title="Left Aligned" align="start">
|
|
211
268
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
212
269
|
<bd-p>Default left-aligned content.</bd-p>
|
|
@@ -223,7 +280,7 @@ export const MixedAlignment = {
|
|
|
223
280
|
export const NoIcon = {
|
|
224
281
|
name : 'No Icons',
|
|
225
282
|
render: () => html`
|
|
226
|
-
<bd-card-section title="Features">
|
|
283
|
+
<bd-card-section title="Features" subtitle="Simple text cards without icons">
|
|
227
284
|
<bd-card-item title="AI Protection">
|
|
228
285
|
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
229
286
|
</bd-card-item>
|
|
@@ -244,7 +301,7 @@ export const NoIcon = {
|
|
|
244
301
|
export const NoSlottedContent = {
|
|
245
302
|
name : 'No Slotted Content',
|
|
246
303
|
render: () => html`
|
|
247
|
-
<bd-card-section title="Features">
|
|
304
|
+
<bd-card-section title="Features" subtitle="Icons with titles only">
|
|
248
305
|
<bd-card-item title="AI Protection">
|
|
249
306
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
250
307
|
</bd-card-item>
|
|
@@ -277,7 +334,7 @@ export const TitleOnly = {
|
|
|
277
334
|
export const RichContent = {
|
|
278
335
|
name : 'Rich Slotted Content',
|
|
279
336
|
render: () => html`
|
|
280
|
-
<bd-card-section title="Plan Details">
|
|
337
|
+
<bd-card-section title="Plan Details" subtitle="What's included in each plan">
|
|
281
338
|
<bd-card-item title="What's included">
|
|
282
339
|
<bd-family-icon slot="icon" width="32" height="32" color="#006DFF"></bd-family-icon>
|
|
283
340
|
<bd-p>Antivirus & Anti-malware</bd-p>
|
|
@@ -298,7 +355,7 @@ export const RichContent = {
|
|
|
298
355
|
export const SingleItem = {
|
|
299
356
|
name : 'Single Item (edge case)',
|
|
300
357
|
render: () => html`
|
|
301
|
-
<bd-card-section title="Feature">
|
|
358
|
+
<bd-card-section title="Feature" subtitle="One card only">
|
|
302
359
|
<bd-card-item title="AI Protection">
|
|
303
360
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
304
361
|
<bd-p>Machine learning-powered protection.</bd-p>
|
|
@@ -308,10 +365,11 @@ export const SingleItem = {
|
|
|
308
365
|
`,
|
|
309
366
|
parameters: { docs: { description: { story: 'Edge case: only one card item.' } } }
|
|
310
367
|
};
|
|
368
|
+
|
|
311
369
|
export const WithImages = {
|
|
312
370
|
name : 'With Images (large + small)',
|
|
313
371
|
render: () => html`
|
|
314
|
-
<bd-card-section title="Our Products">
|
|
372
|
+
<bd-card-section title="Our Products" subtitle="Choose the right plan for you">
|
|
315
373
|
<bd-card-item title="Total Security">
|
|
316
374
|
<img slot="icon" src="/assets/tabs-img1.png" alt="Total Security" />
|
|
317
375
|
<bd-p>Complete protection for all your devices with advanced threat detection and real-time security updates.</bd-p>
|
|
@@ -335,7 +393,7 @@ export const WithImages = {
|
|
|
335
393
|
export const MixedIconsAndImages = {
|
|
336
394
|
name : 'Mixed — Icons and Images',
|
|
337
395
|
render: () => html`
|
|
338
|
-
<bd-card-section title="Mixed Media">
|
|
396
|
+
<bd-card-section title="Mixed Media" subtitle="SVG icons and images together">
|
|
339
397
|
<bd-card-item title="AI Protection">
|
|
340
398
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
341
399
|
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
@@ -360,15 +418,17 @@ export const MixedIconsAndImages = {
|
|
|
360
418
|
`,
|
|
361
419
|
parameters: { docs: { description: { story: 'Mix of SVG icons and large images in the same grid — tests consistent icon row height equalization.' } } }
|
|
362
420
|
};
|
|
421
|
+
|
|
363
422
|
export const Playground = {
|
|
364
423
|
name: '🛝 Playground',
|
|
365
424
|
args: {
|
|
366
|
-
sectionTitle: 'Why Bitdefender',
|
|
367
|
-
|
|
368
|
-
|
|
425
|
+
sectionTitle : 'Why Bitdefender',
|
|
426
|
+
sectionSubtitle: 'Discover the benefits of our award-winning security',
|
|
427
|
+
itemTitle : 'AI Protection',
|
|
428
|
+
align : 'start'
|
|
369
429
|
},
|
|
370
430
|
render: (args) => html`
|
|
371
|
-
<bd-card-section title="${args.sectionTitle}">
|
|
431
|
+
<bd-card-section title="${args.sectionTitle}" subtitle="${args.sectionSubtitle}">
|
|
372
432
|
<bd-card-item title="${args.itemTitle}" align="${args.align}">
|
|
373
433
|
<bd-individual-icon slot="icon" width="32" height="32" color="#006DFF"></bd-individual-icon>
|
|
374
434
|
<bd-p>Powered by machine learning and behavioral analysis.</bd-p>
|
|
@@ -381,5 +441,5 @@ export const Playground = {
|
|
|
381
441
|
</bd-card-item>
|
|
382
442
|
</bd-card-section>
|
|
383
443
|
`,
|
|
384
|
-
parameters: { docs: { description: { story: 'Interactive playground.' } } }
|
|
444
|
+
parameters: { docs: { description: { story: 'Interactive playground with section subtitle support.' } } }
|
|
385
445
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LitElement, html } from "lit";
|
|
2
2
|
import { tokens } from "../../tokens/tokens.js";
|
|
3
|
-
import "../
|
|
3
|
+
import "../Button/Button.js";
|
|
4
4
|
import "../heading/heading.js";
|
|
5
5
|
import "../paragraph/paragraph.js";
|
|
6
6
|
import featuresTabCSS from "./features-tab.css.js";
|