SparkBar.tsx79 lines · main
| 1 | import { cn } from 'ui' |
| 2 | |
| 3 | interface SparkBarProps { |
| 4 | value: number |
| 5 | max?: number |
| 6 | type?: 'horizontal' | 'vertical' |
| 7 | labelTop?: string |
| 8 | labelTopClass?: string |
| 9 | labelBottom?: string |
| 10 | labelBottomClass?: string |
| 11 | barClass?: string |
| 12 | bgClass?: string |
| 13 | borderClass?: string |
| 14 | } |
| 15 | |
| 16 | export const SparkBar = ({ |
| 17 | max = 100, |
| 18 | value = 0, |
| 19 | barClass = 'bg-foreground', |
| 20 | bgClass = '', |
| 21 | type = 'vertical', |
| 22 | borderClass = '', |
| 23 | labelBottom = '', |
| 24 | labelBottomClass = 'tabular-nums', |
| 25 | labelTop = '', |
| 26 | labelTopClass = '', |
| 27 | }: SparkBarProps) => { |
| 28 | if (type === 'horizontal') { |
| 29 | const width = Number((value / max) * 100) |
| 30 | const widthCss = `${width}%` |
| 31 | const hasLabels = labelBottom || labelTop |
| 32 | |
| 33 | return ( |
| 34 | <div className="flex flex-col w-full"> |
| 35 | {hasLabels && ( |
| 36 | <div className="flex align-baseline justify-between pb-1 space-x-8"> |
| 37 | <p |
| 38 | className={cn( |
| 39 | 'text-foreground text-sm truncate capitalize-sentence', |
| 40 | labelTop.length > 0 && 'max-w-[75%]', |
| 41 | labelBottomClass |
| 42 | )} |
| 43 | > |
| 44 | {labelBottom} |
| 45 | </p> |
| 46 | <p className={cn('text-foreground-light text-sm', labelTopClass)}>{labelTop}</p> |
| 47 | </div> |
| 48 | )} |
| 49 | <div |
| 50 | className={`relative rounded-sm h-1 overflow-hidden w-full border p-0 ${ |
| 51 | bgClass ? bgClass : 'bg-surface-400' |
| 52 | } ${borderClass ? borderClass : 'border-none'}`} |
| 53 | > |
| 54 | <div |
| 55 | className={`absolute rounded-sm inset-x-0 bottom-0 h-1 ${barClass} transition-all`} |
| 56 | style={{ width: widthCss }} |
| 57 | ></div> |
| 58 | </div> |
| 59 | </div> |
| 60 | ) |
| 61 | } else { |
| 62 | const totalHeight = 35 |
| 63 | let height = Number((value / max) * totalHeight) |
| 64 | if (height < 2) height = 2 |
| 65 | |
| 66 | return ( |
| 67 | <div |
| 68 | className={`relative rounded-sm w-5 overflow-hidden border p-1 ${ |
| 69 | bgClass ? bgClass : 'bg-gray-400' |
| 70 | } ${borderClass ? borderClass : 'border-none'}`} |
| 71 | style={{ height: totalHeight }} |
| 72 | > |
| 73 | <div className={`absolute inset-x-0 bottom-0 w-5 ${barClass}`} style={{ height }}></div> |
| 74 | </div> |
| 75 | ) |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | export default SparkBar |