Skip to main content

Feedbacks (Toast)

  • Component overview: Feedback notification component for displaying operation results or system status to users. In Figma, both Message (simple message) and Alert (with title) are Toast variants. Also exported as Toast.
  • Current status: Covers Message / Alert × Action Button × five styles: Info, Success, Warning, Error, and AI Feedback.
  • Implementation note: Self-contained toast manager with no third-party dependency. Toaster subscribes to the store and renders toasts into a portal on body; Figma design tokens are applied directly via Tailwind token classes. Toaster has closeButton enabled by default.
  • Figma spec: Feedbacks / Alerts

Basic Usage​

Simplest form: Message (simple message), corresponding to Figma Description=False.

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast('A short and clear sentence is perfect.')}>
      Default
    </Button>
    <Button variant="secondary" onClick={() => toast.info('A short and clear sentence is perfect.')}>
      Info
    </Button>
    <Button variant="secondary" onClick={() => toast.success('A short and clear sentence is perfect.')}>
      Success
    </Button>
    <Button variant="secondary" onClick={() => toast.warning('A short and clear sentence is perfect.')}>
      Warning
    </Button>
    <Button variant="secondary" onClick={() => toast.error('A short and clear sentence is perfect.')}>
      Error
    </Button>
    <Button variant="secondary" onClick={() => toast.aiFeedback('A short and clear sentence is perfect.')}>
      AI Feedback
    </Button>
  </div>,
)

AI Feedback​

A dedicated style for AI-generated feedback: white background with an AI gradient border and a multicolor gradient icon, corresponding to Figma Style=AI Feedback.

Message​

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast.aiFeedback('A short and clear sentence is perfect.')}>
      AI Message
    </Button>
    <Button
      variant="secondary"
      onClick={() =>
        toast.aiFeedback('A short and clear sentence is perfect.', {
          action: { label: 'Button', onClick: () => {} },
        })
      }
    >
      AI Message + Action
    </Button>
  </div>,
)

Alert​

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button
      variant="secondary"
      onClick={() =>
        toast.aiFeedback('Title', { description: 'A short and clear sentence is perfect.' })
      }
    >
      AI Alert
    </Button>
    <Button
      variant="secondary"
      onClick={() =>
        toast.aiFeedback('Title', {
          description: 'A short and clear sentence is perfect.',
          action: { label: 'Confirm', onClick: () => {} },
        })
      }
    >
      AI Alert + Action
    </Button>
    <Button
      variant="secondary"
      onClick={() =>
        toast.aiFeedback('Title', {
          description: 'A short and clear sentence is perfect.',
          action: { label: 'Confirm', onClick: () => {} },
          cancel: { label: 'Cancel', onClick: () => {} },
        })
      }
    >
      AI Alert + Action + Cancel
    </Button>
  </div>,
)

Main Matrix​

The current spec acceptance scope is Style × Description × Action Button. The doc site prioritizes the most essential visible combinations.

Message / Alert​

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast.info('Message')}>Info Message</Button>
    <Button
      variant="secondary"
      onClick={() => toast.info('Alert Title', { description: 'A short and clear sentence is perfect.' })}
    >
      Info Alert
    </Button>
    <Button variant="secondary" onClick={() => toast.success('Message')}>Success Message</Button>
    <Button
      variant="secondary"
      onClick={() => toast.success('Alert Title', { description: 'A short and clear sentence is perfect.' })}
    >
      Success Alert
    </Button>
  </div>,
)

With Title (Alert Form)​

Passing description switches to the Alert layout, corresponding to Figma Description=True.

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast.info('Title', { description: 'A short and clear sentence is perfect.' })}>
      Info
    </Button>
    <Button variant="secondary" onClick={() => toast.success('Title', { description: 'A short and clear sentence is perfect.' })}>
      Success
    </Button>
    <Button variant="secondary" onClick={() => toast.warning('Title', { description: 'A short and clear sentence is perfect.' })}>
      Warning
    </Button>
    <Button variant="secondary" onClick={() => toast.error('Title', { description: 'A short and clear sentence is perfect.' })}>
      Error
    </Button>
  </div>,
)

With Action Button​

Corresponds to Figma Action Button=True.

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast.info('A short and clear sentence is perfect.', {
      action: { label: 'Button', onClick: () => {} },
    })}>
      Message + Action
    </Button>
    <Button variant="secondary" onClick={() => toast.error('Title', {
      description: 'A short and clear sentence is perfect.',
      action: { label: 'Button', onClick: () => {} },
      cancel: { label: 'Button', onClick: () => {} },
    })}>
      Alert + Actions
    </Button>
  </div>,
)

