feat(web): align ops screens with ReUI PRO kit and Frame surface

OpsDashboard+afterKpi на dashboard; FrameDataGrid вместо DataGridCard; KpiStatGrid вместо SectionCards; SettingsShell без Separator. Preview: dashboard-1, stats-12, data-grid-filtering-2, settings-16.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-31 12:15:59 +07:00
co-authored by Cursor
parent 53ce80c9ff
commit c3369059af
20 changed files with 216 additions and 198 deletions
@@ -0,0 +1,53 @@
import type { ReactNode } from 'react'
import {
Frame,
FrameDescription,
FrameHeader,
FramePanel,
FrameTitle,
} from '@/components/reui/frame'
import { cn } from '@evobgp/ui/lib/utils'
/**
* Frame shell for list/grid sections (replaces DataGridCard Card-named API).
* @see https://reui.io/preview/base/data-grid-filtering-2
* @see https://reui.io/docs/components/base/frame
*/
export function FrameDataGrid({
title,
description,
actions,
children,
className,
}: {
title?: ReactNode
description?: ReactNode
actions?: ReactNode
children: ReactNode
className?: string
}) {
const hasHeader = Boolean(title || description || actions)
return (
<Frame dense spacing="sm" className={cn('w-full gap-0 p-0', className)}>
<FramePanel className="flex flex-col gap-0 p-0 shadow-xs">
{hasHeader ? (
<FrameHeader className="flex-row items-start justify-between gap-3 border-b">
<div className="flex min-w-0 flex-1 flex-col gap-px">
{title ? <FrameTitle>{title}</FrameTitle> : null}
{description ? (
<FrameDescription>{description}</FrameDescription>
) : null}
</div>
{actions ? (
<div className="flex shrink-0 flex-wrap items-center justify-end gap-2">
{actions}
</div>
) : null}
</FrameHeader>
) : null}
<div className="p-0">{children}</div>
</FramePanel>
</Frame>
)
}