Toaster props

Every prop of the Toaster component, when it is read, and the provider and hook around it.

On this page

<Toaster> renders the stack and the Island of the controller its <CloudletProvider> supplies. It has no controller prop. This page lists every prop and says when it is read: on every render, or once when the Toaster attaches to the controller after mount. A prop read on attach changes only after a remount, for example with a new key.

app.tsx
import { CloudletProvider, createCloudlet, Toaster } from '@cloudlet/toast';

const cloudlet = createCloudlet();

export function App({ nonce }: { nonce: string }) {
  return (
    <CloudletProvider controller={cloudlet}>
      <Toaster position="auto" theme="system" offsets={{ obstruction: { bottom: 46 } }} nonce={nonce} />
    </CloudletProvider>
  );
}

Props

ToasterProps, every prop optional.

PropTypeDefaultDescription
position'auto' | 'top-center' | 'bottom-center''auto'Which edge the stack sits on. auto is the top from a 48rem wide viewport and the bottom below it, following resizes. Every render.
theme'system' | 'light' | 'dark''system'Colour scheme of the notifications; system follows the user's preference. Every render.
dir'ltr' | 'rtl'the document's dirText direction; rtl mirrors the layout and the swipes. Every render.
containerElement | (() => Element | null) | nulldocument.bodyWhere the portal goes: a connected HTML element of the same document, outside Shadow DOM, or a function returning one. On attach; an invalid one shows nothing and reports invalid-container.
offsetsToasterOffsets—Extra distance from the screen edges, see below. Every render.
noncestring—Nonce for the style blocks Cloudlet creates, for a strict Content Security Policy. Pass the current response's nonce. Every render.
labelsPartial<CloudletLabels>English labelsNames of the controls and regions, see Labels & announcements. Every render.
announcementsPartial<AnnouncementFormatters>English textsWhat screen readers hear, see Labels & announcements. Read for each announcement.
attentionToasterAttention—Auto-open delay for this Toaster, see below. On attach.
autoDismissbooleanthe controller's autoDismissfalse keeps every notification until it is closed, true closes them on their timers; leaving the prop out restores the controller's option. Switching it off stops every timer, switching it on starts each one from its full duration. Every render, without a remount.
motionToasterMotion—Debugging aid for the animation, see below. Every render.
classNamesPartial<Record<CloudletPart, string>>—Your classes per part, added to the own cloudlet-* classes, see below. Every render.

The Toaster attaches after mount, so the server render and the first hydration render are empty. Unmounting it detaches: visible time pauses and every notification and operation stays with the controller, ready for the next Toaster. One controller is shown by one Toaster at a time.

ToasterOffsets

Distance from each screen edge is safe-area inset + gutter + obstruction, in CSS pixels, on physical edges: left stays left in RTL.

FieldTypeDefaultDescription
gutterEdgeInsets--cloudlet-viewport-gutter (16px)Breathing room outside the safe area. An edge you leave out uses the CSS token.
obstructionEdgeInsets0Your own UI over the edge, such as a tab bar, beyond the safe area. An 80px bar that includes a 34px safe area is 46.

EdgeInsets:

FieldTypeDefaultDescription
topnumberper field aboveFinite, ≥ 0, CSS pixels.
rightnumberper field aboveFinite, ≥ 0, CSS pixels.
bottomnumberper field aboveFinite, ≥ 0, CSS pixels.
leftnumberper field aboveFinite, ≥ 0, CSS pixels.

Do not add the keyboard's height: the stack already stays inside the visual viewport. Positioning & offsets explains the formula.

ToasterAttention

FieldTypeDefaultDescription
delaynumberthe controller's attentionDelay (600)Milliseconds from admission before a notification that needs attention opens the Island. An invalid value is ignored with an invalid-input diagnostic; the Toaster still attaches.

ToasterMotion

FieldTypeDefaultDescription
timeScalenumber1Slows every transition: 0.5 is twice as slow. A non-finite or non-positive value means 1.
overridesCloudletMotionOverrides—Replaces motion constants live, for transitions that start after the change. A field that is not a finite number in range (stiffness and mass > 0, the rest ≥ 0) keeps its default.

CloudletMotionOverrides is a partial CloudletMotionConstants, and a nested spring may be partial too: { slide: { damping: 30 } }. A new object is read again; the same object is not. The current values live in packages/cloudlet/src/react/motion.ts.

CloudletSpring is a physical spring, CloudletTimedSpring a spring defined by time:

