@repobit/dex-system-design 0.24.18 → 0.24.20
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/ai-guardian-demo.stories.js +454 -33
- package/src/components/bento-grid/bento-grid.css.js +12 -1
- package/src/components/bento-grid/bento-grid.js +59 -1
- package/src/components/bento-grid/bento-grid.stories.js +45 -0
- package/src/components/cards/card.css.js +56 -0
- package/src/components/cards/card.js +64 -11
- package/src/components/cards/card.stories.js +65 -2
- package/src/components/comparison-panel/comparison-panel.css.js +52 -1
- package/src/components/comparison-panel/comparison-panel.js +6 -1
- package/src/components/compatibility-table/compatibility-table.css.js +29 -13
- package/src/components/compatibility-table/compatibility-table.js +13 -7
- package/src/components/cta-banner/cta-banner.css.js +11 -0
- package/src/components/cta-banner/cta-banner.js +7 -0
- package/src/components/footer/footer-lp.css.js +10 -21
- package/src/components/footer/footer-lp.js +3 -18
- package/src/components/footer/footer-nav-menu.css.js +0 -2
- package/src/components/footer/footer.css.js +18 -35
- package/src/components/footer/footer.js +5 -1
- package/src/components/header/header-code.css.js +208 -10
- package/src/components/header/header-code.js +148 -5
- package/src/components/header/header-code.stories.js +83 -27
- package/src/components/page-switcher/page-switcher.js +1 -1
- package/src/components/paragraph/paragraph.js +6 -0
- package/src/components/quick-answer/quick-answer.css.js +2 -0
- package/src/components/quick-answer/quick-answer.js +1 -1
- package/src/components/terminal/terminal-message.css.js +153 -13
- package/src/components/terminal/terminal-message.js +37 -11
|
@@ -4,6 +4,32 @@ export default css`
|
|
|
4
4
|
:host {
|
|
5
5
|
display: block;
|
|
6
6
|
font-family: var(--typography-fontFamily-sans);
|
|
7
|
+
position: relative;
|
|
8
|
+
background-color: var(--color-neutral-0, #fff);
|
|
9
|
+
overflow: hidden; /* clips the ::after floor grid, which extends past the edges */
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
:host([variant="tint"]) {
|
|
13
|
+
background-image: radial-gradient(ellipse 900px 560px at 84% 8%, rgba(59, 130, 246, 0.16), transparent 65%);
|
|
14
|
+
background-repeat: no-repeat;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
:host([variant="tint"])::after {
|
|
18
|
+
content: "";
|
|
19
|
+
position: absolute;
|
|
20
|
+
left: -20%;
|
|
21
|
+
right: -20%;
|
|
22
|
+
bottom: -38%;
|
|
23
|
+
height: 72%;
|
|
24
|
+
transform-origin: 50% 0;
|
|
25
|
+
transform: perspective(620px) rotateX(64deg);
|
|
26
|
+
background:
|
|
27
|
+
linear-gradient(#006dff1a 1px, #0000 1px) 0 0 / 100% 44px,
|
|
28
|
+
linear-gradient(90deg, #006dff1a 1px, #0000 1px) 0 0 / 44px 100%;
|
|
29
|
+
-webkit-mask-image: linear-gradient(#0000 0%, #000 45%, #0000 100%);
|
|
30
|
+
mask-image: linear-gradient(#0000 0%, #000 45%, #0000 100%);
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
z-index: 0;
|
|
7
33
|
}
|
|
8
34
|
|
|
9
35
|
.bd-headercode-container {
|
|
@@ -15,6 +41,8 @@ export default css`
|
|
|
15
41
|
margin: 0 auto;
|
|
16
42
|
padding: var(--spacing-48) var(--layout-ensemble-inline-padding, var(--spacing-24));
|
|
17
43
|
box-sizing: border-box;
|
|
44
|
+
position: relative;
|
|
45
|
+
z-index: 1;
|
|
18
46
|
}
|
|
19
47
|
|
|
20
48
|
/* === ENTRANCE ANIMATION === */
|
|
@@ -53,9 +81,6 @@ export default css`
|
|
|
53
81
|
gap: var(--spacing-16);
|
|
54
82
|
}
|
|
55
83
|
|
|
56
|
-
/* Slot for a small breadcrumb-style line above the eyebrow
|
|
57
|
-
(e.g. "Bitdefender AI skill-scanner"). Empty by default —
|
|
58
|
-
collapses to nothing when no content is slotted in. */
|
|
59
84
|
.bd-headercode-breadcrumb {
|
|
60
85
|
display: flex;
|
|
61
86
|
flex-wrap: wrap;
|
|
@@ -89,45 +114,200 @@ export default css`
|
|
|
89
114
|
}
|
|
90
115
|
|
|
91
116
|
.bd-headercode-cta {
|
|
92
|
-
display: flex;
|
|
117
|
+
display: inline-flex;
|
|
93
118
|
flex-wrap: wrap;
|
|
94
119
|
align-items: center;
|
|
95
120
|
gap: var(--spacing-16);
|
|
96
121
|
margin-top: var(--spacing-8);
|
|
97
122
|
}
|
|
98
123
|
|
|
99
|
-
/* Slot for a small status badge next to the CTA buttons (e.g. "AVAILABLE").
|
|
100
|
-
Empty by default — collapses to nothing when no content is slotted in. */
|
|
101
124
|
.bd-headercode-badge {
|
|
102
125
|
display: inline-flex;
|
|
103
126
|
align-items: center;
|
|
104
|
-
color: var(--color-neutral-
|
|
127
|
+
color: var(--color-neutral-600);
|
|
105
128
|
font-family: var(--typography-fontFamily-mono, monospace);
|
|
106
129
|
font-size: var(--typography-fontSize-xs, 12px);
|
|
107
130
|
letter-spacing: 0.05em;
|
|
131
|
+
padding: var(--spacing-4, 4px) var(--spacing-12, 12px);
|
|
132
|
+
border: 1px solid var(--color-neutral-200, #e5e7eb);
|
|
133
|
+
border-radius: var(--radius-full, 999px);
|
|
134
|
+
background: var(--color-neutral-0, #fff);
|
|
108
135
|
}
|
|
109
136
|
|
|
110
137
|
.bd-headercode-badge:not(:has(*)) {
|
|
111
138
|
display: none;
|
|
112
139
|
}
|
|
113
140
|
|
|
141
|
+
.bd-headercode-meta {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
width: 100%;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.bd-headercode-meta-spec {
|
|
148
|
+
color: var(--color-neutral-500);
|
|
149
|
+
margin: 0;
|
|
150
|
+
padding-top: var(--spacing-16);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.bd-headercode-meta-facts {
|
|
154
|
+
display: grid;
|
|
155
|
+
grid-template-columns: repeat(3, auto);
|
|
156
|
+
gap: var(--spacing-8) var(--spacing-32);
|
|
157
|
+
margin-top: var(--spacing-40);
|
|
158
|
+
padding-top: var(--spacing-24);
|
|
159
|
+
border-top: 1px solid var(--color-neutral-100);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.bd-headercode-meta-fact {
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: baseline;
|
|
165
|
+
gap: var(--spacing-8, 8px);
|
|
166
|
+
white-space: nowrap;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.bd-headercode-meta-fact-label {
|
|
170
|
+
margin: 0;
|
|
171
|
+
color: var(--color-neutral-400);
|
|
172
|
+
text-transform: uppercase;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.bd-headercode-meta-fact-value {
|
|
176
|
+
margin: 0;
|
|
177
|
+
color: var(--color-neutral-900);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
@media (max-width: 480px) {
|
|
181
|
+
.bd-headercode-meta-facts {
|
|
182
|
+
grid-template-columns: repeat(2, auto);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
114
186
|
/* === RIGHT COLUMN === */
|
|
115
187
|
.bd-headercode-right {
|
|
116
188
|
display: flex;
|
|
117
189
|
flex-direction: column;
|
|
118
190
|
align-items: flex-end;
|
|
119
191
|
gap: var(--spacing-8);
|
|
192
|
+
position: relative;
|
|
120
193
|
}
|
|
121
194
|
|
|
122
|
-
|
|
195
|
+
/* === 3D SCENE === */
|
|
196
|
+
.bd-headercode-scene {
|
|
197
|
+
width: 100%;
|
|
198
|
+
display: flex;
|
|
199
|
+
justify-content: flex-end;
|
|
200
|
+
align-items: center;
|
|
201
|
+
perspective: 1300px;
|
|
202
|
+
min-height: 400px;
|
|
203
|
+
padding: var(--spacing-16, 16px) 0;
|
|
204
|
+
margin: 0;
|
|
205
|
+
position: relative;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.bd-headercode-stack {
|
|
209
|
+
position: relative;
|
|
123
210
|
width: 100%;
|
|
124
211
|
max-width: 520px;
|
|
125
|
-
|
|
212
|
+
transform-style: preserve-3d;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
:host([variant="tint"]) .bd-headercode-stack {
|
|
216
|
+
transform: perspective(1300px)
|
|
217
|
+
rotateY(var(--ry, -10deg))
|
|
218
|
+
rotateX(var(--rx, 6deg))
|
|
219
|
+
rotateZ(1deg);
|
|
220
|
+
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@media (prefers-reduced-motion: reduce) {
|
|
224
|
+
:host([variant="tint"]) .bd-headercode-stack {
|
|
225
|
+
transition: none;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.bd-headercode-right ::slotted(*) {
|
|
230
|
+
display: block;
|
|
231
|
+
width: 100%;
|
|
232
|
+
box-shadow: 0 1px 2px #0003, 0 18px 48px #000a1e73;
|
|
233
|
+
position: relative;
|
|
234
|
+
z-index: 1; /* sits above the rings */
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@media (prefers-reduced-motion: reduce) {
|
|
238
|
+
:host([variant="tint"]) .bd-headercode-stack {
|
|
239
|
+
transform: none;
|
|
240
|
+
}
|
|
126
241
|
}
|
|
127
242
|
|
|
128
243
|
.bd-headercode-terminal-caption {
|
|
129
244
|
color: var(--color-neutral-500);
|
|
130
245
|
margin: 0;
|
|
246
|
+
position: relative;
|
|
247
|
+
z-index: 1;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.bd-headercode-rings {
|
|
251
|
+
position: absolute;
|
|
252
|
+
inset: 0;
|
|
253
|
+
transform-style: preserve-3d;
|
|
254
|
+
pointer-events: none;
|
|
255
|
+
z-index: 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.bd-headercode-ring {
|
|
259
|
+
position: absolute;
|
|
260
|
+
inset: 0;
|
|
261
|
+
border-radius: 28px;
|
|
262
|
+
border: 1.5px solid rgba(0, 109, 255, calc(0.5 - var(--d) * 0.08));
|
|
263
|
+
background: rgba(0, 109, 255, calc(0.05 - var(--d) * 0.008));
|
|
264
|
+
box-shadow: 0 0 26px rgba(0, 109, 255, calc(0.16 - var(--d) * 0.025));
|
|
265
|
+
animation: bd-headercode-ring-breathe 6s ease-in-out calc(var(--d) * -1.2s) infinite;
|
|
266
|
+
transform: translate(calc(var(--d) * 10px), calc(var(--d) * 8px));
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@keyframes bd-headercode-ring-breathe {
|
|
270
|
+
0%, 100% {
|
|
271
|
+
opacity: 0.85;
|
|
272
|
+
}
|
|
273
|
+
50% {
|
|
274
|
+
opacity: 0.45;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
@media (prefers-reduced-motion: reduce) {
|
|
279
|
+
.bd-headercode-ring {
|
|
280
|
+
animation: none;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* === FLOATING ANNOTATION PILLS === */
|
|
285
|
+
.bd-headercode-annotation {
|
|
286
|
+
position: absolute;
|
|
287
|
+
z-index: 2;
|
|
288
|
+
pointer-events: none;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.bd-headercode-annotation--top {
|
|
292
|
+
top: -14px;
|
|
293
|
+
right: 32px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.bd-headercode-annotation--bottom {
|
|
297
|
+
bottom: -14px;
|
|
298
|
+
left: 16px;
|
|
299
|
+
right: auto;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.bd-headercode-annotation:not(:has(*)) {
|
|
303
|
+
display: none;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.bd-headercode-annotation ::slotted(*) {
|
|
307
|
+
width: auto;
|
|
308
|
+
max-width: none;
|
|
309
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
|
|
310
|
+
pointer-events: auto;
|
|
131
311
|
}
|
|
132
312
|
|
|
133
313
|
/* === RESPONSIVE === */
|
|
@@ -142,12 +322,30 @@ export default css`
|
|
|
142
322
|
align-items: stretch;
|
|
143
323
|
}
|
|
144
324
|
|
|
145
|
-
.bd-headercode-
|
|
325
|
+
.bd-headercode-scene {
|
|
326
|
+
min-height: 0;
|
|
327
|
+
perspective: none;
|
|
328
|
+
justify-content: stretch;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.bd-headercode-stack {
|
|
146
332
|
max-width: none;
|
|
147
333
|
}
|
|
148
334
|
|
|
335
|
+
:host([variant="tint"]) .bd-headercode-stack {
|
|
336
|
+
transform: none;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
.bd-headercode-rings {
|
|
340
|
+
display: none;
|
|
341
|
+
}
|
|
342
|
+
|
|
149
343
|
.bd-headercode-description {
|
|
150
344
|
max-width: none;
|
|
151
345
|
}
|
|
346
|
+
|
|
347
|
+
.bd-headercode-annotation {
|
|
348
|
+
display: none;
|
|
349
|
+
}
|
|
152
350
|
}
|
|
153
351
|
`;
|
|
@@ -11,7 +11,11 @@ class HeaderCode extends LitElement {
|
|
|
11
11
|
eyebrow : { type: String },
|
|
12
12
|
title : { type: String },
|
|
13
13
|
description : { type: String },
|
|
14
|
-
terminalCaption: { type: String, attribute: "terminal-caption" }
|
|
14
|
+
terminalCaption: { type: String, attribute: "terminal-caption" },
|
|
15
|
+
variant : { type: String, reflect: true },
|
|
16
|
+
metaSpec : { type: String, attribute: "meta-spec" },
|
|
17
|
+
metaFacts : { type: Array },
|
|
18
|
+
_hasBadge : { state: true }
|
|
15
19
|
};
|
|
16
20
|
|
|
17
21
|
static styles = [tokens, headerCodeCSS];
|
|
@@ -22,6 +26,131 @@ class HeaderCode extends LitElement {
|
|
|
22
26
|
this.title = "";
|
|
23
27
|
this.description = "";
|
|
24
28
|
this.terminalCaption = "";
|
|
29
|
+
this.variant = "default";
|
|
30
|
+
this.metaSpec = "";
|
|
31
|
+
this.metaFacts = [];
|
|
32
|
+
this._hasBadge = false;
|
|
33
|
+
|
|
34
|
+
this._scene = null;
|
|
35
|
+
this._onPointerMove = this._onPointerMove.bind(this);
|
|
36
|
+
this._onPointerLeave = this._onPointerLeave.bind(this);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
firstUpdated() {
|
|
40
|
+
this._bindScene();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
updated(changed) {
|
|
44
|
+
if (changed.has("variant")) this._bindScene();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
disconnectedCallback() {
|
|
48
|
+
super.disconnectedCallback();
|
|
49
|
+
this._unbindScene();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
_bindScene() {
|
|
53
|
+
this._unbindScene();
|
|
54
|
+
if (this.variant !== "tint") return;
|
|
55
|
+
|
|
56
|
+
this._scene = this.shadowRoot?.querySelector(".bd-headercode-scene") || null;
|
|
57
|
+
if (!this._scene) return;
|
|
58
|
+
|
|
59
|
+
this._scene.addEventListener("pointermove", this._onPointerMove);
|
|
60
|
+
this._scene.addEventListener("pointerleave", this._onPointerLeave);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_unbindScene() {
|
|
64
|
+
if (!this._scene) return;
|
|
65
|
+
this._scene.removeEventListener("pointermove", this._onPointerMove);
|
|
66
|
+
this._scene.removeEventListener("pointerleave", this._onPointerLeave);
|
|
67
|
+
this._scene = null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_onPointerMove(event) {
|
|
71
|
+
const rect = this._scene.getBoundingClientRect();
|
|
72
|
+
const px = (event.clientX - rect.left) / rect.width - 0.5;
|
|
73
|
+
const py = (event.clientY - rect.top) / rect.height - 0.5;
|
|
74
|
+
|
|
75
|
+
const ry = px * 18; // deg
|
|
76
|
+
const rx = -py * 12; // deg
|
|
77
|
+
|
|
78
|
+
this.style.setProperty("--rx", `${rx.toFixed(2)}deg`);
|
|
79
|
+
this.style.setProperty("--ry", `${ry.toFixed(2)}deg`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
_onPointerLeave() {
|
|
83
|
+
this.style.removeProperty("--rx");
|
|
84
|
+
this.style.removeProperty("--ry");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_onBadgeSlotChange(event) {
|
|
88
|
+
this._hasBadge = event.target.assignedNodes({ flatten: true }).length > 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
_renderRings() {
|
|
93
|
+
if (this.variant !== "tint") return nothing;
|
|
94
|
+
|
|
95
|
+
return html`
|
|
96
|
+
<div class="bd-headercode-rings" aria-hidden="true">
|
|
97
|
+
<span class="bd-headercode-ring" style="--d:1"></span>
|
|
98
|
+
<span class="bd-headercode-ring" style="--d:2"></span>
|
|
99
|
+
<span class="bd-headercode-ring" style="--d:3"></span>
|
|
100
|
+
<span class="bd-headercode-ring" style="--d:4"></span>
|
|
101
|
+
<span class="bd-headercode-ring" style="--d:5"></span>
|
|
102
|
+
</div>
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_renderBadge() {
|
|
107
|
+
const badgeSlot = html`<slot name="badge" @slotchange=${this._onBadgeSlotChange}></slot>`;
|
|
108
|
+
|
|
109
|
+
return this._hasBadge
|
|
110
|
+
? html`<span class="bd-headercode-badge">${badgeSlot}</span>`
|
|
111
|
+
: html`<span class="bd-headercode-badge-slot-holder" hidden>${badgeSlot}</span>`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
_renderMeta() {
|
|
115
|
+
const hasSpec = !!this.metaSpec;
|
|
116
|
+
const hasFacts = this.metaFacts && this.metaFacts.length > 0;
|
|
117
|
+
|
|
118
|
+
if (!hasSpec && !hasFacts) return nothing;
|
|
119
|
+
|
|
120
|
+
const monoFontFamily = "'IBM Plex Mono', ui-monospace, SFMono-Regular, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace";
|
|
121
|
+
|
|
122
|
+
return html`
|
|
123
|
+
<div class="bd-headercode-meta">
|
|
124
|
+
${hasSpec
|
|
125
|
+
? html`<bd-p
|
|
126
|
+
kind="xsmall"
|
|
127
|
+
class="bd-headercode-meta-spec"
|
|
128
|
+
font-family=${monoFontFamily}
|
|
129
|
+
letter-spacing=".1em"
|
|
130
|
+
>${this.metaSpec}</bd-p>`
|
|
131
|
+
: nothing}
|
|
132
|
+
|
|
133
|
+
${hasFacts
|
|
134
|
+
? html`
|
|
135
|
+
<div class="bd-headercode-meta-facts">
|
|
136
|
+
${this.metaFacts.map(
|
|
137
|
+
(fact) => html`
|
|
138
|
+
<div class="bd-headercode-meta-fact">
|
|
139
|
+
<bd-p
|
|
140
|
+
kind="xsmall"
|
|
141
|
+
class="bd-headercode-meta-fact-label"
|
|
142
|
+
font-family=${monoFontFamily}
|
|
143
|
+
letter-spacing=".1em"
|
|
144
|
+
>${fact.label}</bd-p>
|
|
145
|
+
<bd-p kind="regular" font-weight="700" class="bd-headercode-meta-fact-value">${fact.value}</bd-p>
|
|
146
|
+
</div>
|
|
147
|
+
`
|
|
148
|
+
)}
|
|
149
|
+
</div>
|
|
150
|
+
`
|
|
151
|
+
: nothing}
|
|
152
|
+
</div>
|
|
153
|
+
`;
|
|
25
154
|
}
|
|
26
155
|
|
|
27
156
|
render() {
|
|
@@ -47,14 +176,28 @@ class HeaderCode extends LitElement {
|
|
|
47
176
|
<div class="bd-headercode-cta">
|
|
48
177
|
<slot name="primary-button"></slot>
|
|
49
178
|
<slot name="secondary-button"></slot>
|
|
50
|
-
|
|
51
|
-
<slot name="badge"></slot>
|
|
52
|
-
</span>
|
|
179
|
+
${this._renderBadge()}
|
|
53
180
|
</div>
|
|
181
|
+
|
|
182
|
+
${this._renderMeta()}
|
|
54
183
|
</div>
|
|
55
184
|
|
|
56
185
|
<div class="bd-headercode-right">
|
|
57
|
-
<
|
|
186
|
+
<div class="bd-headercode-annotation bd-headercode-annotation--top">
|
|
187
|
+
<slot name="annotation-top"></slot>
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
<div class="bd-headercode-scene">
|
|
192
|
+
<div class="bd-headercode-stack">
|
|
193
|
+
${this._renderRings()}
|
|
194
|
+
<slot name="terminal-content"></slot>
|
|
195
|
+
</div>
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<div class="bd-headercode-annotation bd-headercode-annotation--bottom">
|
|
199
|
+
<slot name="annotation-bottom"></slot>
|
|
200
|
+
</div>
|
|
58
201
|
|
|
59
202
|
${this.terminalCaption
|
|
60
203
|
? html`<bd-p kind="small" class="bd-headercode-terminal-caption" font-family="'IBM Plex Mono', ui-monospace, SFMono-Regular, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace"
|
|
@@ -14,53 +14,51 @@ export default {
|
|
|
14
14
|
component: `
|
|
15
15
|
**HeaderCode** is a hero/header variant pairing marketing copy on the left with a
|
|
16
16
|
terminal-style code/demo window on the right. Unlike \`bd-header\`, it has no pricing —
|
|
17
|
-
just eyebrow, title, description, two CTA buttons, and a slotted terminal.
|
|
17
|
+
just eyebrow, title, description, two CTA buttons, an optional meta row, and a slotted terminal.
|
|
18
18
|
|
|
19
19
|
The terminal window — including the traffic-light titlebar dots — is owned by
|
|
20
20
|
\`<bd-terminal-message>\`. \`bd-header-code\` additionally renders an optional small
|
|
21
21
|
caption **below** the terminal box via \`terminal-caption\`.
|
|
22
22
|
|
|
23
|
+
\`variant="tint"\` swaps the plain white background for a light-blue gradient with a
|
|
24
|
+
dot-grid pattern, and gives the \`badge\` slot a bordered pill treatment.
|
|
25
|
+
|
|
23
26
|
### Usage
|
|
24
27
|
\`\`\`html
|
|
25
28
|
<bd-header-code
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
variant="tint"
|
|
30
|
+
eyebrow="Privacy for autonomous AI agents"
|
|
31
|
+
title="Bitdefender VPN for AI Agents"
|
|
32
|
+
description="Each prompt gets a fresh, disposable container scoped to a specific location."
|
|
33
|
+
terminal-caption="// illustrative — every connection closes when the prompt ends"
|
|
30
34
|
>
|
|
31
|
-
<
|
|
35
|
+
<span slot="badge">EXTERNAL BETA</span>
|
|
36
|
+
<bd-button-link slot="primary-button" label="Download for macOS" kind="primary">Download for macOS</bd-button-link>
|
|
32
37
|
<bd-button-link slot="secondary-button" label="See how it works" kind="outline">See how it works</bd-button-link>
|
|
33
38
|
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
panel-label="Welcome"
|
|
38
|
-
icon="👋"
|
|
39
|
-
greeting="Hi, I'm AI Guardian."
|
|
40
|
-
intro="I keep an eye on what your AI assistant can access and do:"
|
|
41
|
-
.items=\${["which tools it can use", "which credentials to watch", "which MCP servers to trust"]}
|
|
42
|
-
footer-bold="Let's get started."
|
|
43
|
-
footer="It only takes a minute, and nothing changes until you confirm it."
|
|
44
|
-
show-cursor
|
|
45
|
-
hint="[Enter] to continue · [esc] to cancel"
|
|
46
|
-
></bd-terminal-message>
|
|
39
|
+
<div slot="meta">…facts row…</div>
|
|
40
|
+
|
|
41
|
+
<bd-terminal-message slot="terminal-content" show-titlebar></bd-terminal-message>
|
|
47
42
|
</bd-header-code>
|
|
48
43
|
\`\`\`
|
|
49
44
|
|
|
50
45
|
### Attributes
|
|
51
|
-
| Attribute | Type | Default
|
|
52
|
-
|
|
53
|
-
| \`eyebrow\` | String | \`""\`
|
|
54
|
-
| \`title\` | String | \`""\`
|
|
55
|
-
| \`description\` | String | \`""\`
|
|
56
|
-
| \`terminal-caption\` | String | \`""\`
|
|
46
|
+
| Attribute | Type | Default | Description |
|
|
47
|
+
|----------------------|--------|--------------|---------------------------------------------------------|
|
|
48
|
+
| \`eyebrow\` | String | \`""\` | Small label above the title |
|
|
49
|
+
| \`title\` | String | \`""\` | Main heading (can be overridden via \`title\` slot) |
|
|
50
|
+
| \`description\` | String | \`""\` | Supporting paragraph under the title |
|
|
51
|
+
| \`terminal-caption\` | String | \`""\` | Small caption rendered below the terminal box |
|
|
52
|
+
| \`variant\` | String | \`"default"\` | \`"default"\` or \`"tint"\` — background treatment |
|
|
57
53
|
|
|
58
54
|
### Slots
|
|
59
55
|
| Slot | Description |
|
|
60
56
|
|---------------------|-----------------------------------------------|
|
|
61
57
|
| \`title\` | Overrides the \`title\` attribute if content is provided |
|
|
58
|
+
| \`badge\` | Small pill badge next to the CTAs (e.g. "AVAILABLE", "EXTERNAL BETA") |
|
|
62
59
|
| \`primary-button\` | The main CTA (typically \`bd-button-link\`) |
|
|
63
60
|
| \`secondary-button\` | The secondary CTA |
|
|
61
|
+
| \`meta\` | Freeform row under the CTAs — spec line, facts list, etc. |
|
|
64
62
|
| \`terminal-content\` | Freeform content rendered on the right (typically a \`bd-terminal-message\`) |
|
|
65
63
|
`
|
|
66
64
|
}
|
|
@@ -70,7 +68,8 @@ caption **below** the terminal box via \`terminal-caption\`.
|
|
|
70
68
|
eyebrow : { control: "text", table: { category: "Content" } },
|
|
71
69
|
title : { control: "text", table: { category: "Content" } },
|
|
72
70
|
description : { control: "text", table: { category: "Content" } },
|
|
73
|
-
terminalCaption: { control: "text", table: { category: "Terminal" } }
|
|
71
|
+
terminalCaption: { control: "text", table: { category: "Terminal" } },
|
|
72
|
+
variant : { control: { type: "select" }, options: ["default", "tint"], table: { category: "Appearance" } }
|
|
74
73
|
}
|
|
75
74
|
};
|
|
76
75
|
|
|
@@ -92,6 +91,7 @@ const terminalContent = html`
|
|
|
92
91
|
|
|
93
92
|
const render = (args) => html`
|
|
94
93
|
<bd-header-code
|
|
94
|
+
variant=${args.variant}
|
|
95
95
|
eyebrow=${args.eyebrow}
|
|
96
96
|
title=${args.title}
|
|
97
97
|
description=${args.description}
|
|
@@ -122,6 +122,7 @@ const render = (args) => html`
|
|
|
122
122
|
export const Default = {
|
|
123
123
|
name: "Default — AI Guardian",
|
|
124
124
|
args: {
|
|
125
|
+
variant : "default",
|
|
125
126
|
eyebrow : "Security for autonomous AI agents",
|
|
126
127
|
title : "Bitdefender AI Guardian",
|
|
127
128
|
description : "A security layer between your AI agents and the actions they take — policies, guardrails, and monitoring that let agents run safely.",
|
|
@@ -137,9 +138,60 @@ export const Default = {
|
|
|
137
138
|
}
|
|
138
139
|
};
|
|
139
140
|
|
|
141
|
+
export const TintVariant = {
|
|
142
|
+
name: "Tint Variant — VPN",
|
|
143
|
+
args: {
|
|
144
|
+
variant : "tint",
|
|
145
|
+
eyebrow : "Privacy for autonomous AI agents",
|
|
146
|
+
title : "Bitdefender VPN for AI Agents",
|
|
147
|
+
description : "Each prompt gets a fresh, disposable container scoped to a specific location, so your agent's traffic isn't tied to your home connection or your personal IP.",
|
|
148
|
+
terminalCaption: "// illustrative — every connection closes when the prompt ends"
|
|
149
|
+
},
|
|
150
|
+
render: (args) => html`
|
|
151
|
+
<bd-header-code
|
|
152
|
+
variant=${args.variant}
|
|
153
|
+
eyebrow=${args.eyebrow}
|
|
154
|
+
title=${args.title}
|
|
155
|
+
description=${args.description}
|
|
156
|
+
terminal-caption=${args.terminalCaption}
|
|
157
|
+
>
|
|
158
|
+
<span slot="breadcrumb">Bitdefender AI</span>
|
|
159
|
+
<span slot="breadcrumb">vpn-for-agents</span>
|
|
160
|
+
|
|
161
|
+
<bd-button-link slot="primary-button" label="Download for macOS" kind="primary" size="md" font-size="18px" font-weight="600">Download for macOS</bd-button-link>
|
|
162
|
+
<bd-button-link slot="secondary-button" label="See how it works" kind="primary-outline" size="md" font-size="18px" font-weight="600">See how it works</bd-button-link>
|
|
163
|
+
<span slot="badge">EXTERNAL BETA</span>
|
|
164
|
+
|
|
165
|
+
<bd-terminal-message
|
|
166
|
+
slot="terminal-content"
|
|
167
|
+
show-titlebar
|
|
168
|
+
.lines=${[
|
|
169
|
+
{ type: "strong", text: "VPN for AI Agents · connection log" },
|
|
170
|
+
{ type: "sep" },
|
|
171
|
+
{ type: "dim", text: "MCP vpn_connect(location: frankfurt) [Open]" },
|
|
172
|
+
{ type: "dim", text: "REQUEST agent reaches insurer-compare.com [Server IP]" },
|
|
173
|
+
{ type: "dim", text: "NETWORK hotel Wi-Fi, unencrypted [Protected]" },
|
|
174
|
+
{ type: "dim", text: "MCP vpn_safefetch(location: frankfurt, url:" },
|
|
175
|
+
{ type: "dim", text: " insurer-compare.com) [Scanned]" },
|
|
176
|
+
{ type: "dim", text: "MCP vpn_disconnect(location: frankfurt)" },
|
|
177
|
+
{ type: "dim", text: " — prompt ends [Closed, session cleared]" }
|
|
178
|
+
]}
|
|
179
|
+
></bd-terminal-message>
|
|
180
|
+
</bd-header-code>
|
|
181
|
+
`,
|
|
182
|
+
parameters: {
|
|
183
|
+
docs: {
|
|
184
|
+
description: {
|
|
185
|
+
story: "`variant=\"tint\"` swaps the plain background for the light-blue gradient + dot-grid treatment, and the badge slot renders as a bordered pill. The floating annotation callouts seen in the reference design (\"exit: frankfurt · server IP\", \"tunnel closed — session cleared\") aren't reproduced here — they'd need to be a feature of `bd-terminal-message` itself, which isn't in scope for `bd-header-code`."
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
140
191
|
export const NoEyebrow = {
|
|
141
192
|
name: "No Eyebrow",
|
|
142
193
|
args: {
|
|
194
|
+
variant : "default",
|
|
143
195
|
eyebrow : "",
|
|
144
196
|
title : "Bitdefender AI Guardian",
|
|
145
197
|
description : "A security layer between your AI agents and the actions they take.",
|
|
@@ -158,6 +210,7 @@ export const NoEyebrow = {
|
|
|
158
210
|
export const SingleButton = {
|
|
159
211
|
name: "Single CTA",
|
|
160
212
|
args: {
|
|
213
|
+
variant : "default",
|
|
161
214
|
eyebrow : "Security for autonomous AI agents",
|
|
162
215
|
title : "Bitdefender AI Guardian",
|
|
163
216
|
description : "A security layer between your AI agents and the actions they take.",
|
|
@@ -165,6 +218,7 @@ export const SingleButton = {
|
|
|
165
218
|
},
|
|
166
219
|
render: (args) => html`
|
|
167
220
|
<bd-header-code
|
|
221
|
+
variant=${args.variant}
|
|
168
222
|
eyebrow=${args.eyebrow}
|
|
169
223
|
title=${args.title}
|
|
170
224
|
description=${args.description}
|
|
@@ -192,6 +246,7 @@ export const SingleButton = {
|
|
|
192
246
|
export const NoCaption = {
|
|
193
247
|
name: "No Caption",
|
|
194
248
|
args: {
|
|
249
|
+
variant : "default",
|
|
195
250
|
eyebrow : "Security for autonomous AI agents",
|
|
196
251
|
title : "Bitdefender AI Guardian",
|
|
197
252
|
description : "A security layer between your AI agents and the actions they take.",
|
|
@@ -210,6 +265,7 @@ export const NoCaption = {
|
|
|
210
265
|
export const Playground = {
|
|
211
266
|
name: "Playground",
|
|
212
267
|
args: {
|
|
268
|
+
variant : "default",
|
|
213
269
|
eyebrow : "Security for autonomous AI agents",
|
|
214
270
|
title : "Bitdefender AI Guardian",
|
|
215
271
|
description : "A security layer between your AI agents and the actions they take — policies, guardrails, and monitoring that let agents run safely.",
|
|
@@ -219,7 +275,7 @@ export const Playground = {
|
|
|
219
275
|
parameters: {
|
|
220
276
|
docs: {
|
|
221
277
|
description: {
|
|
222
|
-
story: "Fully interactive story — use the Controls panel to edit eyebrow, title, description, and terminal caption live."
|
|
278
|
+
story: "Fully interactive story — use the Controls panel to edit eyebrow, title, description, variant, and terminal caption live."
|
|
223
279
|
}
|
|
224
280
|
}
|
|
225
281
|
}
|
|
@@ -19,7 +19,7 @@ class BdPageSwitcher extends LitElement {
|
|
|
19
19
|
render() {
|
|
20
20
|
return html`
|
|
21
21
|
<div class="inner">
|
|
22
|
-
<bd-ai-icon class="logo" width="
|
|
22
|
+
<bd-ai-icon class="logo" width="200" height="24"></bd-ai-icon>
|
|
23
23
|
|
|
24
24
|
<nav aria-label="Product navigation">
|
|
25
25
|
${this.items.map(({ title, href, active }) => html`
|