Vector Motion
AI/ML

Data Quality Card - Data Validation Dashboard

Monitor data quality metrics, validation results, and data integrity checks. Track missing values, outliers, and data health across your pipeline.

Data Quality Card

The Data Quality Card displays data quality metrics including completeness, accuracy, and validity scores to ensure high-quality training and inference data.

Preview

Installation

npx shadcn@latest add https://vectormotion.vercel.app/registry/data-quality-card.json
Data Quality Card
'use client'import React from 'react';import { ShieldCheck, Database, RefreshCcw, FileCheck } from 'lucide-react';import { motion } from 'motion/react';import { clsx, type ClassValue } from "clsx"import { twMerge } from "tailwind-merge"import { ResponsiveContainer, RadialBarChart, RadialBar, Tooltip } from 'recharts';function cn(...inputs: ClassValue[]) {   return twMerge(clsx(inputs))}interface QualityMetric {   name: string;   value: number;   fill: string;   [key: string]: any;}interface DataQualityCardProps {   className?: string;   title?: string;   checksPassedCount?: string;   data?: QualityMetric[];   scanTime?: string;   rowCount?: string;}const DEFAULT_DATA: QualityMetric[] = [   { name: 'Completeness', value: 98, fill: '#10b981' },   { name: 'Validity', value: 95, fill: '#3b82f6' },   { name: 'Consistency', value: 92, fill: '#8b5cf6' },];const DEFAULT_TITLE = "Data Quality";const DEFAULT_CHECKS_PASSED_COUNT = "102 CHECKS PASSED";const DEFAULT_SCAN_TIME = "5m ago";const DEFAULT_ROW_COUNT = "2.4M Rows";export const DataQualityCard: React.FC<DataQualityCardProps> = ({   className = "",   title = DEFAULT_TITLE,   checksPassedCount = DEFAULT_CHECKS_PASSED_COUNT,   data = DEFAULT_DATA,   scanTime = DEFAULT_SCAN_TIME,   rowCount = DEFAULT_ROW_COUNT,}) => {   return (      <motion.div         initial={{ opacity: 0, y: 20 }}         animate={{ opacity: 1, y: 0 }}         transition={{ duration: 0.5, delay: 0.2 }}         className={cn(            "relative overflow-hidden rounded-2xl border border-border bg-card text-card-foreground shadow-sm transition-all hover:border-emerald-300 dark:hover:border-emerald-700 hover:shadow-md flex flex-col h-full",            className         )}      >         <div className="p-5 flex flex-col h-full relative z-10">            <div className="mb-2 flex items-start justify-between">               <div>                  <h3 className="font-bold text-lg text-foreground">                     {title}                  </h3>                  <div className="flex items-center gap-2 mt-1">                     <div className="px-2 py-0.5 rounded-full bg-emerald-500/10 border border-emerald-100 dark:border-emerald-800 text-[10px] font-bold text-emerald-500">                        {checksPassedCount}                     </div>                  </div>               </div>               <div className="rounded-lg border-2 border-emerald-100 dark:border-emerald-800 p-2 text-emerald-500 dark:text-emerald-400 flex items-center justify-center">                  <ShieldCheck className="h-5 w-5" />               </div>            </div>            <div className="flex-1 w-full min-h-[140px] relative">               <ResponsiveContainer width="100%" height="100%">                  <RadialBarChart                     cx="50%"                     cy="50%"                     innerRadius="40%"                     outerRadius="100%"                     barSize={10}                     data={data}                     startAngle={180}                     endAngle={0}                  >                     <RadialBar                        background                        label={{ position: 'insideStart', fill: '#fff', fontSize: 0 }} // Hidden label but keeps logic                        dataKey="value"                        cornerRadius={10}                     />                     <Tooltip                        cursor={false}                        content={({ active, payload }) => {                           if (active && payload && payload.length) {                              return (                                 <div className="rounded-lg border border-zinc-200 dark:border-zinc-700 bg-white dark:bg-zinc-800 p-2 shadow-sm text-xs">                                    <span className="font-bold" style={{ color: payload[0].payload.fill }}>                                       {payload[0].payload.name}:                                    </span> {payload[0].value}%                                 </div>                              );                           }                           return null;                        }}                     />                  </RadialBarChart>               </ResponsiveContainer>               <div className="flex gap-2 justify-center mt-2 flex-wrap">                  {data.map((item, i) => (                     <div key={i} className="flex items-center gap-1">                        <div className="w-2 h-2 rounded-full" style={{ backgroundColor: item.fill }} />                        <span className="text-[10px] text-muted-foreground">{item.name}</span>                     </div>                  ))}               </div>            </div>            <div className="mt-4 flex items-center justify-between text-xs text-muted-foreground pt-3 border-t border-border">               <div className="flex items-center gap-1.5">                  <RefreshCcw className="w-3 h-3" />                  <span>Scan: {scanTime}</span>               </div>               <div className="flex items-center gap-1.5">                  <FileCheck className="w-3 h-3" />                  <span>{rowCount}</span>               </div>            </div>            <div className="absolute -bottom-4 -right-4 z-0 opacity-5 pointer-events-none">               <Database className="w-40 h-40 text-emerald-500" />            </div>         </div>      </motion.div>   );};

Props

Prop

Type

Usage

This component is a demo card displaying data quality metrics with animated visualizations and dark mode support.