-

Segment Card

PreviousNext

A compact knowledge segment card for chunks, scores, questions, and metadata.

Installation

pnpm
pnpm dlx shadcn@latest add https://ui.zgi.ai/r/segment-card.json
npm
pnpm dlx shadcn@latest add https://ui.zgi.ai/r/segment-card.json
yarn
yarn dlx shadcn@latest add https://ui.zgi.ai/r/segment-card.json

Component

components/ui/segment-card.tsx
"use client"

import * as React from "react"
import { CircleCheckIcon, HashIcon, MessageSquareIcon } from "lucide-react"

import { cn } from "@/lib/utils"
import { Badge } from "@/components/ui/badge"

export interface SegmentCardMeta {
  label: React.ReactNode
  value: React.ReactNode
}

export interface SegmentCardProps
  extends Omit<React.ComponentProps<"article">, "children" | "title"> {
  title?: React.ReactNode
  children: React.ReactNode
  status?: "enabled" | "disabled" | "draft"
  score?: number
  tokens?: number
  questions?: number
  metadata?: SegmentCardMeta[]
  actions?: React.ReactNode
}

const statusClassName = {
  enabled: "bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
  disabled: "bg-muted text-muted-foreground",
  draft: "bg-amber-500/10 text-amber-700 dark:text-amber-300",
}

export function SegmentCard({
  title,
  children,
  status = "enabled",
  score,
  tokens,
  questions,
  metadata = [],
  actions,
  className,
  ...props
}: SegmentCardProps) {
  return (
    <article
      className={cn(
        "bg-card text-card-foreground rounded-lg border p-4",
        className
      )}
      {...props}
    >
      <div className="flex items-start justify-between gap-3">
        <div className="min-w-0">
          <div className="flex min-w-0 flex-wrap items-center gap-2">
            {title ? (
              <h3 className="truncate text-sm font-medium">{title}</h3>
            ) : null}
            <Badge
              variant="secondary"
              className={cn("h-6 rounded-md border-0", statusClassName[status])}
            >
              <CircleCheckIcon className="size-3.5" />
              {status}
            </Badge>
          </div>
          <p className="text-muted-foreground mt-2 line-clamp-3 text-sm leading-6">
            {children}
          </p>
        </div>
        {actions ? <div className="shrink-0">{actions}</div> : null}
      </div>

      <div className="mt-4 flex flex-wrap gap-2">
        {typeof score === "number" ? (
          <Badge variant="outline" className="h-6 rounded-md">
            Score {(score * 100).toFixed(0)}%
          </Badge>
        ) : null}
        {typeof tokens === "number" ? (
          <Badge variant="outline" className="h-6 rounded-md">
            <HashIcon className="size-3.5" />
            {tokens.toLocaleString()} tokens
          </Badge>
        ) : null}
        {typeof questions === "number" ? (
          <Badge variant="outline" className="h-6 rounded-md">
            <MessageSquareIcon className="size-3.5" />
            {questions} questions
          </Badge>
        ) : null}
      </div>

      {metadata.length ? (
        <dl className="mt-4 grid gap-2 border-t pt-3 text-xs sm:grid-cols-2">
          {metadata.map((item, index) => (
            <div key={index} className="min-w-0">
              <dt className="text-muted-foreground">{item.label}</dt>
              <dd className="mt-1 truncate font-medium">{item.value}</dd>
            </div>
          ))}
        </dl>
      ) : null}
    </article>
  )
}

Usage

import { SegmentCard } from "@/components/ui/segment-card"
 
export function Example() {
  return (
    <SegmentCard
      title="Refund eligibility"
      score={0.92}
      tokens={184}
      questions={6}
    >
      Customers can request a refund within 14 days.
    </SegmentCard>
  )
}

Props

PropTypeDefault
childrenReactNoderequired
titleReactNode-
status"enabled" | "disabled" | "draft""enabled"
scorenumber-
tokensnumber-
questionsnumber-
metadataSegmentCardMeta[][]
actionsReactNode-