Skip to content

Commit

Permalink
feat: add maxToasts prop to limit number of toasts on screen - #39
Browse files Browse the repository at this point in the history
fix: fix android crash when using inside scrollview - #34

fix: reference icon family correctly so as to allow custom close icon - #36

feat: allow custom styling of toast and closebutton - #40
  • Loading branch information
Jean Verster committed Nov 24, 2020
1 parent b4fa8a7 commit 2fc84c0
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 113 deletions.
101 changes: 78 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,40 +112,95 @@ const { toast } = useToast()
<Button onPress={() => toast({ bg: 'myBgColor', color: 'myTextColor' })} />
```

## Fully Customizable Styling

You are now able to fully customize both the style of the Toast component itself, as well as the close button - all while respecting your theme contstraints. This can be achieved through the `toastStyles` and `closeButtonStyles` objects respectively. You can also hide the accent view. These options need to be passed to the internal toast config:

<br />

```
toast({
message: "My First Toast!",
toastStyles: {
bg: "lightblue",
borderRadius: 16,
},
color: "white",
iconColor: "white",
iconFamily: "Entypo",
iconName: "info",
closeButtonStyles: {
px: 4,
bg: "darkgrey",
borderRadius: 16,
},
closeIconColor: "white",
hideAccent: true,
});
```

Above is an example of a fully customized toast which renders the following:
<br />

<p>
<img alt="react-native-styled-toast gif" src="https://i.imgur.com/aQvzU2F.png" width="350">
</p>

## Max Toasts

Along with the new styling updates, you are now also able to limit the number of toasts which a user can see. To do so, simply pass the `maxToasts` prop to the `ToastProvider` component:

```
<ToastProvider maxToasts={2} offset={16} position="BOTTOM">
<Container />
</ToastProvider>
```

<p>
<img alt="react-native-styled-toast gif" src="https://i.imgur.com/4LCdpjP.gif" width="350">
</p>

<br />

## Dark Mode Compatible 🌗

Because of the theming capability of `react-native-styled-toast`, it has out of the box support for dark mode. All you need to do is ensure the color keys you're using for your different modes are the same

<br />

## Props

### `ToastProvider`

| Prop | Type | Required | Description | Default |
| -------------- | ------ | -------- | ---------------------------------------------- | ------------------------- |
| **`position`** | enum | no | Sets the position of the toasts | TOP |
| **`offset`** | number | no | Increases default offset from the top / bottom | Constants.statusBarHeight |
| Prop | Type | Required | Description | Default |
| --------------- | ------ | -------- | ---------------------------------------------- | ------------------------- |
| **`maxToasts`** | number | no | Sets max number of toasts to show | Constants.statusBarHeight |
| **`offset`** | number | no | Increases default offset from the top / bottom | Constants.statusBarHeight |
| **`position`** | enum | no | Sets the position of the toasts | TOP |

### `ToastConfig`

| Prop | Type | Required | Description | Default |
| --------------------------- | ------- | -------- | ---------------------------------------------------------------------- | -------------- |
| **`accentColor`** | string | no | Sets the background color of the accent on the left | undefined |
| **`bg`** | string | no | Sets the background color of the toast | background |
| **`borderColor`** | string | no | Sets border color of toast | border |
| **`closeButtonBgColor`** | string | no | Sets bg color of the close button | muted |
| **`closeIconBorderRadius`** | number | no | Sets the border radius of the close icon container | 4 |
| **`closeIconColor`** | string | no | Sets the color of the close icon | text |
| **`color`** | string | no | Sets the text color of the toast | text |
| **`duration`** | number | no | ms duration of toast before auto closing. 0 = infinite. | 3000 |
| **`hideIcon`** | boolean | no | Toggles whether to show / hide icon | false |
| **`iconColor`** | string | no | Customize icon color using key from theme | undefined |
| **`iconFamily`** | string | no | Allow referencing of custom icon family from react-native-vector-icons | Feather |
| **`iconName`** | string | no | Allow referencing of custom icon name from specified icon family | undefined |
| **`intent`** | enum | no | Updates icon and accent color based on intent. | SUCCESS |
| **`message`** | string | yes | Text message that gets rendered | Toast Message! |
| **`onPress`** | func | no | Function that gets exectuted onPress of toast | () => false |
| **`shouldVibrate`** | boolean | no | Toggles whether phone vibrates on notification | false |
| **`subMessage`** | string | no | Sub message that gets rendered below message | undefined |
| Prop | Type | Required | Description | Default |
| ----------------------- | ------- | -------- | ---------------------------------------------------------------------- | -------------- |
| **`accentColor`** | string | no | Sets the background color of the accent on the left | undefined |
| **`closeButtonStyles`** | object | no | Allows custom styling of the close button, values pull from theme | N/A |
| **`closeIconColor`** | string | no | Sets the color of the close icon | text |
| **`closeIconFamily`** | string | no | Sets the family of the close icon | Feather |
| **`closeIconName`** | string | no | Sets the name of the close icon | 'x' |
| **`closeIconSize`** | string | no | Sets the size of the close icon | 20 |
| **`color`** | string | no | Sets the text color of the toast | text |
| **`duration`** | number | no | ms duration of toast before auto closing. 0 = infinite. | 3000 |
| **`hideAccent`** | boolean | no | Shows / hides accent | undefined |
| **`hideIcon`** | boolean | no | Toggles whether to show / hide icon | false |
| **`iconColor`** | string | no | Customize icon color using key from theme | undefined |
| **`iconFamily`** | string | no | Allow referencing of custom icon family from react-native-vector-icons | Feather |
| **`iconName`** | string | no | Allow referencing of custom icon name from specified icon family | undefined |
| **`intent`** | enum | no | Updates icon and accent color based on intent. | SUCCESS |
| **`message`** | string | yes | Text message that gets rendered | Toast Message! |
| **`onPress`** | func | no | Function that gets exectuted onPress of toast | () => false |
| **`shouldVibrate`** | boolean | no | Toggles whether phone vibrates on notification | false |
| **`subMessage`** | string | no | Sub message that gets rendered below message | undefined |
| **`toastStyles`** | object | no | Allows custom styling of the Toast component. Values pull from theme | undefined |

<br />
<div>Toast icon by <a href="https://www.flaticon.com/authors/ultimatearm" title="ultimatearm">ultimatearm</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
46 changes: 37 additions & 9 deletions src/Context/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react'
import { LayoutAnimation, UIManager } from 'react-native'
import { LayoutAnimation, LayoutAnimationConfig, UIManager } from 'react-native'
import { getStatusBarHeight } from 'react-native-status-bar-height'
import Box from '../Box'
import Toast, { ToastConfig } from '../Toast'
Expand All @@ -10,6 +10,7 @@ type ToastContextType = {
toast: (options: ToastConfig) => void
position?: 'TOP' | 'BOTTOM'
offset?: number
maxToasts?: number
}

export const ToastContext = React.createContext<ToastContextType>({
Expand All @@ -24,20 +25,47 @@ UIManager && UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLay

export type FullToastConfig = ToastConfig & ToastInternalConfig

const ToastProvider: React.FC<Omit<ToastContextType, 'toast'>> = ({ children, position, offset: offsetProp }) => {
const CustomLayoutConfig: LayoutAnimationConfig = {
duration: 300,
create: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity
},
update: {
type: LayoutAnimation.Types.easeInEaseOut
},
delete: {
type: LayoutAnimation.Types.easeInEaseOut,
property: LayoutAnimation.Properties.opacity
}
}

const ToastProvider: React.FC<Omit<ToastContextType, 'toast'>> = ({
children,
position,
offset: offsetProp,
maxToasts
}) => {
const [toasts, setToasts] = React.useState<FullToastConfig[]>([])

const toast = (newToast: ToastConfig) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setToasts((prevToasts) =>
position === 'BOTTOM'
? [...prevToasts, { index: prevToasts.length, id: uuid(), ...newToast }]
: [{ index: prevToasts.length, id: uuid(), ...newToast }, ...prevToasts]
)
LayoutAnimation.configureNext(CustomLayoutConfig)
setToasts((prevToasts) => {
const toasts =
position === 'BOTTOM'
? [...prevToasts, { index: prevToasts.length, id: uuid(), ...newToast }]
: [{ index: prevToasts.length, id: uuid(), ...newToast }, ...prevToasts]
if (maxToasts && prevToasts.length === maxToasts) {
position === 'BOTTOM' ? toasts.shift() : toasts.pop()
return toasts
} else {
return toasts
}
})
}

const hideToast = (id: string) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
LayoutAnimation.configureNext(CustomLayoutConfig)
setToasts((prevToasts) => prevToasts.filter((el) => el.id !== id))
}

Expand Down
6 changes: 2 additions & 4 deletions src/Icon/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// @ts-nocheck

import * as React from 'react'
import Entypo from 'react-native-vector-icons/Entypo'
import EvilIcons from 'react-native-vector-icons/EvilIcons'
Expand All @@ -23,7 +21,7 @@ export type IconProps = SpaceProps &
size: number
testID?: string
}
const Icon: React.SFC<IconProps> = (props) => {
const Icon: React.FC<IconProps> = (props) => {
let Icon
switch (props.family) {
case 'Entypo':
Expand Down Expand Up @@ -66,7 +64,7 @@ const Icon: React.SFC<IconProps> = (props) => {
${color};
${space};
`
return <StyledIcon name={props.name} {...props} />
return <StyledIcon {...props} />
}

export default Icon
Expand Down
Loading

0 comments on commit 2fc84c0

Please # to comment.