{"id":3991,"url":"https://github.com/MAKARD/react-native-toastboard","last_synced_at":"2025-08-04T00:30:56.301Z","repository":{"id":33781299,"uuid":"161917945","full_name":"MAKARD/react-native-toastboard","owner":"MAKARD","description":"Toast feedback messages for React Native","archived":false,"fork":false,"pushed_at":"2024-03-04T09:15:30.000Z","size":800,"stargazers_count":52,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-25T00:50:46.550Z","etag":null,"topics":["notifications","react","react-native","toast","toastboard","toaster"],"latest_commit_sha":null,"homepage":"https://snack.expo.io/@makard/react-native-toastboard","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MAKARD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2018-12-15T15:28:17.000Z","updated_at":"2024-04-23T07:06:37.000Z","dependencies_parsed_at":"2024-03-04T10:44:57.422Z","dependency_job_id":null,"html_url":"https://github.com/MAKARD/react-native-toastboard","commit_stats":{"total_commits":90,"total_committers":4,"mean_commits":22.5,"dds":"0.30000000000000004","last_synced_commit":"fe7edfa1c15ce9401fe0925b679ebef2723c720d"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAKARD%2Freact-native-toastboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAKARD%2Freact-native-toastboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAKARD%2Freact-native-toastboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MAKARD%2Freact-native-toastboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MAKARD","download_url":"https://codeload.github.com/MAKARD/react-native-toastboard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228576891,"owners_count":17939645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["notifications","react","react-native","toast","toastboard","toaster"],"created_at":"2024-01-05T20:16:57.829Z","updated_at":"2024-12-07T07:30:54.216Z","avatar_url":"https://github.com/MAKARD.png","language":"TypeScript","funding_links":[],"categories":["Components"],"sub_categories":["UI"],"readme":"[![codecov](https://codecov.io/gh/MAKARD/react-native-toastboard/branch/master/graph/badge.svg?token=8jbRRNixLc)](https://codecov.io/gh/MAKARD/react-native-toastboard)\n[![CircleCI](https://dl.circleci.com/status-badge/img/gh/MAKARD/react-native-toastboard/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/MAKARD/react-native-toastboard/tree/master)\n\n[Expo snack](https://snack.expo.io/@makard/react-native-toastboard)\n\n# React-Native-Toastboard\n\nToast feedback messages for React Native\n\n\u003cIMG width=\"300\" src=\"https://github.com/MAKARD/react-native-toastboard/assets/25794983/0e5c06dc-a4f2-406b-a212-87e9b7b76e51\"  alt=\"image.png\"/\u003e\n\n# Installation\n\n## Via NPM\n\n```bash\n npm install react-native-toastboard\n```\n\n## Via YARN\n\n```bash\n yarn add react-native-toastboard\n```\n\n# Example\n\n```jsx\nconst appearAnimation = new SlideX(Dimensions.get('screen').width, 0);\nconst holdAnimation = new Zoom(1, .95, { duration: 200, useNativeDriver: true });\n\nconst toastMiddleware = ({ type, message }: Item) =\u003e {\n  if (type !== ToastType.ERROR) {\n    return message;\n  }\n\n  if (typeof message === 'string') {\n    return message;\n  }\n\n  if (message.response \u0026\u0026 message.response.data \u0026\u0026 message.response.data.message) {\n    return message.response.data.message;\n  } else {\n    return 'Some error was happened :(';\n  }\n};\n\nconst renderToast = ({ type, message }: Item) =\u003e {\n  switch (type) {\n    case ToastType.INFO: {\n      return (\n        \u003cAnimated.View style={[styles.info.container, holdAnimation.styles]}\u003e\n          \u003cImage\n            resizeMode=\"cover\"\n            source={Images.iconFaq}\n            style={styles.info.icon}\n          /\u003e\n          \u003cText style={styles.info.text}\u003e{message}\u003c/Text\u003e\n        \u003c/Animated.View\u003e\n      );\n    }\n\n    case ToastType.ERROR: {\n      return (\n        \u003cAnimated.View style={[styles.error.container, this.holdAnimation.styles]}\u003e\n          \u003cImage\n            resizeMode=\"cover\"\n            source={Images.iconWarning}\n            style={styles.error.icon}\n          /\u003e\n          \u003cText style={styles.error.text}\u003e{message}\u003c/Text\u003e\n        \u003c/Animated.View\u003e\n      );\n    }\n\n    case ToastType.SUCCESS: {\n      return (\n        \u003cAnimated.View style={[styles.success.container, this.holdAnimation.styles]}\u003e\n          \u003cImage\n            resizeMode=\"cover\"\n            source={Images.iconCheck}\n            style={styles.success.icon}\n          /\u003e\n          \u003cText style={styles.success.text}\u003e{message}\u003c/Text\u003e\n        \u003c/Animated.View\u003e\n      );\n    }\n\n    default: {\n      throw new Error('Unknown type given');\n    }\n  }\n};\n\nexport const Example = () =\u003e {\n  const onHide = () =\u003e {\n    StatusBar.setHidden(false);\n  };\n\n  const onShow = () =\u003e {\n    StatusBar.setHidden(true);\n  };\n\n  return (\n    \u003cToaster\n      hideOnPress\n\n      onHide={onHide}\n      onShow={onShow}\n      onHoldEnd={holdAnimation.backward}\n      onHoldStart={holdAnimation.forward}\n\n      middleware={toastMiddleware}\n\n      animation={appearAnimation}\n    \u003e\n      {renderToast}\n    \u003c/Toaster\u003e\n  );\n};\n```\n\n# Public interface\n\n## \u003c Toaster /\u003e\n\n`Toaster` component represents a container that displays messages.\n\nAccepts the following props: \n\n`onHide` - a callback that executes `AFTER` message gets hidden. `Optional`.\nTakes native event as the first argument and [message item](#Message-item) as the second argument.\n\n`onShow` - a callback that executes `BEFORE` message gets shown. `Optional`.\nTakes native event as the first argument and [message item](#Message-item) as the second argument.\n\n`onPress` - a callback that executes on container press. `Optional`.\nTakes native event as the first argument and [message item](#Message-item) as the second argument.\n\n`onHoldStart` - a callback that executes when a user holds their touch on message. `Optional`.\nTakes native event as the first argument and [message item](#Message-item) as the second argument.\n\n`onHoldEnd` - a callback that executes when a user releases their touch from message after holding it. `Optional`.\nTakes native event as the first argument and [message item](#Message-item) as the second argument.\n\n`duration` - specifies `common` display time in `msec` for messages. `Optional`. Default - `2000`.\n\n`delayBetween` - specifies delay time in `msec` between showing messages. `Optional`. Default - `0`.\n\n`hideOnPress` - specifies that the message should be closed when a user touches it. `Optional`. Default - `false`.\n\n`containerViewProps` - specifies props for the container's \u003cView\u003e element. `Optional`.\n\n`animation` - specifies animation that applies to hide/show the message. `Optional`. Default - [SlideY](./src/animations/SlideY.ts). See more details below.\n\n`middleware` - executes before the message will be added to a queue. Should return `string`. `Optional`. \nTakes [message item](#Message-item) as argument.\n\n`Toaster` can take children only as `function`:\n```ts\n(item: { type: string; message: string }) =\u003e React.ReactNode;\n```\n\nIn this case, the default `Toast` will be replaced with the returned component.\n\n*NOTE: To stop hide-timer, you can tap and hold your touch on the container as long as you want*\n\n##### Message item\n\nMessage item represents the following interface:\n\n```ts\nitem: {\n\tmessage: string;\n\ttype: \"INFO\" | \"ERROR\" | \"SUCCESS\" | \"DEBUG\";\n\tduration?: number;\n}\n```\n\n#### Creating a message\n\n`Toaster` is a `singleton`. So make sure that you have only one instance.\n\n`Toaster` has several static methods for messages creation:\n\n```ts\n/*\n\tthe first argument specifies the message. REQUIRED.\n\tthe second argument specifies the duration. OPTIONAL. By default - value from props.\n*/\n\nToaster.info(\"message\", 500);\nToaster.error(\"message\", 500);\nToaster.success(\"message\", 500);\nToaster.debug(\"message\", 500);\n```\n\n## Animation\n\nThere are several built-in animations: \n\n - [Opacity](./src/animations/Opacity.ts)\n - [SlideX](./src/animations/SlideX.ts)\n - [SlideY](./src/animations/SlideY.ts)\n - [Zoom](./src/animations/Zoom.ts)\n\n```ts\n/*\n\t- the first argument specifies start-animation value. REQUIRED.\n\t- the second argument specifies end-animation value. REQUIRED.\n\t- the third argument specifies the animation config. This is the same config as in AnimationTimingConfig. OPTIONAL. (https://facebook.github.io/react-native/docs/animated)\n*/\nnew Opacity(0, 1, {\n\t\tduration: 250,\n\t\tuseNativeDriver: true\n\t});\n```\n\nEach animation extends `BaseAnimation` and implements `ToasterAnimation`. So if you want to create custom animation, make sure you correctly implement it:\n\n```tsx\nclass MyCustomAnimation extends BaseAnimation implements ToasterAnimation {\n\t/*\n\t\t1. Animated.timing SHOULD BE WRAPPED INTO PROMISE.\n\t\t2. styles SHOULD RETURN VALID OBJECT STYLES.\n\t*/\n\t\n\t// start animation forward\n\tforward() {\n\t\treturn new Promise((resolve) =\u003e {\n\t\t\tAnimated.timing(this.value, {\n\t\t\t\ttoValue: this.from,\n\t\t\t\t...this.config\n\t\t\t}).start(resolve);\n\t\t});\n\t}\n\n\t// start animation backward\n\tbackward() {\n\t\treturn new Promise((resolve) =\u003e {\n\t\t\tAnimated.timing(this.value, {\n\t\t\t\ttoValue: this.from,\n\t\t\t\t...this.config\n\t\t\t}).start(resolve);\n\t\t});\n\t}\n\t\n\t// applies animation to the container\n\tstyles = {\n\t\ttransform: [{ scale: this.value }]\n\t}\n}\n\n// ...\n\nconst animation = new MyCustomAnimation(-2, 15);\n\n\u003cToaster animation={animation} /\u003e\n```\n\n*NOTE: Always create animation instances outside from the component body OR use memoisation*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMAKARD%2Freact-native-toastboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMAKARD%2Freact-native-toastboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMAKARD%2Freact-native-toastboard/lists"}