feat: реализовать EvoFirewall V1 control plane
API, UI, Linux/MikroTik agents, IP lists, политики, stats, CI и интеграция с auth-portal/EvoBGP. Co-authored-by: Cursor <[email protected]>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { cn } from '@evofw/ui/lib/utils'
|
||||
|
||||
/** Minimal Frame surface (ReUI Frame contract) — preview: https://reui.io/docs/components/base/frame */
|
||||
export function Frame({
|
||||
children,
|
||||
className,
|
||||
dense,
|
||||
}: {
|
||||
children: ReactNode
|
||||
className?: string
|
||||
dense?: boolean
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'bg-card text-card-foreground rounded-xl border shadow-xs',
|
||||
dense ? 'p-3' : 'p-4 md:p-5',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function FrameHeader({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}) {
|
||||
return (
|
||||
<div className={cn('mb-3 flex flex-wrap items-start justify-between gap-2', className)}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function FrameTitle({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}) {
|
||||
return <h2 className={cn('text-base font-semibold tracking-tight', className)}>{children}</h2>
|
||||
}
|
||||
|
||||
export function FrameDescription({
|
||||
children,
|
||||
className,
|
||||
}: {
|
||||
children: ReactNode
|
||||
className?: string
|
||||
}) {
|
||||
return <p className={cn('text-muted-foreground text-sm', className)}>{children}</p>
|
||||
}
|
||||
Reference in New Issue
Block a user