@repobit/dex-system-design 0.24.4 → 0.24.6

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/package.json +4 -4
  3. package/src/components/accordion/accordion.css.js +40 -0
  4. package/src/components/accordion/accordion.js +31 -0
  5. package/src/components/accordion/accordion.stories.js +147 -4
  6. package/src/components/agent-endpoints/agent-endpoints.css.js +92 -0
  7. package/src/components/agent-endpoints/agent-endpoints.js +86 -0
  8. package/src/components/agent-endpoints/agent-endpoints.stories.js +148 -0
  9. package/src/components/ai-guardian-demo.stories.js +848 -0
  10. package/src/components/awards/awards-flex.css.js +169 -0
  11. package/src/components/awards/awards-flex.js +269 -0
  12. package/src/components/awards/awards-flex.stories.js +657 -0
  13. package/src/components/bento-grid/bento-grid.css.js +57 -0
  14. package/src/components/bento-grid/bento-grid.js +186 -0
  15. package/src/components/bento-grid/bento-grid.stories.js +440 -0
  16. package/src/components/bento-grid/bento-item.css.js +105 -0
  17. package/src/components/bento-grid/bento-item.js +57 -0
  18. package/src/components/button/button.css.js +26 -0
  19. package/src/components/button/button.js +8 -0
  20. package/src/components/button/button.stories.js +12 -0
  21. package/src/components/comparison-panel/comparison-panel.css.js +104 -0
  22. package/src/components/comparison-panel/comparison-panel.js +100 -0
  23. package/src/components/comparison-panel/comparison-panel.stories.js +223 -0
  24. package/src/components/compatibility-table/compatibility-table.css.js +243 -0
  25. package/src/components/compatibility-table/compatibility-table.js +123 -0
  26. package/src/components/compatibility-table/compatibility-table.stories.js +189 -0
  27. package/src/components/cta-banner/cta-banner.css.js +60 -0
  28. package/src/components/cta-banner/cta-banner.js +63 -0
  29. package/src/components/dropdown/dropdown.css.js +1 -1
  30. package/src/components/footer/footer.css.js +0 -1
  31. package/src/components/header/header-code.css.js +125 -0
  32. package/src/components/header/header-code.js +69 -0
  33. package/src/components/header/header-code.stories.js +226 -0
  34. package/src/components/heading/heading.css.js +3 -0
  35. package/src/components/icons/bd-ai-icon.js +27 -0
  36. package/src/components/icons/quote-icon.js +28 -0
  37. package/src/components/install-options/install-options.css.js +276 -0
  38. package/src/components/install-options/install-options.js +184 -0
  39. package/src/components/list/list-item/list-item.css.js +3 -3
  40. package/src/components/list/list-item/list-item.js +10 -4
  41. package/src/components/overview/overview.css.js +121 -0
  42. package/src/components/overview/overview.js +63 -0
  43. package/src/components/overview/overview.stories.js +193 -0
  44. package/src/components/page-switcher/page-switcher.css.js +100 -0
  45. package/src/components/page-switcher/page-switcher.js +42 -0
  46. package/src/components/paragraph/paragraph.css.js +1 -5
  47. package/src/components/paragraph/paragraph.js +7 -3
  48. package/src/components/process-steps/process-steps.css.js +95 -0
  49. package/src/components/process-steps/process-steps.js +72 -0
  50. package/src/components/process-steps/process-steps.stories.js +144 -0
  51. package/src/components/quick-answer/quick-answer.css.js +67 -0
  52. package/src/components/quick-answer/quick-answer.js +59 -0
  53. package/src/components/quick-answer/quick-answer.stories.js +160 -0
  54. package/src/components/review/review-grid.css.js +34 -0
  55. package/src/components/review/review-grid.js +63 -0
  56. package/src/components/review/review.css.js +50 -0
  57. package/src/components/review/review.js +58 -0
  58. package/src/components/review/review.stories.js +228 -0
  59. package/src/components/terminal/terminal-cursor.js +49 -0
  60. package/src/components/terminal/terminal-message.css.js +161 -0
  61. package/src/components/terminal/terminal-message.js +169 -0
  62. package/src/components/terminal/terminal-message.stories.js +321 -0
  63. package/src/components/trust-panel/trust-panel.css.js +167 -0
  64. package/src/components/trust-panel/trust-panel.js +116 -0
  65. package/src/components/trust-panel/trust-panel.stories.js +234 -0
  66. package/src/tokens/tokens.css +1 -1
  67. package/src/components/tabsComponent/tabsComponent.css.js +0 -267
  68. package/src/components/tabsComponent/tabsComponent.js +0 -193
  69. package/src/components/tabsComponent/tabsComponent.stories.js +0 -134
  70. package/src/components/tabsComponentFamily/tabsComponentFamily.css.js +0 -181
  71. package/src/components/tabsComponentFamily/tabsComponentFamily.js +0 -180
  72. package/src/components/tabsComponentFamily/tabsComponentFamily.stories.js +0 -319
