Dialog

Dialogは、ユーザーに対して明示的な情報を提示したり、オプションを選択させるためのコンポーネントです。

プロパティ

Dialogは、以下のプロパティをサポートしています。

名前 デフォルト値 説明
open boolean false Dialog を表示するかどうか。
dismissible boolean false Dialog 以外を押しても閉じるかどうか。
positiveText string 決定 primaryボタンの文言を渡します。
negativeText string キャンセル secondaryボタンの文言を渡します。
enableClose boolean false 閉じるボタンを表示できます。
onClick (result: boolean) => void ボタンをクリックされた際に呼び出される関数です。

インストールの手順

以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。
パスは実際のプロジェクトの構成にあわせて更新します。

modals/Dialog.svelte
        <!--
@component
## 概要
- ユーザーに対して情報を提示したり、オプションを選択させるためのコンポーネントです

## 機能
- グループ化して表示することができます
- 任意のコンテンツを配置できます

## Usage
```svelte
<Dialog bind:open={isOpen}>
  {@render children()}
</Dialog>
```
-->

<script module lang="ts">
  import type { Snippet } from 'svelte';
  import type { ClassValue } from 'svelte/elements';
  import { cva, type VariantProps } from 'class-variance-authority';

  export const dialogVariants = cva('relative flex flex-col gap-6 p-6 bg-base-container-default border border-base-stroke-default rounded-lg shadow-lg',
  );

  export type DialogVariants = VariantProps<typeof dialogVariants>;

  export interface DialogProps extends DialogVariants {
    /** Dialogが開いているかどうか */
    open: boolean;
    /** Dialog以外押して閉じれるかどうか */
    dismissible?: boolean;
    /** primaryボタンの文言 */
    positiveText?: string;
    /** secondaryボタンの文言 */
    negativeText?: string;
    /** 閉じれるようにするかどうか */
    enableClose?: boolean;
    /** ボタンが押されたときのハンドラ */
    onClick: (result: boolean) => void;
    /** クラス */
    class?: ClassValue;
    children: Snippet<[]>;
  }
</script>

<script lang="ts">
  import Button from '$lib/components/ui/atoms/Button.svelte';
  import { X } from '@lucide/svelte';
  import { fade, scale } from 'svelte/transition';

  let { class: className, open = $bindable(false), dismissible = false, positiveText = '決定', negativeText = 'キャンセル', enableClose = false, onClick, children }: DialogProps = $props();

  let backgroundElement = $state<HTMLElement>();

  let dialogVariantsClass = $derived(dialogVariants({ class: className }));

  $effect(() => {
    if (open) {
      document.body.classList.add('overflow-hidden');
      document.addEventListener('click', onClickOutside);
      document.addEventListener('keydown', onKeyDown);
    }

    return () => {
      document.body.classList.remove('overflow-hidden');
      document.removeEventListener('click', onClickOutside);
      document.removeEventListener('keydown', onKeyDown);
    };
  });

  // dialog外をクリックしたときにdialogを閉じる
  function onClickOutside(e: MouseEvent) {
    e.preventDefault();
    e.stopPropagation();
    if (!backgroundElement) return;
    if (!(e.target instanceof HTMLElement)) return;
    if (backgroundElement.contains(e.target) && dismissible) {
      open = false;
    }
  }

  // escキーでdrawerを閉じる
  function onKeyDown(e: KeyboardEvent) {
    if (e.key === 'Escape' && dismissible) {
      open = false;
    }
  }
</script>

{#if open}
  <div class="fixed inset-0 z-40 bg-base-container-default/50" bind:this={backgroundElement} transition:fade={{ duration: 150 }}></div>
  <div class="fixed inset-0 z-50 size-fit m-auto">
    <div class={dialogVariantsClass} transition:scale={{ start: 0.9, duration: 150 }}>
      {@render children()}
      <div class="flex justify-end gap-2 max-md:flex-col-reverse">
        <Button class="max-md:w-full" variant="secondary" onclick={() => onClick(false)}>{negativeText}</Button>
        <Button class="max-md:w-full" variant="primary" onclick={() => onClick(true)}>{positiveText}</Button>
      </div>
      {#if enableClose}
        <Button class="absolute top-2 right-2 p-2" tone="ghost" variant="secondary" size="small" isSquare onclick={() => onClick(false)}>
          <X size="1rem" />
        </Button>
      {/if}
    </div>
  </div>
{/if}

      

依存コンポーネント

Dialogを使うときは、以下のコンポーネントもダウンロードが必要です。

使い方


サンプル

Default

特に操作が行われていない、デフォルトの状態です。

EnableClose

閉じるボタンを表示することができます。

With Input,Select

InputSelectなどの要素と組み合わせることもできます。