import PropTypes from 'prop-types';
import { Grid } from '@astryxdesign/core/Grid';
import { getStatusMeta } from 'themes/dt/status';
import SegmentCard from './SegmentCard';
// ==============================|| STATUS TABS ||============================== //
// The top-level status filter on every list page.
//
//
//
// Each entry's `status` resolves through the shared registry for its label,
// icon, colour and hint, so a page supplies only the ORDER of the bands and
// where each count comes from. Pass `label` on an entry to override the
// registry wording.
//
// ---------------------------------------------------------------------------
// Cards, not a tab strip
// ---------------------------------------------------------------------------
// This was a row of Astryx s with a count badge. It is now a row of
// s: same props, same behaviour, same registry — only the
// rendering changed, so no page file needed touching.
//
// The strip was doing three jobs with one line of text: naming the band,
// carrying its count, and being the control that selects it. As cards each of
// those gets its own place — the name, a hint at what the band MEANS, the
// count as the largest thing, and the band's share of the total. The selected
// band is now legible from across the room by its coloured border rather than
// from a 2px underline.
//
// The cost is honest: a card row is taller than a tab strip. That is why the
// count is the dominant element — the row has to earn the height by being
// readable at a glance, not just clickable.
//
// `size` and `hasDivider` are accepted and ignored. They were part of the
// TabList API and several pages still pass them; silently accepting them
// keeps those call sites working rather than spreading unknown props onto a
// DOM node (see this folder's CLAUDE.md §7 on prop-signature changes).
export default function StatusTabs({ value, onChange, tabs, hideHint }) {
// The pill under each count is the band's share of everything shown. It is
// computed from the tabs themselves rather than taken as a prop, so it can
// never disagree with the numbers printed above it.
const total = tabs.reduce((sum, tab) => sum + (Number(tab.count) || 0), 0);
return (
// width="100%" is load-bearing. DataCard renders this slot inside a VStack,
// which aligns its children to the start rather than stretching them, so
// without it the Grid shrinks to a single minWidth column and all eight
// bands stack vertically in a container that had room for six across.
{tabs.map((tab) => {
const meta = getStatusMeta(tab.status);
const Icon = meta.icon;
const count = Number(tab.count) || 0;
// No share line when there is nothing to take a share of — "0% of 0"
// is noise, and an empty band should simply say nothing.
const share = total > 0 ? `${Math.round((count / total) * 100)}% of ${total}` : null;
return (
}
color={meta.color}
isSelected={value === tab.status}
onClick={() => onChange?.(tab.status)}
/>
);
})}
);
}
StatusTabs.propTypes = {
value: PropTypes.string,
onChange: PropTypes.func,
tabs: PropTypes.arrayOf(
PropTypes.shape({
status: PropTypes.string.isRequired,
label: PropTypes.node,
count: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
isUrgent: PropTypes.bool
})
).isRequired,
/** Accepted for call-site compatibility with the previous TabList API. */
size: PropTypes.oneOf(['sm', 'md', 'lg']),
/** Accepted for call-site compatibility with the previous TabList API. */
hasDivider: PropTypes.bool,
/** If true, hides the hint text (meta.hint) on the cards. */
hideHint: PropTypes.bool
};