气泡/容器
Quote Content
Composed quote content display above input field
基础用法
“这是一段引用内容”
带关闭功能
“点击右侧关闭按钮可以关闭这条引用”
长文本溢出处理
“这是一段非常长的引用内容,当内容超出容器宽度时会自动截断并显示省略号,确保布局不会被破坏”
自定义内容
可以引用消息、回复或其他内容
无关闭按钮
“不提供关闭按钮时,引用内容会一直显示”
"use client";
import { useState } from "react";
import { QuoteContentComposed } from "@/components/composed/quote-content/quote-content";
export function QuoteContentDemo() {
const [showQuote1, setShowQuote1] = useState(true);
const [showQuote2, setShowQuote2] = useState(true);
const [showQuote3, setShowQuote3] = useState(true);
return (
<div className="w-full max-w-2xl space-y-4">
{/* 基础用法 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-primary)]">
基础用法
</h3>
<QuoteContentComposed
content="这是一段引用内容"
onClose={() => {
console.log("关闭引用");
}}
/>
</div>
{/* 带关闭功能 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-primary)]">
带关闭功能
</h3>
{showQuote1 && (
<QuoteContentComposed
content="点击右侧关闭按钮可以关闭这条引用"
onClose={() => setShowQuote1(false)}
/>
)}
{!showQuote1 && (
<button
onClick={() => setShowQuote1(true)}
className="appearance-none border-0 bg-transparent p-0 text-sm text-[var(--Text-text-secondary)] hover:text-[var(--Text-text-primary)]"
>
重新显示引用
</button>
)}
</div>
{/* 长文本溢出 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-primary)]">
长文本溢出处理
</h3>
{showQuote2 && (
<QuoteContentComposed
content="这是一段非常长的引用内容,当内容超出容器宽度时会自动截断并显示省略号,确保布局不会被破坏"
onClose={() => setShowQuote2(false)}
/>
)}
</div>
{/* 自定义内容 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-primary)]">
自定义内容
</h3>
{showQuote3 && (
<QuoteContentComposed
content={<span>可以引用消息、回复或其他内容</span>}
onClose={() => setShowQuote3(false)}
/>
)}
</div>
{/* 无关闭按钮 */}
<div className="space-y-2">
<h3 className="text-sm font-medium text-[var(--Text-text-primary)]">
无关闭按钮
</h3>
<QuoteContentComposed content="不提供关闭按钮时,引用内容会一直显示" />
</div>
</div>
);
}
Quote Content 组件用于在输入框上方显示引用内容,包含图标、内容与关闭动作。适用于聊天场景中的引用消息、回复内容等场景。
概述
- 引用内容展示:图标 + 内容 + 关闭按钮的完整布局
- 业务数据适配:支持泛型数据对象,通过 adapter 映射到组件属性
- 灵活定制:支持自定义图标、关闭按钮和插槽渲染
- 类型安全:完整的 TypeScript 类型定义
- 开箱即用:默认样式即可满足常见场景
快速开始
import { QuoteContentComposed } from "@/registry/wuhan/composed/quote-content/quote-content";
export function Example() {
return (
<QuoteContentComposed content="这是一条引用内容" />
);
}特性
- 默认样式:直接使用即可看到完整 UI,无需额外配置
- 自定义图标:前缀图标和关闭图标均可自定义
- 数据适配器:通过
quoteAdapter适配业务数据到组件属性 - 插槽渲染:支持
renderLeading、renderContent、renderClose等插槽 - 可控关闭:支持
closable控制是否显示关闭按钮 - 回调支持:提供
onClose和onCloseQuote两种关闭回调
安装
代码演示
基本用法
最小示例,只传入引用内容。
import { QuoteContentComposed } from "@/registry/wuhan/composed/quote-content/quote-content";
<QuoteContentComposed content="这是一条引用内容" />“这是一条引用内容”
"use client";
import { QuoteContentComposed } from "@/components/composed/quote-content/quote-content";
export function QuoteContentDefault() {
return (
<div className="w-full max-w-2xl">
<QuoteContentComposed content="这是一条引用内容" />
</div>
);
}
自定义图标
自定义前缀图标与关闭图标。
<QuoteContentComposed
content="自定义图标"
icon={<MyIcon />}
closeIcon={<MyCloseIcon />}
onClose={() => console.log("close")}
/>“自定义图标与关闭按钮”
"use client";
import { useState } from "react";
import { QuoteContentComposed } from "@/components/composed/quote-content/quote-content";
import { Reply, XCircle } from "lucide-react";
export function QuoteContentCustomIcon() {
const [visible, setVisible] = useState(true);
return (
<div className="w-full max-w-2xl">
{visible ? (
<QuoteContentComposed
content="自定义图标与关闭按钮"
icon={<Reply className="w-4 h-4 text-slate-500" />}
closeIcon={<XCircle className="w-4 h-4 text-slate-500" />}
onClose={() => setVisible(false)}
/>
) : (
<button
type="button"
onClick={() => setVisible(true)}
className="appearance-none border-0 bg-transparent p-0 text-sm text-muted-foreground hover:text-[var(--Text-text-primary)]"
>
重新显示引用
</button>
)}
</div>
);
}
数据适配(推荐)
业务数据适配,通过 quoteAdapter 将业务数据映射到组件属性。
const quote = { id: "q-1", text: "来自业务数据的引用内容" };
<QuoteContentComposed
quote={quote}
quoteAdapter={(item) => ({ content: item.text })}
onCloseQuote={(item) => console.log("close", item.id)}
/>“来自业务数据的引用内容”
"use client";
import { useState } from "react";
import { QuoteContentComposed } from "@/components/composed/quote-content/quote-content";
type QuoteData = {
id: string;
text: string;
};
export function QuoteContentAdapter() {
const [quote, setQuote] = useState<QuoteData | null>({
id: "q-1",
text: "来自业务数据的引用内容",
});
return (
<div className="w-full max-w-2xl">
{quote ? (
<QuoteContentComposed
quote={quote}
quoteAdapter={(item) => ({ content: item.text })}
onCloseQuote={() => setQuote(null)}
/>
) : (
<button
type="button"
onClick={() => setQuote({ id: "q-2", text: "重新添加的引用内容" })}
className="appearance-none border-0 bg-transparent p-0 text-sm text-muted-foreground hover:text-[var(--Text-text-primary)]"
>
重新添加引用
</button>
)}
</div>
);
}
自定义渲染(高级)
使用插槽完全自定义渲染结构。
<QuoteContentComposed
content="自定义结构"
renderLeading={({ icon }) => <div>{icon}</div>}
renderContent={({ content }) => <div>{content}</div>}
renderClose={({ onClose }) => <button onClick={onClose}>关闭</button>}
/>自定义渲染结构
"use client";
import { QuoteContentComposed } from "@/components/composed/quote-content/quote-content";
import { MessageSquareText } from "lucide-react";
export function QuoteContentCustomRender() {
return (
<div className="w-full max-w-2xl">
<QuoteContentComposed
content="自定义渲染结构"
renderLeading={({ icon }) => (
<div className="flex items-center text-slate-500">
{icon ?? <MessageSquareText className="w-4 h-4" />}
</div>
)}
renderContent={({ content }) => (
<div className="flex-1 text-sm text-slate-700">{content}</div>
)}
renderClose={({ onClose }) => (
<button
type="button"
onClick={(event) => {
event.stopPropagation();
onClose?.();
}}
className="appearance-none border-0 bg-transparent p-0 text-xs text-slate-500 hover:text-slate-900"
>
关闭
</button>
)}
onClose={() => undefined}
/>
</div>
);
}
API
QuoteContentComposed
引用内容组件,支持基础属性和高级定制。
Props
| Prop | Type | Default | Description |
|---|---|---|---|
content | ReactNode | - | 引用内容(最常用) |
quote | T | - | 业务数据对象(泛型支持) |
quoteAdapter | (quote: T) => AdaptedProps | - | 业务数据转组件属性的适配器 |
icon | ReactNode | - | 前缀图标 |
closeIcon | ReactNode | - | 关闭图标 |
onClose | () => void | - | 关闭回调 |
onCloseQuote | (quote: T) => void | - | 关闭回调(带业务数据) |
closable | boolean | true | 是否显示关闭按钮 |
renderQuote | (ctx: RenderContext) => ReactNode | - | 覆盖整体渲染 |
renderLeading | (ctx: RenderContext) => ReactNode | - | 覆盖图标区域 |
renderContent | (ctx: RenderContext) => ReactNode | - | 覆盖内容区域 |
renderClose | (ctx: RenderContext) => ReactNode | - | 覆盖关闭按钮 |
className | string | - | 外层容器样式 |
Example
import { QuoteContentComposed } from "@/registry/wuhan/composed/quote-content/quote-content";
function ChatInput() {
const [quote, setQuote] = useState(null);
return (
<div className="flex flex-col gap-2">
{/* 基础用法 */}
<QuoteContentComposed content="这是一条引用内容" />
{/* 数据适配 */}
{quote && (
<QuoteContentComposed
quote={quote}
quoteAdapter={(item) => ({
content: item.text,
icon: <ReplyIcon />
})}
onCloseQuote={(item) => setQuote(null)}
/>
)}
{/* 完全自定义 */}
<QuoteContentComposed
content="高级定制"
renderContent={({ content }) => (
<div className="text-sm font-medium">{content}</div>
)}
/>
</div>
);
}AdaptedProps
适配器返回的属性类型。
type AdaptedProps = {
content?: ReactNode;
icon?: ReactNode;
closeIcon?: ReactNode;
};RenderContext
渲染函数的上下文参数。
type RenderContext = {
content: ReactNode;
icon?: ReactNode;
closeIcon?: ReactNode;
onClose?: () => void;
closable: boolean;
};使用场景
- 聊天引用:在聊天输入框上方显示引用的消息内容
- 回复消息:论坛、评论系统中的回复功能
- 编辑预览:显示正在编辑或引用的内容
- 引用卡片:文章、文档中的引用块展示
- 消息转发:显示转发的消息来源和内容
最佳实践
- 优先使用数据适配器:当组件与业务数据绑定时,使用
quoteAdapter可以保持类型安全和代码清晰 - 合理使用插槽:只在需要深度定制布局时使用
render*系列插槽 - 控制内容长度:引用内容过长时应截断或限制行数,避免影响 UI 布局
- 回调处理:使用
onCloseQuote而非onClose可以直接获取业务数据,减少状态管理 - 图标一致性:保持图标风格与整体设计系统一致
注意事项
quoteAdapter优先级高于直接传入的属性(如content、icon等)- 使用
renderQuote会完全覆盖组件默认结构,需自行实现所有布局 onCloseQuote只在提供quote属性时才会被调用closable={false}会隐藏关闭按钮,此时onClose和onCloseQuote不会被触发- 建议为引用内容设置最大宽度或截断策略,避免布局问题