Skip to content

Commit

Permalink
feat: add position props to Toaster
Browse files Browse the repository at this point in the history
  • Loading branch information
sveenxx committed Mar 18, 2023
1 parent febead2 commit e638212
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 20 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ Toaster component accepts following props:
| bgColor | Color of toast background |
| textColor | Color of text and close icon |
| customComponent | Custom component to render toast |
| position | Position of toast container |

#### Custom component example:
#### Custom component example:
```tsx
import { Toaster, toast } from 'poply';
import { CustomToast } from './components/custom-toast';
Expand Down
7 changes: 7 additions & 0 deletions apps/web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# web

## 0.1.8

### Patch Changes

- Updated dependencies
- [email protected]

## 0.1.7

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "web",
"version": "0.1.7",
"version": "0.1.8",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const Home: NextPage = () => {
<Toaster
bgColor="#000"
textColor="#fff"
position={'top-right'}
// maxToasts={3}
// maxToastsPerMessage={2}
customComponent={({ remove, message, type }) => (
Expand Down
6 changes: 6 additions & 0 deletions packages/poply/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# poply

## 3.1.5

### Patch Changes

- Add README and position prop

## 3.1.3

### Patch Changes
Expand Down
107 changes: 107 additions & 0 deletions packages/poply/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<p align="center">
<img height=300 src="https://i.imgur.com/MwiRRJB.png" />
</p>
<p align="center">
<img src="https://img.shields.io/npm/v/poply.svg?style=for-the-badge"/>
<img src="https://img.shields.io/bundlephobia/minzip/poply?style=for-the-badge"/>
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-yellow.svg?style=for-the-badge" />
</p>

<p align="center">
<a href="#">https://poply.dev</a><br/>
<strong>🎉 Lightweight toast component for React 🎉</strong>
</p>

## Installation

```sh
# pnpm (recommended):
pnpm add poply

# npm:
npm install poply

# yarn:
yarn add poply
```

## Usage

Add `<Toaster />` to your app component:
```tsx
import { Toaster, toast } from 'poply';

function App() {
return (
<div>
<button onClick={() => toast.info('Hello world!')}>Toast</button>
<Toaster />
</div>
)
}
```

### Usage with Next 13 appDir
Import `Toaster` and render it inside of a Client Coponent:
```tsx
// app/toaster-provider.tsx
'use client'

import { Toaster } from 'poply';

export default function ToasterProvider({ children }: { children: React.ReactNode }) {
return (
<>
{children}
<Toaster />
</>
);
}
```
As your provider has been marked as a Client Component, your Server Component can now directly render it:
```tsx
// app/layout.tsx
import ToasterProvider from './toaster-provider';

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<ToasterProvider>
{children}
</ToasterProvider>
</body>
</html>
);
}
```

## Options

Toaster component accepts following props:

| Prop | Description |
|------------|----------------------------------|
| bgColor | Color of toast background |
| textColor | Color of text and close icon |
| customComponent | Custom component to render toast |
| position | Position of toast container |

#### Custom component example:
```tsx
import { Toaster, toast } from 'poply';
import { CustomToast } from './components/custom-toast';

function App() {
return (
<div>
<button onClick={() => toast.info('Hello world!')}>Toast</button>
<Toaster customComponent={({ message, type }) => <CustomToast message={message} type={type} />} />
</div>
)
}
```

## License

Licensed under MIT
2 changes: 1 addition & 1 deletion packages/poply/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "poply",
"description": "Poply is lightweight toast library for React",
"repository": "sveenxx/poply",
"version": "3.1.3",
"version": "3.1.5",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
Expand Down
26 changes: 20 additions & 6 deletions packages/poply/src/components/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ import React, { memo, ReactNode, useSyncExternalStore } from 'react';
import { toastStore } from '../toast';
import { Toast, ToastProps, ToastWrapper } from './Toast';
import { setup } from 'goober';
import { ToastPosition } from '../types';
import { DEFAULT_POSITION } from '../constants';

setup(React.createElement);

type ToasterProps = {
bgColor?: string;
textColor?: string;
position?: ToastPosition;
duration?: number;
customComponent?: (props: ToastProps) => ReactNode;
};

export const Toaster = ({ bgColor, textColor, customComponent }: ToasterProps) => {
export const Toaster = ({
bgColor,
textColor,
customComponent,
position,
duration,
}: ToasterProps) => {
const toasts = useSyncExternalStore(
toastStore.subscribe,
toastStore.getSnapShot,
Expand All @@ -26,11 +36,13 @@ export const Toaster = ({ bgColor, textColor, customComponent }: ToasterProps) =
pointerEvents: 'none',
}}
>
{toasts.map((toast) =>
customComponent ? (
{toasts.map((toast) => {
const toastPosition = toast.position || position || DEFAULT_POSITION;

return customComponent ? (
<ToastWrapper
toastIndex={toasts.indexOf(toast)}
position={toast.position}
position={toastPosition}
isVisible={toast.isVisible}
key={toast.id}
>
Expand All @@ -39,6 +51,7 @@ export const Toaster = ({ bgColor, textColor, customComponent }: ToasterProps) =
bgColor,
remove: toast.destroy,
textColor,
position: toastPosition,
toastIndex: toasts.indexOf(toast),
})}
</ToastWrapper>
Expand All @@ -47,12 +60,13 @@ export const Toaster = ({ bgColor, textColor, customComponent }: ToasterProps) =
{...toast}
bgColor={bgColor}
textColor={textColor}
position={toastPosition}
remove={toast.destroy}
key={toast.id}
toastIndex={toasts.indexOf(toast)}
/>
),
)}
);
})}
</div>
);
};
3 changes: 3 additions & 0 deletions packages/poply/src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const DEFAULT_DURATION = 3000;
export const DEFAULT_POSITION = 'bottom-center';
export const TOAST_CLOSE_DELAY = 300;
13 changes: 4 additions & 9 deletions packages/poply/src/toast.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { DefaultOptions, Toast, ToastType } from './types';
import { DefaultOptions, Toast, ToastPosition, ToastType } from './types';
import { getRandomId } from './utils/get-random-id';

const DEFAULT_OPTIONS = {
position: 'bottom-center',
duration: 3000,
} as DefaultOptions;
const TOAST_CLOSE_DELAY = 300;
import { DEFAULT_DURATION, TOAST_CLOSE_DELAY } from './constants';

const observers = new Set<{
(): void;
Expand Down Expand Up @@ -85,8 +80,8 @@ export const toastStore = Object.freeze({
// return;
// }

const duration = options.duration || DEFAULT_OPTIONS.duration;
const position = options.position || DEFAULT_OPTIONS.position;
const duration = options.duration || DEFAULT_DURATION;
const position = options.position;
const id = getRandomId();

toasts = [
Expand Down
4 changes: 2 additions & 2 deletions packages/poply/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type DefaultOptions = {
position: ToastPosition;
position: ToastPosition | undefined;
duration: number;
};

Expand All @@ -18,7 +18,7 @@ export type Toast = {
message: string;
type: ToastType;
duration: number;
position: ToastPosition;
position: ToastPosition | undefined;
timeout: ReturnType<typeof setTimeout>;
isVisible: boolean;
destroy: () => void;
Expand Down

0 comments on commit e638212

Please sign in to comment.