npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

rubillex_frog-modal

v1.4.5

Published

Modal helper for Nuxt 3 (forked from https://github.com/froggyxyz/frog-modal)

Downloads

69

Readme

Оригинальный репозиторий

Этот проект является форком froggyxyz/frog-modal

frog-modal

npm version npm downloads License Nuxt

A module for simplifying modal window management in Nuxt.js applications.

Table of Contents

Installation

# Using pnpm
pnpm add rubillex_frog-modal

# Using yarn
yarn add rubillex_frog-modal

# Using npm
npm install rubillex_frog-modal

Quick Start

  1. Add rubillex_frog-modal to the modules section of your nuxt.config.ts:
export default defineNuxtConfig({
  modules: ["rubillex_frog-modal"],
});
  1. Add the FrogModal component to your app.vue:
<template>
  <div>
    <FrogModal />
    <NuxtPage />
  </div>
</template>

Usage

const { setModal, closeModal, clearModals, isOpen } = useFrogModal();

// Opening a modal window
setModal(YourModalComponent, {
  // props
});

// Closing the last opened modal window
closeModal();

// Closing all modal windows
clearModals();

Custom Modal Component Structure

Your custom modal component should be wrapped with FrogModalWrapper component. Here's an example of a basic modal component:

<template>
  <FrogModalWrapper
    :desktop-position="FrogModalWrapperPosition.CENTER"
    :mobile-position="FrogModalWrapperPosition.BOTTOM"
    mobile-swipe-to-close
    class="modal"
  >
    <!-- Optional header slot -->
    <template #header>
      <div class="modal-header">Your Header</div>
    </template>

    <!-- Modal content -->
    <div class="modal-content">
      <p>Your modal content here</p>
      <button @click="emit('customEmit', 'Some data')">
        Trigger Custom Event
      </button>
    </div>
  </FrogModalWrapper>
</template>

<script lang="ts" setup>
import { useFrogModal } from "frog-modal";
import type { YourModalProps, YourModalEmits } from "./your-modal.types";

// Define props and emits
defineProps<YourModalProps>();
const emit = defineEmits<YourModalEmits>();

// Access modal methods if needed
const { setModal } = useFrogModal();
</script>

<style scoped>
.modal {
  /* Your modal styles */
  min-width: 250px;
  background-color: #fff;
  border-radius: 8px;
  padding: 16px;
}
</style>

FrogModalWrapper Props

| Prop | Type | Default | Description | | ------------------ | ------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- | | desktopPosition | FrogModalWrapperPosition | .CENTER | Modal position on desktop (see available positions below) | | mobilePosition | FrogModalWrapperPosition | .CENTER | Modal position on mobile (see available positions below) | | mobileSwipeToClose | boolean | false | Enable swipe-to-close on mobile devices | | headerWrapperClass | string | undefined | Allows you to add a custom CSS class to the modal window title wrapper (usually used to stylize the area to swipe on mobileSwipeToClose) |

Available Modal Positions

The modal can be positioned using the FrogModalWrapperPosition enum, which is automatically imported by the module:

// FrogModalWrapperPosition is automatically imported
// No need to import it manually

enum FrogModalWrapperPosition {
  TOP = "top",
  BOTTOM = "bottom",
  LEFT = "left",
  RIGHT = "right",
  CENTER = "center",
  FULL = "full",
}

Example usage:

<template>
  <FrogModalWrapper
    :desktop-position="FrogModalWrapperPosition.CENTER"
    :mobile-position="FrogModalWrapperPosition.BOTTOM"
  >
    <!-- Modal content -->
  </FrogModalWrapper>
</template>

Available positions:

  • TOP - Modal appears from the top of the screen
  • BOTTOM - Modal appears from the bottom of the screen
  • LEFT - Modal appears from the left side
  • RIGHT - Modal appears from the right side
  • CENTER - Modal appears in the center of the screen
  • FULL - Modal takes up the full screen

Animation Configuration

The timing of modal animations (fade in/out) can be configured through the useFrogModal composable:

const { setModal } = useFrogModal({
  fadeInDelay: 200, // Delay before fade in animation starts (in ms)
  fadeOutDelay: 200, // Delay before fade out animation starts (in ms)
});

These parameters can be set globally when initializing the composable, and they will apply to all modals opened using this instance.

Note: The actual animation duration and timing function are controlled by CSS variables --frog-modal-animation-duration and --frog-modal-animation-timing.

Component Features

Header Slot

The header slot is specifically designed for mobile devices when using mobileSwipeToClose. It provides a draggable area at the top of the modal that users can swipe down to close the modal. This feature is mainly used with the bottom position on mobile.

Mobile Swipe to Close

When mobileSwipeToClose is enabled:

  • On mobile devices, users can swipe down to close the modal
  • The header slot becomes a draggable area
  • This feature is most commonly used with bottom position on mobile
  • Provides a native-feeling interaction on touch devices

Component Structure Guidelines

  1. Always wrap your modal content with FrogModalWrapper
  2. Use the header slot for custom header content, especially when implementing swipe-to-close on mobile
  3. Place your main modal content directly inside the wrapper
  4. Define your props and emits types for TypeScript support
  5. Use the useFrogModal composable if you need to open nested modals

Styling

You can customize the appearance of modal windows in two ways:

Using CSS Variables

:root {
  /* Modal overlay */
  --frog-modal-transition: visibility 0.2s, opacity 0.2s;
  --frog-modal-overlay-opacity: 0.5;
  --frog-modal-overlay-background: #0e151e;

  /* Animation timing */
  --frog-modal-animation-duration: 0.3s;
  --frog-modal-animation-timing: ease-in-out;
}

These variables control:

  • --frog-modal-animation-duration: Duration of modal animations (default: 0.3s)
  • --frog-modal-animation-timing: Timing function for animations (default: ease-in-out)

Using CSS Classes

The modal system uses the following class structure:

/* Main modal container */
.frog-modal {
  /* Styles for the visible modal container */
}

.frog-modal.hide {
  /* Styles for the hidden modal container */
}

/* Individual modal entity */
.frog-modal__entity {
  /* Styles for each modal instance */
}

/* Modal overlay */
.frog-modal__overlay {
  /* Styles for the backdrop */
  background-color: var(--frog-modal-overlay-background, #0e151e);
  opacity: var(--frog-modal-overlay-opacity, 0.5);
}

The class structure follows this hierarchy:

  1. .frog-modal - Main container for all modals
  2. .frog-modal__entity - Container for each individual modal instance
  3. .frog-modal__overlay - Backdrop overlay for each modal
  4. Your custom modal component classes

Each modal instance gets a unique z-index based on its position in the stack, ensuring proper layering of multiple modals.

Animation Configuration

The timing of modal animations (fade in/out) can be configured through the useFrogModal composable:

const { setModal } = useFrogModal({
  fadeInDelay: 200, // Delay before fade in animation starts (in ms)
  fadeOutDelay: 200, // Delay before fade out animation starts (in ms)
});

These parameters can be set globally when initializing the composable, and they will apply to all modals opened using this instance.

Note: The actual animation duration and timing function are controlled by CSS variables --frog-modal-animation-duration and --frog-modal-animation-timing.

TypeScript

Type Definitions

For proper TypeScript support, define your modal's props and emits types in a separate file:

// your-modal.types.ts
export type YourModalProps = {
  text: string;
  // other props...
};

export type YourModalEmits = {
  customEmit: [message: string];
  // other emits...
};

Basic Usage with TypeScript

<template>
  <FrogModalWrapper
    :desktop-position="FrogModalWrapperPosition.BOTTOM"
    :mobile-position="FrogModalWrapperPosition.BOTTOM"
    mobile-swipe-to-close
    class="modal"
  >
    <p>{{ text }}</p>
    <button @click="emit('customEmit', 'Custom message')">
      Trigger Custom Event
    </button>
  </FrogModalWrapper>
</template>

<script lang="ts" setup>
import { useFrogModal } from "frog-modal";
import type { YourModalProps, YourModalEmits } from "./your-modal.types";

// Define props and emits using the types
defineProps<YourModalProps>();
const emit = defineEmits<YourModalEmits>();

// Access modal methods if needed
const { setModal } = useFrogModal();
</script>

Opening Typed Modals

When opening a modal, TypeScript will provide type checking for both props and emits:

const { setModal } = useFrogModal();

// TypeScript will ensure all required props are provided
setModal<YourModalProps, YourModalEmits>(YourModal, {
  text: "Hello!", // Required prop
  onCustomEmit: (message: string) => {
    // TypeScript knows the exact type of the message parameter
    console.log(message);
  },
});

Type Safety Features

  • Props type checking ensures all required props are provided
  • Emits type checking ensures event handlers match the defined types
  • TypeScript will show errors if:
    • Required props are missing
    • Wrong prop types are provided
    • Event handlers don't match the defined types
    • Wrong number of arguments are passed to event handlers

API

useFrogModal

Parameters

| Parameter | Type | Default | Description | | ------------------- | ------- | ------- | -------------------------------------------- | | closeOnOverlayClick | boolean | true | Close modal window when clicking the overlay | | closeOnEsc | boolean | true | Close modal window when pressing Esc |

Methods

| Method | Description | | ----------- | ----------------------------------- | | setModal | Opens a modal window | | closeModal | Closes the last opened modal window | | clearModals | Closes all open modal windows | | isOpen | Modal window state (boolean) |

Prefetching Asynchronous Modal Windows

Directive v-frog-modal-prefetch

A custom directive v-frog-modal-prefetch has been added, allowing you to prefetch asynchronous modal components either on hover or when the element becomes visible in the viewport.

Usage:

<button v-frog-modal-prefetch.visible="testModalLoader" @click="openModal()">
  Open modal
</button>
  • binding — a function that returns a promise with the async component (for example, the result of an import).
  • .visible — a modifier that triggers prefetching when the element appears in the viewport (using IntersectionObserver).
  • If no modifier is specified, prefetching will be triggered on hover (mouseenter) by default.

Examples:

  • Prefetch on hover:

    <button v-frog-modal-prefetch="testModalLoader" @click="openModal()">
      Open modal
    </button>
  • Prefetch when visible:

    <button v-frog-modal-prefetch.visible="testModalLoader" @click="openModal()">
      Open modal
    </button>

Hook useAsyncComponentWrapper

For convenient work with asynchronous components, use the hook:

const { component: TestModal, loader: testModalLoader } =
  useAsyncComponentWrapper(() => import("~/components/TestModal/index.vue"));
  • component — the async component to be passed to the modal.
  • loader — the prefetch function (used in the directive).

Opening a Modal Window

To open a modal window, use the setModal function from the useFrogModal hook:

setModal<TestModalProps, TestModalEmits>(TestModal, {
  text: "test",
  onCustomEmit: handleClick,
});

Examples

Basic Usage

const { setModal } = useFrogModal();

// Opening a simple modal window
setModal(SimpleModal, {
  title: "Title",
  content: "Content",
});

Usage with Events

const { setModal } = useFrogModal();

setModal(FormModal, {
  onSubmit: (data) => {
    console.log(data);
  },
});

License

MIT