Designing and Implementing Modal Dialogs dengan Claude Code
Learn about designing and implementing modal dialogs using Claude Code. Includes practical code examples.
設計原則 modal・dialog
modal pengguna 注意 特定 operasi 集中させるUIpola.Namun、フォーカスmanajemenやキーボードoperasi、スクリーンリーダーdukungan 怠る dan 、アクセシビリティ masalah 引き起こ.Claude Code 使えば、WAI-ARIA準拠 modal 正しくimplementasi bisa dilakukan.
HTML dialogelemenを使ったimplementasi
> HTML標準 dialogelemen 使ったmodalkomponen buatkan.
> アクセシビリティ dan animasi support.
import { useRef, useEffect } from 'react';
interface DialogProps {
open: boolean;
onClose: () => void;
title: string;
children: React.ReactNode;
}
function Dialog({ open, onClose, title, children }: DialogProps) {
const dialogRef = useRef<HTMLDialogElement>(null);
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) return;
if (open) {
dialog.showModal();
} else {
dialog.close();
}
}, [open]);
useEffect(() => {
const dialog = dialogRef.current;
if (!dialog) return;
const handleClose = () => onClose();
dialog.addEventListener('close', handleClose);
const handleClick = (e: MouseEvent) => {
if (e.target === dialog) onClose();
};
dialog.addEventListener('click', handleClick);
return () => {
dialog.removeEventListener('close', handleClose);
dialog.removeEventListener('click', handleClick);
};
}, [onClose]);
return (
<dialog
ref={dialogRef}
aria-labelledby="dialog-title"
className="rounded-xl shadow-2xl p-0 backdrop:bg-black/50 backdrop:backdrop-blur-sm
max-w-lg w-full open:animate-fadeIn"
>
<div className="p-6">
<div className="flex items-center justify-between mb-4">
<h2 id="dialog-title" className="text-xl font-bold">{title}</h2>
<button onClick={onClose} aria-label="Close"
className="rounded-full p-1 hover:bg-gray-100">✕</button>
</div>
{children}
</div>
</dialog>
);
}
konfirmasidialog
> 「Deleteしてよろしい dengan すか?」 seperti konfirmasidialog Promiseベース dengan 使えるよう.
import { createRoot } from 'react-dom/client';
interface ConfirmOptions {
title: string;
message: string;
confirmLabel?: string;
cancelLabel?: string;
variant?: 'danger' | 'default';
}
function confirm(options: ConfirmOptions): Promise<boolean> {
return new Promise((resolve) => {
const container = document.createElement('div');
document.body.appendChild(container);
const root = createRoot(container);
const handleClose = (result: boolean) => {
root.unmount();
container.remove();
resolve(result);
};
root.render(
<Dialog open={true} onClose={() => handleClose(false)} title={options.title}>
<p className="text-gray-600 mb-6">{options.message}</p>
<div className="flex justify-end gap-3">
<button onClick={() => handleClose(false)}
className="px-4 py-2 border rounded-lg hover:bg-gray-50">
{options.cancelLabel ?? 'キャンセル'}
</button>
<button onClick={() => handleClose(true)}
className={`px-4 py-2 rounded-lg text-white ${
options.variant === 'danger' ? 'bg-red-600 hover:bg-red-700' : 'bg-blue-600 hover:bg-blue-700'
}`}>
{options.confirmLabel ?? 'konfirmasi'}
</button>
</div>
</Dialog>
);
});
}
// Usage example
async function handleDelete(id: string) {
const ok = await confirm({
title: 'Delete konfirmasi',
message: 'こ 項目 Delete よろしい すか?こ operasi 取り消せません。',
confirmLabel: 'Delete',
variant: 'danger',
});
if (ok) await deleteItem(id);
}
commandパレット
function CommandPalette({ commands, onClose }: { commands: Command[]; onClose: () => void }) {
const [query, setQuery] = useState('');
const [activeIndex, setActiveIndex] = useState(0);
const filtered = commands.filter((c) =>
c.label.toLowerCase().includes(query.toLowerCase())
);
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'ArrowDown') {
e.preventDefault();
setActiveIndex((prev) => Math.min(prev + 1, filtered.length - 1));
} else if (e.key === 'ArrowUp') {
e.preventDefault();
setActiveIndex((prev) => Math.max(prev - 1, 0));
} else if (e.key === 'Enter' && filtered[activeIndex]) {
filtered[activeIndex].action();
onClose();
}
};
return (
<Dialog open={true} onClose={onClose} title="commandパレット">
<input
autoFocus
value={query}
onChange={(e) => { setQuery(e.target.value); setActiveIndex(0); }}
onKeyDown={handleKeyDown}
placeholder="command pencarian..."
className="w-full px-3 py-2 border rounded-lg mb-3"
role="combobox"
aria-expanded={true}
/>
<ul role="listbox" className="max-h-64 overflow-y-auto">
{filtered.map((cmd, i) => (
<li key={cmd.id} role="option" aria-selected={i === activeIndex}
onClick={() => { cmd.action(); onClose(); }}
className={`px-3 py-2 rounded cursor-pointer ${i === activeIndex ? 'bg-blue-100' : 'hover:bg-gray-50'}`}>
{cmd.label}
</li>
))}
</ul>
</Dialog>
);
}
Summary
Untuk Claude Codeを使えば、HTML dialogelemenをpemanfaatanしたアクセシブルなmodalから、konfirmasidialog、commandパレットまでefisienにpembangunanできます。toastnotifikasiとの使い分けはtoastnotifikasiimplementasiを、アクセシビリティのdasar, lihat アクセシビリティガイド.
dialogelemen 仕様 MDN Web Docs - dialog silakan lihat.
PDF Gratis: Cheatsheet Claude Code dalam 5 Menit
Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.
Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.
Tentang Penulis
Masa
Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.
Artikel Terkait
7 template CLAUDE.md untuk Claude Code yang bisa langsung dipakai di proyek nyata
Tujuh template CLAUDE.md praktis untuk app solo, situs konten, API, repo tim, dan codebase legacy, plus kegagalan yang perlu dihindari.
Panduan Approval dan Sandbox Claude Code | Pengaturan aman untuk kerja harian
Cara membagi aksi Claude Code ke allow, ask, deny, dan sandbox dengan settings praktis, hooks, dan contoh workflow nyata.
Panduan Lengkap Memulai Claude Code 2026 | 7 Langkah dari Nol hingga Siap Pakai di Dunia Kerja
Panduan pemula lengkap untuk pengguna baru Claude Code. Dari instalasi hingga mengintegrasikannya ke workflow pengembangan nyata — mencakup semua jebakan yang Masa hadapi di awal.