Toast

Toast는 일시적인 알림 메시지를 사용자에게 표시하는 컴포넌트입니다.

Toast 컴포넌트는 화면의 모서리에 일시적인 알림 메시지를 표시하는 데 사용됩니다.

사용자의 작업에 대한 피드백을 제공하고, 피드백을 하나의 리스트로 관리하기 때문에 다른 컴포넌트와 사용 방식이 다릅니다.

import './styles.css';

import { Button, Toast } from '@vapor-ui/core';

const toastManager = Toast.createToastManager();

export default function Default() {
    return (
        <Toast.Provider toastManager={toastManager}>
            <App />
        </Toast.Provider>
    );
}

const App = () => {
    const addToast = () => {
        toastManager.add({
            title: 'This is a toast message!',
            description: 'Here is a description for the toast message.',
        });
    };

    return <Button onClick={addToast}>Add Toast</Button>;
};

Property

Methods

Toast를 추가, 업데이트 및 제거할 수 있습니다.

import './styles.css';

import { Button, HStack, Toast } from '@vapor-ui/core';

const toastManager = Toast.createToastManager();

export default function Method() {
    return (
        <Toast.Provider toastManager={toastManager}>
            <App />
        </Toast.Provider>
    );
}

const App = () => {
    const toastManager = Toast.useToastManager();

    const addToast = () => {
        toastManager.add({
            title: 'This is a toast message added by method!',
            description: 'Here is a description for the toast message added by method.',
        });
    };

    const updateToast = () => {
        const id = toastManager.add({
            title: 'This is a toast message to be updated!',
            description: 'Here is a description for the toast message to be updated.',

            actionProps: {
                children: 'Update',
                onClick: () => {
                    toastManager.update(id, {
                        title: 'Updated!',
                        colorPalette: 'success',
                    });
                },
            },
        });
    };

    const removeToast = () => {
        const id = toastManager.add({
            title: 'This is a toast message to be removed!',
            description: 'Here is a description for the toast message to be removed.',

            actionProps: {
                children: 'Remove',
                onClick: () => {
                    toastManager.close(id);
                    toastManager.add({
                        title: 'Toast removed!',
                        colorPalette: 'danger',
                    });
                },
            },
        });
    };

    const promiseToast = () => {
        const fakePromise = new Promise<string>((resolve, reject) => {
            setTimeout(() => {
                if (Math.random() > 0.5) resolve('Data loaded successfully!');
                else reject(new Error('Failed to load data'));
            }, 3000);
        });

        toastManager.promise(fakePromise, {
            loading: {
                title: 'Loading...',
                description: 'Please wait while we load the data.',
                colorPalette: 'info',
            },
            success: {
                title: 'Success!',
                description: 'The data has been loaded successfully.',
                colorPalette: 'success',
            },
            error: {
                title: 'Error!',
                description: 'There was an error loading the data.',
                colorPalette: 'danger',
            },
        });
    };

    return (
        <HStack gap="$400" alignItems="center">
            <Button onClick={addToast}>Add Toast</Button>

            <Button onClick={updateToast}>Update Toast</Button>

            <Button onClick={removeToast}>Remove Toast</Button>

            <Button onClick={promiseToast}>Promise Toast</Button>
        </HStack>
    );
};

ColorPalette

Toast의 색상 팔레트를 설정합니다.

import './styles.css';

import { Button, HStack, Toast } from '@vapor-ui/core';

const toastManager = Toast.createToastManager();

export default function ColorPalette() {
    const addToast = (colorPalette: 'info' | 'danger' | 'success') => {
        toastManager.add({
            title: 'This is a color palette toast message!',
            description: 'Here is a description for the color palette toast message.',
            colorPalette,
        });
    };

    return (
        <Toast.Provider toastManager={toastManager}>
            <HStack gap="$400" alignItems="center">
                <Button colorPalette="secondary" onClick={() => addToast('info')}>
                    Info Toast
                </Button>
                <Button colorPalette="danger" onClick={() => addToast('danger')}>
                    Danger Toast
                </Button>
                <Button colorPalette="success" onClick={() => addToast('success')}>
                    Success Toast
                </Button>
            </HStack>
        </Toast.Provider>
    );
}

Examples

Action

Action 버튼과 함께 사용할 수 있습니다.

import './styles.css';

import { Button, Toast } from '@vapor-ui/core';

const toastManager = Toast.createToastManager();

export default function Action() {
    const handleActionToast = () => {
        toastManager.add({
            title: 'This is an action toast message!',
            description: 'Here is a description for the action toast message.',
            actionProps: {
                children: 'action',
                onClick: () => {
                    alert('Action button clicked!');
                },
            },
        });
    };

    return (
        <Toast.Provider toastManager={toastManager}>
            <Button onClick={handleActionToast}>Action Toast</Button>
        </Toast.Provider>
    );
}

Close

