unnamed-ui
基础

Custom Sources

Source marker with popover preview and external/internal status

这是一个带有来源标记的文本示例1,点击角标可打开引用来源侧边栏。

外部引用示例3,支持弹出卡片预览与来源区分。

"use client";

import { useMemo, useState } from "react";
import CustomSources from "@/components/composed/custom-sources/custom-sources";
import SourcesSidebar from "@/components/composed/sources-sidebar/sources-sidebar";
import type { SourceItem } from "@/components/composed/custom-sources/utils";

const useMockSources = () =>
  useMemo<SourceItem[]>(
    () => [
      {
        key: 1,
        title: "内部知识库 - AI技术趋势",
        content: "内部资料汇总了 2026 年 AI 技术的发展重点与落地方向。",
        sourceType: "internal",
        domain: "internal.knowledge.base",
      },
      {
        key: 2,
        title: "产品设计规范 v3.2",
        content: "包含交互、视觉与组件规范,供团队统一设计语言。",
        sourceType: "internal",
        url: "/docs/design-system",
      },
      {
        key: 3,
        title: "2026 AI 产业趋势报告",
        content: "外部报告总结了行业规模、技术演进与应用场景。",
        url: "https://example.com/ai-trends",
        favicon: "https://www.google.com/s2/favicons?domain=example.com&sz=16",
        sourceType: "external",
        domain: "example.com",
        sourceName: "电子创新网",
      },
    ],
    [],
  );

export function CustomSourcesDemo() {
  const sources = useMockSources();
  const [sidebarOpen, setSidebarOpen] = useState(false);

  const handleOpenSidebar = () => {
    setSidebarOpen(true);
  };

  return (
    <div className="flex flex-wrap gap-6">
      <div className="min-w-[280px] flex-1 rounded-lg border border-[var(--Border-border-neutral)] p-4">
        <p className="text-sm text-[var(--Text-text-secondary)]">
          这是一个带有来源标记的文本示例
          <CustomSources sources={sources} onOpenSidebar={handleOpenSidebar}>
            1
          </CustomSources>
          ,点击角标可打开引用来源侧边栏。
        </p>
        <p className="mt-3 text-sm text-[var(--Text-text-secondary)]">
          外部引用示例
          <CustomSources sources={sources} onOpenSidebar={handleOpenSidebar}>
            3
          </CustomSources>
          ,支持弹出卡片预览与来源区分。
        </p>
      </div>

      {sidebarOpen && (
        <div className="shrink-0 rounded-lg border border-[var(--Border-border-neutral)]">
          <SourcesSidebar
            sources={sources}
            onClose={() => setSidebarOpen(false)}
          />
        </div>
      )}
    </div>
  );
}

CustomSources 用于在文本中以 <sup> 标记来源,并在悬浮时展示来源卡片信息。适合与 Markdown 渲染配合使用。

Overview

  • 来源标记:以数字角标形式展示
  • 来源区分:支持内部与外部来源样式
  • 悬浮卡片:展示标题与摘要
  • 侧边栏联动:点击角标可触发外部侧边栏

Quick Start

import CustomSources from "@/registry/wuhan/composed/custom-sources/custom-sources";

const sources = [
  { key: 1, title: "内部知识库", content: "内部摘要", sourceType: "internal" },
  {
    key: 2,
    title: "外部报告",
    content: "外部摘要",
    url: "https://example.com/report",
    sourceType: "external",
    domain: "example.com",
  },
];

export function Example() {
  return (
    <p>
      引用来源示例
      <CustomSources sources={sources} onOpenSidebar={() => {}}>
        1
      </CustomSources>
    </p>
  );
}

Installation

pnpm dlx shadcn@latest add http://localhost:3000/r/wuhan/custom-sources.json

Components

Primitives

  • CustomSourcesWrapper - 外层容器
  • CustomSourcesMarker - 角标样式
  • CustomSourcesCardContent - 弹层卡片容器
  • CustomSourcesCardHeader - 卡片头部
  • CustomSourcesCardSiteInfo - 站点信息容器
  • CustomSourcesCardLogo - 站点图标
  • CustomSourcesCardSiteName - 站点名称
  • CustomSourcesCardAction - 操作按钮容器
  • CustomSourcesCardTitle - 标题文本
  • CustomSourcesCardDescription - 描述文本

API (Composed)

属性类型默认值说明
sourcesSourceItem[][]来源数据列表
activeKeynumber-强制指定当前来源 key
onOpenSidebar(payload: { sources: SourceItem[]; activeKey?: number }) => void-点击角标回调
messageIdstring-预留扩展字段
childrenReact.ReactNode-<sup> 中的文本