フローティングパネルFloatingPanelExperimental

作業面やキャンバス上に、ツール、状態、補助情報を重ねて表示するパネルです。必要に応じてドラッグやリサイズも有効化できます。

プレビュー

状態とバリエーション

キャンバス上の複数パネル

ツールパネルやプロパティパネルのように、作業面に重ねて配置します。

ドラッグ・リサイズ可能

タイトルバーをドラッグして移動し、右下のハンドルでサイズを調整できます。

フローティングツールバー

編集対象の近くに、アイコン操作をまとめた小さなパネルを置きます。

通知と状態

作業の完了や確認が必要な状態を、画面上に一時的に重ねます。

固定幅の情報パネル

背景を透過しない情報パネルとして使う場合は solid を選びます。

プロパティ

表は横にスクロールできます
プロパティ初期値説明
variant"glass" | "solid" | "ghost""glass"パネルの見た目を切り替えます。
titlestring-ヘッダーに表示する任意のタイトルです。
dragEnabledbooleanfalseタイトルバーをドラッグハンドルとして移動を有効にします。
resizablebooleanfalse右下からサイズ変更できるようにします。
minWidth / minHeightnumber220 / 140リサイズ時の最小サイズを指定します。
contentClassNamestring-スクロール領域など、本文エリアに追加する className です。

使い方

import { FloatingPanel } from "@gunjo/ui";
import { IconBox as Box, IconPointer as MousePointer2, IconStack2 as Layers } from "@tabler/icons-react";

export function CanvasFloatingPanels() {
  const tools = [
    { icon: MousePointer2, label: "選択" },
    { icon: Box, label: "四角形" },
    { icon: Layers, label: "レイヤー" },
  ];

  return (
    <div className="relative min-h-[420px] w-full overflow-hidden rounded-lg border bg-muted/30 p-4 sm:p-6">
      <div
        className="grid h-full min-h-[380px] place-items-center rounded-md border border-dashed bg-background/70 text-sm text-muted-foreground"
        style={{
          backgroundImage: "radial-gradient(hsl(var(--muted-foreground) / 0.22) 1px, transparent 1px)",
          backgroundSize: "18px 18px",
        }}
      >
        キャンバス領域
      </div>
      <FloatingPanel
        title="ツール"
        variant="glass"
        dragEnabled
        resizable
        minWidth={180}
        minHeight={180}
        className="absolute left-8 top-8 h-72 w-56 sm:left-10 sm:top-10"
      >
        <div className="space-y-1 p-3">
          {tools.map(({ icon: Icon, label }) => (
            <button key={label} type="button" className="flex w-full items-center gap-2 rounded-md px-2 py-2 text-left text-sm hover:bg-muted">
              <Icon className="h-4 w-4" />
              <span>{label}</span>
            </button>
          ))}
        </div>
      </FloatingPanel>
      <FloatingPanel
        title="プロパティ"
        variant="solid"
        dragEnabled
        resizable
        minWidth={220}
        minHeight={180}
        className="absolute left-[calc(100%-18rem)] top-[calc(100%-13.25rem)] h-[11.25rem] w-64 sm:left-[calc(100%-18.5rem)] sm:top-[calc(100%-13.75rem)]"
      >
        <dl className="grid grid-cols-2 gap-2 p-3 text-xs">
          <div className="rounded-md bg-muted p-2"><dt className="text-muted-foreground">X</dt><dd className="font-semibold">240</dd></div>
          <div className="rounded-md bg-muted p-2"><dt className="text-muted-foreground">Y</dt><dd className="font-semibold">120</dd></div>
          <div className="rounded-md bg-muted p-2"><dt className="text-muted-foreground">W</dt><dd className="font-semibold">300</dd></div>
          <div className="rounded-md bg-muted p-2"><dt className="text-muted-foreground">H</dt><dd className="font-semibold">200</dd></div>
        </dl>
      </FloatingPanel>
    </div>
  );
}

使用コンポーネント

設計の判断(UIXHERO)

「いつ・なぜ使うか」の判断は、姉妹サイト UIXHERO の記事で解説しています。