Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

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:

npminstalltunangn-react-modal

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

import{TunangnModal,dialog}"tunangn-react-modal";exportdefaultfunctionApp(){return(<div><buttononClick={()=>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:

NameTypeDescription
typeMITypesUse to modify the title of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
clearDefaultInlineStyleboolean | undefinedClear 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.
classNamestring | undefinedClass 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) | undefinedUse 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:

NameTypeDescription
titlestring | JSX.Element | undefinedUse to modify the title of modal item.
contentstring | JSX.Element | undefinedUse 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:
NameTypeDescription
namestringName of Modal Item.
typestring | JSX.Element | undefinedUse to modify the content of modal item.
placeOn (Only for Side)SidePlaces | undefinedWhere is side placed?
position (Only for Snackbar)SnackbarPositions | undefinedWhat is position of snackbar?
duration (Only for Snackbar)number | null | undefinedHow long does snackbar last? If you want to disable the auto-close behaviour, you can assign null to this option.
getDatagetData<T>(): TUse to get data from open function.
  • utils: an object contains helper functions to support the modal item has behaviour almost like default one.
NameTypeDescription
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.
runAnimationMITypes | undefinedType 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:

NameTypeDescription
cancelBtnLabelstring | JSX.Element | null | undefinedUse to set label for cancel button of dialog. You can hide this button by assign null.
agreeBtnLabelstring | JSX.Element | null | undefinedUse 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";letdialogTitle=<p>Terms and Conditions <spanstyle={{color: "red"}}>*</span></p>;exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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";letsideTitle=<pstyle={{display: "flex",alignItems: "center"}}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>photo_library</span>Images
</p>;exportdefaultfunctionApp(){const[imageUrls,setImageUrls]=React.useState<Array<string>>([]);React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/200/300"));Promise.all(promises).then(responses=>{leturls: string[]=[];responses.forEach(response=>{urls.push(response.url);});setImageUrls(urls);});},[]);return(<><TunangnModal/><buttononClick={()=>{side({title: sideTitle,content: (<divstyle={{overflowY: "scroll",maxHeight: "calc(100vh - 48px)"}}>{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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:

NameTypeDescription
colorstring | undefinedUse to modify the background color of header.

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

import{TunangnModal,snackbar}"tunangn-react-modal";letsuccessSnackbar={title: <spanclassName="material-symbols-outlined">check_circle</span>,content: "You action is performed successfully.",color: "success"};leterrorSnackbar={title: <spanclassName="material-symbols-outlined">error</span>,content: "There is an error.",color: "error"};letwarningSnackbar={title: <spanclassName="material-symbols-outlined">warning</span>,content: "Your requesting data will cause an unexpected side effect!!! ",color: "warning"};letotherSnackbar={title: <spanclassName="material-symbols-outlined">attach_money</span>,content: "You payment is processed.",color: "#a8329b"};exportdefaultfunctionApp(){return(<><TunangnModal/><buttononClick={()=>{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:

exportdefaultfunctionProfile(props: CustomizedModalItemProps){// Ref of containerconstprofileRef=React.useRef<HTMLDivElement>(null);constdata=props.item.getData()asany;props.item.getDataconst[imageUrls,setImageUrls]=React.useState<Array<string>>([]);const[user,setUser]=React.useState<UserSideData>();React.useEffect(()=>{letpromises=Array(10).fill(0).map(i=>fetch("https://picsum.photos/300"));// Get usergetUser(data.userId).then(user=>setUser(user));// Resolve imagesPromise.all(promises).then(responses=>{leturls: 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(<divref={profileRef}style={props.utils.getContainerStyle({minWidth: "420px",padding: ".75rem",borderTopLeftRadius: "16px",borderBottomLeftRadius: "16px",overflowY: "scroll"})}><divclassName="profile-header"><divclassName="user-info">{user
? (<><imgclassName="user-info-image"src={user.url}style={{marginRight: "0.75rem"}}/><strong>{user.name}</strong></>)
: <strong>There isn't user.</strong>}</div><spanclassName="material-symbols-outlined btn-close"onClick={()=>props.close({isAgree: false})}>close</span></div><divclassName="profile-body"><pclassName="user-info-bio">{user?.bio}</p><h3style={{marginBottom: ".75rem"}}>Shortcuts</h3>{sideBodyContent.shortcuts.map((shortcut,index)=>(<divclassName="profile-shortcut border-top"key={index}style={{padding: ".75rem 0"}}>{shortcut.map(article=>(<buttonclassName="btn-article"key={article.id}><spanclassName="material-symbols-outlined"style={{marginRight: ".75rem"}}>{article.icon}</span><span>{upperCaseFirstChar(article.name)}</span></button>))}</div>))}<h3className="border-top"style={{padding: ".75rem 0"}}>Images</h3><divclassName="profile-images">{imageUrls.length>0 ?
imageUrls.map((url,index)=>{return<imgsrc={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";importProfile,{openSideProfile,profileSideName}from"./components/profile/Profile";// Assign user id. There are 2 userids: user-01 and user-02letuserId="user-02";exportdefaultfunctionApp(){return(<><headerclassName="app-header"><p></p><spanclassName="material-symbols-outlined btn-profile"onClick={()=>openSideProfile(userId)}>account_circle</span></header><TunangnModalitems={{myProfileSide: {type: "side",placeOn: "right",element: Profile}}}/></>)}

Result

image

You can see the source in the live demo above

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages