admin/components/forms/AdminFormLayout.tsx
alisaza e1eaf5eff5 feat: initial ghabilee-admin backoffice app
Extract admin dashboard from ghabilee-frontend2 into a dedicated Next.js
app for backoffice.ghabilee.ir (no SEO indexing / Clarity).
2026-09-05 13:12:59 +03:30

50 lines
1.7 KiB
TypeScript

import type { PropsWithChildren, ReactNode } from 'react'
import clsx from 'clsx'
type AdminFormSectionProps = PropsWithChildren<{
className?: string
contained?: boolean
description?: ReactNode
title: ReactNode
}>
export function AdminFormSection({ children, className, contained = true, description, title }: AdminFormSectionProps) {
return (
<section className={clsx(contained && 'admin-surface p-4', className)}>
<header className="flex items-start gap-3 border-b border-secondary-40 pb-3">
<span
aria-hidden
className="mt-2 size-2 shrink-0 rounded-full bg-primary-600 ring-4 ring-primary-50"
/>
<div>
<h2 className="text-sm font-bold text-secondary-10 sm:text-base">{title}</h2>
{description ? <p className="mt-1 text-xs leading-5 text-secondary-30">{description}</p> : null}
</div>
</header>
<div className="mt-5">{children}</div>
</section>
)
}
type AdminFormActionsProps = PropsWithChildren<{
className?: string
helper?: ReactNode
sticky?: boolean
}>
export function AdminFormActions({ children, className, helper, sticky = false }: AdminFormActionsProps) {
return (
<footer
className={clsx(
'flex flex-col-reverse gap-3 rounded-2xl border border-secondary-40 bg-white/95 p-3 shadow-[0_-4px_20px_rgba(51,58,68,0.04)] backdrop-blur sm:flex-row sm:items-center sm:justify-between sm:px-4',
sticky && 'sticky bottom-3 z-20',
className
)}
>
{helper ? <p className="text-xs leading-5 text-secondary-30">{helper}</p> : <span />}
<div className="flex flex-wrap items-center gap-2">{children}</div>
</footer>
)
}