Takazudo Modular Styleguide

MDX/Conversation

Default
Multi Paragraph Turn

Component Source

conversation.tsx

import type { FunctionComponent, ComponentChildren } from 'preact';

/**
 * Conversation / dialogue layout for interview- or podcast-style articles.
 *
 * Renders a vertical stack of speaker turns. Use it when an article is a
 * translated transcript of a two-party conversation (host ↔ guest) rather than
 * a step-by-step guide. Each `<Turn>` carries a `speaker` label and its spoken
 * text; the `role` prop switches the visual accent so the two sides of the
 * dialogue are easy to scan.
 *
 * Example (MDX):
 *
 *   <Conversation>
 *     <Turn speaker="ロブ(4ms)" role="host">質問テキスト…</Turn>
 *     <Turn speaker="リチャード・ディヴァイン" role="guest">回答テキスト…</Turn>
 *   </Conversation>
 */

interface ConversationProps {
  children: ComponentChildren;
}

export const Conversation: FunctionComponent<ConversationProps> = ({ children }) => {
  return <div className="flex flex-col gap-y-vgap-md md:gap-y-vgap-lg mb-vgap-lg">{children}</div>;
};

type TurnRole = 'host' | 'guest';

interface TurnProps {
  /** Display label for the speaker (e.g. a name, shown above the spoken text). */
  speaker: string;
  /** Visual variant: `guest` is accented, `host` is secondary. Defaults to `guest`. */
  role?: TurnRole;
  children: ComponentChildren;
}

// Literal class strings (not interpolated tokens) so Tailwind's source scan
// extracts them. The left border + name color distinguish the two speakers.
const ROLE_BORDER: Record<TurnRole, string> = {
  host: 'border-zd-gray',
  guest: 'border-zd-strong',
};

const ROLE_NAME: Record<TurnRole, string> = {
  host: 'text-zd-subtext',
  guest: 'text-zd-strong',
};

export const Turn: FunctionComponent<TurnProps> = ({ speaker, role = 'guest', children }) => {
  return (
    <div className={`border-l-3 ${ROLE_BORDER[role]} pl-hgap-sm`}>
      <p className={`font-futura ${ROLE_NAME[role]} text-sm md:text-base mb-vgap-xs`}>{speaker}</p>
      <div className="zd-article-body max-w-none">{children}</div>
    </div>
  );
};

Story Source

conversation.stories.tsx

import { Conversation, Turn } from './conversation';

/**
 * Conversation Component
 *
 * A dialogue layout for interview- / podcast-style articles. Renders a vertical
 * stack of speaker turns, each with a speaker label and its spoken text. The
 * `role` prop on `<Turn>` switches the visual accent so the two sides of a
 * conversation are easy to scan (`guest` is accented, `host` is secondary).
 */
export const meta = {
  title: 'MDX/Conversation',
};

/**
 * Default - a short two-party exchange
 */
export const Default = () => (
  <Conversation>
    <Turn speaker="ロブ(4ms)" role="host">
      <p>4ms製品はいつから使っているんですか?</p>
    </Turn>
    <Turn speaker="リチャード・ディヴァイン" role="guest">
      <p>
        最初にDanから買ったのはクロックディバイダーだったと思います。もう14、15年くらい前ですね。
      </p>
    </Turn>
  </Conversation>
);

/**
 * Multi-paragraph turn - body text flows with article spacing
 */
export const MultiParagraphTurn = () => (
  <Conversation>
    <Turn speaker="リチャード・ディヴァイン" role="guest">
      <p>
        ハードウェアに本格的に移ったきっかけは、ARP
        2600を手に入れたときでした。これも質屋で見つけたんです。
      </p>
      <p>
        リングモジュレーションとは何か、2つのオシレーター間のFMとは何か——音作りの基礎を全部この一台で学びました。
      </p>
    </Turn>
    <Turn speaker="ロブ(4ms)" role="host">
      <p>なるほど。Maxを使っていた時期もありましたよね?</p>
    </Turn>
  </Conversation>
);