Additional Capabilities​

Programmatic Control​

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => {
      const id = toast.loading('Loading...')
      setTimeout(() => toast.success('Done!', { id }), 2000)
    }}>
      Promise simulation
    </Button>
    <Button variant="secondary" onClick={() => toast.dismiss()}>
      Dismiss all
    </Button>
  </div>,
)

Long Unbreakable Text​

Text with no natural break opportunity — file names, URLs, tokens — wraps inside the 420px width instead of overflowing. Both the title and the description use overflow-wrap: anywhere.

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => toast.success('已将 "320X240(1)_rmv8_904kbps_15fps_rma_44100hz_96.5kbps" 移动至 "cccc"')}>
      Long file name (Message)
    </Button>
    <Button variant="secondary" onClick={() => toast.info('Upload finished', {
      description: 'https://example.com/a/very/long/path/320X240(1)_rmv8_904kbps_15fps_rma_44100hz_96.5kbps.mp4',
    })}>
      Long URL (Alert)
    </Button>
  </div>,
)

Feedbacks Namespace​

The Feedbacks namespace is equivalent to importing toast / Toaster directly and is suitable for unified usage under the patterns semantic.

Result
Loading...
Live Editor
render(
  <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}>
    <Button variant="secondary" onClick={() => Feedbacks.toast.info('Namespaced message')}>
      Feedbacks.toast.info
    </Button>
  </div>,
)

Size Spec​

Typography​

FormTokenFont SizeLine HeightFont Weight
Message titleFont-Size-Body / Line-Height-Body14px—Regular (400)
Alert titleFont-Size-H3 / Line-Height-H318px—SemiBold (600)
DescriptionFont-Size-Body / Line-Height-Body14px—Regular (400)

Figma Variant Mapping​

Figma formFigma attributestoast API
MessageDescription=False, Action=Falsetoast.info('msg')
Message + ActionDescription=False, Action=Truetoast.info('msg', { action })
AlertDescription=True, Action=Falsetoast.info('title', { description })
Alert + ActionsDescription=True, Action=Truetoast.info('title', { description, action, cancel })

Color Tokens​

VariantOverlay/icon color
infoTemplate Community/Icon/Sky#528fcc
successTemplate Community/Icon/Moss#4cbf69
warningTemplate Community/Icon/Mustard#bfa043
errorTemplate Community/Icon/Coral#cc5266

Container​

PropertyTokenValue
Left paddingSpacing_1616px
Right paddingSpacing_1212px
Vertical paddingSpacing_88px
Border radiusRadius_55px
ShadowEffects/Shadow/Default0 0 32px rgba(0,0,0,0.1)
Overlay opacity—18% (before: pseudo-element)

Props​

Toaster​

Toast host container — place a single instance at the app root.

PropTypeDefaultDescription
positionToastPosition'top-center'Toast position (top/bottom × left/center/right)
closeButtonbooleantrueContainer default for the close button; can be overridden per toast
durationnumber4000Default auto-dismiss duration (ms); overridable per toast
visibleToastsnumber3Number of fully visible toasts when stacked
classNamestring—Custom container class
styleCSSProperties—Custom container inline style

toast functions​

MethodDescription
toast('msg')Default Toast
toast.info('msg')Info variant
toast.success('msg')Success variant
toast.warning('msg')Warning variant
toast.error('msg')Error variant
toast('title', { description })With title (Alert form)
toast.aiFeedback('msg')AI Feedback variant
toast.loading('msg')Loading variant (no auto-dismiss by default)
toast('msg', { action: { label, onClick } })With action button
toast('msg', { closeButton: true })Force-show close button (overrides container & shape rules)
toast('msg', { closeButton: false })Force-hide close button
toast('msg', { id })Reuse an existing id to update in place (e.g. loading → success)
toast.dismiss(id?)Dismiss specific or all toasts

Feedbacks​

PropTypeDefaultDescription
ToasterComponentType<ToasterProps>-Toast container component
toasttypeof toast-Trigger function under the namespace

Usage Constraints​

  • <Toaster /> must be placed in the application root component — only one instance is needed globally.
  • Toast position, duration, and other settings are configured via <Toaster> props or the second argument of toast().
  • Variant icons (info/success/warning/error/aiFeedback) are provided by the design system via the icon contract; default has no icon and loading shows a spinner.