package/CHANGELOG.md CHANGED
@@ -3,6 +3,21 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.24.6](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.24.5...@repobit/dex-system-design@0.24.6) (2026-09-04)
7
+
8
+ ### Bug Fixes
9
+
10
+ * **DEX-1014:** new review component
11
+ * **DEX-1014:** new review component
12
+
13
+
14
+ ## [0.24.5](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.24.4...@repobit/dex-system-design@0.24.5) (2026-09-01)
15
+
16
+ ### Bug Fixes
17
+
18
+ * **DEX-1014:** bitdefender AI components and new adjustments for components
19
+
20
+
6
21
  ## [0.24.4](https://github.com/bitdefender/dex-core/compare/@repobit/dex-system-design@0.24.3...@repobit/dex-system-design@0.24.4) (2026-09-01)
7
22
 
8
23
  ### Bug Fixes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@repobit/dex-system-design",
3
- "version": "0.24.4",
3
+ "version": "0.24.6",
4
4
  "description": "Design system based on Web Components.",
5
5
  "author": "Iordache Matei Cezar <miordache@bitdefender.com>",
6
6
  "homepage": "https://github.com/bitdefender/dex-core#readme",
@@ -74,8 +74,8 @@
74
74
  "url": "https://github.com/bitdefender/dex-core/issues"
75
75
  },
76
76
  "dependencies": {
77
- "@repobit/dex-store": "1.6.20",
78
- "@repobit/dex-store-elements": "2.0.25",
77
+ "@repobit/dex-store": "1.6.22",
78
+ "@repobit/dex-store-elements": "2.0.27",
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": "ce79d0c8b5feaab29ecbb54359d1035221a854b9"
95
+ "gitHead": "fd22ce80b8bee483acc6ac7739bdd940df5a64a5"
96
96
  }
@@ -195,6 +195,46 @@ export const accordionItem = css`
195
195
  width: 100%;
196
196
  }
197
197
  }
198
+
199
+ /* === CHEVRON VARIANT (text + arrow icon only, no visible border/pill/background) === */
200
+ .header--chevron {
201
+ display: inline-flex;
202
+ align-items: center;
203
+ justify-content: flex-start;
204
+ width: auto;
205
+ gap: var(--spacing-8);
206
+ padding: 0;
207
+ border: none;
208
+ border-radius: 0;
209
+ background: none;
210
+ margin-bottom: var(--spacing-24);
211
+ font-size: var(--typography-fontSize-sm);
212
+ font-weight: var(--typography-fontWeight-semibold);
213
+ }
214
+
215
+ .header--chevron .title-badge-wrapper {
216
+ flex: 0 1 auto;
217
+ }
218
+
219
+ .header--chevron .title {
220
+ color: var(--color-blue-600);
221
+ white-space: nowrap;
222
+ }
223
+
224
+ .header--chevron:hover .title {
225
+ text-decoration: underline;
226
+ }
227
+
228
+ .toggle--chevron {
229
+ width: 16px;
230
+ min-width: 16px;
231
+ height: 16px;
232
+ margin-top: 0;
233
+ }
234
+
235
+ .content--chevron {
236
+ padding: 0;
237
+ }
198
238
  `;
199
239
 
