Notifications 시스템
Notifications 시스템
Mantine 알림 시스템이에요. @mantine/notifications 패키지로 제공되며 MIT 라이선스로 배포돼요.
출처: 문서
본문
설치
yarn add @mantine/notifications
설치 후 애플리케이션의 루트에서 패키지 스타일을 import 해요:
import '@mantine/core/styles.css';
// ‼️ notifications 스타일은 core 패키지 스타일 다음에 import 하세요
import '@mantine/notifications/styles.css';
애플리케이션 어디든 Notifications 컴포넌트를 추가해요. 다음에 주의하세요:
-
Notifications컴포넌트를 MantineProvider 안에서 렌더링해야 해요 -
애플리케이션을
Notifications컴포넌트로 감쌀 필요는 없어요 – provider가 아니라 일반 컴포넌트예요 -
여러
Notifications컴포넌트를 렌더링하면 안 돼요 – 그러면 알림이 중복돼요
import { MantineProvider } from '@mantine/core';
import { Notifications } from '@mantine/notifications';
function Demo() {
return (
<MantineProvider>
<Notifications />
{/* Your app here */}
</MantineProvider>
);
}
완료! 이제 모든 알림 시스템 기능을 사용할 수 있어요.
import { Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
function Demo() {
return (
<Button
onClick={() =>
notifications.show({
title: 'Default notification',
message: 'Do not forget to star Mantine on GitHub! 🌟',
})
}
>
Show notification
</Button>
);
}
스타일 import를 잊지 마세요
위의 설치 안내를 따랐는데도 뭔가 동작하지 않는다면(position prop이 동작하지 않거나, 알림이 바닥에 붙어 있으면) notification 스타일을 import 하지 않은 함정에 빠진 거예요! 문제를 해결하려면 애플리케이션 루트에 notification 스타일을 import 해요:
import '@mantine/notifications/styles.css';
함수
@mantine/notifications 패키지는 다음 함수를 가진 notifications 객체를 내보내요:
-
notifications.show– 현재 상태와limit에 따라 주어진 알림을 알림 목록이나 큐에 추가해요 -
notifications.hide– 알림 상태와 큐에서 주어진id를 가진 알림을 제거해요 -
notifications.update– 이전에 상태나 큐에 추가된 알림을 업데이트해요 -
notifications.updateState– 현재 알림 상태와 큐를 인자로 주어진 콜백을 실행하고 반환된 값으로 상태를 업데이트해요 -
notifications.clean– 알림 상태와 큐에서 모든 알림을 제거해요 -
notifications.cleanQueue– 큐에서 모든 알림을 제거해요
모든 함수는 @mantine/notifications 패키지에서 import 할 수 있으며 애플리케이션 어디서든 사용할 수 있어요:
import { notifications } from '@mantine/notifications';
이 함수들을 개별적으로 import 할 수도 있어요:
// alias functions
import {
cleanNotifications, // notifications.clean
cleanNotificationsQueue, // notifications.cleanQueue
hideNotification, // notifications.hide
showNotification, // notifications.show
updateNotification, // notifications.update
updateNotificationsState, // notifications.updateState
} from '@mantine/notifications';
Notification props
notifications.show와 notifications.update 함수는 다음 속성을 가진 객체로 호출할 수 있어요:
-
id– 알림 id, 알림을 업데이트하고 제거하는 데 사용돼요; 기본적으로id는 임의로 생성돼요 -
position– 알림 위치; 기본적으로Notifications컴포넌트의positionprop 값이 사용돼요 -
withBorder– 알림이 테두리를 가질지 여부를 결정해요 -
withCloseButton– 닫기 버튼이 보일지 여부를 결정해요 -
allowClose– 알림을 닫기 버튼, 드래그 또는 가로 스크롤 스와이프로 닫을 수 있는지 결정해요, 기본true -
onClose– 알림이 마운트 해제될 때 호출돼요 -
onOpen– 알림이 마운트될 때 호출돼요 -
autoClose– 알림이 자동으로 닫힐 시간(ms)을 정의해요; 자동 닫기를 비활성화하려면false사용 -
priority– 활성 알림 수가limit를 초과할 때 사용되는 표시 우선순위; 숫자가 높을수록 먼저 표시돼요, 기본0 -
message– 필수 알림 본문 -
color, icon, title, radius, className, style, loading– Notification 컴포넌트에 전달되는 props
message를 제외한 모든 속성은 선택이에요.
import { XIcon } from '@phosphor-icons/react';
import { notifications } from '@mantine/notifications';
// Bare minimum – message is required for all notifications
notifications.show({ message: 'Hello' });
// Most used notification props
notifications.show({
id: 'hello-there',
position: 'bottom-center',
withCloseButton: true,
allowClose: true,
onClose: () => console.log('unmounted'),
onOpen: () => console.log('mounted'),
autoClose: 5000,
title: "You've been compromised",
message: 'Leave the building immediately',
color: 'red',
icon: <XIcon />,
className: 'my-notification-class',
style: { backgroundColor: 'red' },
loading: false,
});
닫기 상호작용
알림은 왼쪽이나 오른쪽으로 드래그하거나, hover 상태에서 가로 스크롤 스와이프로 닫을 수 있어요.
Notifications에 allowDragDismiss와 allowScrollDismiss를 사용해 두 상호작용을 비활성화해요:
import { Notifications } from '@mantine/notifications';
function Demo() {
return <Notifications allowDragDismiss={false} allowScrollDismiss={false} />;
}
특정 알림을 닫을 수 없게 하려면 notifications.show 또는 notifications.update에서 allowClose: false를 설정해요. 이것은 그 알림의 닫기 버튼을 숨기고 드래그/스크롤 닫기를 비활성화해요.
알림 스타일 커스터마이즈
style, className 또는 Styles API의 classNames, styles props로 알림 스타일을 커스터마이즈할 수 있어요. 보통 theme 객체에서 classNames prop으로 Notification 스타일을 재정의하는 것이 더 좋아요.
import { Button, Group } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import classes from './Demo.module.css';
function Demo() {
return (
<Group>
<Button
onClick={() =>
notifications.show({
title: 'Notification with custom styles',
message: 'It is default blue',
classNames: classes,
})
}
>
Default notification
</Button>
<Button
onClick={() =>
notifications.show({
color: 'red',
title: 'Notification with custom styles',
message: 'It is red',
classNames: classes,
})
}
>
Error notification
</Button>
</Group>
);
}
Notifications 컨테이너 위치
notifications.show 함수에서 알림 위치를 정의할 수 있어요. 가능한 position 값:
-
top-left -
top-right -
top-center -
bottom-left -
bottom-right -
bottom-center
import { Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
const positions = [
'top-left',
'top-right',
'bottom-left',
'bottom-right',
'top-center',
'bottom-center',
] as const;
function Demo() {
const buttons = positions.map((position) => (
<Button
key={position}
onClick={() =>
notifications.show({
title: `Notification at ${position}`,
message: `Notification at ${position} message`,
position,
})
}
>
{position}
</Button>
));
return {buttons};
}
position을 Notifications 컴포넌트에 정의할 수 있어요. 다음 예시에서 notifications.show 함수에 position이 정의되지 않으면 알림이 화면 오른쪽 위 모서리에 표시돼요:
import { Notifications } from '@mantine/notifications';
function Demo() {
return <Notifications position="top-right" />;
}
Limit과 큐
Notifications에 limit prop을 설정해 한 번에 표시되는 최대 알림 수를 제한할 수 있어요:
import { Notifications } from '@mantine/notifications';
function Demo() {
return <Notifications limit={3} />;
}
limit에 도달한 후 추가된 모든 알림은 큐에 추가되고, 현재 상태의 알림이 숨겨지면 표시돼요.
import { Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
function Demo() {
return (
<Button
onClick={() => {
Array(10).fill(0).forEach((_, index) => {
setTimeout(() => {
notifications.show({
title: `Notification ${index + 1}`,
message: 'Most notifications are added to queue',
});
}, 200 * index);
});
}}
>
Show 10 notifications
</Button>
);
}
우선순위
기본적으로 알림은 삽입 순서(FIFO)로 표시 상태와 큐에 분배돼요: 첫 limit 개수의 알림이 표시되고 나머지는 큐에서 기다려요. 활성 알림이 limit보다 많을 때 어떤 알림이 표시 슬롯을 차지할지 제어하려면 notifications.show 또는 notifications.update에 priority 속성을 설정해요.
-
priority가 더 높은 알림은 더 낮은 알림보다 먼저 표시돼요. -
priority가 같은 알림은 삽입 순서(FIFO)를 유지해요. -
priority는 기본0이므로 설정하지 않은 알림은 이전과 똑같이 동작해요. -
표시된 집합 안에서 더 높은 우선순위의 알림이 먼저 렌더링돼요.
표시 상태가 이미 limit에 도달했는데 높은 우선순위 알림이 추가되면 그것이 표시 슬롯을 차지하고 가장 낮은 우선순위의 표시 알림이 큐로 이동돼요 – 이미 표시되었더라도요. 우선순위는 각 위치에 대해 독립적으로 적용돼요.
표시 상태에서 큐로 다시 이동된 알림은 마운트 해제되고, 표시 슬롯으로 돌아올 때 다시 마운트되므로 onOpen 콜백이 표시될 때마다 실행된다는 점에 주의하세요.
다음 예시에서 Notifications 컴포넌트는 limit={1}을 사용해요. 먼저 낮은 우선순위 알림을 표시한 다음 높은 우선순위 알림을 표시해요: 높은 우선순위 알림이 낮은 우선순위 알림을 대체하고, 그것은 큐로 이동되어 높은 우선순위 알림이 닫히면 다시 표시돼요.
import { Button, Group } from '@mantine/core';
import { createNotificationsStore, notifications, Notifications } from '@mantine/notifications';
// Dedicated store with limit={1} so the priority behavior is easy to see
const store = createNotificationsStore();
function Demo() {
return (
<>
<Notifications store={store} limit={1} position="top-center" autoClose={false} />
<Group>
<Button
onClick={() =>
notifications.show(
{
title: 'Low priority',
message: 'I am pushed to the queue when an urgent notification arrives',
autoClose: false,
priority: 0,
},
store
)
}
>
Show low priority
</Button>
<Button
onClick={() =>
notifications.show(
{
title: 'High priority',
message: 'I take the visible slot even when the limit is reached',
color: 'red',
autoClose: false,
priority: 10,
},
store
)
}
>
Show high priority
</Button>
</Group>
</>
);
}
상태와 큐에서 알림 제거
상태나 큐에서 특정 알림을 제거하려면 notifications.hide 함수를 사용해요:
import { notifications } from '@mantine/notifications';
const id = notifications.show({ message: 'Hello!' });
notifications.hide(id);
큐에서 모든 알림을 제거하려면 notifications.cleanQueue 함수를, 상태와 큐 양쪽에서 모든 알림을 제거하려면 notifications.clean을 사용해요:
import { Group, Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
function Demo() {
return (
<Group>
<Button
onClick={() => {
Array(10)
.fill(0)
.forEach((_, index) => {
notifications.show({
title: `Notification ${index + 1}`,
message: 'Most notifications are added to queue',
autoClose: false,
});
});
}}
>
Show 10 notifications
</Button>
<Button onClick={() => notifications.cleanQueue()}>Clean queue</Button>
<Button onClick={() => notifications.clean()}>Clean all</Button>
</Group>
);
}
알림 업데이트
import { Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
import { CheckIcon } from '@phosphor-icons/react';
function Demo() {
return (
<Button
onClick={() => {
const id = notifications.show({
loading: true,
title: 'Loading your data',
message: 'Data will be loaded in 3 seconds, you cannot close this yet',
autoClose: false,
allowClose: false,
});
setTimeout(() => {
notifications.update({
id,
color: 'teal',
title: 'Data was loaded',
message: 'Notification will close in 2 seconds, you can close this notification now',
icon: <CheckIcon />,
loading: false,
autoClose: 2000,
allowClose: true,
});
}, 3000);
}}
>
Show update notification
</Button>
);
}
자동 닫기
Notifications로 자동 닫기 시간을 구성할 수 있어요:
import { Notifications } from '@mantine/notifications';
// All notifications will be closed automatically in 4000ms
function Demo() {
return <Notifications autoClose={4000} />;
}
또는 notifications.show/notifications.update 함수에서 알림별로 구성할 수 있어요:
import { notifications } from '@mantine/notifications';
notifications.show({
message: 'I will close in 500ms seconds',
autoClose: 500,
});
notifications.update({
id: 'hello',
message: 'I will never close',
autoClose: false,
});
notifications.show와 notifications.update 함수의 autoClose prop이 더 높은 우선순위를 가져요.
import { Group, Button } from '@mantine/core';
import { notifications } from '@mantine/notifications';
function Demo() {
return (
<Group>
<Button onClick={() => notifications.show({ message: 'I will close in 4 seconds' })}>
Notifications Provider timeout
</Button>
<Button
onClick={() =>
notifications.show({
message: 'I will close in 500ms',
autoClose: 500,
})
}
>
Closes in 500ms
</Button>
<Button
onClick={() =>
notifications.show({
color: 'blue',
title: 'I will never close',
message: 'unless you click X',
autoClose: false,
})
}
>
Never closes automatically
</Button>
</Group>
);
}
hover 시 자동 닫기 일시정지
기본적으로 어떤 알림을 hover하면 모든 표시 알림의 자동 닫기 타이머가 일시정지돼요. pauseResetOnHover prop으로 이 동작을 바꿀 수 있어요:
-
pauseResetOnHover="all"(기본) – 어떤 알림이 hover되면 모든 알림의 자동 닫기를 일시정지해요 -
pauseResetOnHover="notification"– hover된 알림만 자동 닫기를 일시정지해요
import { Notifications } from '@mantine/notifications';
function Demo() {
return <Notifications pauseResetOnHover="notification" />;
}
커스텀 알림 렌더링
Notifications 컴포넌트의 renderNotification prop 또는 notifications.show/notifications.update의 알림별 prop을 사용해 기본 알림을 커스텀 콘텐츠로 완전히 교체해요. 커스텀 알림에도 모든 애니메이션(enter, exit, drag dismiss, scroll dismiss)이 유지돼요:
import { Avatar, Button, Group, rem, Text } from '@mantine/core';
import { notifications } from '@mantine/notifications';
function Demo() {
return (
<Button
onClick={() =>
notifications.show({
autoClose: false,
renderNotification: (notification) => (
<Group bg="white" p="md" style={{ border: '1px solid gray', borderRadius: 8 }}>
<Avatar radius="xl">DM</Avatar>
<div>
<Text fw={700} size="sm">Dan sent you a message</Text>
<Text size="sm" c="dimmed">Hey, are you free for a quick call?</Text>
</div>
<Group>
<Button size="xs" onClick={() => notifications.hide(notification.id!)}>
Reply
</Button>
<Button size="xs" variant="default" onClick={() => notifications.hide(notification.id!)}>
Dismiss
</Button>
</Group>
</Group>
),
message: '',
})
}
>
Show custom notification
</Button>
);
}
스택 레이아웃
Notifications 컴포넌트에 layout="stacked"를 설정해 알림을 스택 레이아웃으로 표시해요. 이때 가장 최근 알림만 완전히 보이고, 이전 알림들은 그 뒤로 살짝 보여요.
스택은 마우스로 hover하면, 키보드 포커스가 들어오면, 터치 기기에서 탭하면 펼쳐져요 – 바깥을 탭하면 다시 접혀요. 접힌 동안 첫 번째 알림 뒤의 알림들은 inert라서 포커스할 수 없고 스크린 리더에서 숨겨져요.
참고: 스택 데모는 페이지의 다른 알림에 영향을 주지 않기 위해 별도의 store를 사용해요.
import { Button, Group } from '@mantine/core';
import { Notifications, notifications } from '@mantine/notifications';
function Demo() {
return (
<>
{/* Replace your existing Notifications with layout="stacked" */}
<Notifications layout="stacked" position="bottom-right" />
<Button
onClick={() => {
notifications.show({
title: 'New notification',
message: 'This notification is part of a stacked layout',
});
}}
>
Show stacked notification
</Button>
</>
);
}
알림 상태 구독
useNotifications 훅으로 알림 상태 변경을 구독할 수 있어요. 이 훅은 notifications와 queue 배열을 가진 객체를 반환해요. notifications 배열은 현재 표시되고 있는 모든 알림을, queue는 표시를 기다리는 알림을 포함해요.
function Demo() {
const [counter, { increment }] = useCounter();
const notificationsStore = useNotifications();
const showNotification = () => {
notifications.show({
title: `Notification ${counter}`,
message: 'Most notifications are added to queue',
});
increment();
};
return (
<>
<Button onClick={showNotification}>Show notification</Button>
<div>
<Text>Notifications state</Text>
{JSON.stringify(notificationsStore.notifications, null, 2)}
</div>
<div>
<Text>Notifications queue</Text>
{JSON.stringify(notificationsStore.queue, null, 2)}
</div>
</>
);
}