Segmented Progress Stat Card
Segmented Progress Stat Card is a React and Tailwind CSS card component written for Uncode and yours to ship. Copy it and paste it into your project.
Uncode
cards
What it is
Segmented Progress Stat Card is a React and Tailwind CSS card component written for Uncode and yours to ship. Copy it and paste it into your project.
How to use it
Open it in the catalogue, press copy, and paste it into your project. The prompt you copy carries the code and the rules that tell your agent to reproduce it without changing anything.
Five free copies a month. No card.
Needs
npm i @tanstack/react-table
Licence
This component was written for this catalogue. It is yours to ship in client work and in products you sell, under the terms of use.
Segmented Progress Stat Card
'use client';
import { createContext, ReactNode, useContext } from 'react';
import { cn } from '@/lib/utils';
import { ColumnFiltersState, RowData, SortingState, Table } from '@tanstack/react-table';
declare module '@tanstack/react-table' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface ColumnMeta<TData extends RowData, TValue> {
headerTitle?: string;
headerClassName?: string;
cellClassName?: string;
skeleton?: ReactNode;
expandedContent?: (row: TData) => ReactNode;
}
}
export type DataGridApiFetchParams = {
pageIndex: number;
pageSize: number;
sorting?: SortingState;
filters?: ColumnFiltersState;
searchQuery?: string;
};
export type DataGridApiResponse<T> = {
data: T[];
empty: boolean;
pagination: {
total: number;
page: number;
};
};
export interface DataGridContextProps<TData extends object> {
props: DataGridProps<TData>;
table: Table<TData>;
recordCount: number;
isLoading: boolean;
}
export type DataGridRequestParams = {
pageIndex: number;
pageSize: number;
sorting?: SortingState;
columnFilters?: ColumnFiltersState;
};
export interface DataGridProps<TData extends object> {
className?: string;
table?: Table<TData>;
recordCount: number;
children?: ReactNode;
onRowClick?: (row: TData) => void;
isLoading?: boolean;
loadingMode?: 'skeleton' | 'spinner';
loadingMessage?: ReactNode | string;
emptyMessage?: ReactNode | string;
tableLayout?: {
dense?: boolean;
cellBorder?: boolean;
rowBorder?: boolean;
rowRounded?: boolean;
stripped?: boolean;
headerBackground?: boolean;
headerBorder?: boolean;
headerSticky?: boolean;
width?: 'auto' | 'fixed';
columnsVisibility?: boolean;
columnsResizable?: boolean;
columnsPinnable?: boolean;
columnsMovable?: boolean;
columnsDraggable?: boolean;
rowsDraggable?: boolean;
};
tableClassNames?: {
base?: string;
header?: string;
headerRow?: string;
headerSticky?: string;
body?: string;
bodyRow?: string;
footer?: string;
edgeCell?: string;
};
}
const DataGridContext = createContext<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
DataGridContextProps<any> | undefined
>(undefined);
function useDataGrid() {
const context = useContext(DataGridContext);
if (!context) {
throw new Error('useDataGrid must be used within a DataGridProvider');
}
return context;
}
function DataGridProvider<TData extends object>({
children,
table,
...props
}: DataGridProps<TData> & { table: Table<TData> }) {
return (
<DataGridContext.Provider
value={{
props,
table,
recordCount: props.recordCount,
isLoading: props.isLoading || false,
}}
>
{children}
</DataGridContext.Provider>
);
}
function DataGrid<TData extends object>({ children, table, ...props }: DataGridProps<TData>) {
const defaultProps: Partial<DataGridProps<TData>> = {
loadingMode: 'skeleton',
tableLayout: {
dense: false,
cellBorder: false,
rowBorder: true,
rowRounded: false,
stripped: false,
headerSticky: false,
headerBackground: true,
headerBorder: true,
width: 'fixed',
columnsVisibility: false,
columnsResizable: false,
columnsPinnable: false,
columnsMovable: false,
columnsDraggable: false,
rowsDraggable: false,
},
tableClassNames: {
base: '',
header: '',
headerRow: '',
headerSticky: 'sticky top-0 z-10 bg-background/90 backdrop-blur-xs',
body: '',
bodyRow: '',
footer: '',
edgeCell: '',
},
};
const mergedProps: DataGridProps<TData> = {
...defaultProps,
...props,
tableLayout: {
...defaultProps.tableLayout,
...(props.tableLayout || {}),
},
tableClassNames: {
...defaultProps.tableClassNames,
...(props.tableClassNames || {}),
},
};
// Ensure table is provided
if (!table) {
throw new Error('DataGrid requires a "table" prop');
}
return (
<DataGridProvider table={table} {...mergedProps}>
{children}
</DataGridProvider>
);
}
function DataGridContainer({
children,
className,
border = true,
}: {
children: ReactNode;
className?: string;
border?: boolean;
}) {
return (
<div data-slot="data-grid" className={cn('grid w-full', border && 'border border-border rounded-lg', className)}>
{children}
</div>
);
}
export { useDataGrid, DataGridProvider, DataGrid, DataGridContainer };