2023-09-01 16:52:43 +00:00
|
|
|
import clsx from 'clsx';
|
|
|
|
import React from 'react';
|
|
|
|
|
|
|
|
type HealthStatus = 'health' | 'error' | 'warning' | 'none';
|
|
|
|
|
2023-10-10 11:47:05 +00:00
|
|
|
export interface HealthBarBeat {
|
|
|
|
title?: string;
|
|
|
|
status: HealthStatus;
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface HealthBarProps {
|
|
|
|
size?: 'small' | 'large';
|
|
|
|
beats: HealthBarBeat[];
|
2023-09-01 16:52:43 +00:00
|
|
|
}
|
|
|
|
export const HealthBar: React.FC<HealthBarProps> = React.memo((props) => {
|
2023-10-10 11:47:05 +00:00
|
|
|
const size = props.size ?? 'small';
|
|
|
|
|
2023-09-01 16:52:43 +00:00
|
|
|
return (
|
2023-10-10 11:47:05 +00:00
|
|
|
<div
|
|
|
|
className={clsx('flex', {
|
|
|
|
'gap-[3px]': size === 'small',
|
|
|
|
'gap-1': size === 'large',
|
|
|
|
})}
|
|
|
|
>
|
2023-09-03 11:28:53 +00:00
|
|
|
{props.beats.map((beat, i) => (
|
2023-09-01 16:52:43 +00:00
|
|
|
<div
|
2023-09-03 11:28:53 +00:00
|
|
|
key={i}
|
2023-09-01 16:52:43 +00:00
|
|
|
title={beat.title}
|
|
|
|
className={clsx(
|
2023-10-10 11:47:05 +00:00
|
|
|
'rounded-full hover:scale-150 transition-transform',
|
|
|
|
{
|
|
|
|
'w-[5px] h-4': size === 'small',
|
|
|
|
'w-2 h-8': size === 'large',
|
|
|
|
},
|
2023-09-01 16:52:43 +00:00
|
|
|
{
|
|
|
|
'bg-green-500': beat.status === 'health',
|
|
|
|
'bg-red-600': beat.status === 'error',
|
|
|
|
'bg-yellow-400': beat.status === 'warning',
|
|
|
|
'bg-gray-400': beat.status === 'none',
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
HealthBar.displayName = 'HealthBar';
|