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 🙏

© 2024 – Pkg Stats / Ryan Hefner

tunangn-react-modal

v1.0.6

Published

Use to show message by using Dialog, snackbar or to show side in React

Downloads

7

Readme

tunangn-react-modal

Use to show message by using Dialog, snackbar or to show side in React. You can use this package easily to manage your dialog, snackbar or side. Ensure for privacy!! Dialog, side and snackbar only show (in screen or in DOM Tree) if they are opened.

Live demo

See more examples in live demo.

Note

  • This will not cause unexpected re-renders to other components when you open modal item(s). (Only the modal react component re-render)
  • This package contains default items that you just use them to solve many cases.
  • I use typescript in all examples.

Install

You can install it by:

npm install tunangn-react-modal

Import to App.jsx or App.tsx and open default dialog:

import { TunangnModal, dialog } "tunangn-react-modal";

export default function App() {
  return (
    <div>
      <button onClick={() => dialog({ title: "My first dialog" })}>Open my dialog</button>
      <TunangnModal />
    </div>
  )
}

How to use?

I will show you how to use TunangnModal in this article.

An default modal item always has 4 components:

  • Header has title and x button (optional).
  • Body has content.
  • Footer: depend on type of Modal Item, the Footer will has difference children. Firstly, I want to talk about title and content.
  • Container: wrap all components above.

Table of Contents

TunangnModal

This is the Modal React Component that you have to place it in App Component. There are 3 default modal items, you can use all of them immediately with dialog, side and snackbar from tunangn-react-modal.