Close 버튼을 제거할 수 있습니다.

import './styles.css';

import { Button, Toast } from '@vapor-ui/core';

const toastManager = Toast.createToastManager();

export default function Close() {
    const addToast = () => {
        toastManager.add({
            title: 'This is a toast message without close button!',
            description: 'Here is a description for the toast message without close button.',
            close: false,
        });
    };

    return (
        <Toast.Provider toastManager={toastManager}>
            <Button onClick={addToast}>Wihtout Close Button</Button>
        </Toast.Provider>
    );
}

Icon

Icon을 커스텀 할 수 있습니다.

import './styles.css';

import { Button, HStack, Toast } from '@vapor-ui/core';
import { CertificateIcon, HeartIcon, WarningIcon } from '@vapor-ui/icons';

const toastManager = Toast.createToastManager();

export default function Icon() {
    const addToast = (
        colorPalette: Toast.RootPrimitive.ToastObject['colorPalette'],
        icon: Toast.RootPrimitive.ToastObject['icon'],
    ) => {
        toastManager.add({
            title: 'This is a color palette toast message!',
            description: 'Here is a description for the color palette toast message.',
            colorPalette,
            icon,
        });
    };

    return (
        <Toast.Provider toastManager={toastManager}>
            <HStack gap="$400" alignItems="center">
                <Button
                    colorPalette="secondary"
                    onClick={() => addToast('info', <HeartIcon color="white" />)}
                >
                    Info Toast
                </Button>
                <Button
                    colorPalette="danger"
                    onClick={() => addToast('danger', <WarningIcon color="white" />)}
                >
                    Danger Toast
                </Button>
                <Button
                    colorPalette="success"
                    onClick={() => addToast('success', <CertificateIcon color="white" />)}
                >
                    Success Toast
                </Button>
            </HStack>
        </Toast.Provider>
    );
}

Custom

Toast 아이템을 완전히 커스텀할 수 있습니다.

import './styles.css';

import type { PropsWithChildren } from 'react';

import { Button, HStack, IconButton, Toast, VStack } from '@vapor-ui/core';
import { InfoCircleIcon } from '@vapor-ui/icons';

const toastManager = Toast.createToastManager();

export default function Custom() {
    // const { add } = Toast.useToastManager();

    const showToast = () => {
        const removeToast = (id: string) => {
            toastManager.close(id);
        };

        const id = toastManager.add({
            title: 'This is a custom toast message!',
            description: 'Here is a description for the custom toast message.',
            colorPalette: 'info',
            icon: <InfoCircleIcon />,

            actionProps: {
                children: 'Undo',
                onClick: () => removeToast(id),
            },
        });
    };

    return (
        <ToastProvider>
            <Button onClick={showToast}>Show Toast</Button>
        </ToastProvider>
    );
}

const ToastProvider = (props: PropsWithChildren) => {
    return (
        <div>
            {props.children}

            <Toast.ProviderPrimitive toastManager={toastManager} timeout={3500}>
                <Toast.PortalPrimitive>
                    <Toast.ViewportPrimitive>
                        <ToastList />
                    </Toast.ViewportPrimitive>
                </Toast.PortalPrimitive>
            </Toast.ProviderPrimitive>
        </div>
    );
};

const ToastList = () => {
    const { toasts } = Toast.useToastManager();

    return toasts.map((toast) => {
        return (
            <Toast.RootPrimitive
                key={toast.id}
                toast={toast}
                backgroundColor="$white"
                border="1px solid"
                borderColor="$normal"
                padding="$200"
            >
                <Toast.ContentPrimitive>
                    <HStack gap="$100">
                        <Toast.IconPrimitive marginY="3px" />

                        <VStack>
                            <Toast.TitlePrimitive color="$normal-200" />
                            <Toast.DescriptionPrimitive color="$normal-200" />
                        </VStack>
                    </HStack>

                    <Toast.ActionPrimitive />
                    <Toast.ClosePrimitive
                        render={<IconButton aria-label="Close toast" size="sm" variant="ghost" />}
                        position="absolute"
                        color="$normal-200"
                        style={{ right: 8, top: 8 }}
                    />
                </Toast.ContentPrimitive>
            </Toast.RootPrimitive>
        );
    });
};

Props

Toast.Provider

Loading component documentation...

Toast.ProviderPrimitive

Loading component documentation...

Toast.PortalPrimitive

Loading component documentation...

Toast.ViewportPrimitive

Loading component documentation...

Toast.RootPrimitive

Loading component documentation...

Toast.ContentPrimitive

Loading component documentation...

Toast.TitlePrimitive

Loading component documentation...

Toast.DescriptionPrimitive

Loading component documentation...

Toast.ActionPrimitive

Loading component documentation...

Toast.ClosePrimitive

Loading component documentation...

Toast.IconPrimitive

Loading component documentation...

useToastManager

Loading component documentation...