MDX/Conversation
Default
Multi Paragraph Turn
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>
);
};
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>
);