TunangnModal has 3 properties:

  • canUseWhiteBG: Will white background or black background be used?.
  • className: (don't recommend) replace the default class name. If you replace the default class name, make sure you have suitable style because the default inline style will be unapply.
  • items: if you want to custom you own modal items, you can use this properties.

items is an object contains options to assign modal item to list. Its properties:

| Name | Type | Description | | :------------ | :------------ | :------------ | | type | MITypes | Use to modify the title of modal item. | | placeOn (Only for Side) | SidePlaces \| undefined | Where is side placed? | | position (Only for Snackbar) | SnackbarPositions \| undefined | What is position of snackbar? | | duration (Only for Snackbar) | number \| null \| undefined | How long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option. | | clearDefaultInlineStyle | boolean \| undefined | Clear default inline stlyes. You can use the default class name to style the UI component for Modal Item. Note: this option will not work if you use element as Function Component or using this option if you want to write css to the default class name. | | className | string \| undefined | Class name of item's container. This will be based class name for other ui element components. You don't need clearDefaultInlineStyle to clear the default inline style, because the default inline style will be cleared if className option is assigned. Note: this option will not work if you use element as Function Component or using this option if you just want to modify UI Element with your own css | | element | ((props: CustomizedModalItemProps) => JSX.Element) \| undefined | Use this option if you want to create you own modal item. |

Modal Item Data

Note: You cannot use these properties in your own customized modal item.

When you open an dialog with dialog function, an side with side function or an snackbar with snackbar function. You can pass an object to this function, an this object is data of Modal Item, the data that you want to modify the content of modal item. Each modal item always has title and content, so you can pass an object with title, content properties to modify the default modal item.

{
  title?: string | JSX.Element,
  content?: string | JSX.Element
}

All default modal items have same data: | Name | Type | Description | | :------------ | :------------ | :------------ | | title | string \| JSX.Element \| undefined | Use to modify the title of modal item. | | content | string \| JSX.Element \| undefined | Use to modify the content of modal item. |

Modal Item Properties (Default and Customized)

Modal Item Data is a part of Modal Item Properties. Including:

  • close: a function that you can use to close the modal item. Sometime, you will need to pass a result to this function. It returns a result object. The result object:
{
  isAgree: boolean,
  data?: any,
  message?: string
}
  • item: an object contains properties and methods of modal item:

| Name | Type | Description | | :------------ | :------------ | :------------ | | name | string | Name of Modal Item. | | type | string \| JSX.Element \| undefined | Use to modify the content of modal item. | | placeOn (Only for Side) | SidePlaces \| undefined | Where is side placed? | | position (Only for Snackbar) | SnackbarPositions \| undefined | What is position of snackbar? | | duration (Only for Snackbar) | number \| null \| undefined | How long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option. | | getData | getData<T>(): T | Use to get data from open function. |

  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.

| Name | Type | Description | | :------------ | :------------ | :------------ | | getContainerStyle | (style?: React.CSSProperties \| undefined) => React.CSSProperties | [Recommend] Use to get container style. You can pass your custom style to this function, your style will override the default one. | | runAnimation | MITypes \| undefined | Type of Modal Item. |

Dialog

Note: You cannot use these properties in your own customized modal item.

I will show a dialog and open another dialog depend on result.isAgree. Firstly, import dialog from tunangn-react-modal, dialog receive a data object contains title, content and its own properties:

| Name | Type | Description | | :------------ | :------------ | :------------ | | cancelBtnLabel | string \| JSX.Element \| null \| undefined | Use to set label for cancel button of dialog. You can hide this button by assign null. | | agreeBtnLabel | string \| JSX.Element \| null \| undefined | Use to set label for agree button of dialog. You can hide this button by assign null. |

Let's show a dialog

import { TunangnModal, dialog } "tunangn-react-modal";

let dialogTitle = <p>Terms and Conditions <span style={{color: "red"}}>*</span></p>;

export default function App() {
  return (
    <>
      <TunangnModal />
      <button onClick={() => {
        dialog({
          title: dialogTitle,
          content: (
            <div>
              <p>Please read carefully:</p>
              <h4>Item 1</h4>
              <h4>Item 2</h4>
              <h4>Item 3</h4>
              <h4>Item 4</h4>
              <h4>Item 5</h4>
            </div>
          )
        })
        .then(result => {
          if(result.isAgree) {
            dialog({ title: dialogTitle, content: "You accepted our terms and conditions.", cancelBtnLabel: null })
          } else {
            dialog({ title: dialogTitle, content: "You unaccepted :(", agreeBtnLabel: null })
          }
        })
      }}>Open default dialog</button>
    </>
  )
}

You can see in the example above, there are 2 dialog with difference content will be showed depend on result.isAgree. And I will hide cancel button with agreed dialog, hide agree button with canceled dialog.

Result

Open dialog

image

Trying agree

image

Trying cancel

image

Side

Note: You cannot use these properties in your own customized modal item.

Side doesn't have its own properties.

I wil show left-side (default) with title and content has 10 images.

Let's show a side

import { TunangnModal, side } "tunangn-react-modal";

let sideTitle = <p style={{display: "flex", alignItems: "center"}}>
  <span className="material-symbols-outlined" style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;

export default function App() {
  const [imageUrls, setImageUrls] = React.useState<Array<string>>([]);

  React.useEffect(() => {
    let promises = Array(10).fill(0).map(i => fetch("https://picsum.photos/200/300"));
    Promise.all(promises).then(responses => {
      let urls: string[] = [];
      responses.forEach(response => {
        urls.push(response.url);
      });
      setImageUrls(urls);
    });
  }, []);

  return (
    <>
      <TunangnModal />
      <button onClick={() => {
        side({
          title: sideTitle,
          content: (
            <div style={{ overflowY: "scroll", maxHeight: "calc(100vh - 48px)" }}>
              {
                imageUrls.length > 0 ?
                imageUrls.map((url, index) => {
                  return <img src={url} key={index} />
                }) :
                <p>There aren't images.</p>
              }
            </div>
          )
        })
      }}>Open images side</button>
    </>
  )
}

10 images are response, but the side will not be re-render. I think you have the answer, so you need to customize you own side. I will show you in the last example!!!

Result

image

I re-open the side to see 10 images.

Snackbar

Note: You cannot use these properties in your own customized modal item.

Snackbar has 1 property: | Name | Type | Description | | :------------ | :------------ | :------------ | | color | string \| undefined | Use to modify the background color of header. |

I will show 4 various snackbar with various title and content.

import { TunangnModal, snackbar } "tunangn-react-modal";

let successSnackbar = {
  title: <span className="material-symbols-outlined">check_circle</span>,
  content: "You action is performed successfully.",
  color: "success"
};

let errorSnackbar = {
  title: <span className="material-symbols-outlined">error</span>,
  content: "There is an error.",
  color: "error"
};

let warningSnackbar = {
  title: <span className="material-symbols-outlined">warning</span>,
  content: "Your requesting data will cause an unexpected side effect!!! ",
  color: "warning"
};

let otherSnackbar = {
  title: <span className="material-symbols-outlined">attach_money</span>,
  content: "You payment is processed.",
  color: "#a8329b"
};

export default function App() {
  return (
    <>
      <TunangnModal />
      <button onClick={() => {
        snackbar(successSnackbar);
      }}>Open snackbar</button>
    </>
  )
}

Result

The success snackbar

image

The error snackbar

image

The waring snackbar

image

The other snackbar

image

Customize your own Tunangn Modal Item

I will build a small profile right-side with:

  • Username, user's avatar.
  • Use css.
  • Remove almost inline styles.
  • Fetch data (images).

I will create a file in src/components/profile/Profile.tsx:

export default function Profile(props: CustomizedModalItemProps) {
  // Ref of container
  const profileRef = React.useRef<HTMLDivElement>(null);
  const data = props.item.getData() as any;

  props.item.getData

  const [imageUrls, setImageUrls] = React.useState<Array<string>>([]);
  const [user, setUser] = React.useState<UserSideData>();

  React.useEffect(() => {
    let promises = Array(10).fill(0).map(i => fetch("https://picsum.photos/300"));

    // Get user
    getUser(data.userId).then(user => setUser(user));

    // Resolve images
    Promise.all(promises).then(responses => {
      let urls: string[] = [];
      responses.forEach(response => {
        urls.push(response.url);
      });
      setImageUrls(urls);
    });

    // Use container's ref to perform animation when profile is showed.
    props.utils.runAnimation!(profileRef.current!);
  }, []);

  return (
    <div
      ref={profileRef}
      style={props.utils.getContainerStyle({
        minWidth: "420px",
        padding: ".75rem",
        borderTopLeftRadius: "16px",
        borderBottomLeftRadius: "16px",
        overflowY: "scroll"
      })}
    >
      <div className="profile-header">
        <div className="user-info">
          {
            user
            ? (
              <>
                <img className="user-info-image" src={user.url} style={{marginRight: "0.75rem"}} />
                <strong>{user.name}</strong>
              </>
            )
            : <strong>There isn't user.</strong>
          }
        </div>
        <span className="material-symbols-outlined btn-close" onClick={() => props.close({ isAgree: false })}>close</span>
      </div>
      <div className="profile-body">
        <p className="user-info-bio">
          { user?.bio }
        </p>
        <h3 style={{marginBottom: ".75rem"}}>Shortcuts</h3>
        {
          sideBodyContent.shortcuts.map((shortcut, index) => (
            <div className="profile-shortcut border-top" key={index} style={{padding: ".75rem 0"}}>
              {
                shortcut.map(article => (
                  <button className="btn-article" key={article.id}>
                    <span className="material-symbols-outlined" style={{marginRight: ".75rem"}}>{article.icon}</span>
                    <span>{upperCaseFirstChar(article.name)}</span>
                  </button>
                ))
              }
            </div>
          ))
        }
        <h3 className="border-top" style={{padding: ".75rem 0"}}>Images</h3>
        <div className="profile-images">
          {
            imageUrls.length > 0 ?
            imageUrls.map((url, index) => {
              return <img src={url} key={index} />
            }) :
            <p>There aren't images.</p>
          }
        </div>
      </div>
    </div>
  )
}

Then import Profile.tsx to App.tsx and use it:

import { TunangnModal, openTMI } "tunangn-react-modal";

import Profile, { openSideProfile, profileSideName } from "./components/profile/Profile";

// Assign user id. There are 2 userids: user-01 and user-02
let userId = "user-02";

export default function App() {
  return (
    <>
      <header className="app-header">
        <p></p>
        <span className="material-symbols-outlined btn-profile" onClick={() => openSideProfile(userId)}>account_circle</span>
      </header>
      <TunangnModal
        items={{
          myProfileSide: {
            type: "side",
            placeOn: "right",
            element: Profile
          }
        }}
      />
    </>
  )
}

Result

image

You can see the source in the live demo above