TIP
Each example uses its own instance of NoticeBubbleManager
, which is why notices from different examples can overlay each other.
Basic notice
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show basic notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show basic notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
NoticeBubble not in portal
If NoticeBubbleContainer has disablePortal
it will add position: sticky
to Bubbles
.
Parent should have position: relative
and overflow
with scroll.
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
initialAnimation: true,
duration: 300000,
});
};
return (
<div
style={{ border: '1px dashed #eee', height: '180px', position: 'relative', overflow: 'auto' }}
>
<div style={{ height: '800px' }}>
<NoticeBubbleContainer manager={manager} disablePortal={true} />
<Button onClick={handleClick} m={5}>
Show basic notice
</Button>
</div>
</div>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
initialAnimation: true,
duration: 300000,
});
};
return (
<div
style={{ border: '1px dashed #eee', height: '180px', position: 'relative', overflow: 'auto' }}
>
<div style={{ height: '800px' }}>
<NoticeBubbleContainer manager={manager} disablePortal={true} />
<Button onClick={handleClick} m={5}>
Show basic notice
</Button>
</div>
</div>
);
};
export default Demo;
Focus management
In this example keyboard focus is automatically set on the first interactive element in the bubble.
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const openButtonRef = React.useRef<HTMLButtonElement>(null);
const handleClick = () => {
const { focus } = manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
action: <Button theme='invert'>Undo</Button>,
initialAnimation: true,
duration: 0,
onClose: () => {
setTimeout(() => {
if (document.activeElement === document.body) {
openButtonRef.current?.focus();
}
}, 500);
},
});
focus();
};
return (
<>
<Button onClick={handleClick} ref={openButtonRef}>
Show notice with undo action
</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Link from 'intergalactic/link';
const manager = new NoticeBubbleManager();
const Demo = () => {
const openButtonRef = React.useRef<HTMLButtonElement>(null);
const handleClick = () => {
const { focus } = manager.add({
children: (
<>
Link was moved to <Link href='#'>Cats from outer space group</Link>
</>
),
action: <Button theme='invert'>Undo</Button>,
initialAnimation: true,
duration: 0,
onClose: () => {
setTimeout(() => {
if (document.activeElement === document.body) {
openButtonRef.current?.focus();
}
}, 500);
},
});
focus();
};
return (
<>
<Button onClick={handleClick} ref={openButtonRef}>
Show notice with undo action
</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Reload action
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const openButtonRef = React.useRef<HTMLButtonElement>(null);
const handleClick = () => {
const { focus } = manager.add({
children: 'Data for 5 new profiles is ready. Please reload the page to view it.',
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
initialAnimation: true,
duration: 0,
onClose: () => {
setTimeout(() => {
if (document.activeElement === document.body) {
openButtonRef.current?.focus();
}
}, 500);
},
});
focus();
};
return (
<>
<Button onClick={handleClick} ref={openButtonRef}>
Show notice with reload action
</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const openButtonRef = React.useRef<HTMLButtonElement>(null);
const handleClick = () => {
const { focus } = manager.add({
children: 'Data for 5 new profiles is ready. Please reload the page to view it.',
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
initialAnimation: true,
duration: 0,
onClose: () => {
setTimeout(() => {
if (document.activeElement === document.body) {
openButtonRef.current?.focus();
}
}, 500);
},
});
focus();
};
return (
<>
<Button onClick={handleClick} ref={openButtonRef}>
Show notice with reload action
</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Completion state
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import { Flex } from 'intergalactic/flex-box';
import CheckM from 'intergalactic/icon/Check/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<Flex justifyContent='center' alignItems='center' gap={1}>
<CheckM color='--intergalactic-icon-primary-success' />
Undone
</Flex>
),
initialAnimation: true,
duration: 4000,
});
};
return (
<>
<Button onClick={handleClick}>Show notice with completion state</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import { Flex } from 'intergalactic/flex-box';
import CheckM from 'intergalactic/icon/Check/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: (
<Flex justifyContent='center' alignItems='center' gap={1}>
<CheckM color='--intergalactic-icon-primary-success' />
Undone
</Flex>
),
initialAnimation: true,
duration: 4000,
});
};
return (
<>
<Button onClick={handleClick}>Show notice with completion state</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Success notice
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import CheckM from 'intergalactic/icon/Check/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
icon: <CheckM color='--intergalactic-icon-primary-success' />,
children: 'Keyword was successfully moved to Keyword Analyzer!',
initialAnimation: true,
duration: 5000,
});
};
return (
<>
<Button onClick={handleClick}>Show success notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import CheckM from 'intergalactic/icon/Check/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
icon: <CheckM color='--intergalactic-icon-primary-success' />,
children: 'Keyword was successfully moved to Keyword Analyzer!',
initialAnimation: true,
duration: 5000,
});
};
return (
<>
<Button onClick={handleClick}>Show success notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Failure notice
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import WarningM from 'intergalactic/icon/Warning/m';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show failure notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import WarningM from 'intergalactic/icon/Warning/m';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show failure notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Notice with loading state
Activate the Try again button in the notice to see the loading state.
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import WarningM from 'intergalactic/icon/Warning/m';
import ReloadM from 'intergalactic/icon/Reload/m';
import Spin from 'intergalactic/spin';
import { Flex } from 'intergalactic/flex-box';
const manager = new NoticeBubbleManager();
let notice = null;
const Demo = () => {
const tryAgain = async () => {
if (!notice) return;
notice.update({
icon: null,
children: (
<Flex justifyContent='center' gap={1}>
<Spin size='xs' theme='invert' />
Loading...
</Flex>
),
action: null,
});
await new Promise((resolve) => setTimeout(resolve, 1500));
notice.update({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' onClick={tryAgain} addonLeft={ReloadM}>
Try again
</Button>
),
});
};
const handleClick = async () => {
if (notice) {
notice.remove();
await new Promise((resolve) => setTimeout(resolve, 500));
}
notice = manager.add({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' onClick={tryAgain} addonLeft={ReloadM}>
Try again
</Button>
),
initialAnimation: true,
duration: 20000,
});
};
return (
<>
<Button onClick={handleClick}>Show dynamic notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import WarningM from 'intergalactic/icon/Warning/m';
import ReloadM from 'intergalactic/icon/Reload/m';
import Spin from 'intergalactic/spin';
import { Flex } from 'intergalactic/flex-box';
const manager = new NoticeBubbleManager();
let notice = null;
const Demo = () => {
const tryAgain = async () => {
if (!notice) return;
notice.update({
icon: null,
children: (
<Flex justifyContent='center' gap={1}>
<Spin size='xs' theme='invert' />
Loading...
</Flex>
),
action: null,
});
await new Promise((resolve) => setTimeout(resolve, 1500));
notice.update({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' onClick={tryAgain} addonLeft={ReloadM}>
Try again
</Button>
),
});
};
const handleClick = async () => {
if (notice) {
notice.remove();
await new Promise((resolve) => setTimeout(resolve, 500));
}
notice = manager.add({
children: 'Unfortunately, your recent changes were not saved. Try again later.',
icon: <WarningM color='--intergalactic-icon-primary-warning' />,
action: (
<Button theme='invert' onClick={tryAgain} addonLeft={ReloadM}>
Try again
</Button>
),
initialAnimation: true,
duration: 20000,
});
};
return (
<>
<Button onClick={handleClick}>Show dynamic notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
Special events notice
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import MailSent from 'intergalactic/illustration/MailSent';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Your post is on its way, and we will take great care of it!',
icon: <MailSent />,
initialAnimation: true,
duration: 10000,
});
};
return (
<>
<Button onClick={handleClick}>Show special event notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import MailSent from 'intergalactic/illustration/MailSent';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Your post is on its way, and we will take great care of it!',
icon: <MailSent />,
initialAnimation: true,
duration: 10000,
});
};
return (
<>
<Button onClick={handleClick}>Show special event notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
No connection notice
Use type="warning"
for this case.
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Spin from 'intergalactic/spin';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
icon: <Spin size='xs' theme='invert' />,
children: 'Server connection lost. Reconnecting...',
type: 'warning',
initialAnimation: true,
duration: 10000,
});
};
return (
<>
<Button onClick={handleClick}>Show no connection notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import Spin from 'intergalactic/spin';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
icon: <Spin size='xs' theme='invert' />,
children: 'Server connection lost. Reconnecting...',
type: 'warning',
initialAnimation: true,
duration: 10000,
});
};
return (
<>
<Button onClick={handleClick}>Show no connection notice</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
No connection notice with action
Use type="warning"
for this case.
tsx
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Server connection lost. Check your internet connection and reload the page.',
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
type: 'warning',
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show no connection notice with action</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;
import React from 'react';
import { NoticeBubbleContainer, NoticeBubbleManager } from 'intergalactic/notice-bubble';
import Button from 'intergalactic/button';
import ReloadM from 'intergalactic/icon/Reload/m';
const manager = new NoticeBubbleManager();
const Demo = () => {
const handleClick = () => {
manager.add({
children: 'Server connection lost. Check your internet connection and reload the page.',
action: (
<Button theme='invert' addonLeft={ReloadM}>
Reload the page
</Button>
),
type: 'warning',
initialAnimation: true,
duration: 0,
});
};
return (
<>
<Button onClick={handleClick}>Show no connection notice with action</Button>
<NoticeBubbleContainer manager={manager} />
</>
);
};
export default Demo;