LoginSignup
2
0

More than 1 year has passed since last update.

Vue.jsとVueUseでフォーカスの逃げないModalを作るメモ

Last updated at Posted at 2023-03-11

Vue.jsとVueUseでフォーカスの逃げないModalを作るメモ(備忘録)

フォーカスが外に・・・

image.png
モーダルを作るときにフォーカスが後ろにいかないよう制御が必要だと思いますが、
VueUseで「focus-trap」をラップした機能が使えるのでそれを使用します。

VueUseインストール

Vue3.2系が使える環境にVueUseをインストール
※focus-trapをラップしている機能なのでfocus-trapもインストール

npm i @vueuse/integrations
npm i focus-trap

モーダルなコンポーネントのSFCで・・・

まずは完成形

 ※デモページで含まれる不要な要素は割愛

<script setup lang="ts">
import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';
import { ref, watch } from 'vue';
type Props = {
  isShow: boolean;
};
const props = defineProps<Props>();
type Emits = {
  (e: 'close'): void;
};
const emit = defineEmits<Emits>();
const target = ref();
const { hasFocus, activate, deactivate } = useFocusTrap(target);

</script>
<template>
  <div class="card" ref="target">
    <div
      class="card-header bg-primary text-white d-flex justify-content-between align-items-center"
    >
      フォーカス制御されたモーダル1
      <button
        type="button"
        class="btn btn-outline-light"
        @click="emit('close')"
      >
        閉じる{{ hasFocus }}
      </button>
    </div>
    <div class="card-body bg-light">
      <div class="mb-3">
        <label class="form-label">入力</label>
        <input type="text" class="form-control" placeholder="" />
      </div>
    </div>
  </div>
</template>

詳しく

useFocusTrapをImport

import { useFocusTrap } from '@vueuse/integrations/useFocusTrap';

focusTrapをon-offするために親要素からモーダルが表示しているかどうかの情報を受取る

type Props = {
  isShow: boolean;
};
const props = defineProps<Props>();

focusTrapを設置する要素用のrefオブジェクト

const target = ref();

モーダルの表示非表示を見てfocusTrapを制御

watch(
  () => props.isShow,
  () => {
    if (props.isShow) {
      activate();
    } else {
      deactivate();
    }
  }
);

テンプレートでフォーカス制御する要素にrefをあてるのを忘れずに。

  <div class="card" @click.stop ref="target">

でもこれだと?

image.png

「モーダル要素の外をクリックしてモーダルを閉じる」ができなくなる。
※緑の領域のクリックイベントが発火しない

解決策

 const { hasFocus, activate, deactivate } = useFocusTrap(target, {
  allowOutsideClick: true,
});

useFocusTrapの第2引数に[allowOutsideClick]を設定すればクリックが可能に。

GitHubにサンプル上げてます

ついでにGitHubにデモページも・・・

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0