Skip to content
Median
Esc
↑↓navigate↵open⌘Jpreview
On this page

Components

Pick a component, install the package, and find every export of @mediansh/widget.

Install

npm install @mediansh/widget
pnpm add @mediansh/widget
yarn add @mediansh/widget
bun add @mediansh/widget
import "@mediansh/widget/styles.css";

Import the stylesheet once. The peer dependencies are react and react-dom 18 or 19, and convex 1.25 or newer below 2. The package is marked "use client", so a Next.js server component can render it directly. Keys, environment variables and CSP are on Install the widget.

Which component

Component Renders Results go to Without React
MedianSupport A launcher in the corner that opens a chat panel A conversation in Inbox mountMedianSupport()
MedianSupportModal The same launcher, with the panel centered over the page A conversation in Inbox mountMedianSupportModal()
MedianContactForm A form on your page with email, message and your own fields Inbox. It joins the visitor’s open conversation, or starts one mountMedianContactForm()
MedianFeedback A note box that opens from your own trigger or from code Signal, filed as a bug or a suggestion mountMedianFeedback()

Mount functions take the component’s props as one object, plus a target for the contact form. See Without React.

Keys

Every component takes one of two props.

Prop Value Use it when
apiKey The median_pk_ id from publicKeyFromMedianKey(MEDIAN_KEY) Visitors are anonymous, or you pass user yourself
identity The path of a route built with medianIdentity Your session lives on the server. The route returns the key and the signed in user

Pass both to render on apiKey at once and pick up the user when the route answers. With neither, the component prints an error. See Identity.

Shared rules

  • Mount one support panel per page, MedianSupport or MedianSupportModal. Two share one open state and open together.
  • Mount one MedianFeedback per page, for the same reason. Its open state is separate from the support panel’s.
  • Components with the same key share one visitor. A chat message, a contact form send and a feedback note from one browser belong to the same customer. The browser keeps that visitor in localStorage.
  • An error inside a component hides that component and prints to the console. Your page keeps running.
  • Component text is in English, with no locale prop. The agent’s reply language is on Built-in abilities.
  • Colors come from your page’s CSS variables. See Theming.

Exports

Export Kind Documented on
MedianSupport Component Support widget
MedianSupportModal Component Support modal
MedianContactForm Component Contact form
MedianFeedback Component Feedback panel
mountMedianSupport, mountMedianSupportModal, mountMedianContactForm, mountMedianFeedback Function Without React
medianSupport, medianFeedback Object Control from code
useMedianSupport, useMedianFeedback Hook Control from code
useMedianContact Hook Contact form
sendMedianContact Function Contact form
reportError Function Crash reports
useCanReportError Hook Crash reports
Type Documented on
MedianSupportProps, MedianUser, SupportLauncherKind Support widget
MedianSupportModalProps Support modal
MedianContactFormProps, MedianContactField, MedianContactFieldKind, MedianContactMessage, MedianContactOptions, MedianContactControl, UseMedianContactOptions Contact form
MedianFeedbackProps Feedback panel
MedianSupportControl, MedianFeedbackControl Control from code
MedianSupportInstance, MedianSupportModalInstance, MedianContactFormInstance, MedianContactFormMountOptions, MedianFeedbackInstance Without React
MedianErrorReportOptions, MedianErrorReportOutcome Crash reports
MedianDiagnostics Context and diagnostics

The Portal* names from @tryportal/widget, such as PortalSupport, still work. They will be removed in a later major version.

Accessibility

The support panel and the modal handle these for you.

  • Every icon button has a label, such as Close support and Send message.
  • The launcher is labelled Chat with Acme support, plus the unread count when there is one.
  • The thread is a log region with aria-live="polite", so new replies are announced. The unread card is a polite status region.
  • Agent avatars are announced by name.
  • The closed panel is inert, so nothing in it takes focus.
  • Escape closes the panel. Focus moves into the panel on open. On close it returns to the launcher, or with launcher="hidden" to the element that opened the panel.

Was this page helpful?