Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 34 additions & 37 deletions libs/remix-ui/toaster/src/lib/toaster.css
Original file line number Diff line number Diff line change
@@ -1,43 +1,40 @@
.remixui_tooltip {
z-index: 1001;
display: flex;
justify-content: space-between;
align-items: center;
position: fixed;
min-height: 50px;
padding: 16px 24px 12px;
border-radius: 3px;
left: 40%;
font-size: 14px;
text-align: center;
bottom: -0px;
flex-direction: row;
/* Sonner toast styling */
.remixui_sonner_toast {
border-radius: 8px;
padding: 16px 24px;
font-size: 14px;
min-width: 300px;
max-width: 500px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
@-webkit-keyframes remixui_animatebottom {
0% {bottom: -300px}
100% {bottom: 0px}

.remixui_custom_toast {
display: flex;
align-items: center;
gap: 12px;
}
@keyframes remixui_animatebottom {
0% {bottom: -300px}
100% {bottom: 0px}

/* Override Sonner default styles to match Remix theme */
[data-sonner-toaster] {
z-index: 1001 !important;
}
@-webkit-keyframes remixui_animatetop {
0% {bottom: 0px}
100% {bottom: -300px}

[data-sonner-toast] {
background: var(--bs-body-bg, #f8f9fa) !important;
color: var(--bs-dark, #212529) !important;
border: 0px solid var(--bs-dark, #6c757d) !important;
font-weight: 500;
}
@keyframes remixui_animatetop {
0% {bottom: 0px}
100% {bottom: -300px}

[data-sonner-toast][data-styled="true"] {
padding: 16px 24px !important;
gap: 12px !important;
}
.remixui_animateTop {
-webkit-animation-name: remixui_animatetop;
-webkit-animation-duration: 2s;
animation-name: remixui_animatetop;
animation-duration: 2s;
}
.remixui_animateBottom {
-webkit-animation-name: remixui_animatebottom;
-webkit-animation-duration: 2s;
animation-name: remixui_animatebottom;
animation-duration: 2s;

/* Dark theme support */
[data-sonner-toast][data-theme="dark"],
.dark [data-sonner-toast] {
background: var(--bs-dark, #212529) !important;
color: var(--bs-light, #f8f9fa) !important;
border: 0px solid var(--bs-secondary, #6c757d) !important;
}
170 changes: 39 additions & 131 deletions libs/remix-ui/toaster/src/lib/toaster.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {useEffect, useState} from 'react' // eslint-disable-line
import {ModalDialog} from '@remix-ui/modal-dialog' // eslint-disable-line
import React, {useEffect} from 'react' // eslint-disable-line
import {Toaster as SonnerToaster, toast} from 'sonner'

import './toaster.css'

Expand All @@ -12,143 +12,51 @@ export interface ToasterProps {
}

export const Toaster = (props: ToasterProps) => {
const [state, setState] = useState<{
message: string | JSX.Element
hide: boolean
hiding: boolean
timeOutId: any
timeOut: number
showModal: boolean
showFullBtn: boolean
}>({
message: '',
hide: true,
hiding: false,
timeOutId: null,
timeOut: props.timeOut || 7000,
showModal: false,
showFullBtn: false
})

useEffect(() => {
if (props.message) {
const timeOutId = setTimeout(() => {
setState((prevState) => {
return { ...prevState, hiding: true }
})
}, state.timeOut)

setState((prevState) => {
if (typeof props.message === 'string' && props.message.length > 201) {
const shortTooltipText = props.message.substring(0, 200) + '...'

return {
...prevState,
hide: false,
hiding: false,
timeOutId,
message: shortTooltipText
// Show toast using Sonner
const duration = props.timeOut || 2000

if (typeof props.message === 'string') {
toast(props.message, {
duration,
onDismiss: () => {
props.handleHide && props.handleHide()
},
onAutoClose: () => {
props.handleHide && props.handleHide()
}
} else {
const shortTooltipText = props.message

return {
...prevState,
hide: false,
hiding: false,
timeOutId,
message: shortTooltipText
})
} else {
// For JSX elements, use toast.custom
toast.custom(
() => (
<div className="remixui_custom_toast">
{props.message}
</div>
),
{
duration,
onDismiss: () => {
props.handleHide && props.handleHide()
},
onAutoClose: () => {
props.handleHide && props.handleHide()
}
}
}
})
}
}, [props.message, props.timestamp])

useEffect(() => {
if (state.hiding) {
setTimeout(() => {
closeTheToaster()
}, 1800)
}
}, [state.hiding])

const showFullMessage = () => {
setState((prevState) => {
return { ...prevState, showModal: true }
})
}

const hideFullMessage = () => {
//eslint-disable-line
setState((prevState) => {
return { ...prevState, showModal: false }
})
}

const closeTheToaster = () => {
if (state.timeOutId) {
clearTimeout(state.timeOutId)
}
props.handleHide && props.handleHide()
setState((prevState) => {
return {
...prevState,
message: '',
hide: true,
hiding: false,
timeOutId: null,
showModal: false
)
}
})
}

const handleMouseEnter = () => {
if (state.timeOutId) {
clearTimeout(state.timeOutId)
}
setState((prevState) => {
return { ...prevState, timeOutId: null }
})
}

const handleMouseLeave = () => {
if (!state.timeOutId) {
const timeOutId = setTimeout(() => {
setState((prevState) => {
return { ...prevState, hiding: true }
})
}, state.timeOut)

setState((prevState) => {
return { ...prevState, timeOutId }
})
}
}
}, [props.message, props.timestamp])

return (
<>
<ModalDialog id="toaster" message={props.message} cancelLabel="Close" cancelFn={() => {}} hide={!state.showModal} handleHide={hideFullMessage} />
{!state.hide && (
<div
data-shared="tooltipPopup"
className={`remixui_tooltip mb-4 alert alert-info p-2 ${state.hiding ? 'remixui_animateTop' : 'remixui_animateBottom'}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
<span className="px-2">
{state.message}
{state.showFullBtn && (
<button className="btn btn-secondary btn-sm mx-3" style={{ whiteSpace: 'nowrap' }} onClick={showFullMessage}>
Show full message
</button>
)}
</span>
<span style={{ alignSelf: 'baseline' }}>
<button data-id="tooltipCloseButton" className="fas fa-times btn-close p-0 mt-2" onClick={closeTheToaster}></button>
</span>
</div>
)}
</>
<SonnerToaster
position="bottom-center"
offset="25vh"
toastOptions={{
className: 'remixui_sonner_toast',
}}
/>
)
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
"sol2uml": "^2.4.3",
"solhint": "^3.4.1",
"solidity-comments-extractor": "^0.0.8",
"sonner": "^2.0.7",
"string-similarity": "^4.0.4",
"svg2pdf.js": "^2.2.1",
"text-encoding": "^0.7.0",
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -28743,6 +28743,11 @@ sonic-boom@^2.2.1:
dependencies:
atomic-sleep "^1.0.0"

sonner@^2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/sonner/-/sonner-2.0.7.tgz#810c1487a67ec3370126e0f400dfb9edddc3e4f6"
integrity sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==

sort-keys@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
Expand Down