Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/foundations/ui/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ const useDialogElement = (
) => {
const ref = useRef<HTMLDialogElement>(null);

// Emit modal-open or modal-close custom event when the dialog is opened or closed,
// so other components can react to it
useEffect(() => {
const origin = ref.current;
if (!origin) return;

const openEvent = new CustomEvent(
open ? 'ui:modal-open' : 'ui:modal-close',
{
detail: { origin: ref.current },
Comment thread
andrre-ls marked this conversation as resolved.
}
);
window.dispatchEvent(openEvent);
}, [open]);

useLayoutEffect(() => {
const element = ref.current;
if (!element) return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Button } from '@/foundations/ui/button/button';
import { toast } from '@/foundations/ui/toaster/toaster';

Comment thread
andrre-ls marked this conversation as resolved.
const ToasterDescriptionPreview = () => {
return (
<div className="flex flex-col gap-4">
<Button
type="button"
size="sm"
variant="outline"
onClick={() => {
toast({
title: 'This is a toast notification!',
description:
'A lightweight notification that appears temporarily to provide feedback about an action or event.',
});
}}
>
Show Toast
</Button>
</div>
);
};

export default ToasterDescriptionPreview;
49 changes: 49 additions & 0 deletions src/foundations/ui/toaster/examples/toaster-drawer.preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Button } from '@/foundations/ui/button/button';
import { Drawer } from '@/foundations/ui/drawer/drawer';
import { toast } from '@/foundations/ui/toaster/toaster';

Comment thread
andrre-ls marked this conversation as resolved.
const ToasterDrawerPreview = () => {
return (
<div className="flex gap-2">
<Button
type="button"
size="sm"
variant="outline"
onClick={() => {
toast({
title: 'This is a toast notification!',
});
}}
>
Emit Toast
</Button>
<Drawer>
<Drawer.Trigger asChild>
<Button size="sm" variant="outline">
Open Drawer
</Button>
</Drawer.Trigger>
<Drawer.Content>
<p>This is a drawer content.</p>

<div className="flex py-4">
<Button
type="button"
size="sm"
variant="outline"
onClick={() => {
toast({
title: 'This is a toast notification!',
});
}}
>
Emit Toast
</Button>
</div>
</Drawer.Content>
</Drawer>
</div>
);
};

export default ToasterDrawerPreview;
43 changes: 43 additions & 0 deletions src/foundations/ui/toaster/examples/toaster-duration.preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Button } from '@/foundations/ui/button/button';
import { toast } from '@/foundations/ui/toaster/toaster';

Comment thread
andrre-ls marked this conversation as resolved.
const ToasterDurationPreview = () => {
return (
<div className="flex gap-2">
<Button
type="button"
size="sm"
variant="outline"
onClick={() => toast({ title: 'This is a 7 second toast!' })}
>
Default
</Button>
<Button
type="button"
size="sm"
variant="outline"
onClick={() =>
toast({ title: 'This is a 3 second toast!', duration: 3000 })
}
>
Short
</Button>
<Button
type="button"
size="sm"
variant="outline"
onClick={() =>
toast({
title: 'This is an infinity toast!',
description: 'It will not disappear until you dismiss it.',
duration: Infinity,
})
}
>
Infinite
</Button>
</div>
);
};

export default ToasterDurationPreview;
47 changes: 47 additions & 0 deletions src/foundations/ui/toaster/examples/toaster-variants.preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Button } from '@/foundations/ui/button/button';
import { toast } from '@/foundations/ui/toaster/toaster';

Comment thread
andrre-ls marked this conversation as resolved.
const ToasterVariantsPreview = () => {
return (
<div className="flex gap-2">
<Button
type="button"
size="sm"
variant="outline"
onClick={() =>
toast({ title: 'This is a toast notification!', variant: 'default' })
}
>
Default
</Button>
<Button
type="button"
size="sm"
variant="outline"
onClick={() =>
toast({
title: 'This is a positive toast notification!',
variant: 'positive',
})
}
>
Positive
</Button>
<Button
type="button"
size="sm"
variant="outline"
onClick={() =>
toast({
title: 'This is a negative toast notification!',
variant: 'negative',
})
}
>
Negative
</Button>
</div>
);
};

export default ToasterVariantsPreview;
23 changes: 23 additions & 0 deletions src/foundations/ui/toaster/examples/toaster.preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Button } from '@/foundations/ui/button/button';
import { toast } from '@/foundations/ui/toaster/toaster';

Comment thread
andrre-ls marked this conversation as resolved.
const ToasterPreview = () => {
return (
<div className="flex flex-col gap-4">
<Button
type="button"
size="sm"
variant="outline"
onClick={() => {
toast({
title: 'This is a toast notification!',
});
}}
>
Show Toast
</Button>
</div>
);
};

export default ToasterPreview;
57 changes: 57 additions & 0 deletions src/foundations/ui/toaster/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: Toaster
description: A component for displaying transient messages to users, such as notifications or alerts.

preview: toaster
files:
- src/foundations/ui/toaster/toaster.tsx

dependencies:
- name: motion
href: https://motion.dev

folder: UI
---

> This component relies on custom events emitted by the `Modal` component. Ensure your `Modal` implementation dispatches the `ui:modal-open` and `ui:modal-close` events accordingly.

## Usage

Render the `Toaster` component at the root of your application.

```tsx
import { Toaster } from "@/components/ui/toaster";

Comment thread
andrre-ls marked this conversation as resolved.
function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Toaster />
</body>
</html>
);
}
```

Then, you can use the `toast` function to display messages.

```tsx
import { toast } from "@/components/ui/toaster";

Comment thread
andrre-ls marked this conversation as resolved.
toast({ title: "This is a toast message!" });
```

## Example

### With Description

<Preview slug="toaster-description" />

### Variants

<Preview slug="toaster-variants" />

### Duration

<Preview slug="toaster-duration" />
Loading
Loading