Toast
A message that appears on the screen to provide feedback on an action.
Usage
'use client'
import { XIcon } from 'lucide-react'
import { Button, IconButton, Toast } from '~/components/ui'
const toaster = Toast.createToaster({
placement: 'bottom-end',
overlap: true,
gap: 16,
})
export const Demo = () => (
<>
<Button
variant="outline"
onClick={() =>
toaster.create({
title: 'Toast Title',
description: 'Toast Description',
type: 'info',
})
}
>
Add Toast
</Button>
<Toast.Toaster toaster={toaster}>
{(toast) => (
<Toast.Root key={toast.id}>
<Toast.Title>{toast.title}</Toast.Title>
<Toast.Description>{toast.description}</Toast.Description>
<Toast.ActionTrigger asChild>
<Button variant="link" size="sm">
Action
</Button>
</Toast.ActionTrigger>
<Toast.CloseTrigger asChild>
<IconButton size="sm" variant="link">
<XIcon />
</IconButton>
</Toast.CloseTrigger>
</Toast.Root>
)}
</Toast.Toaster>
</>
)
Installation
npx @park-ui/cli components add toast
1
Styled Primitive
Copy the code snippet below into ~/components/ui/primitives/toast.tsx
'use client'
import type { Assign } from '@ark-ui/react'
import { Toast } from '@ark-ui/react/toast'
import { toast } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(toast)
export const Root = withProvider<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Toast.ActionTriggerProps>
>(Toast.Root, 'root')
export const ActionTrigger = withContext<
HTMLButtonElement,
Assign<HTMLStyledProps<'button'>, Toast.ActionTriggerProps>
>(Toast.ActionTrigger, 'actionTrigger')
export const CloseTrigger = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Toast.CloseTriggerProps>
>(Toast.CloseTrigger, 'closeTrigger')
export const Description = withContext<
HTMLDivElement,
Assign<HTMLStyledProps<'div'>, Toast.DescriptionProps>
>(Toast.Description, 'description')
export const Title = withContext<HTMLDivElement, Assign<HTMLStyledProps<'div'>, Toast.TitleProps>>(
Toast.Title,
'title',
)
export {
ToastContext as Context,
Toaster,
createToaster,
type ToastContextProps as ContextProps,
type ToasterProps,
} from '@ark-ui/react/toast'
import { type Assign, Toast } from '@ark-ui/solid'
import type { ComponentProps } from 'solid-js'
import { toast } from 'styled-system/recipes'
import type { HTMLStyledProps } from 'styled-system/types'
import { createStyleContext } from '~/lib/create-style-context'
const { withProvider, withContext } = createStyleContext(toast)
export type RootProps = ComponentProps<typeof Root>
export const Root = withProvider<Assign<HTMLStyledProps<'div'>, Toast.RootProps>>(
Toast.Root,
'root',
)
export const ActionTrigger = withContext<
Assign<HTMLStyledProps<'button'>, Toast.ActionTriggerProps>
>(Toast.ActionTrigger, 'actionTrigger')
export const CloseTrigger = withContext<Assign<HTMLStyledProps<'div'>, Toast.CloseTriggerProps>>(
Toast.CloseTrigger,
'closeTrigger',
)
export const Description = withContext<Assign<HTMLStyledProps<'div'>, Toast.DescriptionProps>>(
Toast.Description,
'description',
)
export const Title = withContext<Assign<HTMLStyledProps<'div'>, Toast.TitleProps>>(
Toast.Title,
'title',
)
export {
ToastContext as Context,
createToaster,
Toaster,
type ToastContextProps as ContextProps,
type ToasterProps,
} from '@ark-ui/solid'
No snippet found
Extend ~/components/ui/primitives/index.ts
with the following line:
export * as Toast from './toast'
2
Integrate Recipe
If you're not using @park-ui/preset
, add the following recipe to yourpanda.config.ts
:
import { toastAnatomy } from '@ark-ui/anatomy'
import { defineSlotRecipe } from '@pandacss/dev'
export const toast = defineSlotRecipe({
className: 'toast',
slots: toastAnatomy.keys(),
base: {
root: {
background: 'bg.default',
borderRadius: 'l3',
boxShadow: 'lg',
minWidth: 'xs',
height: 'var(--height)',
opacity: 'var(--opacity)',
overflowWrap: 'anywhere',
p: '4',
position: 'relative',
scale: 'var(--scale)',
translate: 'var(--x) var(--y) 0',
willChange: 'translate, opacity, scale',
zIndex: 'var(--z-index)',
transitionDuration: 'slow',
transitionProperty: 'translate, scale, opacity, height',
transitionTimingFunction: 'default',
},
title: {
color: 'fg.default',
fontWeight: 'semibold',
textStyle: 'sm',
},
description: {
color: 'fg.muted',
textStyle: 'sm',
},
actionTrigger: {
mt: '2',
},
closeTrigger: {
position: 'absolute',
top: '3',
right: '3',
},
},
})