🚀 新規事業

modal-stacking

最終更新 2026年05月09日 / 40_新規事業/SCALE_Build/カタログ/機能集/modal-stacking.md

モーダル積層管理

用途

複数モーダルを安全に積み重ねるパターン。z-indexとEscキー処理。

特徴

  • z-index自動管理
  • Escキー処理
  • スクロールロック

コード(コピペ用)

'use client';
import { useEffect, useRef, ReactNode } from 'react';

let stackDepth = 0;

// z-index 自動管理 + Esc キー対応モーダル
export function Modal({ open, onClose, children }: { open: boolean; onClose: () => void; children: ReactNode }) {
  const z = useRef(0);

  useEffect(() => {
    if (!open) return;
    stackDepth++;
    z.current = 50 + stackDepth * 10;
    // 一番上のモーダルだけ Esc を効かせる
    const me = stackDepth;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape' && me === stackDepth) onClose();
    };
    document.addEventListener('keydown', onKey);
    // body スクロールロック(最初のモーダル時だけ)
    if (stackDepth === 1) document.body.style.overflow = 'hidden';
    return () => {
      stackDepth--;
      document.removeEventListener('keydown', onKey);
      if (stackDepth === 0) document.body.style.overflow = '';
    };
  }, [open, onClose]);

  if (!open) return null;
  return (
    <div className="fixed inset-0 bg-black/60 flex items-center justify-center p-4" style={{ zIndex: z.current }} onClick={onClose}>
      <div className="bg-zinc-900 border border-zinc-800 rounded-2xl p-6 max-w-2xl w-full" onClick={(e) => e.stopPropagation()}>
        {children}
      </div>
    </div>
  );
}

使い方

対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。

注意事項

  • 依存パッケージを忘れず追加