New

PropertyList

Key-value property display with labels, values, copy buttons, and badges

Data Displaypropertiesdetailskey-valueinfo

Dependencies

shadcn/ui components needed:

npx shadcn@latest add cardnpx shadcn@latest add badgenpx shadcn@latest add buttonnpx shadcn@latest add separator

How to use this component

Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.

Code

1"use client"
2
3import * as React from "react"
4import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
5import { Badge } from "@/components/ui/badge"
6import { Button } from "@/components/ui/button"
7import { Separator } from "@/components/ui/separator"
8import { cn } from "@/lib/utils"
9
10interface PropertyListProps {
11 className?: string
12}
13
14interface Property {
15 label: string
16 value: string
17 type?: "text" | "id" | "badge" | "date"
18 badgeVariant?: "default" | "secondary" | "outline"
19 copyable?: boolean
20}
21
22const properties: Property[] = [
23 { label: "Project ID", value: "PRJ-2024-8F4A2", type: "id", copyable: true },
24 { label: "Status", value: "Active", type: "badge", badgeVariant: "default" },
25 { label: "Created", value: "November 15, 2024", type: "date" },
26 { label: "Owner", value: "Sarah Chen", type: "text" },
27 { label: "Email", value: "sarah.chen@company.com", type: "text", copyable: true },
28 { label: "Region", value: "US West", type: "text" },
29 { label: "Type", value: "Web Application", type: "badge", badgeVariant: "outline" },
30 { label: "Last Updated", value: "2 hours ago", type: "date" },
31]
32
33export function PropertyList({ className }: PropertyListProps) {
34 const [copied, setCopied] = React.useState<string | null>(null)
35
36 const handleCopy = (value: string, label: string) => {
37 navigator.clipboard.writeText(value)
38 setCopied(label)
39 setTimeout(() => setCopied(null), 2000)
40 }
41
42 return (
43 <Card className={cn("w-full max-w-lg", className)}>
44 <CardHeader>
45 <CardTitle>Project Details</CardTitle>
46 </CardHeader>
47 <CardContent>
48 <div className="space-y-0">
49 {properties.map((prop, i) => (
50 <React.Fragment key={prop.label}>
51 <div className="grid grid-cols-3 gap-4 py-3">
52 <div className="text-sm font-medium text-muted-foreground">{prop.label}</div>
53 <div className="col-span-2 flex items-center justify-between gap-2">
54 {prop.type === "id" ? (
55 <code className="text-xs bg-muted px-2 py-1 rounded font-mono">{prop.value}</code>
56 ) : prop.type === "badge" ? (
57 <Badge variant={prop.badgeVariant}>{prop.value}</Badge>
58 ) : (
59 <span className={cn("text-sm", prop.type === "date" && "text-muted-foreground")}>{prop.value}</span>
60 )}
61 {prop.copyable && (
62 <Button
63 size="sm"
64 variant="ghost"
65 className="h-7 px-2 text-xs"
66 onClick={() => handleCopy(prop.value, prop.label)}
67 >
68 {copied === prop.label ? "Copied!" : "Copy"}
69 </Button>
70 )}
71 </div>
72 </div>
73 {i < properties.length - 1 && <Separator />}
74 </React.Fragment>
75 ))}
76 </div>
77 </CardContent>
78 </Card>
79 )
80}

Related Data Display Components

Command Palette

Search for a command to run...