Skip to content

Commit

Permalink
chore: wip
Browse files Browse the repository at this point in the history
  • Loading branch information
cschroeter committed Oct 12, 2023
1 parent c1d1bc5 commit 80e7344
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 62 deletions.
40 changes: 32 additions & 8 deletions .xstate/toast.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ const fetchMachine = createMachine({
context: {
"hasTypeChanged && isChangingToLoading": false,
"hasDurationChanged || hasTypeChanged": false,
"!isLoadingType": false
"!isLoadingType": false,
"hasAnimation": false,
"hasAnimation": false,
"hasAnimation": false
},
on: {
UPDATE: [{
Expand Down Expand Up @@ -52,27 +55,47 @@ const fetchMachine = createMachine({
target: "active",
actions: ["setCreatedAt"]
},
DISMISS: "dismissing"
DISMISS: [{
cond: "hasAnimation",
target: "dismissing",
actions: "invokeOnClosing"
}, {
target: "inactive",
actions: ["invokeOnClosing", "notifyParentToRemove"]
}]
}
},
active: {
tags: ["visible"],
activities: "trackDocumentVisibility",
after: {
VISIBLE_DURATION: "dismissing"
VISIBLE_DURATION: [{
cond: "hasAnimation",
target: "dismissing",
actions: "invokeOnClosing"
}, {
target: "inactive",
actions: ["invokeOnClosing", "notifyParentToRemove"]
}]
},
on: {
DISMISS: "dismissing",
DISMISS: [{
cond: "hasAnimation",
target: "dismissing",
actions: "invokeOnClosing"
}, {
target: "inactive",
actions: ["invokeOnClosing", "notifyParentToRemove"]
}],
PAUSE: {
target: "persist",
actions: "setRemainingDuration"
}
}
},
dismissing: {
entry: "invokeOnClosing",
after: {
REMOVE_DELAY: {
on: {
ANIMATION_END: {
target: "inactive",
actions: "notifyParentToRemove"
}
Expand All @@ -94,6 +117,7 @@ const fetchMachine = createMachine({
guards: {
"hasTypeChanged && isChangingToLoading": ctx => ctx["hasTypeChanged && isChangingToLoading"],
"hasDurationChanged || hasTypeChanged": ctx => ctx["hasDurationChanged || hasTypeChanged"],
"!isLoadingType": ctx => ctx["!isLoadingType"]
"!isLoadingType": ctx => ctx["!isLoadingType"],
"hasAnimation": ctx => ctx["hasAnimation"]
}
});
12 changes: 8 additions & 4 deletions examples/next-ts/pages/toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ function ToastItem({ actor }: { actor: toast.Service }) {
},
}

if (state.context.render) {
return state.context.render(api)
}

return (
<pre {...api.rootProps}>
<div {...progressbarProps} />
Expand All @@ -41,9 +45,6 @@ export default function Page() {
const [state, send] = useMachine(
toast.group.machine({
id: useId(),
defaultOptions: {
placement: "top-start",
},
}),
{
context: controls.context,
Expand Down Expand Up @@ -76,10 +77,13 @@ export default function Page() {
placement: "bottom-start",
title: "Ooops! Something was wrong",
type: "error",
render: (props) => {
return <div>{props.title}</div>
},
})
}}
>
Notify (Error)
Custom Render Notify (Error)
</button>
<button
onClick={() => {
Expand Down
4 changes: 3 additions & 1 deletion packages/machines/toast/src/toast-group.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export function groupMachine(userContext: UserDefinedGroupContext) {
guard: (ctx) => ctx.toasts.length < ctx.max,
actions: (ctx, evt, { self }) => {
const options = {
...ctx.defaultOptions,
placement: ctx.placement,
duration: ctx.duration,
render: ctx.render,
...evt.toast,
pauseOnPageIdle: ctx.pauseOnPageIdle,
pauseOnInteraction: ctx.pauseOnInteraction,
Expand Down
18 changes: 3 additions & 15 deletions packages/machines/toast/src/toast.connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,6 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
send("DISMISS")
},

render() {
return state.context.render?.({
id: state.context.id,
type: state.context.type,
duration: state.context.duration,
title: state.context.title,
placement: state.context.placement,
description: state.context.description,
dismiss() {
send("DISMISS")
},
})
},

rootProps: normalize.element({
...parts.root.attrs,
dir: state.context.dir,
Expand All @@ -55,11 +41,13 @@ export function connect<T extends PropTypes>(state: State, send: Send, normalize
role: "status",
"aria-atomic": "true",
tabIndex: 0,
onAnimationEnd() {
send("ANIMATION_END")
},
style: {
position: "relative",
pointerEvents: "auto",
margin: "calc(var(--toast-gutter) / 2)",
"--remove-delay": `${state.context.removeDelay}ms`,
"--duration": `${state.context.duration}ms`,
},
onKeyDown(event) {
Expand Down
1 change: 1 addition & 0 deletions packages/machines/toast/src/toast.dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export const dom = createScope({
getDescriptionId: (ctx: Ctx) => `toast:${ctx.id}:description`,
getCloseTriggerId: (ctx: Ctx) => `toast${ctx.id}:close`,
getPortalId: (ctx: GroupCtx) => `toast-portal:${ctx.id}`,
getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),
})
26 changes: 17 additions & 9 deletions packages/machines/toast/src/toast.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getToastDuration } from "./toast.utils"
const { not, and, or } = guards

export function createToastMachine(options: Options = {}) {
const { type = "info", duration, id = "toast", placement = "bottom", removeDelay = 0, ...restProps } = options
const { type = "info", duration, id = "toast", placement = "bottom", ...restProps } = options
const ctx = compact(restProps)

const computedDuration = getToastDuration(duration, type)
Expand All @@ -18,12 +18,12 @@ export function createToastMachine(options: Options = {}) {
id,
entry: "invokeOnOpen",
initial: type === "loading" ? "persist" : "active",
onEvent: console.log,
context: {
id,
type,
remaining: computedDuration,
duration: computedDuration,
removeDelay,
createdAt: Date.now(),
placement,
...ctx,
Expand Down Expand Up @@ -64,18 +64,27 @@ export function createToastMachine(options: Options = {}) {
target: "active",
actions: ["setCreatedAt"],
},
DISMISS: "dismissing",
DISMISS: [
{ guard: "hasAnimation", target: "dismissing", actions: "invokeOnClosing" },
{ target: "inactive", actions: ["invokeOnClosing", "notifyParentToRemove"] },
],
},
},

active: {
tags: ["visible"],
activities: "trackDocumentVisibility",
after: {
VISIBLE_DURATION: "dismissing",
VISIBLE_DURATION: [
{ guard: "hasAnimation", target: "dismissing", actions: "invokeOnClosing" },
{ target: "inactive", actions: ["invokeOnClosing", "notifyParentToRemove"] },
],
},
on: {
DISMISS: "dismissing",
DISMISS: [
{ guard: "hasAnimation", target: "dismissing", actions: "invokeOnClosing" },
{ target: "inactive", actions: ["invokeOnClosing", "notifyParentToRemove"] },
],
PAUSE: {
target: "persist",
actions: "setRemainingDuration",
Expand All @@ -84,9 +93,8 @@ export function createToastMachine(options: Options = {}) {
},

dismissing: {
entry: "invokeOnClosing",
after: {
REMOVE_DELAY: {
on: {
ANIMATION_END: {
target: "inactive",
actions: "notifyParentToRemove",
},
Expand Down Expand Up @@ -115,11 +123,11 @@ export function createToastMachine(options: Options = {}) {
isLoadingType: (ctx) => ctx.type === "loading",
hasTypeChanged: (ctx, evt) => evt.toast?.type !== ctx.type,
hasDurationChanged: (ctx, evt) => evt.toast?.duration !== ctx.duration,
hasAnimation: (ctx) => (dom.getRootEl(ctx)?.getAnimations() ?? []).length > 0,
},

delays: {
VISIBLE_DURATION: (ctx) => ctx.remaining,
REMOVE_DELAY: (ctx) => ctx.removeDelay,
},

actions: {
Expand Down
39 changes: 15 additions & 24 deletions packages/machines/toast/src/toast.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ export interface ToastOptions {
/**
* Custom function to render the toast element.
*/
render?: (options: RenderOptions) => any
/**
* The duration for the toast to kept alive before it is removed.
* Useful for exit transitions.
*/
removeDelay?: number
render?: (options: MachineApi) => any
/**
* Function called when the toast has been closed and removed
*/
Expand All @@ -67,10 +62,6 @@ export interface ToastOptions {

export type Options = Partial<ToastOptions>

export type RenderOptions = Omit<ToastOptions, "render"> & {
dismiss(): void
}

/* -----------------------------------------------------------------------------
* Machine context
* -----------------------------------------------------------------------------*/
Expand All @@ -84,23 +75,21 @@ interface SharedContext {
* Whether to pause the toast when interacted with
*/
pauseOnInteraction?: boolean

/**
* The default options for the toast
* The placement of the toast
*/
placement?: Placement
/**
* The duration the toast will be visible
*/
defaultOptions?: Partial<Pick<ToastOptions, "duration" | "removeDelay" | "placement">>
duration?: number
}

export interface MachineContext
extends SharedContext,
extends Omit<SharedContext, "duration" | "placement">,
RootProperties,
CommonProperties,
Omit<ToastOptions, "removeDelay"> {
/**
* The duration for the toast to kept alive before it is removed.
* Useful for exit transitions.
*/
removeDelay: number
ToastOptions {
/**
* The document's text/writing direction.
*/
Expand Down Expand Up @@ -143,6 +132,11 @@ interface GroupPublicContext extends SharedContext, DirectionProperty, CommonPro
* The offset from the safe environment edge of the viewport
*/
offsets: string | Record<"left" | "right" | "bottom" | "top", string>

/**
* Custom function to render the toast element.
*/
render?: (options: MachineApi) => any
}

export type UserDefinedGroupContext = RequiredBy<GroupPublicContext, "id">
Expand Down Expand Up @@ -303,10 +297,7 @@ export interface MachineApi<T extends PropTypes = PropTypes> {
* Function to instantly dismiss the toast.
*/
dismiss(): void
/**
* Function render the toast in the DOM (based on the defined `render` property)
*/
render(): any

rootProps: T["element"]
titleProps: T["element"]
descriptionProps: T["element"]
Expand Down
2 changes: 1 addition & 1 deletion shared/src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,7 @@ main [data-testid="scrubber"] {
}

[data-scope="toast"][data-part="root"][data-state="closed"] {
animation-duration: var(--toast-remove-delay);
animation-duration: 250ms;
animation-name: fadeOut;
}

Expand Down

0 comments on commit 80e7344

Please sign in to comment.