Files
Doormilexpress_console/src/components/nearle_components/PageHeader.js

89 lines
3.5 KiB
JavaScript

import PropTypes from 'prop-types';
import { HStack } from '@astryxdesign/core/HStack';
import { VStack } from '@astryxdesign/core/VStack';
import { Heading } from '@astryxdesign/core/Heading';
import { Text } from '@astryxdesign/core/Text';
import { StatusDot } from '@astryxdesign/core/StatusDot';
import { DT } from 'themes/dt/tokens';
// ==============================|| PAGE HEADER ||============================== //
//
// A plain, un-boxed page title + optional live indicator + an action slot
// (zone selector, primary button, etc.), so every operator page opens with a
// calm, corporate heading.
//
// The STRUCTURE follows KROW's page frame; the colours and the type are the
// console's own and are unchanged — `Heading level={1}` and `Text
// type="supporting"` resolve to exactly the same tokens they did before.
//
// Title · meta · ● Live [ actions ]
// subtitle
// ──────────────────────────────────────────────────────────────
//
// Two things the KROW work changed:
//
// - The bottom hairline. KROW closes every page header with a rule, and it
// is what makes the header read as a REGION of the page rather than as
// the first item in the content stack — without it, a page header and a
// section heading look identical and the page has no top.
//
// - `live` moved from beside the subtitle up onto the title row. It was
// putting the page's only motion cue on its quietest line; a live
// indicator belongs where people look for it. It is still the same
// pulsing `StatusDot variant="success"` — nothing about its colour moved.
//
// `meta` is new and optional: a real count that belongs beside the name
// ("1,248 orders"), with tabular figures so it doesn't jitter as it updates.
//
// `action` keeps its name and still wraps to its own line once it can't fit,
// which is the behaviour the old responsive `direction={{ xs: 'column', sm:
// 'row' }}` was approximating.
export default function PageHeader({ title, subtitle, meta, live = false, action }) {
return (
<VStack
gap={0}
padding={0}
style={{
paddingBottom: 16,
// The existing hairline at 50% alpha — a page header's rule should sit
// under the table borders it introduces, not match them.
borderBottom: `1px solid ${DT.borderSubtle}80`
}}
>
<HStack justify="between" vAlign="center" wrap="wrap" gap={2} paddingBlock={1}>
{/* minWidth in `style` — VStack has no such prop (see StatCard). */}
<VStack gap={0.5} padding={0} style={{ minWidth: 0 }}>
<HStack gap={2} vAlign="center" wrap="wrap">
<Heading level={1} maxLines={1}>
{title}
</Heading>
{meta != null && (
<Text type="supporting" hasTabularNumbers>
{meta}
</Text>
)}
{live && <StatusDot variant="success" label="Live" isPulsing />}
</HStack>
{subtitle && <Text type="supporting">{subtitle}</Text>}
</VStack>
{action && (
<HStack gap={1.5} vAlign="center" wrap="wrap" style={{ flexShrink: 0 }}>
{action}
</HStack>
)}
</HStack>
</VStack>
);
}
PageHeader.propTypes = {
title: PropTypes.node,
subtitle: PropTypes.node,
meta: PropTypes.node,
live: PropTypes.bool,
action: PropTypes.node
};