Komponen / Lapisan & umpan balik
Alert
Peringatan sistem ringkas ala macOS/iOS di tengah layar: judul, pesan, dan satu–dua tombol. Untuk keputusan cepat yang tidak bisa ditunda — hapus, sesi berakhir, koneksi terputus.
Destructive
Aksi merusak: tombol Danger, ikon peringatan otomatis, dan fokus awal jatuh ke Batal sehingga Enter tidak langsung menghapus.
Lampiran: PO-customer-PT-Graha.pdf
import { useState } from 'react';
import { Alert, Button } from '@divistant/circca-react';
import { Trash } from '@phosphor-icons/react';
// Destructive: tombol aksi Danger, ikon peringatan, fokus awal jatuh ke Batal agar Enter tidak menghapus.
export default function Example() {
const [status, setStatus] = useState('Lampiran: PO-customer-PT-Graha.pdf');
return (
<div className="grid justify-items-start gap-3">
<Alert
type="destructive"
title="Hapus lampiran?"
message="PO-customer-PT-Graha.pdf akan dihapus dari PO-2026-0142 dan tidak bisa dikembalikan."
actionLabel="Hapus"
onAction={() => setStatus('Lampiran dihapus oleh Anisa Nugraha.')}
trigger={
<Button leadingVisual={Trash}>Hapus lampiran</Button>
}
/>
<p className="type-callout-default text-muted">{status}</p>
</div>
);
}Satu pilihan
`cancelLabel={null}` menghilangkan tombol Batal; Esc dan klik di luar tidak menutup. Dibuka oleh aplikasi lewat `open` terkontrol.
import { useState } from 'react';
import { Alert, Button } from '@divistant/circca-react';
import { LockSimple } from '@phosphor-icons/react';
// Satu pilihan: cancelLabel={null} — tanpa tombol Batal, Esc dan klik di luar tidak menutup.
// Biasanya dibuka oleh aplikasi (open terkontrol), bukan oleh tombol.
export default function Example() {
const [open, setOpen] = useState(false);
return (
<div className="grid justify-items-start gap-3">
<Button onClick={() => setOpen(true)}>Simulasikan sesi habis</Button>
<Alert
open={open}
onOpenChange={setOpen}
icon={LockSimple}
title="Sesi berakhir"
message="Anda keluar otomatis setelah 30 menit tidak aktif. Masuk lagi untuk melanjutkan; draf PO-2026-0142 sudah tersimpan."
actionLabel="Masuk lagi"
cancelLabel={null}
onAction={() => setOpen(false)}
/>
</div>
);
}Aksi async & tombol bertumpuk
Bila `onAction` mengembalikan Promise, tombol menampilkan loading dan Alert tertutup setelah berhasil; bila gagal tetap terbuka. `stacked` untuk label yang terlalu panjang untuk berdampingan.
Belum tersambung ulang.
import { useState } from 'react';
import { Alert, Button } from '@divistant/circca-react';
import { WifiSlash } from '@phosphor-icons/react';
// onAction mengembalikan Promise: tombol menampilkan loading dan Alert baru tertutup setelah berhasil.
// Bila gagal (Promise ditolak), Alert tetap terbuka — perbarui `message`. `stacked` untuk label panjang.
export default function Example() {
const [attempt, setAttempt] = useState(0);
const [status, setStatus] = useState('Belum tersambung ulang.');
const reconnect = () =>
new Promise<void>((resolve, reject) => {
setTimeout(() => {
setAttempt(a => a + 1);
if (attempt === 0) reject(new Error('timeout'));
else {
setStatus('Tersambung kembali ke BizOps.');
resolve();
}
}, 1200);
});
return (
<div className="grid justify-items-start gap-3">
<Alert
icon={WifiSlash}
title="Koneksi ke BizOps terputus"
message={
attempt === 0
? 'Perubahan pada PO-2026-0142 belum terkirim. Periksa jaringan lalu coba sambungkan ulang.'
: 'Masih belum tersambung. Coba sekali lagi atau lanjutkan bekerja secara luring.'
}
actionLabel="Sambungkan ulang"
cancelLabel="Lanjutkan luring"
stacked
onAction={reconnect}
onCancel={() => setStatus('Bekerja luring; perubahan dikirim saat tersambung.')}
onOpenChange={next => next && setAttempt(0)}
trigger={<Button>Simulasikan koneksi putus</Button>}
/>
<p className="type-callout-default text-muted">{status}</p>
</div>
);
}