Komponen / Tata letak
SplitView
Kerangka layar BizOps: sidebar kaca berisi NavList, area isi (Toolbar + daftar/detail/form), dan inspector opsional di kanan. Di layar sempit sidebar menjadi panel yang bisa dibuka/ditutup.
Sidebar + isi
Layar Daftar: sidebar kaca 248 px berisi NavList Tile, lalu header layar dan isi. Contoh memakai tinggi tetap 420 px; di aplikasi pakai className="h-dvh".
PO Customer
142 dokumen
- Diproses
PO-2026-0142
PT Mitra Energi Persada
- Menunggu BAST
PO-2026-0143
PT Sinar Logistik Nusantara
- Selesai
PO-2026-0145
CV Data Prima
import { useState, type MouseEvent } from 'react';
import { Button, NavList, SplitView, StateLabel } from '@divistant/circca-react';
import { Briefcase, FileText, House, Plus, Receipt, ShoppingCart } from '@phosphor-icons/react';
const PO = [
{ no: 'PO-2026-0142', customer: 'PT Mitra Energi Persada', status: <StateLabel tone="info" size="sm">Diproses</StateLabel> },
{ no: 'PO-2026-0143', customer: 'PT Sinar Logistik Nusantara', status: <StateLabel tone="warning" size="sm">Menunggu BAST</StateLabel> },
{ no: 'PO-2026-0145', customer: 'CV Data Prima', status: <StateLabel tone="success" size="sm">Selesai</StateLabel> },
];
// Kerangka layar Daftar: sidebar kaca berisi NavList (Tile) + isi. Tinggi bingkai tetap agar muat di pratinjau.
export default function Example() {
const [aktif, setAktif] = useState('po-customer');
const item = (id: string) => ({
href: '#',
current: aktif === id,
onClick: (e: MouseEvent) => {
e.preventDefault();
setAktif(id);
},
});
return (
<SplitView
landmarks={false}
className="h-[420px] overflow-hidden rounded-2xl border-[0.5px] border-default"
sidebar={
<NavList label="Navigasi utama" iconStyle="tile">
<NavList.Item icon={House} {...item('beranda')}>
Beranda
</NavList.Item>
<NavList.Group title="Order & pengadaan" tone="info">
<NavList.Item icon={FileText} {...item('po-customer')}>
PO Customer
</NavList.Item>
<NavList.Item icon={ShoppingCart} {...item('po-distributor')}>
PO Distributor
</NavList.Item>
</NavList.Group>
<NavList.Group title="Proyek" tone="warning">
<NavList.Item icon={Briefcase} {...item('project')}>
Project
</NavList.Item>
</NavList.Group>
<NavList.Group title="Finance" tone="highlight">
<NavList.Item icon={Receipt} {...item('invoice')}>
Invoice
</NavList.Item>
</NavList.Group>
</NavList>
}
>
<div className="flex h-[52px] shrink-0 items-center gap-2 px-3">
<SplitView.SidebarToggle />
<div className="min-w-0 flex-1">
<h2 className="truncate type-headline-default text-default">PO Customer</h2>
<p className="type-footnote-default text-muted">142 dokumen</p>
</div>
<Button variant="primary" leadingVisual={Plus}>
Buat PO
</Button>
</div>
<ul className="grid rounded-xl border-[0.5px] border-default bg-default">
{PO.map(po => (
<li key={po.no} className="flex items-center gap-3 border-b-[0.5px] border-muted px-4 py-3 last:border-b-0">
<div className="min-w-0 flex-1">
<p className="type-body-default-medium text-default">{po.no}</p>
<p className="truncate type-footnote-default text-muted">{po.customer}</p>
</div>
{po.status}
</li>
))}
</ul>
</SplitView>
);
}Dengan inspector
Drawer di slot inspector (Medium 320 px) menyatu di kanan saat baris dipilih. Bila bingkai lebih sempit dari 1024 px, Drawer otomatis menjadi overlay di dalam bingkai.
PO Customer
import { useState } from 'react';
import { Button, DescriptionList, Drawer, NavList, SplitView, StateLabel, cn, formatMoney } from '@divistant/circca-react';
import { FileText, House, ShoppingCart } from '@phosphor-icons/react';
const PO = [
{ no: 'PO-2026-0142', customer: 'PT Mitra Energi Persada', nilai: 186_000_000, termin: 'Termin 60 / 40' },
{ no: 'PO-2026-0143', customer: 'PT Sinar Logistik Nusantara', nilai: 74_500_000, termin: 'Lunas di muka' },
{ no: 'PO-2026-0145', customer: 'CV Data Prima', nilai: 32_000_000, termin: 'Termin 50 / 50' },
];
// Inspector: Drawer menyatu di kanan saat baris dipilih. Bila bingkai lebih sempit dari
// inspectorCollapseBelow (1024 px), Drawer otomatis menjadi overlay di dalam bingkai.
export default function Example() {
const [dipilih, setDipilih] = useState<string | null>('PO-2026-0142');
const po = PO.find(p => p.no === dipilih);
return (
<SplitView
landmarks={false}
className="h-[420px] overflow-hidden rounded-2xl border-[0.5px] border-default"
sidebar={
<NavList label="Navigasi utama" iconStyle="tile">
<NavList.Item icon={House} href="#" onClick={e => e.preventDefault()}>
Beranda
</NavList.Item>
<NavList.Group title="Order & pengadaan" tone="info">
<NavList.Item icon={FileText} href="#" current onClick={e => e.preventDefault()}>
PO Customer
</NavList.Item>
<NavList.Item icon={ShoppingCart} href="#" onClick={e => e.preventDefault()}>
PO Distributor
</NavList.Item>
</NavList.Group>
</NavList>
}
inspector={
po && (
<Drawer
title={po.no}
subtitle={po.customer}
open
onOpenChange={open => !open && setDipilih(null)}
footer={
<>
<Drawer.Close>
<Button>Tutup</Button>
</Drawer.Close>
<Button variant="primary">Buka detail</Button>
</>
}
>
<div className="grid gap-3 pt-1 pb-4">
<StateLabel tone="info" size="sm" className="justify-self-start">
Diproses
</StateLabel>
<DescriptionList
variant="plain"
items={[
{ label: 'Nilai', value: formatMoney(po.nilai), numeric: true },
{ label: 'Penagihan', value: po.termin },
{ label: 'Sales', value: 'Anisa Nugraha' },
]}
/>
</div>
</Drawer>
)
}
>
<div className="flex h-[52px] shrink-0 items-center gap-2 px-3">
<SplitView.SidebarToggle />
<h2 className="type-headline-default text-default">PO Customer</h2>
</div>
<ul className="grid rounded-xl border-[0.5px] border-default bg-default">
{PO.map(p => (
<li key={p.no} className="border-b-[0.5px] border-muted last:border-b-0">
<button
type="button"
aria-pressed={dipilih === p.no}
onClick={() => setDipilih(p.no)}
className={cn(
'flex w-full min-w-0 flex-col px-4 py-3 text-left outline-none focus-visible:shadow-focus',
dipilih === p.no ? 'bg-action-selected' : 'hover:bg-action-hover',
)}
>
<span className="type-body-default-medium text-default">{p.no}</span>
<span className="truncate type-footnote-default text-muted">{p.customer}</span>
</button>
</li>
))}
</ul>
</SplitView>
);
}Layar sempit
Di bawah 720 px sidebar menjadi panel overlay. SplitView.SidebarToggle di header layar membukanya; Esc atau memilih tautan menutupnya dan fokus kembali ke tombol.
Project
Isi layar Project
import { useState, type MouseEvent } from 'react';
import { NavList, SplitView } from '@divistant/circca-react';
import { Briefcase, FileText, House, Receipt } from '@phosphor-icons/react';
// Bingkai sempit (< collapseBelow, bawaan 720 px): sidebar menjadi panel overlay. Tombol toggle di header layar
// (SplitView.SidebarToggle) membukanya; Esc atau memilih tautan menutupnya dan fokus kembali ke tombol.
export default function Example() {
const [aktif, setAktif] = useState('project');
const item = (id: string) => ({
href: '#',
current: aktif === id,
onClick: (e: MouseEvent) => {
e.preventDefault();
setAktif(id);
},
});
const judul = { beranda: 'Beranda', 'po-customer': 'PO Customer', project: 'Project', invoice: 'Invoice' }[aktif];
return (
<SplitView
landmarks={false}
className="mx-auto h-[420px] max-w-[390px] overflow-hidden rounded-2xl border-[0.5px] border-default"
sidebar={
<NavList label="Navigasi utama" iconStyle="tile">
<NavList.Item icon={House} {...item('beranda')}>
Beranda
</NavList.Item>
<NavList.Group title="Order & pengadaan" tone="info">
<NavList.Item icon={FileText} {...item('po-customer')}>
PO Customer
</NavList.Item>
</NavList.Group>
<NavList.Group title="Proyek" tone="warning">
<NavList.Item icon={Briefcase} {...item('project')}>
Project
</NavList.Item>
</NavList.Group>
<NavList.Group title="Finance" tone="highlight">
<NavList.Item icon={Receipt} {...item('invoice')}>
Invoice
</NavList.Item>
</NavList.Group>
</NavList>
}
>
<div className="flex h-[52px] shrink-0 items-center gap-2 px-1">
<SplitView.SidebarToggle />
<h2 className="type-headline-default text-default">{judul}</h2>
</div>
<div className="grid flex-1 place-items-center rounded-xl border-[0.5px] border-default bg-default p-6 text-center type-callout-default text-muted">
Isi layar {judul}
</div>
</SplitView>
);
}