Files
portainer/app/react/components/StatusSummaryBar/StatusSummaryBar.tsx

109 lines
2.7 KiB
TypeScript

import { ReactNode } from 'react';
import clsx from 'clsx';
import { FilterBarButton, Color } from './FilterBarButton';
import { FilterBarActiveIndicator } from './FilterBarActiveIndicator';
export interface StatusSegment<TValue = string> {
key: TValue;
label: string;
count: number;
color: Color;
}
interface Props<TValue> {
total: number;
segments: Array<StatusSegment<TValue>>;
value: TValue | null;
onChange: (filter: TValue | null) => void;
radioGroupName?: string;
ariaLabel?: string;
isLoading?: boolean;
'data-cy'?: string;
rightSlot?: ReactNode;
}
export function StatusSummaryBar<TValue extends string = string>({
total,
segments,
value,
onChange,
radioGroupName = 'status-summary-filter',
ariaLabel = 'Filter by status',
isLoading = false,
'data-cy': dataCy = 'status-summary-bar',
rightSlot,
}: Props<TValue>) {
const isAllSelected = !value || value === 'all' || value === 'custom';
const activeLabel = segments.find((s) => s.key === value)?.label;
function handleSegmentClick(key: TValue) {
onChange(value === key ? null : key);
}
return (
<div
className={clsx(
'relative flex flex-wrap items-stretch',
'border border-solid',
'border-gray-5 th-highcontrast:border-white th-dark:border-gray-8',
'overflow-y-hidden rounded-lg',
'bg-white th-highcontrast:bg-transparent th-dark:bg-graphite-800'
)}
data-cy={dataCy}
role="radiogroup"
aria-label={ariaLabel}
>
<FilterBarButton
count={total}
label="Total"
isSelected={isAllSelected}
onClick={() => onChange(null)}
name={radioGroupName}
isLoading={isLoading}
data-cy={`${dataCy}-total`}
/>
<Separator />
{segments.map(({ key, label, count, color }) => (
<FilterBarButton
key={key}
color={color}
count={count}
label={label}
isSelected={value === key}
onClick={() => handleSegmentClick(key)}
name={radioGroupName}
data-cy={`${dataCy}-${key}`}
/>
))}
{rightSlot ? (
<div className="ml-auto flex items-center">
<div className="flex items-center px-3">{rightSlot}</div>
</div>
) : (
activeLabel && (
<div className="ml-auto hidden xl:!flex">
<Separator />
<FilterBarActiveIndicator
label={activeLabel}
onClear={() => onChange(null)}
/>
</div>
)
)}
</div>
);
}
function Separator() {
return (
<div
className="w-px shrink-0 self-stretch bg-[var(--border-widget)]"
aria-hidden="true"
/>
);
}