Repository: CleverCloud/clever-components
Pull request #1349: feat(cc-block-detail): init cc-block-detail component
Author: login: clara-layus-cc
Created: 2025-02-27T16:18:34Z | Merged: 2025-03-06T16:43:44Z

Fix #1348 

# What does this PR do?

Introduce the `cc-block-detail` component. This component displays more information in the `cc-block` footer as command lines.

# How to review?
- Check the code
- Check the stories in the preview
- Check if the design is close enough to the [wireframe](https://www.figma.com/design/rC5NuHHEZ1E7HEEAbQyvuq/CC-Block-new?node-id=8-771&t=SkZ82Je83zrQ47OH-1) made by Marion

Linked issue #1348: cc-block-detail: init component
## Context

The purpose of this component is to add more information in the footer of a cc-block. This will allow for example to add a CLI command list going with the cc-block information as well as documentation links.

## Inputs

### Attributes/properties

| Property | Type   | Default value | Mandatory | Description |
|----------|--------|---------------|-----------|-------------|
| `isOpen`    | `Boolean` | `false`        | `false`    | Defines whether the content is visible or not |

### Slots

| Name  | Description |
|-------|-------------|
| `tab-title` | The title of the tab. Try to only use text.        |
| `link` | A zone dedicated to link, for example to documentation. |
| `content` | A zone dedicated to main content. |

### CSS custom property

No CSS custom property.

### CSS part

No CSS part.

## Outputs

No outputs.


Diff:
diff --git a/src/components/cc-block-detail/cc-block-details.js b/src/components/cc-block-detail/cc-block-details.js
new file mode 100644
index 000000000..1b7c499ce
--- /dev/null
+++ b/src/components/cc-block-detail/cc-block-details.js
@@ -0,0 +1,131 @@
+import { css, html, LitElement } from 'lit';
+import { iconRemixArrowDownSLine as iconArrowDown } from '../../assets/cc-remix.icons.js';
+import { dispatchCustomEvent } from '../../lib/events.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ * The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @fires {CustomEvent<boolean>} cc-block-details:is-open-change - Fires is-open state whenever it changes.
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetails extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+    dispatchCustomEvent(this, 'is-open-change', !this.isOpen);
+  }
+
+  render() {
+    return html`
+      <div class="wrapper">
+        <button class="button" aria-expanded="${this.isOpen}" aria-controls="content" @click=${this._onClickToggle}>
+          <slot name="button-text"></slot>
+          <cc-icon .icon="${iconArrowDown}"></cc-icon>
+        </button>
+        <div id="content" class="content"><slot name="content"></slot></div>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+    `;
+  }
+
+  static get styles() {
+    return [
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .wrapper {
+          column-gap: 1em;
+          display: grid;
+          grid-template-areas: 'button links' 'content content';
+          justify-items: start;
+        }
+
+        .button {
+          align-items: center;
+          background-color: transparent;
+          border: solid 1px transparent;
+          display: flex;
+          font-family: inherit;
+          font-size: 1em;
+          grid-area: button;
+          padding: 0.25em 0.6em 0.35em;
+          transition: all 0.3s;
+        }
+
+        :host([is-open]) .button {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em) var(--cc-border-radius-default, 0.25em) 0 0;
+          margin-bottom: 0;
+        }
+
+        .button:hover {
+          border-radius: var(--cc-border-radius-default, 0.25em);
+        }
+
+        :host(:not([is-open])) .button:hover {
+          border: solid 1px var(--cc-color-border-neutral-strong, #8c8c8c);
+        }
+
+        .button cc-icon {
+          margin-left: 0.1em;
+          transition: all 0.3s;
+        }
+
+        :host([is-open]) .button cc-icon {
+          transform: rotate(180deg);
+        }
+
+        :host(:not([is-open])) .button:hover cc-icon {
+          transform: rotate(90deg);
+        }
+
+        .content {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em);
+          display: none;
+          grid-area: content;
+          padding: 1em;
+        }
+
+        :host([is-open]) .content {
+          display: block;
+        }
+
+        .links {
+          align-items: center;
+          display: flex;
+          gap: 0.5em;
+          grid-area: links;
+          justify-self: end;
+        }
+      `,
+    ];
+  }
+}
+
+window.customElements.define('cc-block-details', CcBlockDetails);
diff --git a/src/components/cc-block-detail/cc-block-details.stories.js b/src/components/cc-block-detail/cc-block-details.stories.js
new file mode 100644
index 000000000..1b7a78939
--- /dev/null
+++ b/src/components/cc-block-detail/cc-block-details.stories.js
@@ -0,0 +1,68 @@
+import { makeStory } from '../../stories/lib/make-story.js';
+import './cc-block-details.js';
+import '../cc-block/cc-block.js';
+
+export default {
+  tags: ['autodocs'],
+  title: '🧬 Molecules/<cc-block-details>',
+  component: 'cc-block-details',
+};
+
+const conf = {
+  component: 'cc-block',
+};
+
+const ccBlockHtmlExample = `
+  <div slot="header-title">This is my block</div>
+  <div slot="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque feugiat dui at leo porta dignissim. Etiam ut purus ultrices, pulvinar tellus quis, cursus massa. Mauris dignissim accumsan ex, at vestibulum lectus fermentum id. Quisque nec magna arcu. Quisque in metus sed erat sodales euismod eget id purus. Sed sagittis rhoncus mauris. Ut sit amet urna ac nunc semper porta. Nam ut felis eu velit luctus rutrum. Nam leo nisl, molestie a varius non, ullamcorper sit amet tortor. Donec in convallis ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent hendrerit venenatis erat, eu malesuada nulla viverra eu. Curabitur porta risus augue, non rutrum lectus hendrerit a.</div>
+`;
+
+const defaultHtmlExample = `
+  ${ccBlockHtmlExample}
+  <cc-block-details slot="footer-left">
+    <div slot="button-text">Command line</div>
+    <a slot="link" href="">See documentation</a>
+    <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. <a href="#">Fake link</a></div>
+  </cc-block-details>
+`;
+
+export const defaultStory = makeStory(conf, {
+  items: [
+    {
+      innerHTML: defaultHtmlExample,
+    },
+  ],
+});
+
+const openHtmlExample = `
+  ${ccBlockHtmlExample}
+  <cc-block-details is-open=true slot="footer-left">
+    <div slot="button-text">Command line</div>
+    <a slot="link" href="">See documentation</a>
+    <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. <a href="#">Fake link</a></div>
+  </cc-block-details>
+`;
+
+export const openStory = makeStory(conf, {
+  items: [
+    {
+      innerHTML: openHtmlExample,
+    },
+  ],
+});
+
+const withoutLinkHtmlExample = `
+  ${ccBlockHtmlExample}
+  <cc-block-details slot="footer-left">
+    <div slot="button-text">Command line</div>
+    <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. <a href="#">Fake link</a></div>
+  </cc-block-details>
+`;
+
+export const withoutLinkStory = makeStory(conf, {
+  items: [
+    {
+      innerHTML: withoutLinkHtmlExample,
+    },
+  ],
+});


Reviews:
user: login: pdesoyres-cc
body: Nice PR @clara-layus-cc , I left some comments and suggestions. My main concern is about the name of this component.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-28T10:36:43Z
user: login: clara-layus-cc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-02-28T13:40:51Z
user: login: pdesoyres-cc
body: LGTM. Well done @clara-layus-cc 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-02-28T14:50:36Z
user: login: hsablonniere
body: Hey @clara-layus-cc, congrats for this first component!! :+1: :clap: 

I added a few comments here and there. Here are additional feedbacks:

* I want footers with CLI tab + documentation links to look the same as footers with just a documentation link
  * We discussed that this component should maybe support situations without the CLI tab but I'm not sure
  * Let's discuss it together
* We will need to make sure the link looks the same as other links (color, hover...), maybe it's not that important for the story of this component as it's just a slot
* The following border radius are not the same as the design (bottom left, bottom right, top right)
* I have some doubts about the `iconArrowUp`, I like the animation but I'm not sure about the directions
* I like the focus state but I think the hover is too suble
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-03-03T13:51:58Z
user: login: Galimede
body: Hey Clara, nice work and congrats for your first component! :tada: 

I agree with Hubert feedbacks, don't have a lot to say on my side, GG! :muscle: 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-03T14:06:29Z
user: login: clara-layus-cc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T15:30:45Z
user: login: clara-layus-cc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T16:00:33Z
user: login: florian-sanders-cc
body: Congrats on your first component @clara-layus-cc :tada: :tada: 

The code is very clean and well documented, this is great work!

As discussed the timing was difficult and I could not make a11y recommendations before the implementation so we need to modify some parts of the component to fix a few issues.

This is normal and absolutely not your fault :wink:  

Let's discuss the fixes together in sync when you are available (with @roberttran-cc if he wants / has the time to join).

Here are a few global notes:
- **suggestion:** for the icon animation + orientation, we need to agree on a standard and use the same everywhere. The `cc-block` component already implements an animation for the same usecase: [cc-block - ribbon with toggle story](https://www.clever-cloud.com/doc/clever-components/?path=/story/%F0%9F%A7%AC-molecules-cc-block--ribbon-with-toggle). I personally prefer the one from `cc-block` but it should probably be discussed with Marion and we'll adjust to use the same everywhere (we'll open a separate issue if `cc-block` needs to be modified),
- **nitpick:** I think we should rename the component to `cc-block-details` (plural) because the singular doesn't exactly mean the same in English (very subtle difference though).
- **suggestion:** add a story for cases without documentation links.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T11:08:41Z
user: login: florian-sanders-cc
body: Only need to remove the `.test` file but apart from that, all good.

Excellent work @clara-layus-cc, you rock (yeah, I know, only old people use this phrase nowadays :older_man:)!!
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T08:38:45Z
user: login: florian-sanders-cc
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T10:46:18Z
user: login: florian-sanders-cc
body: All good! Great work again @clara-layus-cc :wink: 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-05T16:08:39Z
user: login: hsablonniere
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-05T16:44:49Z
user: login: hsablonniere
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-06T16:37:52Z

Review comments:
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: suggestion: if the state can take only two values, why not using a `boolean` and rename the property to `isOpen` (`false` by default) ?
created_at: 2025-02-28T10:27:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: fix: Since this component seams to be very generic, I'm not sure we should name it with `cli` suffix. Suggestion:

* `CcBlockDetail`
* `CcBlockFooter`

created_at: 2025-02-28T10:32:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {BlockToggleState} Sets the state of the toggle behaviour. */
+    this.toggle = 'close';
+  }
+
+  _onClickToggle() {
+    if (this.toggle === 'close') {
+      this.toggle = 'open';
+    } else {
+      this.toggle = 'close';
+    }
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.toggle === 'open' ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.toggle === 'open' ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default);
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: fix: we need a default value
created_at: 2025-02-28T10:33:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {BlockToggleState} Sets the state of the toggle behaviour. */
+    this.toggle = 'close';
+  }
+
+  _onClickToggle() {
+    if (this.toggle === 'close') {
+      this.toggle = 'open';
+    } else {
+      this.toggle = 'close';
+    }
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.toggle === 'open' ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.toggle === 'open' ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default);
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: fix: we need a default value
created_at: 2025-02-28T10:33:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {BlockToggleState} Sets the state of the toggle behaviour. */
+    this.toggle = 'close';
+  }
+
+  _onClickToggle() {
+    if (this.toggle === 'close') {
+      this.toggle = 'open';
+    } else {
+      this.toggle = 'close';
+    }
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.toggle === 'open' ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.toggle === 'open' ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default);
+          border-radius: var(--cc-border-radius-default) var(--cc-border-radius-default) 0 0;
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: fix: we need a default value
created_at: 2025-02-28T10:34:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {BlockToggleState} Sets the state of the toggle behaviour. */
+    this.toggle = 'close';
+  }
+
+  _onClickToggle() {
+    if (this.toggle === 'close') {
+      this.toggle = 'open';
+    } else {
+      this.toggle = 'close';
+    }
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.toggle === 'open' ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.toggle === 'open' ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default);
+          border-radius: var(--cc-border-radius-default) var(--cc-border-radius-default) 0 0;
+          margin-bottom: 0;
+        }
+
+        .tab cc-icon {
+          transition: all 0.3s;
+        }
+
+        .tab.open cc-icon {
+          transform: rotate(-180deg);
+        }
+
+        .tab.close:hover cc-icon {
+          transform: rotate(-90deg);
+        }
+
+        cc-icon {
+          margin-left: 0.1em;
+        }
+
+        .content {
+          background-color: var(--cc-color-bg-default);
path: src/components/cc-block-cli/cc-block-cli.js
user: login: pdesoyres-cc
body: fix: we need a default value
created_at: 2025-02-28T10:34:14Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,56 @@
+import { makeStory } from '../../stories/lib/make-story.js';
+import './cc-block-cli.js';
+import '../cc-block/cc-block.js';
+
+export default {
+  tags: ['autodocs'],
+  title: '🧬 Molecules/<cc-block-cli>',
+  component: 'cc-block-cli',
+};
+
+const conf = {
+  component: 'cc-block',
+};
+
+const ccBlockHtmlExemple = `
+  <div slot="header-title">This is my block</div>
+  <div slot="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque feugiat dui at leo porta dignissim. Etiam ut purus ultrices, pulvinar tellus quis, cursus massa. Mauris dignissim accumsan ex, at vestibulum lectus fermentum id. Quisque nec magna arcu. Quisque in metus sed erat sodales euismod eget id purus. Sed sagittis rhoncus mauris. Ut sit amet urna ac nunc semper porta. Nam ut felis eu velit luctus rutrum. Nam leo nisl, molestie a varius non, ullamcorper sit amet tortor. Donec in convallis ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent hendrerit venenatis erat, eu malesuada nulla viverra eu. Curabitur porta risus augue, non rutrum lectus hendrerit a.</div>
+`;
+
+const defaultHtmlExample = `
+  ${ccBlockHtmlExemple}
+  <div slot="footer" style="background-color: var(--cc-color-bg-neutral); border-top: solid 2px #cdcdcd">
+    <cc-block-cli>
+      <div slot="tab-title">Command line</div>
+      <a slot="link" href="">See documentation</a>
+      <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. </div>
+    </cc-block-cli>
+  </div>
+`;
+
+export const defaultStory = makeStory(conf, {
+  items: [
+    {
+      innerHTML: defaultHtmlExample,
+    },
+  ],
+});
+
+const openByDefaultHtmlExample = `
+  ${ccBlockHtmlExemple}
+  <div slot="footer" style="background-color: var(--cc-color-bg-neutral); border-top: solid 2px #cdcdcd">
+    <cc-block-cli toggle="open">
+      <div slot="tab-title">Command line</div>
+      <a slot="link" href="">See documentation</a>
+      <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. </div>
+    </cc-block-cli>
+  </div>
+`;
+
+export const openByDefaultStory = makeStory(conf, {
path: src/components/cc-block-cli/cc-block-cli.stories.js
user: login: pdesoyres-cc
body: nitpick; maybe rename to `openStory`
created_at: 2025-02-28T10:35:31Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,122 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * @typedef {import('./cc-block-cli.types.js').BlockToggleState} BlockToggleState
+ */
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockCli extends LitElement {
+  static get properties() {
+    return {
+      toggle: { type: String, reflect: true },
path: src/components/cc-block-cli/cc-block-cli.js
user: login: clara-layus-cc
body: It’s a good idea. Initially, the values were not the same but now that there are only two, passing with booleans will simplify the code.
created_at: 2025-02-28T13:40:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: nitpick: `boolean` should be lowercase
created_at: 2025-03-03T13:23:30Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: note: not a real issue but since the component has the `is-open` attribute reflected, we can remove the `${this.isOpen ? 'open' : 'close'}` (see below for CSS).
created_at: 2025-03-03T13:36:44Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default, 0.25em);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em) var(--cc-border-radius-default, 0.25em) 0 0;
+          margin-bottom: 0;
+        }
+
+        .tab cc-icon {
+          transition: all 0.3s;
+        }
+
+        .tab.open cc-icon {
+          transform: rotate(-180deg);
+        }
+
+        .tab.close:hover cc-icon {
+          transform: rotate(-90deg);
+        }
+
+        cc-icon {
+          margin-left: 0.1em;
+        }
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: issue: this should be grouped with the `.tab cc-icon` selector. Maybe both can be put in just `cc-ion` first.
created_at: 2025-03-03T13:38:04Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default, 0.25em);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em) var(--cc-border-radius-default, 0.25em) 0 0;
+          margin-bottom: 0;
+        }
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: note: we can rely directly on the reflected `is-open` attribute with this selector instead:

```
:host([is-open="true"]) .tab
```
created_at: 2025-03-03T13:39:26Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default, 0.25em);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em) var(--cc-border-radius-default, 0.25em) 0 0;
+          margin-bottom: 0;
+        }
+
+        .tab cc-icon {
+          transition: all 0.3s;
+        }
+
+        .tab.open cc-icon {
+          transform: rotate(-180deg);
+        }
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: note: we can rely directly on the reflected `is-open` attribute with this selector instead:

```
:host([is-open="true"]) cc-icon
```
created_at: 2025-03-03T13:39:56Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
+          padding: 0.25em 0.6em 0.35em;
+        }
+
+        .tab:hover {
+          border-radius: var(--cc-border-radius-default, 0.25em);
+        }
+
+        .tab.open {
+          background-color: var(--cc-color-bg-default, #fff);
+          border-radius: var(--cc-border-radius-default, 0.25em) var(--cc-border-radius-default, 0.25em) 0 0;
+          margin-bottom: 0;
+        }
+
+        .tab cc-icon {
+          transition: all 0.3s;
+        }
+
+        .tab.open cc-icon {
+          transform: rotate(-180deg);
+        }
+
+        .tab.close:hover cc-icon {
+          transform: rotate(-90deg);
+        }
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: note: we can rely directly on the reflected `is-open` attribute with this selector instead:

```
:host([is-open="true"]) .tab:hover cc-icon
```
created_at: 2025-03-03T13:40:08Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: question: is this needed?
created_at: 2025-03-03T13:40:35Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: issue: we may need an explicit `font-family` (set to a token or unset), for now it's a different font than the rest because `button` has default styles.
created_at: 2025-03-03T13:41:40Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,56 @@
+import { makeStory } from '../../stories/lib/make-story.js';
+import './cc-block-detail.js';
+import '../cc-block/cc-block.js';
+
+export default {
+  tags: ['autodocs'],
+  title: '🧬 Molecules/<cc-block-detail>',
+  component: 'cc-block-detail',
+};
+
+const conf = {
+  component: 'cc-block',
+};
+
+const ccBlockHtmlExemple = `
path: src/components/cc-block-detail/cc-block-detail.stories.js
user: login: hsablonniere
body: nitpick: `ccBlockHtmlExemple` => `ccBlockHtmlExample`
created_at: 2025-03-03T13:42:07Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,56 @@
+import { makeStory } from '../../stories/lib/make-story.js';
+import './cc-block-detail.js';
+import '../cc-block/cc-block.js';
+
+export default {
+  tags: ['autodocs'],
+  title: '🧬 Molecules/<cc-block-detail>',
+  component: 'cc-block-detail',
+};
+
+const conf = {
+  component: 'cc-block',
+};
+
+const ccBlockHtmlExemple = `
+  <div slot="header-title">This is my block</div>
+  <div slot="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque feugiat dui at leo porta dignissim. Etiam ut purus ultrices, pulvinar tellus quis, cursus massa. Mauris dignissim accumsan ex, at vestibulum lectus fermentum id. Quisque nec magna arcu. Quisque in metus sed erat sodales euismod eget id purus. Sed sagittis rhoncus mauris. Ut sit amet urna ac nunc semper porta. Nam ut felis eu velit luctus rutrum. Nam leo nisl, molestie a varius non, ullamcorper sit amet tortor. Donec in convallis ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent hendrerit venenatis erat, eu malesuada nulla viverra eu. Curabitur porta risus augue, non rutrum lectus hendrerit a.</div>
+`;
+
+const defaultHtmlExample = `
+  ${ccBlockHtmlExemple}
+  <div slot="footer" style="background-color: var(--cc-color-bg-neutral); border-top: solid 2px #cdcdcd">
+    <cc-block-detail>
+      <div slot="tab-title">Command line</div>
+      <a slot="link" href="">See documentation</a>
+      <div slot="content">Praesent tincidunt dapibus elit, sed posuere risus sodales quis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Integer ultrices maximus ligula eu efficitur. Nulla luctus ipsum vitae dui gravida, sodales ornare dolor viverra. Vivamus pretium scelerisque ultricies. Nulla consectetur euismod euismod. Interdum et malesuada fames ac ante ipsum primis in faucibus. Cras dignissim id sapien non facilisis. Suspendisse vitae pretium orci. Nunc aliquam pellentesque nunc, at tincidunt nisi lobortis a. </div>
+    </cc-block-detail>
+  </div>
path: src/components/cc-block-detail/cc-block-detail.stories.js
user: login: hsablonniere
body: suggestions:

* if we use the `slot="footer-left"` instead of `footer`, we'll get the gray background, the border and padding
  * we can remove the shadow in the cc-block in another commit if Marion agrees
* I we do this, we can remove the extra div and set the `slot` directly on the `cc-block-detail`

(same for the other story)
created_at: 2025-03-03T13:46:42Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
path: src/components/cc-block-detail/cc-block-detail.js
user: login: Galimede
body: question: should we add that its main purpose is to be used with a `cc-block`?
created_at: 2025-03-03T13:59:11Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
path: src/components/cc-block-detail/cc-block-detail.js
user: login: Galimede
body: I was thinking the same :+1: 
created_at: 2025-03-03T14:04:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
path: src/components/cc-block-detail/cc-block-detail.js
user: login: clara-layus-cc
body: Yes, it's a good idea.
created_at: 2025-03-03T15:30:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
path: src/components/cc-block-detail/cc-block-detail.js
user: login: clara-layus-cc
body: Yes because all its properties have default values that do not match the design.
created_at: 2025-03-03T16:00:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,112 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands. The main purpose is to be used with a cc-block.
path: src/components/cc-block-detail/cc-block-detail.js
user: login: florian-sanders-cc
body: **suggestion:**
```suggestion
 * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
 * The main purpose is to be used with a cc-block.
```
created_at: 2025-03-04T09:47:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,112 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands. The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle behaviour. */
path: src/components/cc-block-detail/cc-block-detail.js
user: login: florian-sanders-cc
body: **suggestion:**
```suggestion
    /** @type {boolean} Sets the state of the toggle. */
```
created_at: 2025-03-04T10:21:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,112 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands. The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
path: src/components/cc-block-detail/cc-block-detail.js
user: login: florian-sanders-cc
body: **fix:** if we modify a public property, then we must dispatch an event with the updated value, for instance `cc-block-detail:is-open-change` or something like `cc-block-detail:toggle-change`.

Don't hesistate to ping me if the reason for this is unclear, we'll discuss it in sync :wink:
```suggestion
    this.isOpen = !this.isOpen;
    dispatchCustomEvent(this, 'is-open-change', !this.isOpen)
```
(don't forget to document this event with `@fires` in the JSDoc of the `CcBlockDetail` class, see the example here: https://github.com/CleverCloud/clever-components/blob/master/src/components/cc-block/cc-block.js#L27)
created_at: 2025-03-04T10:32:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,112 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands. The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
path: src/components/cc-block-detail/cc-block-detail.js
user: login: florian-sanders-cc
body: **suggestion**: I would avoid talking about tabs since it usually implies we're dealing with a tab component ([several tabs](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)), when we're actually dealing with a toggle button / disclosure pattern.
Only people working in a11y use the `disclosure` naming (https://www.w3.org/WAI/ARIA/apg/patterns/disclosure/) so we could go with `toggle-button`? 

Also, we could make it clear that we only want text by specifying it in the slot name:

```suggestion
          <slot name="toggle-button-text"></slot>
```


```suggestion
          <slot name="button-text"></slot>
```
created_at: 2025-03-04T10:39:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,112 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands. The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
path: src/components/cc-block-detail/cc-block-detail.js
user: login: florian-sanders-cc
body: **fix:** you could not anticipate this but for a11y, we need the controlled zone (`div.content`) to directly follow the button that controls it (`button.tab`).

This is essential because keyboard users and screen reader users expect to be able to browse the content of the displayed zone right after having toggled the display of the zone.

If the zone is not directly after the button: 

- some screen reader users may not understand where the zone is and what this button does,
- it makes it a little bit more difficult to go back to the button from the zone if we want to hide it: we have to tab through the documentation link first to reach the toggle button.

Let's discuss it in sync, the solution for such usecases is:

- proper DOM order (button, then zone, then documentation link),
- rely on CSS to place the documentation link next to the button.


We'll also need to add `aria-expanded` & `aria-controls` attributes to the button so ping me when you're available and we'll do it together :wink:
created_at: 2025-03-04T10:55:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,11 @@
+/* eslint-env node, mocha */
path: src/components/cc-block-detail/cc-block-details.test.js
user: login: florian-sanders-cc
body: **Todo:** you can remove this file, tests on stories are now handled automatically by a plugin :+1: 
created_at: 2025-03-05T08:36:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,124 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowDownSLine as iconArrowDown } from '../../assets/cc-remix.icons.js';
+import { dispatchCustomEvent } from '../../lib/events.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ * The main purpose is to be used with a cc-block.
+ *
+ * @cssdisplay block
+ *
+ * @fires {CustomEvent<boolean>} cc-block-details:is-open-change - Fires is-open state whenever it changes.
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetails extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {boolean} Sets the state of the toggle. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+    dispatchCustomEvent(this, 'is-open-change', !this.isOpen);
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+        <button class="button" aria-expanded="${this.isOpen}" aria-controls="content" @click=${this._onClickToggle}>
+          <slot name="button-text"></slot>
+          <cc-icon .icon="${iconArrowDown}"></cc-icon>
+        </button>
+      </div>
+      ${this.isOpen ? html` <div id="content" class="content"><slot name="content"></slot></div> ` : null}
path: src/components/cc-block-detail/cc-block-details.js
user: login: florian-sanders-cc
body: **suggestion:** sorry I didn't notice this before
With components that show / hide content, it's better (not mandatory) to place the content in the DOM and hide / show it through CSS (or the `hidden` attribute).

Why is it better? Because when it's supported, we may use the [hidden="until-found" (only works in Chrome)](https://developer.chrome.com/docs/css-ui/hidden-until-found). 
Is it always better? No, sometimes it's better for perfs to only add content if it's needed but since we're dealing with simple / short content here, I think we're good :+1: 
created_at: 2025-03-05T10:46:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,114 @@
+import { css, html, LitElement } from 'lit';
+import { accessibilityStyles } from '../../styles/accessibility.js';
+import { iconRemixArrowUpSLine as iconArrowUp } from '../../assets/cc-remix.icons.js';
+import '../cc-icon/cc-icon.js';
+
+/**
+ * A display component with mostly HTML+CSS and an open/close toggle feature organized with slots to display information such as CLI commands.
+ *
+ * @cssdisplay block
+ *
+ * @slot tab-title - The title of the tab. Try to only use text.
+ * @slot link - A zone dedicated to link, for example to documentation.
+ * @slot content - A zone dedicated to main content.
+ */
+
+export class CcBlockDetail extends LitElement {
+  static get properties() {
+    return {
+      isOpen: { type: Boolean, reflect: true, attribute: 'is-open' },
+    };
+  }
+
+  constructor() {
+    super();
+
+    /** @type {Boolean} Sets the state of the toggle behaviour. */
+    this.isOpen = false;
+  }
+
+  _onClickToggle() {
+    this.isOpen = !this.isOpen;
+  }
+
+  render() {
+    return html`
+      <div class="menu">
+        <button class="tab ${this.isOpen ? 'open' : 'close'}" @click=${this._onClickToggle}>
+          <slot name="tab-title"></slot>
+          <cc-icon .icon="${iconArrowUp}"></cc-icon>
+        </button>
+        <div class="links">
+          <slot name="link"></slot>
+        </div>
+      </div>
+      ${this.isOpen ? html` <div class="content"><slot name="content"></slot></div> ` : null}
+    `;
+  }
+
+  static get styles() {
+    return [
+      accessibilityStyles,
+      // language=CSS
+      css`
+        :host {
+          display: block;
+        }
+
+        .menu {
+          column-gap: 1em;
+          display: flex;
+          justify-content: space-between;
+        }
+
+        .tab {
+          align-items: center;
+          background-color: transparent;
+          border: none;
+          display: flex;
+          font-size: 1em;
path: src/components/cc-block-detail/cc-block-detail.js
user: login: hsablonniere
body: My bad, you're absolutely right :+1: 
created_at: 2025-03-05T16:44:49Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-02-27T16:25:07Z
body: 🔎 A preview has been automatically published : https://clever-components-preview.cellar-c2.services.clever-cloud.com/feat/cc-block-cli/index.html.

_This preview will be deleted once this PR is closed._
author_association: CONTRIBUTOR
user: login: marion-izd
created_at: 2025-03-04T13:32:58Z
body: Very good work Clara ! 
As we discussed during our sync, here are a few comments (more design than code 😅) :
- the direction of the up/down arrows in relation to open/close, which are reversed
- the hover/focus can be accentuated with a border that's slightly darker grey than the background
- the border radius of the content frame
- the icon on the documentation link, but if we need to harmonise it with all the other links, we can wait.

As for the content section with the various commands, I imagine that will be the subject of a separate story? 
You'll let me know if you want another sync 😉
author_association: NONE
user: login: hsablonniere
created_at: 2025-03-05T16:48:37Z
body: @clara-layus-cc This seems good to me (code and SB preview). I only have one last thing. The tab order of the toggle button and the link is not natural. I wonder if we want to "fix" it. @florian-sanders-cc WDYT?
author_association: MEMBER
user: login: florian-sanders-cc
created_at: 2025-03-05T16:57:33Z
body: > @clara-layus-cc This seems good to me (code and SB preview). I only have one last thing. The tab order of the toggle button and the link is not natural. I wonder if we want to "fix" it. @florian-sanders-cc WDYT?

Damn my bad I didn't pay enough attention & wasn't specific enough in my guidelines. Yes, we need to place the link as the very last item of the component :+1: (feel free to ping me if it's unclear @clara-layus-cc, especially because these days I'm really absent minded :sweat_smile:)
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-06T16:44:28Z
body: 🔎 The preview has been automatically deleted.
author_association: CONTRIBUTOR