Bar List
blode-ui/bar-listFreeComponent
A compact comparison list that visualises values as horizontal bars.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/mblode/blode-ui/main/public/r/bar-list.jsonSource
1import type * as React from "react";23import { cn } from "@/lib/utils";45interface BarListItemBase {6 color?: string;7 href?: string;8 icon?: React.ComponentType<{ className?: string }>;9 key?: string;10 name: string;11 target?: React.HTMLAttributeAnchorTarget;12 value: number;13}1415interface BarListProps<16 T extends object = Record<string, never>,17> extends React.ComponentProps<"div"> {18 color?: string;19 data?: (T & BarListItemBase)[];20 labelFormatter?: (label: string) => React.ReactNode;21 showAnimation?: boolean;22 sortOrder?: "ascending" | "descending";23 valueFormatter?: (value: number) => React.ReactNode;24}2526const EMPTY_BAR_LIST_DATA: never[] = [];2728const defaultValueFormatter = (value: number): string => value.toLocaleString();2930const defaultLabelFormatter = (label: string): string => label;3132const BarList = <T extends object = Record<string, never>>({33 className,34 color = "hsl(var(--chart-1))",35 data = EMPTY_BAR_LIST_DATA,36 labelFormatter = defaultLabelFormatter,37 showAnimation = false,38 sortOrder = "descending",39 valueFormatter = defaultValueFormatter,40 ...props41}: BarListProps<T>) => {42 const sortedData = [...data].toSorted((a, b) =>43 sortOrder === "ascending" ? a.value - b.value : b.value - a.value,44 );4546 const maxValue = Math.max(0, ...sortedData.map((item) => item.value));4748 const widths = sortedData.map((item) => {49 if (item.value === 0 || maxValue === 0) {50 return 0;51 }5253 return Math.max((item.value / maxValue) * 100, 2);54 });5556 const rowHeight = "h-8";5758 return (59 <div60 className={cn("flex justify-between space-x-6", className)}61 data-slot="bar-list"62 data-sort={sortOrder}63 {...props}64 >65 <div className="relative w-full">66 {sortedData.map((item, index) => {67 const Icon = item.icon;6869 return (70 <div71 className="group flex w-full items-center py-1"72 data-slot="bar-list-row"73 key={item.key ?? item.name}74 >75 <div76 className={cn("relative flex items-center rounded-sm transition-all", rowHeight, {77 "duration-500": showAnimation,78 "mb-0": index === sortedData.length - 1,79 })}80 style={{81 transition: showAnimation ? "all 1s" : undefined,82 width: `${widths[index]}%`,83 }}84 >85 <div86// … truncated
Files it writes
More from blode/ui
All 85 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | blode/ui | Components | Free | 2 deps | |
| Alertalert | blode/ui | Components | Free | no deps | |
| Alert Dialogalert-dialog | blode/ui | Components | Free | 1 dep | |
| Ask User Questionsask-user-questions | blode/ui | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | blode/ui | Components | Free | 1 dep | |
| Attachmentattachment | blode/ui | Components | Free | 1 dep | |
| Autocompleteautocomplete | blode/ui | Components | Free | 1 dep | |
| Avataravatar | blode/ui | Components | Free | 1 dep |