200
240
  export const accordionSection = css`
@@ -1,6 +1,8 @@
1
1
  import { LitElement, html } from "lit";
2
2
  import { tokens } from "../../tokens/tokens.js";
3
3
  import "../heading/heading.js";
4
+ import "../icons/arrow-down-icon.js";
5
+ import "../icons/arrow-up-icon.js";
4
6
  import "../icons/minus-icon.js";
5
7
  import "../icons/plus-icon.js";
6
8
  import "../paragraph/paragraph.js";
@@ -12,6 +14,7 @@ export class BdAccordionItem extends LitElement {
12
14
  static properties = {
13
15
  open : { type: Boolean, reflect: true },
14
16
  title : { type: String },
17
+ chevron : { type: Boolean, reflect: true }, // text + arrow icon variant
15
18
  _panelId: { type: String, state: true }
16
19
  };
17
20
 
@@ -19,6 +22,7 @@ export class BdAccordionItem extends LitElement {
19
22
  super();
20
23
  this.open = false;
21
24
  this.title = "";
25
+ this.chevron = false;
22
26
  this._panelId = `acc-panel-${Math.random().toString(36)
23
27
  .slice(2, 11)}`;
24
28
  }
@@ -46,6 +50,33 @@ export class BdAccordionItem extends LitElement {
46
50
  render() {
47
51
  const badgeEl = this.querySelector("[slot='badge']");
48
52
 
53
+ if (this.chevron) {
54
+ return html`
55
+ <button
56
+ type="button"
57
+ class="header header--chevron"
58
+ aria-expanded="${this.open}"
59
+ aria-controls="${this._panelId}"
60
+ @click=${this.toggle}
61
+ @focusin=${this._onTriggerFocusIn}
62
+ @focusout=${this._onTriggerFocusOut}
63
+ >
64
+ <span class="title-badge-wrapper">
65
+ <span class="title">${this.title}</span>
66
+ ${badgeEl ? badgeEl.cloneNode(true) : ""}
67
+ </span>
68
+ <span class="toggle toggle--chevron" aria-hidden="true">
69
+ ${this.open
70
+ ? html`<bd-arrow-up-icon size="16" color="#006DFF"></bd-arrow-up-icon>`
71
+ : html`<bd-arrow-down-icon size="16" color="#006DFF"></bd-arrow-down-icon>`}
72
+ </span>
73
+ </button>
74
+ <div id="${this._panelId}" class="content content--chevron" ?hidden=${!this.open}>
75
+ <slot></slot>
76
+ </div>
77
+ `;
78
+ }
79
+
49
80
  return html`
50
81
  <button
51
82
  type="button"
@@ -1,4 +1,5 @@
1
1
  import { html } from "lit";
2
+ import "../compatibility-table/compatibility-table.js";
2
3
  import "./accordion.js";
3
4
 
4
5
  export default {
@@ -22,6 +23,12 @@ Two Lit web components for building accordion sections.
22
23
  </bd-accordion-section>
23
24
  \`\`\`
24
25
 
26
+ \`bd-accordion-item\` also supports a \`chevron\` variant — plain blue text with an arrow
27
+ icon (\`bd-arrow-down-icon\`/\`bd-arrow-up-icon\`) on the right, no border or
28
+ background — instead of the default left-side plus/minus icon. Combine it with
29
+ \`bd-compatibility-table\` (\`variant="risk"\`) to build a collapsible risk-mapping
30
+ table, as shown below.
31
+
25
32
  ### Attributes
26
33
 
27
34
  #### \`bd-accordion-section\`
@@ -34,10 +41,11 @@ Two Lit web components for building accordion sections.
34
41
  | \`guide-href\` | String | \`#\` | URL for the user guide link |
35
42
 
36
43
  #### \`bd-accordion-item\`
37
- | Attribute | Type | Default | Description |
38
- |-----------|---------|---------|--------------------------------------|
39
- | \`title\` | String | — | Trigger label |
40
- | \`open\` | Boolean | \`false\`| Whether the panel is expanded |
44
+ | Attribute | Type | Default | Description |
45
+ |-----------|---------|---------|-------------------------------------------------------------------------|
46
+ | \`title\` | String | — | Trigger label |
47
+ | \`open\` | Boolean | \`false\`| Whether the panel is expanded |
48
+ | \`chevron\` | Boolean | \`false\`| Renders the plain text + arrow-icon style instead of the default left plus/minus icon |
41
49
  `
42
50
  }
43
51
  }
