// Styled Toast = the unstyled @tamagui/toast behavior + the default skin, // layered here in `tamagui`. Single skin definition; the shadcn registry item is // generated from this file. Because the behavior renders its default toast // content internally, the styled default content lives HERE and is wired through // Toast.List's `renderItem`, so the copy-paste registry item is a complete, // customizable toast (no hidden styling in the behavior package). // // Surfaced at both the `tamagui` root (shadowing the unstyled @tamagui/toast // composable Toast) and the `tamagui/toast` subpath. There is exactly one Toast // API in v3 — the old imperative ToastProvider/useToastController was removed. import { Toast as ToastBehavior, toast, useToastItem, useToasts, type ExternalToast, type ToastItemRenderProps, type ToastListProps, type ToastPosition, type ToastRootProps, type ToastT, } from '@tamagui/toast' import { createRefComponent, styled, type TamaguiElement, withStaticProperties, } from '@tamagui/core' import { SizableText } from '@tamagui/text' import { XStack, YStack } from '@tamagui/stacks' /* ------------------------------------------------------------------------------------------------- * Styled parts — the default skin over the unstyled @tamagui/toast primitives. * -----------------------------------------------------------------------------------------------*/ export const ToastItem = styled(ToastBehavior.Item, { displayName: 'ToastItem', backgroundColor: 'background', borderRadius: '6', paddingHorizontal: '4', paddingVertical: '3', borderWidth: 1, borderColor: 'border-color', shadowColor: 'rgba(0, 0, 0, 0.15)', shadowOffset: { width: 0, height: 4 }, shadowRadius: 12, outlineWidth: 'focus-visible:2px', outlineColor: 'focus-visible:color-8', outlineStyle: 'focus-visible:solid', }) export const ToastTitle = styled(ToastBehavior.Title, { displayName: 'ToastTitle', color: 'color', fontWeight: '600', size: '4', }) export const ToastDescription = styled(ToastBehavior.Description, { displayName: 'ToastDescription', color: 'color-11', size: '2', }) // flat on purpose: the glyph is the whole affordance, so it only brightens on // hover instead of carrying a chip of its own export const ToastClose = styled(ToastBehavior.Close, { displayName: 'ToastClose', backgroundColor: 'transparent', color: 'color-9 hover:color press:color', }) export const ToastAction = styled(ToastBehavior.Action, { displayName: 'ToastAction', borderRadius: '2', paddingHorizontal: '2', backgroundColor: 'color-5 hover:color-6 press:color-7', }) /* ------------------------------------------------------------------------------------------------- * ToastDefaultContent — the default toast body (icon / title / description / * actions / close), styled. Rendered via Toast.List's renderItem below. * -----------------------------------------------------------------------------------------------*/ function ToastDefaultContent({ toast: t }: { toast: ToastT }) { const { closeButton } = useToasts() const { handleClose } = useToastItem() const dismissible = t.dismissible !== false const title = typeof t.title === 'function' ? t.title() : t.title const description = typeof t.description === 'function' ? t.description() : t.description return ( {title ? {title} : null} {description ? {description} : null} {t.action || t.cancel ? ( {t.cancel ? ( { t.cancel?.onClick?.(e) handleClose() }} > {t.cancel.label} ) : null} {t.action ? ( { t.action?.onClick?.(e) if (!(e as any).defaultPrevented) { handleClose() } }} > {t.action.label} ) : null} ) : null} {closeButton && dismissible ? : null} ) } const renderStyledToast = ({ toast: t, index }: ToastItemRenderProps) => ( ) // Capture the behavior parts up front. `withStaticProperties` assigns onto the // component it is given, so composing directly onto ToastBehavior would rewrite // @tamagui/toast's own Toast.List/.Item for every consumer of the unstyled // package — and ToastList below would end up rendering itself. const BehaviorList = ToastBehavior.List const BehaviorViewport = ToastBehavior.Viewport const BehaviorIcon = ToastBehavior.Icon // Styled list — defaults renderItem to the styled default content so a bare // `` is styled; a consumer-supplied renderItem still overrides it. function ToastList(props: ToastListProps) { return } /* ------------------------------------------------------------------------------------------------- * Toast — the styled composable API (styled parts on the behavior root). * -----------------------------------------------------------------------------------------------*/ // A distinct root, so the styled parts hang off this skin instead of mutating // the shared behavior component (see BehaviorList above). const ToastRoot = createRefComponent( function Toast(props, ref) { return } ) export const Toast = withStaticProperties(ToastRoot, { Viewport: BehaviorViewport, List: ToastList, Item: ToastItem, Title: ToastTitle, Description: ToastDescription, Close: ToastClose, Action: ToastAction, Icon: BehaviorIcon, }) // Re-export the non-visual surface so `tamagui/toast` is a drop-in for the // styled toast: imperative API, render hooks, and the public types. export { toast, useToastItem, useToasts } export type { ExternalToast, ToastPosition, ToastT }