Conversation

Chat-style dialogue display. Blockquotes become alternating speaker messages with a chat bubble UI.

Basic usage

Use blockquotes with bold speaker names to create a conversation.

{% conversation %}
> **Alice:** Hey, have you tried refrakt.md yet?

> **Bob:** Not yet — what makes it different?

> **Alice:** You write plain Markdown and runes decide how it renders. Same list can be nav links, feature cards, or action buttons.

> **Bob:** That sounds really flexible. I'll check it out!
{% /conversation %}
<div data-rune="conversation">
  <div data-name="messages">
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker"></span>
      <meta content="left" data-field="align">
      <div data-name="body">
        <p>
          <strong marker="**">Alice:</strong>
          Hey, have you tried refrakt.md yet?
        </p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker"></span>
      <meta content="right" data-field="align">
      <div data-name="body">
        <p>
          <strong marker="**">Bob:</strong>
          Not yet — what makes it different?
        </p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker"></span>
      <meta content="left" data-field="align">
      <div data-name="body">
        <p>
          <strong marker="**">Alice:</strong>
          You write plain Markdown and runes decide how it renders. Same list can be nav links, feature cards, or action buttons.
        </p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker"></span>
      <meta content="right" data-field="align">
      <div data-name="body">
        <p>
          <strong marker="**">Bob:</strong>
          That sounds really flexible. I'll check it out!
        </p>
      </div>
    </div>
  </div>
</div>

Alice: Hey, have you tried refrakt.md yet?

Bob: Not yet — what makes it different?

Alice: You write plain Markdown and runes decide how it renders. Same list can be nav links, feature cards, or action buttons.

Bob: That sounds really flexible. I'll check it out!

<div class="rf-conversation" data-rune="conversation" data-density="compact">
  <div data-name="messages" class="rf-conversation__messages">
    <div data-field="message" class="rf-conversation-message rf-conversation-message--left" data-align="left" data-rune="conversation-message" data-density="full">
      <span data-field="speaker"></span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>
          <strong marker="**">Alice:</strong>
           Hey, have you tried refrakt.md yet?
        </p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--right" data-align="right" data-rune="conversation-message" data-density="full">
      <span data-field="speaker"></span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>
          <strong marker="**">Bob:</strong>
           Not yet — what makes it different?
        </p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--left" data-align="left" data-rune="conversation-message" data-density="full">
      <span data-field="speaker"></span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>
          <strong marker="**">Alice:</strong>
           You write plain Markdown and runes decide how it renders. Same list can be nav links, feature cards, or action buttons.
        </p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--right" data-align="right" data-rune="conversation-message" data-density="full">
      <span data-field="speaker"></span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>
          <strong marker="**">Bob:</strong>
           That sounds really flexible. I'll check it out!
        </p>
      </div>
    </div>
  </div>
</div>

Named speakers

Use the speakers attribute to automatically alternate between named speakers without inline bold markup.

{% conversation speakers="Support, Customer" %}
> How can I help you today?

> I'm having trouble with the installation.

> Have you tried running npm install with the --legacy-peer-deps flag?

> That fixed it — thank you!
{% /conversation %}
<div data-rune="conversation">
  <div data-name="messages">
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker">Support</span>
      <meta content="left" data-field="align">
      <div data-name="body">
        <p>How can I help you today?</p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker">Customer</span>
      <meta content="right" data-field="align">
      <div data-name="body">
        <p>I'm having trouble with the installation.</p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker">Support</span>
      <meta content="left" data-field="align">
      <div data-name="body">
        <p>Have you tried running npm install with the --legacy-peer-deps flag?</p>
      </div>
    </div>
    <div data-field="message" data-rune="conversation-message">
      <span data-field="speaker">Customer</span>
      <meta content="right" data-field="align">
      <div data-name="body">
        <p>That fixed it — thank you!</p>
      </div>
    </div>
  </div>
</div>
Support

How can I help you today?

Customer

I'm having trouble with the installation.

Support

Have you tried running npm install with the --legacy-peer-deps flag?

Customer

That fixed it — thank you!

<div class="rf-conversation" data-rune="conversation" data-density="compact">
  <div data-name="messages" class="rf-conversation__messages">
    <div data-field="message" class="rf-conversation-message rf-conversation-message--left" data-align="left" data-rune="conversation-message" data-density="full">
      <span data-field="speaker">Support</span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>How can I help you today?</p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--right" data-align="right" data-rune="conversation-message" data-density="full">
      <span data-field="speaker">Customer</span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>I'm having trouble with the installation.</p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--left" data-align="left" data-rune="conversation-message" data-density="full">
      <span data-field="speaker">Support</span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>Have you tried running npm install with the --legacy-peer-deps flag?</p>
      </div>
    </div>
    <div data-field="message" class="rf-conversation-message rf-conversation-message--right" data-align="right" data-rune="conversation-message" data-density="full">
      <span data-field="speaker">Customer</span>
      <div data-name="body" class="rf-conversation-message__body">
        <p>That fixed it — thank you!</p>
      </div>
    </div>
  </div>
</div>

Attributes

AttributeTypeDefaultDescription
speakersstringComma-separated speaker names for automatic alternation

Common attributes

All block runes share these attributes for layout and theming.

AttributeTypeDefaultDescription
widthstringcontentPage grid width: content, wide, or full
spacingstringVertical spacing: flush, tight, default, loose, or breathe
insetstringHorizontal padding: flush, tight, default, loose, or breathe
tintstringNamed colour tint from theme configuration
tint-modestringautoColour scheme override: auto, dark, or light
bgstringNamed background preset from theme configuration