Skip to content

useOutsideClick ​

Listen for clicks that occur outside the defined boundaries.

Usage ​

ts
import { ImpulseElement, registerElement } from '@ambiki/impulse';
import useOutsideClick from '@ambiki/impulse-view-components/dist/hooks/use_outside_click';

@registerElement('pop-over')
export default class PopoverElement extends ImpulseElement {
  connected() {
    useOutsideClick(this, {
      boundaries: [document.querySelector('#button')],
      callback: () => {
        // Only proceed if the popover element is open.
        if (this.open) {
          this.hidden = true;
        }
      },
    });
  }

  get open() {
    return !this.hasAttribute('hidden');
  }
}

Arguments ​

ts
useOutsideClick(element, options);

element ​

NameDefaultDescription
elementN/AThe impulse element (usually this).

options ​

NameDefaultDescription
boundariesN/AAn array of HTML elements that should avoid invoking the callback function when clicking inside of it.
callbackN/AThe function to call when an outside click is detected. Signature: callback: (event: Event, element: HTMLElement) => void

Ambiki teammates ​

In the callback function, you will need to prevent the default behavior of the event so that parent dialogs and popovers remain open when clicking outside of it.

ts
import { ImpulseElement, registerElement } from '@ambiki/impulse';
import useOutsideClick from '@ambiki/impulse-view-components/dist/hooks/use_outside_click';
import { isLooselyFocusable } from '@ambiki/impulse-view-components/dist/helpers/focus';

@registerElement('pop-over')
export default class PopoverElement extends ImpulseElement {
  connected() {
    useOutsideClick(this, {
      boundaries: [document.querySelector('#button')],
      callback: (event: Event, target: HTMLElement) => {
        // Only proceed if the popover element is open.
        if (this.open) {
          this.hidden = true;
          // Prevent modals from closing accidentally.
          if (!isLooselyFocusable(target)) {
            event.preventDefault();
          }
        }
      },
    });
  }

  get open() {
    return !this.hasAttribute('hidden');
  }
}

Released under the MIT License.