@@ -240,4 +248,139 @@ export const ManyItems = {
240
248
  </bd-accordion-item>
241
249
  </bd-accordion-section>
242
250
  `
251
+ };
252
+
253
+
254
+ // ─── Chevron variant — risk mapping (matches reference design) ────────────────
255
+
256
+ export const RiskMappingAccordion = {
257
+ name : "Chevron variant — Risk mapping table",
258
+ render: () => html`
259
+ <div style="max-width: 900px;">
260
+ <bd-h as="h2" font-weight="700" style="margin: 0 0 8px;">Coverage against agentic AI risk categories</bd-h>
261
+ <bd-p kind="regular" style="color: var(--color-neutral-700); margin: 0 0 24px;">
262
+ How AI Guardian maps to the risk categories the industry is standardising on for agentic applications.
263
+ </bd-p>
264
+
265
+ <bd-accordion-item chevron title="Show the full mapping (6 categories)">
266
+ <bd-compatibility-table
267
+ variant="risk"
268
+ .rows=${[
269
+ { category: "Prompt injection", coverage: "Inspects agent inputs and actions; returns allowed, flagged or blocked" },
270
+ { category: "Tool and MCP misuse", coverage: "Detects and blocks malicious or tampered MCP tools before invocation" },
271
+ { category: "Excessive or unscoped permissions", coverage: "Policy baseline defines what agents may do with tools, files and actions" },
272
+ { category: "Sensitive data exposure", coverage: "Detects credential and secret exposure before it leaves the machine" },
273
+ { category: "Unvetted extensions and skills", coverage: "Scans and validates skills before they run" },
274
+ { category: "Unmonitored agent activity", coverage: "Real-time tool-call monitoring with an auditable record" }
275
+ ]}
276
+ ></bd-compatibility-table>
277
+ </bd-accordion-item>
278
+
279
+ <bd-p kind="small" style="color: var(--color-neutral-500); margin-top: 16px;">
280
+ Category naming follows OWASP Top 10 for Agentic Applications (2026).
281
+ </bd-p>
282
+ </div>
283
+ `,
284
+ parameters: {
285
+ docs: {
286
+ description: {
287
+ story: "The chevron variant of bd-accordion-item (plain blue text, bd-arrow-down-icon/bd-arrow-up-icon on the right, no border) toggling a bd-compatibility-table in risk variant (2 columns: Risk category / AI Guardian coverage)."
288
+ }
289
+ }
290
+ }
291
+ };
292
+
293
+
294
+ // ─── Chevron variant — collapsed state ─────────────────────────────────────────
295
+
296
+ export const ChevronCollapsed = {
297
+ name : "Chevron variant — collapsed",
298
+ render: () => html`
299
+ <bd-accordion-item chevron title="Show the full mapping (6 categories)">
300
+ <bd-compatibility-table
301
+ variant="risk"
302
+ .rows=${[
303
+ { category: "Prompt injection", coverage: "Inspects agent inputs and actions; returns allowed, flagged or blocked" },
304
+ { category: "Tool and MCP misuse", coverage: "Detects and blocks malicious or tampered MCP tools before invocation" }
305
+ ]}
306
+ ></bd-compatibility-table>
307
+ </bd-accordion-item>
308
+ `,
309
+ parameters: {
310
+ docs: {
311
+ description: {
312
+ story: "Starts collapsed — click the text to expand and see the icon switch from bd-arrow-down-icon to bd-arrow-up-icon."
313
+ }
314
+ }
315
+ }
316
+ };
317
+
318
+
319
+ // ─── Default plus/minus vs chevron, side by side ───────────────────────────────
320
+
321
+ export const DefaultVsChevron = {
322
+ name : "Default plus/minus vs chevron",
323
+ render: () => html`
324
+ <div style="display: flex; flex-direction: column; gap: 32px;">
325
+ <div>
326
+ <bd-p kind="small" style="color: var(--color-neutral-500); margin-bottom: 8px;">Default (plus/minus, left icon)</bd-p>
327
+ <bd-accordion-item title="Default accordion item">
328
+ <p>Regular accordion content, unaffected by the new chevron variant.</p>
329
+ </bd-accordion-item>
330
+ </div>
331
+
332
+ <div>
333
+ <bd-p kind="small" style="color: var(--color-neutral-500); margin-bottom: 8px;">Chevron (plain text, right arrow icon, no border)</bd-p>
334
+ <bd-accordion-item chevron title="Chevron accordion item">
335
+ <p>Same underlying component, opt-in chevron styling via the chevron attribute.</p>
336
+ </bd-accordion-item>
337
+ </div>
338
+ </div>
339
+ `,
340
+ parameters: {
341
+ docs: {
342
+ description: {
343
+ story: "The two styles side by side, demonstrating that the chevron attribute is purely additive — existing default accordion items are completely unaffected."
344
+ }
345
+ }
346
+ }
347
+ };
348
+ // ─── Chevron variant — operational details (light table variant) ───────────
349
+
350
+ export const OperationalDetailsAccordion = {
351
+ name : "Chevron variant — Operational details (light table)",
352
+ render: () => html`
353
+ <div style="max-width: 900px;">
354
+ <bd-h as="h2" font-weight="700" style="margin: 0 0 8px;">How it runs</bd-h>
355
+ <bd-p kind="regular" style="color: var(--color-neutral-700); margin: 0 0 24px;">
356
+ AI Guardian installs from a signed macOS installer and runs as a background service; the rows below list how it installs, where analysis happens, and what the BETA costs.
357
+ </bd-p>
358
+
359
+ <bd-accordion-item chevron title="Show operational details (11 rows)">
360
+ <bd-compatibility-table
361
+ variant="light"
362
+ .rows=${[
363
+ { label: "Runs as", value: "Background service on the endpoint" },
364
+ { label: "Install method", value: "Download the macOS installer (.dmg)" },
365
+ { label: "System permissions required", value: "Granted during install, when the Bitdefender agent asks" },
366
+ { label: "Installer", value: "Signed with a Bitdefender Apple Developer ID and recognised by macOS" },
367
+ { label: "Agent version checks", value: "Handled by the installer" },
368
+ { label: "Where analysis happens", value: "On-device, with some checks (such as URL reputation) using Bitdefender cloud services" },
369
+ { label: "Prompt data", value: "Analysed on-device — prompts never leave your Mac" },
370
+ { label: "Offline operation", value: "Some features" },
371
+ { label: "Performance overhead", value: "Designed to be minimal; not yet measured" },
372
+ { label: "Availability", value: "Open BETA, free download" },
373
+ { label: "Price during BETA", value: "Free" }
374
+ ]}
375
+ ></bd-compatibility-table>
376
+ </bd-accordion-item>
377
+ </div>
378
+ `,
379
+ parameters: {
380
+ docs: {
381
+ description: {
382
+ story: "Same chevron bd-accordion-item pattern as the risk mapping example, this time revealing a bd-compatibility-table in the new light variant — no outer border/background, just a 2-column grid of label/value rows with thin dividers. Matches the \"How it runs\" reference exactly."
383
+ }
384
+ }
385
+ }
243
386
  };
@@ -0,0 +1,92 @@
1
+ import { css } from "lit";
2
+
3
+ export default css`
4
+ :host {
5
+ display: block;
6
+ font-family: var(--typography-fontFamily-sans);
7
+ }
8
+
9
+ .bd-agentendpoints-wrapper {
10
+ max-width: var(--layout-ensemble-max-width, 1200px);
11
+ margin: 0 auto;
12
+ padding: var(--spacing-48) var(--layout-ensemble-inline-padding, var(--spacing-24));
13
+ box-sizing: border-box;
14
+ }
15
+
16
+ .bd-agentendpoints-eyebrow {
17
+ display: block;
18
+ margin: 0 0 var(--spacing-8);
19
+ color: var(--color-blue-500);
20
+ }
21
+
22
+ .bd-agentendpoints-title {
23
+ display: block;
24
+ margin: 0 0 var(--spacing-16);
25
+ color: var(--color-neutral-1000);
26
+ line-height: var(--typography-lineHeight-tight, 1.1);
27
+ }
28
+
29
+ .bd-agentendpoints-description {
30
+ display: block;
31
+ margin: 0 0 var(--spacing-24);
32
+ color: var(--color-neutral-600);
33
+ max-width: 70ch;
34
+ }
35
+
36
+ .bd-agentendpoints-row {
37
+ display: flex;
38
+ flex-wrap: wrap;
39
+ gap: var(--spacing-12);
40
+ margin-bottom: var(--spacing-12);
41
+ }
42
+
43
+ .bd-agentendpoints-row:last-of-type {
44
+ margin-bottom: 0;
45
+ }
46
+
47
+ /* === button--outline-white ===
48
+ White pill button with a thin gray border, rounded corners — used both
49
+ for the /endpoint links (with a leading arrow, monospace label) and the
50
+ "Ask <assistant>" links (with a leading brand icon). Reusable class,
51
+ not scoped to this component only. */
52
+ .button--outline-white {
53
+ display: inline-flex;
54
+ align-items: center;
55
+ gap: var(--spacing-8);
56
+ padding: var(--spacing-10, 10px) var(--spacing-16);
57
+ background: var(--color-neutral-0, #fff);
58
+ border: 1px solid var(--color-neutral-200, #e5e7eb);
59
+ border-radius: var(--radius-full, 999px);
60
+ color: var(--color-neutral-800);
61
+ font-size: var(--typography-fontSize-sm);
62
+ font-weight: var(--typography-fontWeight-medium, 500);
63
+ text-decoration: none;
64
+ white-space: nowrap;
65
+ transition: border-color 0.2s ease, background 0.2s ease;
66
+ }
67
+
68
+ .button--outline-white:hover {
69
+ border-color: var(--color-blue-300, #93c5fd);
70
+ background: var(--color-blue-50, #eef4ff);
71
+ }
72
+
73
+ .bd-agentendpoints-arrow {
74
+ color: var(--color-neutral-400, #9ca3af);
75
+ }
76
+
77
+ .bd-agentendpoints-mono {
78
+ font-family: var(--typography-fontFamily-mono, monospace);
79
+ color: var(--color-neutral-700);
80
+ }
81
+
82
+ .bd-agentendpoints-icon {
83
+ display: block;
84
+ flex-shrink: 0;
85
+ }
86
+
87
+ @media (max-width: 599px) {
88
+ .bd-agentendpoints-wrapper {
89
+ padding: var(--spacing-32) var(--spacing-24);
90
+ }
91
+ }
92
+ `;
@@ -0,0 +1,86 @@
1
+ import { LitElement, html, nothing } from "lit";
2
+ import { tokens } from "../../tokens/tokens.js";
3
+ import "../heading/heading.js";
4
+ import "../paragraph/paragraph.js";
5
+ import agentEndpointsCSS from "./agent-endpoints.css.js";
6
+
7
+ class AgentEndpoints extends LitElement {
8
+ static properties = {
9
+ eyebrow : { type: String },
10
+ title : { type: String },
11
+ description: { type: String },
12
+ endpoints : { type: Array }, // [{ label: String, href: String }]
13
+ assistants : { type: Array } // [{ label: String, href: String, icon: String }]
14
+ };
15
+
16
+ static styles = [tokens, agentEndpointsCSS];
17
+
18
+ constructor() {
19
+ super();
20
+ this.eyebrow = "";
21
+ this.title = "";
22
+ this.description = "";
23
+ this.endpoints = [];
24
+ this.assistants = [];
25
+ }
26
+
27
+ render() {
28
+ return html`
29
+ <div class="bd-agentendpoints-wrapper">
30
+ ${this.eyebrow
31
+ ? html`<bd-p kind="regular" font-weight="var(--typography-fontWeight-semibold, 600)" class="bd-agentendpoints-eyebrow"><slot name="eyebrow">${this.eyebrow}</slot></bd-p>`
32
+ : nothing}
33
+
34
+ ${this.title
35
+ ? html`<bd-h as="h2" class="bd-agentendpoints-title"><slot name="title">${this.title}</slot></bd-h>`
36
+ : nothing}
37
+
38
+ ${this.description
39
+ ? html`<bd-p kind="regular" class="bd-agentendpoints-description"><slot name="description">${this.description}</slot></bd-p>`
40
+ : nothing}
41
+
42
+ ${this.endpoints && this.endpoints.length
43
+ ? html`
44
+ <div class="bd-agentendpoints-row">
45
+ ${this.endpoints.map(
46
+ (ep) => html`
47
+ <a class="button--outline-white" href=${ep.href} target="_blank" rel="noopener noreferrer">
48
+ <span class="bd-agentendpoints-arrow" aria-hidden="true">→</span>
49
+ <span class="bd-agentendpoints-mono">${ep.label}</span>
50
+ </a>
51
+ `
52
+ )}
53
+ </div>
54
+ `
55
+ : nothing}
56
+
57
+ ${this.assistants && this.assistants.length
58
+ ? html`
59
+ <div class="bd-agentendpoints-row">
60
+ ${this.assistants.map(
61
+ (a) => html`
62
+ <a
63
+ class="button--outline-white"
64
+ href=${a.href}
65
+ target="_blank"
66
+ rel="noopener noreferrer"
67
+ aria-label="${a.label} (opens in new tab)"
68
+ >
69
+ ${a.icon
70
+ ? html`<img src=${a.icon} alt="" class="bd-agentendpoints-icon" width="20" height="20" loading="lazy" />`
71
+ : nothing}
72
+ <span>${a.label}</span>
73
+ </a>
74
+ `
75
+ )}
76
+ </div>
77
+ `
78
+ : nothing}
79
+
80
+ <slot name="rows"></slot>
81
+ </div>
82
+ `;
83
+ }
84
+ }
85
+
86
+ customElements.define("bd-agent-endpoints", AgentEndpoints);
@@ -0,0 +1,148 @@
1
+ import { html } from "lit";
2
+ import "./agent-endpoints.js";
3
+
4
+ export default {
5
+ title : "Components/Agent Endpoints",
6
+ component : "bd-agent-endpoints",
7
+ tags : ["autodocs"],
8
+ parameters: {
9
+ layout: "padded",
10
+ docs : {
11
+ description: {
12
+ component: `
13
+ **AgentEndpoints** shows an eyebrow/title/description block followed by two rows of
14
+ pill-shaped links: machine-readable endpoint URLs (\`/llms.txt\`, \`/sitemap.xml\`,
15
+ etc.) and "Ask <assistant>" quick links (ChatGPT, Perplexity, Gemini, Copilot).
16
+
17
+ Both rows share the same \`button--outline-white\` class — a reusable white pill with
18
+ a thin border — so the visual style stays consistent across any future use of that
19
+ class elsewhere.
20
+
21
+ ### Usage
22
+ \`\`\`html
23
+ <bd-agent-endpoints
24
+ eyebrow="For AI agents and assistants"
25
+ title="Machine-readable endpoints"
26
+ description="This site is built to be read by AI assistants, browsers, and agents. Structured, curated context is available at:"
27
+ .endpoints=\${[
28
+ { label: "/llms.txt", href: "/llms.txt" },
29
+ { label: "/llms-full.txt", href: "/llms-full.txt" },
30
+ { label: "/index.md", href: "/index.md" },
31
+ { label: "/sitemap.xml", href: "/sitemap.xml" },
32
+ { label: "/robots.txt", href: "/robots.txt" }
33
+ ]}
34
+ .assistants=\${[
35
+ { label: "Ask ChatGPT", href: "https://chatgpt.com/?q=...", icon: "/openai-brands-solid-full.svg" },
36
+ { label: "Ask Perplexity", href: "https://www.perplexity.ai/search?q=...", icon: "/perplexity-icon-dark.svg" }
37
+ ]}
38
+ ></bd-agent-endpoints>
39
+ \`\`\`
40
+
41
+ ### Attributes
42
+ | Attribute | Type | Default | Description |
43
+ |------------------|--------|---------|--------------------------------------------------------------|
44
+ | \`eyebrow\` | String | \`""\` | Small blue label above the title |
45
+ | \`title\` | String | \`""\` | Heading (or the \`title\` slot) |
46
+ | \`description\` | String | \`""\` | Paragraph under the title (or the \`description\` slot) |
47
+ | \`endpoints\` | Array | \`[]\` | \`{ label, href }\` — rendered with a leading arrow, monospace label |
48
+ | \`assistants\` | Array | \`[]\` | \`{ label, href, icon }\` — rendered with a leading icon image |
49
+
50
+ ### Slots
51
+ | Slot | Description |
52
+ |-------------------|------------------------------------------------------------|
53
+ | \`eyebrow\` | Overrides the \`eyebrow\` attribute |
54
+ | \`title\` | Overrides the \`title\` attribute |
55
+ | \`description\` | Overrides the \`description\` attribute |
56
+ | \`rows\` | Extra freeform pill rows appended after the two generated ones |
57
+ `
58
+ }
59
+ }
60
+ }
61
+ };
62
+
63
+ const render = (args) => html`
64
+ <bd-agent-endpoints
65
+ eyebrow=${args.eyebrow}
66
+ title=${args.title}
67
+ description=${args.description}
68
+ .endpoints=${args.endpoints}
69
+ .assistants=${args.assistants}
70
+ ></bd-agent-endpoints>
71
+ `;
72
+
73
+ export const Default = {
74
+ name: "Default — Machine-Readable Endpoints",
75
+ args: {
76
+ eyebrow : "For AI agents and assistants",
77
+ title : "Machine-readable endpoints",
78
+ description: "This site is built to be read by AI assistants, browsers, and agents. Structured, curated context is available at:",
79
+ endpoints : [
80
+ { label: "/llms.txt", href: "/llms.txt" },
81
+ { label: "/llms-full.txt", href: "/llms-full.txt" },
82
+ { label: "/index.md", href: "/index.md" },
83
+ { label: "/sitemap.xml", href: "/sitemap.xml" },
84
+ { label: "/robots.txt", href: "/robots.txt" }
85
+ ],
86
+ assistants: [
87
+ { label: "Ask ChatGPT", href: "https://chatgpt.com/?q=Summarize%20https%3A%2F%2Fai.bitdefender.com%2F", icon: "/openai-brands-solid-full.svg" },
88
+ { label: "Ask Perplexity", href: "https://www.perplexity.ai/search?q=Summarize%20https%3A%2F%2Fai.bitdefender.com%2F", icon: "/perplexity-icon-dark.svg" },
89
+ { label: "Ask Gemini", href: "https://gemini.google.com/app?q=Summarize%20https%3A%2F%2Fai.bitdefender.com%2F", icon: "/Google_Gemini_icon_2025.svg" },
90
+ { label: "Ask Copilot", href: "https://copilot.microsoft.com/?q=Summarize%20https%3A%2F%2Fai.bitdefender.com%2F", icon: "/microsoft-copilot.svg" }
91
+ ]
92
+ },
93
+ render,
94
+ parameters: {
95
+ docs: {
96
+ description: {
97
+ story: "Matches the reference design exactly: eyebrow, title, description, a row of 5 endpoint pills, and a row of 4 assistant pills, all using button--outline-white."
98
+ }
99
+ }
100
+ }
101
+ };
102
+
103
+ export const EndpointsOnly = {
104
+ name: "Endpoints Only",
105
+ args: {
106
+ eyebrow : "For AI agents and assistants",
107
+ title : "Machine-readable endpoints",
108
+ description: "",
109
+ endpoints : [
110
+ { label: "/llms.txt", href: "/llms.txt" },
111
+ { label: "/sitemap.xml", href: "/sitemap.xml" }
112
+ ],
113
+ assistants: []
114
+ },
115
+ render,
116
+ parameters: {
117
+ docs: {
118
+ description: {
119
+ story: "assistants left empty — only the endpoints row renders."
120
+ }
121
+ }
122
+ }
123
+ };
124
+
125
+ export const Playground = {
126
+ name: "Playground",
127
+ args: {
128
+ eyebrow : "For AI agents and assistants",
129
+ title : "Machine-readable endpoints",
130
+ description: "This site is built to be read by AI assistants, browsers, and agents.",
131
+ endpoints : [
132
+ { label: "/llms.txt", href: "/llms.txt" },
133
+ { label: "/sitemap.xml", href: "/sitemap.xml" },
134
+ { label: "/robots.txt", href: "/robots.txt" }
135
+ ],
136
+ assistants: [
137
+ { label: "Ask ChatGPT", href: "https://chatgpt.com/?q=test", icon: "/openai-brands-solid-full.svg" }
138
+ ]
139
+ },
140
+ render,
141
+ parameters: {
142
+ docs: {
143
+ description: {
144
+ story: "Fully interactive — use the Controls panel to edit eyebrow, title, description, and both pill arrays live."
145
+ }
146
+ }
147
+ }
148
+ };