Giter Site home page Giter Site logo

ardeora / solid-toast Goto Github PK

View Code? Open in Web Editor NEW
804.0 5.0 23.0 383 KB

Customizable Toast Notifications for SolidJS

Home Page: https://www.solid-toast.com

License: MIT License

TypeScript 93.93% JavaScript 1.57% HTML 1.47% CSS 3.03%
notifications solid-js toast

solid-toast's Introduction

Solid Toast header image showing a cute toaster with a toast popping out


Create beautiful, customizable toasts in SolidJS.


Features

  • Easily Customizable
  • Promise API
  • Lightweight
  • Accessible
  • SSR Support

Installation

With yarn

yarn add solid-toast

With NPM

npm install solid-toast

Getting Started

Add a Toaster to your component tree. This component will render all toasts. Now you can trigger toast() from anywhere!

import toast, { Toaster } from 'solid-toast';

const notify = () => toast('Here is your toast.');

const App = () => {
  return (
    <div>
      <button onClick={notify}>Make me a toast</button>
      <Toaster />
    </div>
  );
};

Documentation

toast() Function

Call this function from anywhere to create a toast.

Available Options

You can provide ToastOptions as the second argument. They will overwrite all options received from the <Toaster/> component.

toast('This is a simple toast!', {
  duration: 5000,
  position: 'top-right',
  // Add a delay before the toast is removed
  // This can be used to time the toast exit animation
  unmountDelay: 500,
  // Styling - Supports CSS Objects, classes, and inline styles
  // Will be applied to the toast container
  style: {
    'background-color': '#f00',
  },
  className: 'my-custom-class',
  // Custom Icon - Supports text as well as JSX Elements
  icon: '🍩',
  // Set accent colors for default icons that ship with Solid Toast
  iconTheme: {
    primary: '#fff',
    secondary: '#000',
  },
  // Aria Props - Supports all ARIA props
  aria: {
    role: 'status',
    'aria-live': 'polite',
  },
});

Creating Toasts

There are several options for creating toasts

Blank
toast('This is a blank toast!');

Blank toasts do not come with a default icon. However, you can set a custom JSX Element/Text (Emoji) icon by placing it in the icon option.

Success
toast.success('Successfully saved!');

Creates a notification with an animated checkmark. Color accents can be themed with the iconTheme option.

Error
toast.error('Something went wrong!');

Creates a notification with an animated error icon. Color accents can be themed with the iconTheme option.

Loading
toast.loading('Loading Photos...');

Shows a toast with a loading indicator icon. The content can later be updated with an error or success icon. See how to update the toast content here.

Promise

The promise() function can be used to create a toast from a promise. This function will automatically show a loading icon and update the toast with the result of the promise.

const myPromise = fetchData();

toast.promise(myPromise, {
  loading: 'Loading',
  success: <b>Got the data</b>,
  error: 'An error occurred 😔',
});
Custom Toast

You also have the ability to completely customize the appearance of your toast. A custom JSX Element can be passed in like so:

toast.custom(() => (
  <div>
    <h1>Custom Toast</h1>
    <p>This is a custom toast!</p>
  </div>
));
Advanced Option

You can also hook into the toast life-cycle by adding a parameter to the JSX Function call like so:

toast.custom(
  (t) => (
    <div>
      <h1>Custom Toast</h1>
      <p>This is a custom toast!</p>
      <p>{t.visible ? 'Showing' : 'I will close in 1 second'}</p>
      <button onClick={() => toast.dismiss(t.id)}>Close Toast</button>
    </div>;
  ),
  {
    unmountDelay: 1000,
  }
);

Helpful Utilities

Dismiss Toasts Programatically

You can manually dismiss a notification with toast.dismiss. Beware that it triggers the exit animation and does not remove the Toast instantly. Toasts will auto-remove after 500ms by default. You can adjust the dismiss duration with the unmountDelay option.

Dismiss Single Toast
const toastId = toast.loading('Loading...');
// ...
toast.dismiss(toastId);

Dismiss all toasts by omitting all arguments.

Dismiss All Toasts
toast.dismiss();
Remove Toasts Instantly

Toasts can be removed instantly with toast.remove. This will not trigger the exit animation and remove the toast instantly.

toast.remove(toastId);
// or
toast.remove();
Updating Toasts

Each toast call returns a unique id. Use this id in the toast options to update an existing toast.

