š®[New Component] Toasts
See original GitHub issueAcceptance Criteria
- Allows users to add an āactionā which is a button styled like a bolded link.
- Handles keyboard shortcut for focusing Toast action
- If keyboard shortcut is used, it should not auto-dismiss
- Has prop for removing the auto-dismiss on the toast
- Has prop for configuring auto-dismiss timing
- Has proper animation
- Only allow one Toast to appear on the page at a time
- Exposes an
onToastDismiss
function - Fully documented
- Fully tested
- TS exports written
- TS exports tested in codesandbox
- TS export tested in another project
Component Structure
Internal Components (will not be publicly exposed by PRC)
useToastInternal
- handles all the functionality of toasts: adding a toast, removing a toast, setting up auto dismiss, and generating the props needed by
ToastContainer
- Iāve also housed all the TS interfaces that are reused in a few different places in this file. In PRC these will all be moved to the index.d.ts file so didnāt worry too much about making sure these were in the right place for now.
Toast
- Used by
ToastContainer
- Not meant to be used on itās own publicly
- Handles the
ctrl + t
keyboard shortcut (this is handled in the component instead of the hook so that I have easy access to the call to action ref) - Calls the
action
click handler
Public Components
ToastContainer
- Applies the
useToastsInternal
hook passing along theautoDismiss
andtimeout
configuration options passed toToastContainer
through itās props. useToastsInternal
returns theaddToast
function and thegetToastProps
function- Sets up a context provider, with the
addToast
function as itās value - Maps through all toasts and applies the props from
getToastProps
to each individual toast (these props include thecancelAutoDismiss
andstartRemovingToast
functions that we need to use for the keyboard shortcut.
useToasts
& addToast
useToasts
is a very simple hook that just returns theaddToast
function from the context object. This makes it so that users donāt have to calluseContext
themselves and we donāt have to publicly export the context object fromToastContainer
to the user. It also will throw a console error if you try to use the hook somewhere thatās not wrapped byToastContainer
. A little silly but feels nice for DX.
addToast
arguments:
Name | Type | Description |
---|---|---|
message | string | Message to display inside of toast |
type | string | One of success , default , warning or error |
onDismiss | callback | Callback to run when the toast leaves the page |
action | Object | Used to create an action link inside the Toast. See the below table for configuration options. |
action
objects:
Name | Type | Description |
---|---|---|
text | string | Action button text |
handleOnClick | function | Function to call after the user clicks the action. |
export const MyComponent = () => {
const { addToast } = useToasts();
...
const submitAndStopEditing = () => {
addToast({
message: "Changes saved",
type: "success",
onToastDismiss: () => window.alert("toast has left"),
action: { text: "Undo", handleOnClick: () => window.alert("hi")}
});
}
What Toasts do not do
-
Toasts do not manage focus when the toast is dismissed. Users should manage this themselves and Primer should provide guidelines on the best way to do this from an accessibility standpoint.
-
We donāt currently allow more than one Toast on the page at a time. Iāve written the code so that if we do decide to add this functionality in the future, it shouldnāt be a breaking change. But I think we need to spend more time thinking about the UX impact of having multiple Toasts on a page as well as the accessibility impact. Right now we are getting around the accessibility issues of having disappearing content by providing a keyboard shortcut users can use to jump to the action item in the Toast - if there are more than one Toasts on the page which Toast would we jump to? Would we need to āfreezeā the other Toasts while the user is on the first one, and how would we allow users to jump between Toasts to check them all out? What would happen if something like an undo action in one toast effected the state of the table/data in such a way that clicking undo on another Toast on the page had unexpected effects? For all these reasons I think we should stick with the constraint of only having one Toast on the page at a time.
-
Ability to use a link for the action item. Navigating to new pages from within a Toast is not currently supported and needs UX/design thought before being considered.
Open Questions
- Should we add a note to the alert about the keyboard shortcut?
- Are there any other handlers/hooks into when a toast is show/hidden that we anticipate needing?
- Should we try to handle focus management after the toast leaves ourselves? My gut was that we should leave this up to the consuming application but we could add a
returnFocusRef
property to theaddToast
args that we use to return focus when the user either presses enter on the Toast or closes it with their mouse.
Needs design support
-
What should happen to the toast when longer text is added? Should it wrap to two lines? What should the min/max width of a Toast be?
-
Should we allow folks to put navigational links as action items inside of the Toast?
-
Since the Toast component is one that could be abused in ways that are annoying/inaccessible, it will be important to have really solid usage guidelines written up, ideally before we ship this in PRC. Some of the items I anticipate us needing to address:
- Timeout settings: Iāve read that 500ms per word is standard. The default in Toasts is 5000ms, but we should guide users to adjust this if thereās more text in their Toast
- Maximum text length: we should guide folks on the best length for Toast text. We donāt want people adding paragraphs to a Toast
- When Toast usage is appropriate / not appropriate
- Guidelines on having actions inside of Toasts - generally I think we should guide people to use actions inside of a Toast only when totally necessary.
- When to use a modal vs when to use a Toast
- How to manage focus when the Toast is closed: applications should return the focus back to the item that triggered the toast after a
click
orenter
on the Toast
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (6 by maintainers)
Top GitHub Comments
Has there been a decision made to not upstream the
Toast
components anymore?Hey @davilag! Sorry for the delayed response, Iāve been on PTO the past few weeks. I checked in with our product design team and I think we should hold off on working on the Toast for now. Weāve got some coordination work between a couple different teams/use cases that we need to do before moving forward with this one! Thanks for checking this issue out though! š