FieldTypeDescription
stiffnessnumberCloudletSpring: spring stiffness.
dampingnumberCloudletSpring: resistance.
massnumberCloudletSpring: moving mass.
durationnumberCloudletTimedSpring: settles in about this many milliseconds.
bouncenumberCloudletTimedSpring: overshoot; 0 has none.

CloudletMotionConstants: durations in milliseconds at timeScale: 1, offsets and blur in CSS pixels.

FieldTypeDescription
enterCloudletTimedSpring & { scale, offset, fade }A new pill appearing: starting scale, offset in px and opacity fade in ms.
exitCloudletTimedSpringThe last notification, or a dismissed top pill, leaving.
shapeOpenCloudletSpringThe pill's shape opening into the Island.
shapeCloseCloudletSpringThe shape collapsing into the pill or adjusting to new content.
slideCloudletSpringMoving between notifications in the Island; swipes release with it.
badgeCloudletTimedSpring & { scale }The badge appearing; scale is its hidden scale.
tailsnumberThe stack's tails retracting on open and returning on collapse.
chromeDelay, chromeIn, chromeOut, chromeOffsetnumberClose button, body and indicator: delay, fade in, fade out on collapse, rise in px.
headerOut, headerIn, blurnumberTitle and icon blur swap: outgoing, incoming, blur radius in px.
bodyOut, bodyIn, bodyOffsetnumberBody crossfade: outgoing, incoming, rise of the incoming body in px.
bodyQuietnumberA body update sooner than this after the previous one changes the text in place, without a crossfade.
countSwapnumberBadge number and indicator text swap.
progressnumberProgress ring value tween.
hover, hoverLiftnumberHover: duration, and the extra tail spread per step in px.
reducednumberWith reduced motion, every transition becomes an opacity change of this length.

classNames

classNames adds your classes next to the own cloudlet-* class of each part; it never replaces it. Empty and non-string values are ignored. Theming with CSS tokens is on Styling & strict CSP.

CloudletPartElement
hostThe notifications region, div.cloudlet-host.
stackdiv.cloudlet-stack.
pillThe collapsed stack's button, button.cloudlet-pill.
tailEach of up to two tails behind the pill, div.cloudlet-tail.
badgeThe count on the pill, span.cloudlet-badge.
islandThe shell shared by the pill and the Island, div.cloudlet-shell.
headerdiv.cloudlet-header.
icondiv.cloudlet-icon.
titleh2.cloudlet-title.
closebutton.cloudlet-close.
bodydiv.cloudlet-body.
descriptiondiv.cloudlet-description.
actionsdiv.cloudlet-actions.
actionEvery action button: the primary action, retry and cancel.
indicatorThe Island's dots line, div.cloudlet-indicator.
overflowThe missed-notifications line in the indicator, div.cloudlet-overflow.

CloudletProvider

<CloudletProvider controller={cloudlet}> makes a controller available to useCloudlet, useOptionalCloudlet and <Toaster> below it. It only supplies the instance: it never creates a controller and never disposes it.

The controller may be null while it does not exist yet, for example when an effect creates it: the server render and the first client render then have no controller. Under a null controller <Toaster> renders nothing and useOptionalCloudlet() returns null, so your children can render on the server. See SSR & Next.js.

CloudletProviderProps:

PropTypeDefaultDescription
controllerReactCloudletController | null—Required. The controller you created and own, or null until it exists.
childrenReactNode—Your application, including the <Toaster>.

useCloudlet

useCloudlet() returns the ReactCloudletController of the nearest CloudletProvider. Outside a provider, or while the provider's controller is null, it throws an Error that says so.

save-button.tsx
import { useCloudlet } from '@cloudlet/toast';

export function SaveButton() {
  const cloudlet = useCloudlet();
  return <button onClick={() => cloudlet.show({ title: 'Saved', kind: 'success' })}>Save</button>;
}

useOptionalCloudlet

useOptionalCloudlet() returns the controller of the nearest CloudletProvider, or null outside a provider and while its controller is null. Use it in components that also render before the controller exists, such as on the server.

save-button.tsx
import { useOptionalCloudlet } from '@cloudlet/toast';

export function SaveButton() {
  const cloudlet = useOptionalCloudlet();
  return (
    <button disabled={!cloudlet} onClick={() => cloudlet?.show({ title: 'Saved', kind: 'success' })}>
      Save
    </button>
  );
}

The signatures of the React exports are also exported as types: CloudletProviderComponent, UseCloudlet, UseOptionalCloudlet and ToasterComponent.