- Gallery
- Data Display
- PropertyList
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 separatorHow 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"23import * 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"910interface PropertyListProps {11 className?: string12}1314interface Property {15 label: string16 value: string17 type?: "text" | "id" | "badge" | "date"18 badgeVariant?: "default" | "secondary" | "outline"19 copyable?: boolean20}2122const 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]3233export function PropertyList({ className }: PropertyListProps) {34 const [copied, setCopied] = React.useState<string | null>(null)3536 const handleCopy = (value: string, label: string) => {37 navigator.clipboard.writeText(value)38 setCopied(label)39 setTimeout(() => setCopied(null), 2000)40 }4142 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 <Button63 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}