# 🍞 burnt
Cross-platform toasts for React Native, powered by native elements.
- [Install](#installation)
- [Usage](#api)
Now with Android, iOS & Web Support.
## Alerts
https://user-images.githubusercontent.com/13172299/202289223-8a333223-3afa-49c4-a001-a70c76150ef0.mp4
## ...and Toasts
https://user-images.githubusercontent.com/13172299/231801324-3f0858a6-bd61-4d74-920f-4e77b80d26c1.mp4
## ...and Web Support
https://user-images.githubusercontent.com/13172299/236826405-b5f423bb-dafd-4013-a941-7accbea43c14.mp4
## Context
See this
[Twitter thread](https://twitter.com/FernandoTheRojo/status/1592923529644625920).
## What
This is a library with a `toast` and `alert` method for showing ephemeral UI.
On iOS, it wraps [`SPIndicator`](https://github.com/ivanvorobei/SPIndicator) and
[`AlertKit`](https://github.com/sparrowcode/AlertKit).
On Android, it wraps `ToastAndroid` from `react-native`. `Burnt.alert()` falls
back to `Burnt.toast()` on Android. This may change in a future version.
On Web, it wraps [`sonner`](https://github.com/emilkowalski/sonner) by Emil
Kowalski.
Burnt works with both the old & new architectures. It's built on top of JSI,
thanks to Expo's new module system.
## Features
- Simple, imperative `toast` that uses **native** components under the hood,
rather than using React state with JS-based UI.
- Animated icons
- iOS App Store-like `alert` popups
- Overlays on top of native iOS modals
- Loading alerts
## Modals
Displaying toasts on top of modals has always been an issue in React Native.
With Burnt, this works out of the box.
https://user-images.githubusercontent.com/13172299/231801096-2894fbf3-4df7-45d7-9c72-f80d36fd45ef.mp4
## Usage
```tsx
import * as Burnt from "burnt";
Burnt.toast({
title: "Burnt installed.",
preset: "done",
message: "See your downloads.",
});
```
You can also `Burnt.alert()` and `Burnt.dismissAllAlerts()`.
## TODO
- [x] iOS support
- [x] Android support
- [x] Custom iOS icons
- [x] Web support
## Installation
```sh
yarn add burnt
```
### Expo
Burnt likely requires Expo SDK 46+.
```sh
npx expo install burnt expo-build-properties
```
Add the `expo-build-properties` plugin to your `app.json`/`app.config.js`,
setting the deployment target to `13.0` (or higher):
```js
export default {
plugins: [
[
"expo-build-properties",
{
ios: {
deploymentTarget: "13.0",
},
},
],
],
};
```
Then, you'll need to rebuild your dev client. Burnt will not work in Expo Go.
```sh
npx expo prebuild --clean
npx expo run:ios
```
The config plugin ensures that your iOS app has at least iOS 13 as a deployment
target, which is required for Burnt (as well as Expo SDK 47+).
### Web Support
To enable Web support, you need to add the `` to the root of your
app. If you're using Next.js, add this into your `_app.tsx` component.
```tsx
// _app.tsx
import { Toaster } from "burnt/web";
function MyApp({ Component, pageProps }) {
return (
<>
>
);
}
```
If you're using Next.js, add `burnt` to your `transpilePackages` in `next.config.js`.
```tsx
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: [
// Your other packages here
"burnt"
]
}
```
To configure your `Toaster`, please reference the `sonner`
[docs](https://github.com/emilkowalski/sonner/tree/main#theme).
### Expo Web
If you're using Expo Web, you'll need to add the following to your
`metro.config.js` file:
```js
// Learn more https://docs.expo.io/guides/customizing-metro
const { getDefaultConfig } = require("expo/metro-config");
const config = getDefaultConfig(__dirname);
// --- burnt ---
config.resolver.sourceExts.push("mjs");
config.resolver.sourceExts.push("cjs");
// --- end burnt ---
module.exports = config;
```
### Plain React Native
```sh
pod install
```
### Solito
```sh
cd applications/app
expo install burnt expo-build-properties
npx expo prebuild --clean
npx expo run:ios
cd ../..
yarn
```
Be sure to also follow the [expo](#expo) instructions and [web](#web-support)
instructions.
## API
### `toast`
https://user-images.githubusercontent.com/13172299/202275423-300671e5-3918-4d5d-acae-0602160de252.mp4
`toast(options): Promise`
```tsx
Burnt.toast({
title: "Congrats!", // required
preset: "done", // or "error", "none", "custom"
message: "", // optional
haptic: "none", // or "success", "warning", "error"
duration: 2, // duration in seconds
shouldDismissByDrag: true,
from: "bottom", // "top" or "bottom"
// optionally customize layout
layout: {
iconSize: {
height: 24,
width: 24,
},
},
icon: {
ios: {
// SF Symbol. For a full list, see https://developer.apple.com/sf-symbols/.
name: "checkmark.seal",
color: "#1D9BF0",
},
web: ,
},
});
```
### `alert`
https://user-images.githubusercontent.com/13172299/202275324-4f6cb5f5-a103-49b5-993f-2030fc836edb.mp4
_The API changed since recording this video. It now uses object syntax._
`alert(options): Promise`
```tsx
import * as Burnt from "burnt";
export const alert = () => {
Burnt.alert({
title: "Congrats!", // required
preset: "done", // or "error", "heart", "custom"
message: "", // optional
duration: 2, // duration in seconds
// optionally customize layout
layout: {
iconSize: {
height: 24,
width: 24,
},
},
icon: {
ios: {
// SF Symbol. For a full list, see https://developer.apple.com/sf-symbols/.
name: "checkmark.seal",
color: "#1D9BF0",
},
web: ,
},
});
};
```
On Web, this will display a regular toast. This may change in the future.
### `dismissAllAlerts()`
Does what you think it does! In the future, I'll allow async spinners for
promises, and it'll be useful then.
## Contribute
```sh
yarn build
cd example
yarn
npx expo run:ios # do this again whenever you change native code
```
You can edit the iOS files in `ios/`, and then update the JS accordingly in
`src`.
## Thanks
Special thanks to [Tomasz Sapeta](https://twitter.com/tsapeta) for offering help
along the way.
Expo Modules made this so easy to build, and all with Swift – no Objective C.
It's my first time writing Swift, and it was truly a breeze.