const toastId = toast.loading('Loading...');
// ...
toast.success('This worked', {
  id: toastId,
});

Toaster Component

This component will render all toasts.

Available Options

<Toaster
  position="top-center"
  // Spacing between each toast in pixels
  gutter={8}
  containerClassName=""
  containerStyle={{}}
  toastOptions={{
    // Define default options that each toast will inherit. Will be overwritten by individual toast options
    className: '',
    duration: 5000,
    style: {
      background: '#363636',
      color: '#fff',
    },
  }}
/>

Acknowledgements

This project is inspired by

solid-toast's People

Contributors

ardeora avatar beiyanyunyi avatar dependabot[bot] avatar kkomelin avatar m4rvr avatar nathanbabcock avatar ps73 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

solid-toast's Issues

Headless version available?

This is not a bug report, it's more of a question.

Is there any chance to get a headless (= zero styles) version of this plugin?
Maybe by making the contents of /src/core available to use?

[Feature Request] Use svg <animate> instead of css

The <svg> element have <animate> element, which can set animates for its parent element. Documents are avaliable on MDN.

Here're some advantages:

  • Declarative. Declarable in TSX, no goober, no keyframes string.
  • No transform.
  • Smaller and faster. Without js in animation, solid can use setInnerHTML to render svg.

Here's my code in progress. It's not ready to be merged because there're still something to do:

  • SuccessIcon has not been rewritten.
  • The animation is linear now, I'm trying to use calcMode so that we can have a cubic-bezier timed animation.
  • We can refactor some <animate /> into independent variables.

Loading Toast dismisses automatically, if toaster sets default

If the Toaster configures a default duration, then toasts created with toast.loading ignore will use the default duration, instead of Infinity, like it should

<Toaster position="top-center" toastOptions={{ duration:5000 }} />

toast.loading("Message")

Expected result: the loading toast should stay there indefinitely
Actual result: the loading toast disappears after the default duration

Add Tests For Solid Toast

There are multiple combinations of ways to use/configure solid-toast. We need to add tests to make sure the configuration follows the correct hierarchy and manages edge cases correctly.

Lazy Loading

Is it possible to lazy load this package?

My use case is that most users will never see a toast, so I don’t want them to pay the price of extra JS unnecessarily

it’s pretty easy to lazy load the “toast” object, but the problem is the Toaster container. I’ll try do It by dynamically attaching it to the DOM on first use (maybe using Solid Portal?), but in case someone already solved this, please share 😊

Customize toast

This isn't an issue, just a question.

How can I customize a toast globally? For example, change the background color that can work across the app?

Thank you!

Promise Toast

Hey!
I have multiple questions about the toast.promise

  1. How can I execute JS code after the promise was a success?
  2. How can I display a error given by the promise when it failed?

Toast style reactivity

Example:

<Toaster
    position="top-right"
    gutter={24}
    toastOptions={{
        style: darkMode() ? {
            background: '#363636',
            color: '#fff',
        } : {},
    }}
    containerStyle={{'margin-top': '50px'}}
/>

Changes of darkMode only get applied to new toasts, but not pre-existing ones. Is there a way to pass reactivity inside a toast?

Wrong style in Mozilla Firefox

图片

When using success and error toasts, it will act like this. It seems that the svg element should be given height and width props (the height= and the width= props, not in CSS).

It works well on browsers using blink as their core, such as Google Chrome and Microsoft Edge, so if you're going to debug, you should install Mozilla Firefox.

Big custom icons are not centered in toast

Custom JSX icons are currently size constrained by 20x20 and that causes issues with aligning.

Example:
example

Code:

toast("example", {
  icon: <div style={{
    "height": "30px",
    "width": "30px",
    "border-radius": "50%",
    "background-color": "red",
  }}/>,
});

Syntax error when including solid-toast in latest version of SolidJS

When trying to import solid_toast with the latest version of SolidJS like this

import toast, { Toaster } from 'solid-toast';

I get the following error

Error when evaluating SSR module module.tsx: failed to import "solid-toast"
|- \node_modules\solid-toast\dist\esm\index.js:1
import { createSignal, untrack, createRoot, createEffect, onCleanup, For, Switch, Match, createMemo, onMount } from 'solid-js';
^^^^^^

SyntaxError: Cannot use import statement outside a module      
    at internalCompileFunction (node:internal/vm:73:18) 

I'm using these versions

