Skip to content

Commit

Permalink
feat(toast): redesign hooks to compatible with placement and styles (#…
Browse files Browse the repository at this point in the history
…708)

* feat(toast): redesign hooks to compatible with placement and styles

* docs: update APIs of Toast component

* feat(toast): slightly resize the action buttons to fit the overall layout

* fix(toast): restore the timer after remove the element from the stack top
  • Loading branch information
unix authored Feb 4, 2022
1 parent 18c6f7f commit 3f9e190
Show file tree
Hide file tree
Showing 20 changed files with 654 additions and 427 deletions.
36 changes: 23 additions & 13 deletions components/geist-provider/geist-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import {
GeistUIContent,
GeistUIContextParams,
UpdateToastsFunction,
UpdateToastsIDFunction,
UpdateToastsLayoutFunction,
} from '../utils/use-geist-ui-context'
import ThemeProvider from './theme-provider'
import useCurrentState from '../utils/use-current-state'
import ToastContainer, { ToastWithID } from '../use-toasts/toast-container'
import ToastContainer from '../use-toasts/toast-container'
import { GeistUIThemes } from '../themes/presets'
import { defaultToastLayout } from '../use-toasts/use-toast'

export type GeistProviderProps = {
themes?: Array<GeistUIThemes>
Expand All @@ -19,28 +22,35 @@ const GeistProvider: React.FC<PropsWithChildren<GeistProviderProps>> = ({
themeType,
children,
}) => {
const [toasts, setToasts, toastsRef] = useCurrentState<Array<ToastWithID>>([])
const [toastHovering, setToastHovering] = useState<boolean>(false)
const updateToasts: UpdateToastsFunction<ToastWithID> = (
fn: (toasts: ToastWithID[]) => ToastWithID[],
) => {
const [lastUpdateToastId, setLastUpdateToastId] =
useState<GeistUIContextParams['lastUpdateToastId']>(null)
const [toasts, setToasts, toastsRef] = useCurrentState<GeistUIContextParams['toasts']>(
[],
)
const [toastLayout, setToastLayout, toastLayoutRef] =
useCurrentState<GeistUIContextParams['toastLayout']>(defaultToastLayout)
const updateToasts: UpdateToastsFunction = fn => {
const nextToasts = fn(toastsRef.current)
setToasts(nextToasts)
}

const updateToastHoverStatus = (fn: () => boolean) => {
const nextHoverStatus = fn()
setToastHovering(nextHoverStatus)
const updateToastLayout: UpdateToastsLayoutFunction = fn => {
const nextLayout = fn(toastLayoutRef.current)
setToastLayout(nextLayout)
}
const updateLastToastId: UpdateToastsIDFunction = fn => {
setLastUpdateToastId(fn())
}

const initialValue = useMemo<GeistUIContextParams>(
() => ({
toasts,
toastHovering,
toastLayout,
updateToasts,
updateToastHoverStatus,
lastUpdateToastId,
updateToastLayout,
updateLastToastId,
}),
[toasts, toastHovering],
[toasts, toastLayout, lastUpdateToastId],
)

return (
Expand Down
2 changes: 1 addition & 1 deletion components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export { default as useAllThemes } from './use-all-themes'
export type { AllThemesConfig } from './use-all-themes'

export { default as useToasts } from './use-toasts'
export type { Toast } from './use-toasts'
export type { Toast, ToastInput, ToastAction, ToastLayout } from './use-toasts'

export { default as User } from './user'
export type { UserProps } from './user'
Expand Down
2 changes: 1 addition & 1 deletion components/snippet/snippet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const SnippetComponent: React.FC<React.PropsWithChildren<SnippetProps>> = ({
const theme = useTheme()
const { SCALES } = useScale()
const { copy } = useClipboard()
const [, setToast] = useToasts()
const { setToast } = useToasts()
const ref = useRef<HTMLPreElement>(null)
const isMultiLine = text && Array.isArray(text)

Expand Down
172 changes: 96 additions & 76 deletions components/use-toasts/__tests__/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`UseToast should render different actions 1`] = `
"<div class=\\"toast-container \\"><div class=\\"toast \\"><div class=\\"message\\">hello</div><div class=\\"action\\"><button type=\\"button\\" class=\\"btn \\"><div class=\\"text\\">remove</div><style>
"<div class=\\"toasts\\"><div class=\\"toast toast-enter\\"><div class=\\"message\\">hello</div><div class=\\"action\\"><button type=\\"button\\" class=\\"btn \\"><div class=\\"text\\">remove</div><style>
.btn {
box-sizing: border-box;
display: inline-block;
line-height: calc(2.083333333333333 * 16px);
line-height: calc(1.6666666666666665 * 16px);
border-radius: 6px;
font-weight: 400;
font-size: calc(0.7291666666666666 * 16px);
font-size: 13px;
user-select: none;
outline: none;
text-transform: capitalize;
Expand All @@ -25,14 +25,14 @@ exports[`UseToast should render different actions 1`] = `
cursor: pointer;
pointer-events: auto;
box-shadow: none;
--geist-ui-button-icon-padding: calc(0.6058333333333332 * 16px);
--geist-ui-button-height: calc(2.083333333333333 * 16px);
--geist-ui-button-icon-padding: calc(0.48466666666666663 * 16px);
--geist-ui-button-height: calc(1.6666666666666665 * 16px);
--geist-ui-button-color: #fff;
--geist-ui-button-bg: #000;
min-width: min-content;
width: auto;
height: calc(2.083333333333333 * 16px);
padding: 0 calc(0.9583333333333331 * 16px) 0 calc(0.9583333333333331 * 16px);
height: calc(1.6666666666666665 * 16px);
padding: 0 calc(0.7666666666666666 * 16px) 0 calc(0.7666666666666666 * 16px);
margin: 0 0 0 0;
}
Expand Down Expand Up @@ -68,10 +68,10 @@ exports[`UseToast should render different actions 1`] = `
.btn {
box-sizing: border-box;
display: inline-block;
line-height: calc(2.083333333333333 * 16px);
line-height: calc(1.6666666666666665 * 16px);
border-radius: 6px;
font-weight: 400;
font-size: calc(0.7291666666666666 * 16px);
font-size: 13px;
user-select: none;
outline: none;
text-transform: capitalize;
Expand All @@ -88,14 +88,14 @@ exports[`UseToast should render different actions 1`] = `
cursor: pointer;
pointer-events: auto;
box-shadow: none;
--geist-ui-button-icon-padding: calc(0.6058333333333332 * 16px);
--geist-ui-button-height: calc(2.083333333333333 * 16px);
--geist-ui-button-icon-padding: calc(0.48466666666666663 * 16px);
--geist-ui-button-height: calc(1.6666666666666665 * 16px);
--geist-ui-button-color: #666;
--geist-ui-button-bg: #fff;
min-width: min-content;
width: auto;
height: calc(2.083333333333333 * 16px);
padding: 0 calc(0.9583333333333331 * 16px) 0 calc(0.9583333333333331 * 16px);
height: calc(1.6666666666666665 * 16px);
padding: 0 calc(0.7666666666666666 * 16px) 0 calc(0.7666666666666666 * 16px);
margin: 0 0 0 0;
}
Expand Down Expand Up @@ -140,33 +140,15 @@ exports[`UseToast should render different actions 1`] = `
color: #000;
border: 0;
border-radius: 6px;
padding: 16pt;
position: absolute;
bottom: 0;
right: 0;
opacity: 1;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
transform: translate3d(0, 100%, 0px) scale(1);
transition: transform 400ms ease 0ms, visibility 200ms ease 0ms,
opacity 200ms ease 0ms;
}
.toast.visible {
opacity: 1;
transform: translate3d(0, calc(100% + -75px + -0px), -0px) scale(1);
}
.toast.hide {
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: all 350ms cubic-bezier(0.1, 0.2, 0.1, 1);
overflow: hidden;
}
.message {
align-items: center;
height: 100%;
transition: opacity 0.4s ease;
font-size: 0.875rem;
font-size: 0.875em;
display: -webkit-box;
word-break: break-all;
padding-right: 8pt;
Expand All @@ -177,30 +159,58 @@ exports[`UseToast should render different actions 1`] = `
-webkit-line-clamp: 2;
line-height: 1.1rem;
}
.toast :global(button + button) {
margin-left: 4pt;
.toast-enter {
opacity: 0;
height: 0;
padding: 0;
margin: 0;
transform: translate(60px, 60px);
}
.toast-enter-active {
opacity: 1;
height: auto;
margin: 8px 0;
padding: 12px 16px;
transform: translate(0, 0);
}
.toast-leave {
opacity: 1;
transform: translate(0, 0);
height: auto;
margin: 8px 0;
padding: 12px 16px;
}
.toast-leave-active {
opacity: 0;
transform: translate(50px, -15px) scale(0.85);
}
</style></div><style>
.toast-container {
.toasts {
position: fixed;
width: 420px;
max-width: 90vw;
bottom: 16pt;
width: auto;
max-width: 100%;
right: 16pt;
bottom: 16pt;
z-index: 2000;
transition: all 400ms ease;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.toast-container.hover {
transform: translate3d(0, -10px, 0);
.top {
bottom: unset;
flex-direction: column-reverse;
top: 16pt;
}
.left {
right: unset;
left: 16pt;
}
</style></div>"
`;
exports[`UseToast should work with different types 1`] = `
"<div class=\\"toast-container \\"><div class=\\"toast visible \\"><div class=\\"message\\">hello</div><div class=\\"action\\"></div><style>
"<div class=\\"toasts\\"><div class=\\"toast toast-enter toast-enter-active\\"><div class=\\"message\\">hello</div><div class=\\"action\\"></div><style>
.toast {
width: 420px;
max-width: 90vw;
Expand All @@ -213,33 +223,15 @@ exports[`UseToast should work with different types 1`] = `
color: white;
border: 0;
border-radius: 6px;
padding: 16pt;
position: absolute;
bottom: 0;
right: 0;
opacity: 1;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.12);
transform: translate3d(0, 100%, 0px) scale(1);
transition: transform 400ms ease 0ms, visibility 200ms ease 0ms,
opacity 200ms ease 0ms;
}
.toast.visible {
opacity: 1;
transform: translate3d(0, calc(100% + -75px + -0px), -0px) scale(1);
}
.toast.hide {
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: all 350ms cubic-bezier(0.1, 0.2, 0.1, 1);
overflow: hidden;
}
.message {
align-items: center;
height: 100%;
transition: opacity 0.4s ease;
font-size: 0.875rem;
font-size: 0.875em;
display: -webkit-box;
word-break: break-all;
padding-right: 8pt;
Expand All @@ -250,24 +242,52 @@ exports[`UseToast should work with different types 1`] = `
-webkit-line-clamp: 2;
line-height: 1.1rem;
}
.toast :global(button + button) {
margin-left: 4pt;
.toast-enter {
opacity: 0;
height: 0;
padding: 0;
margin: 0;
transform: translate(60px, 60px);
}
.toast-enter-active {
opacity: 1;
height: auto;
margin: 8px 0;
padding: 12px 16px;
transform: translate(0, 0);
}
.toast-leave {
opacity: 1;
transform: translate(0, 0);
height: auto;
margin: 8px 0;
padding: 12px 16px;
}
.toast-leave-active {
opacity: 0;
transform: translate(50px, -15px) scale(0.85);
}
</style></div><style>
.toast-container {
.toasts {
position: fixed;
width: 420px;
max-width: 90vw;
bottom: 16pt;
width: auto;
max-width: 100%;
right: 16pt;
bottom: 16pt;
z-index: 2000;
transition: all 400ms ease;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.toast-container.hover {
transform: translate3d(0, -10px, 0);
.top {
bottom: unset;
flex-direction: column-reverse;
top: 16pt;
}
.left {
right: unset;
left: 16pt;
}
</style></div>"
`;
Loading

0 comments on commit 3f9e190

Please sign in to comment.