From 5b6961ffed217e5f5940037e6fbc446358549f8d Mon Sep 17 00:00:00 2001 From: Gilad Gray Date: Mon, 29 Jan 2018 15:04:38 -0800 Subject: [PATCH] Toast docs + children support (#2048) * Toaster renders children after state.toasts * Toast docs: clarify usage * Overlay supports falsy children * docs * three ways to use a toaster --- .../core/src/components/overlay/overlay.tsx | 7 +- packages/core/src/components/toast/toast.md | 127 +++++++++++------- .../core/src/components/toast/toaster.tsx | 8 +- packages/core/test/overlay/overlayTests.tsx | 10 ++ 4 files changed, 98 insertions(+), 54 deletions(-) diff --git a/packages/core/src/components/overlay/overlay.tsx b/packages/core/src/components/overlay/overlay.tsx index d7767fbe6b..a1c8bea798 100644 --- a/packages/core/src/components/overlay/overlay.tsx +++ b/packages/core/src/components/overlay/overlay.tsx @@ -156,8 +156,11 @@ export class Overlay extends React.PureComponent { const { children, className, inline, isOpen, transitionDuration, transitionName } = this.props; - const childrenWithTransitions = React.Children.map(children, (child: React.ReactElement) => { - // add a special class to each child that will automatically set the appropriate + const childrenWithTransitions = React.Children.map(children, (child?: React.ReactChild) => { + if (child == null || typeof child !== "object") { + return child; + } + // add a special class to each child element that will automatically set the appropriate // CSS position mode under the hood. also, make the container focusable so we can // trap focus inside it (via `enforceFocus`). const decoratedChild = React.cloneElement(child, { diff --git a/packages/core/src/components/toast/toast.md b/packages/core/src/components/toast/toast.md index 6891192ae5..848b091bba 100644 --- a/packages/core/src/components/toast/toast.md +++ b/packages/core/src/components/toast/toast.md @@ -2,13 +2,6 @@ A toast is a lightweight, ephemeral notice from an application in direct response to a user's action. -`Toast`s have a built-in timeout of five seconds. Users can also dismiss them manually by clicking the × button. -Hovering the cursor over a toast prevents it from disappearing. When the cursor leaves the toast, the toast's timeout restarts. -Similarly, focusing the toast (for example, by hitting the `tab` key) halts the timeout, and blurring restarts the timeout. - -You can add one additional action button to a toast. You might use this to undo the user's action, for example. - -You can also apply the same visual intent styles to `Toast`s that you can to [`Button`s](#core/components/button.css-api). Toasts can be configured to appear at either the top or the bottom of an application window, and it is possible to have more than one toast onscreen at a time. @@ -20,29 +13,30 @@ have more than one toast onscreen at a time. The `Toast` and `Toaster` components are available in the __@blueprintjs/core__ package. Make sure to review the [general usage docs for JS components](#blueprint.usage). -The `Toaster` component provides the static `create` method that returns a new `Toaster` instance, rendered into an -element attached to ``. (You can also specify the element to render into if desired.) A `Toaster` instance -has a collection of methods to show and hide toasts in its given container. +@### Toast -Your application can contain several `Toaster` instances and easily share them across the codebase as modules. +`Toast`s have a built-in timeout of five seconds. Users can also dismiss them manually by clicking the × button. +Hovering the cursor over a toast prevents it from disappearing. When the cursor leaves the toast, the toast's timeout restarts. +Similarly, focusing the toast (for example, by hitting the `tab` key) halts the timeout, and blurring restarts the timeout. -```tsx -// toaster.ts -import { Position, Toaster } from "@blueprintjs/core"; +You can add one additional action button to a toast. You might use this to undo the user's action, for example. -export const OurToaster = Toaster.create({ - className: "my-toaster", - position: Position.BOTTOM_RIGHT, -}); -``` +You can also apply the same visual intent styles to `Toast`s that you can to [`Button`s](#core/components/button.css-api). -```tsx -// application.ts -import { OurToaster } from "./toaster"; +@interface IToastProps -const key = OurToaster.show({ message: "Toasted!" }); -OurToaster.update(key, { message: "Still toasted!" }); -``` +@### Toaster + +The `Toaster` React component is a stateful container for a single list of toasts. Internally, it +uses [`Overlay`](#core/components/overlay) to manage children and transitions. It can be vertically +aligned along the top or bottom edge of its container (new toasts will slide in from that edge) and +horizontally aligned along the left edge, center, or right edge of its container. + +There are three ways to use the `Toaster` component: + +1. `Toaster.create(props)` static method returns a new `IToaster` instance. Use the instance method `toaster.show()` to manipulate this instance. __(recommended)__ +1. `...`: Render a `` element with React `children`. +1. ` ref.show({ ...toast })} />`: Render a `` element and use the `ref` prop to access its instance methods.
Working with multiple toasters
@@ -58,51 +52,79 @@ OurToaster.update(key, { message: "Still toasted!" }); enable `autoFocus` for a `Toaster` via a prop, if desired.
-@### Static method + +@interface IToasterProps + +@## Static usage + +The `Toaster` component provides the static `create` method that returns a new `Toaster` instance, rendered into an +element attached to ``. A `Toaster` instance +has a collection of methods to show and hide toasts in its given container. ```ts Toaster.create(props?: IToasterProps, container = document.body): IToaster ``` -Create a new `Toaster` instance. The `Toaster` will be rendered into a new element appended to the -given `container`. The `container` determines which element toasts are positioned relative to; the -default value of `` allows them to use the entire viewport. + +The `Toaster` will be rendered into a new element appended to the given `container`. The `container` determines which element toasts are positioned relative to; the default value of `` allows them to use the entire viewport. Note that the return type is `IToaster`, which is a minimal interface that exposes only the instance methods detailed below. It can be thought of as `Toaster` minus the `React.Component` methods, because the `Toaster` should not be treated as a normal React component. -@interface IToasterProps +@interface IToaster -@### Instance methods +@### Example -
IToaster
+Your application can contain several `Toaster` instances and easily share them across the codebase as modules. -- `show(props: IToastProps): string` — Show a new toast to the user. -Returns the unique key of the new toast. -- `update(key: string, props: IToastProps): void` — -Updates the toast with the given key to use the new props. -Updating a key that does not exist is effectively a no-op. -- `dismiss(key: string): void` — Dismiss the given toast instantly. -- `clear(): void` — Dismiss all toasts instantly. -- `getToasts(): IToastProps[]` — Returns the options for all current toasts. +The following code samples demonstrate our preferred pattern for intergrating a toaster into a React application: -@interface IToastProps +#### `toaster.ts` +```tsx +import { Position, Toaster } from "@blueprintjs/core"; + +/** Singleton toaster instance. Create separate instances for different options. */ +export const AppToaster = Toaster.create({ + className: "recipe-toaster", + position: Position.TOP, +}); +``` -@### React component +#### `application.ts` +```tsx +import { Button } from "@blueprintjs/core"; +import * as React from "react"; +import { AppToaster } from "./toaster"; -The `Toaster` React component is a stateful container for a single list of toasts. Internally, it -uses [`Overlay`](#core/components/overlay) to manage children and transitions. It can be vertically -aligned along the top or bottom edge of its container (new toasts will slide in from that edge) and -horizontally aligned along the left edge, center, or right edge of its container. +export class App extends React.PureComponent { + render() { + return