"solid-js": "^1.8.3",
"solid-start": "^0.3.10",
"solid-toast": "^0.5.0"
"solid-start-node": "^0.3.10",
"tailwindcss": "^3.3.3",
"typescript": "^4.9.5",
"vite": "^4.4.9"

Any thoughts?

LoaderIcon parsing failure under 1.5

Hi, I'm using Solid-start alpha 101 which bundles Solid 1.5.x.

Importing the Toaster component fails with this message:

[plugin:vite:import-analysis] Failed to parse source for import analysis because the content contains invalid JS syntax. If you are using JSX, make sure to name the file with the .jsx or .tsx extension.

/Users/jchatard/Desktop/toast/node_modules/solid-toast/dist/source/components/LoaderIcon.jsx:5:12
3  |      <path fill="none" stroke={props.secondary || '#4b5563'} stroke-width="4" stroke-linecap="round" stroke-miterlimit="10" d="M16,6c3,0,5.7,1.3,7.5,3.4c0.6,0.7,1.1,1.4,1.5,2.2">
4  |        <animateTransform attributeName="transform" type="rotate" from="0 16 16" to="360 16 16" dur="0.75s" repeatCount="indefinite"/>
5  |      </path>
   |             ^
6  |    </svg>);

Seems like it's complaining about the SVG, structure...

You can try here: https://stackblitz.com/github/jchatard/solid-toast-parse-issue?file=src%2Froutes%2Findex.tsx
Repro repo here: https://github.com/jchatard/solid-toast-parse-issue

Thank a bunch!
Jérémy

[SSR] Library isn't compatible with SSR and shares its state between all the clients

Solid-toast creates a store in global scope which is literally just a global variable that's created only once on the server and being shared across all the clients afterwards:

const [store, setStore] = createStore<State>({

Reproduction: https://stackblitz.com/edit/solid-ssr-vite-n1tsrb?file=src%2Froutes%2Findex.tsx,src%2Froot.tsx

  1. Open reproduction and wait till a toast is popped up.
  2. Update the page after this.

As you can see, a toast pops up immediately even though we have a timer set up for this. A toast will still be there even if you comment out this timer and update the page one more time.

I think it makes sense to leverage Context API here and create independent store for every provider, but probably this would require some breaking changes.

Toasts don't reorder when one of the toasts has been updated

When updating manually a toast with providing a new toast body with toast(newBody, {id: id), if the new body has bigger height that the original, the rest of the toasts don't update and don't accomodate for the new height, so the updated toast gets cut off partially.

How to remove the inline style?

It's a beautiful component
I use tailwindcss in solid project, but when i use this component i have some question, i can't overwrite the background whit classname
How can i remove the inline style, i want use two theme in my project, so the toast need chang the color when the project chang the theme, if toast can remove the inline style, i think it's will be easy like this
image
thanks for your help

[SSR] `y.template is not a function`

Hey! I'm using solid-toast with Astro and I'm getting y.template is not a function when using it.
It seems like a common problem if the library isn't SSR compatible.

IIRC it's recommended to ship Solid libraries with preserved JSX so the bundler can decide which build (client or server) to use.

Any chance to get this implemented? Maybe bundling with rollup-preset-solid?

Problem with new `moduleResolution: bundler` (Typescript 5.0)

I noticed this error after adding "moduleResolution": "bundler" in my tsconfig.json.

solid-toast-module-resolution-bundler

I don't fully understand the error message, but I found an easy way to fix it by modifying node_modules/solid-toast/package.json. If I add this line, the error instantly goes away:

  "exports": {
    ".": {
+      "types": "./dist/types/index.d.ts",
      "solid": "./dist/source/index.jsx",
      "import": "./dist/esm/index.js",
      "browser": "./dist/esm/index.js",
      "require": "./dist/cjs/index.js",
      "node": "./dist/cjs/index.js"
    }
  },

I'll put it in a PR if this seems like the proper fix.

[Feature Request] Do not use transform to set the position of an element

transform: `translateY(${offset * (top ? 1 : -1)}px)`,

It seem that you're using transform to set the position of toast container. Use transform in animations is a good idea, but when the animation is end, it turns out to an issue.

When an element was transformed, the text anti-aliasing and hinting will lose effectiveness, which make a bad looking of fonts. This is especially obvious in Chinese characters, for example:

图片

The first line is not transformed and it displays well, but the follow lines don't.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.