@clubmed/usg-chat-ui
v1.8.0
Published
Reusable ClubMed USG chat experience
Readme
Reusable chat experience extracted from the ClubMed USG project. Everything is published as ESM-only output so it can be consumed by any Vite/Next/CRA-style React host.
Installation
npm install @clubmed/usg-chat-uiProvider setup
Drop the ready-made <Chat /> organism into your page and pass the minimal props (apiUrl, accessToken, user, optional logout). Internally it wires the chat provider, HTTP client, and feature contexts so you don’t need to juggle multiple wrappers.
import type {ChatUser} from "@clubmed/usg-chat-ui";
import {Chat} from "@clubmed/usg-chat-ui/organisms/Chat";;
const session = useSession(); // host-specific auth hook
export function ChatPanel() {
const user: ChatUser | null = session
? {
userId: session.userId,
userName: session.name,
userEmail: session.email,
}
: null;
return (
<ChatProvider>
apiUrl={process.env.API_URL!}
accessToken={session.accessToken}
user={user}
logout={session.logout}
>
<Chat />
</ChatProvider>
);
}Configuration keys
| Field | Description |
|----------------------|-----------------------------------------------------------------------------------------|
| config.apiUrl | Base URL for server-to-server requests (e.g. https://backend.internal). |
| config.fetcher | Optional custom fetch implementation (for SSR polyfills, logging, etc.). |
| config.accessToken | Latest access token. When omitted/null, requests are sent anonymously. |
| config.user | Lightweight { userId, userName, userEmail } object propagated via headers. |
| logout | Optional handler wired into settings so users can disconnect directly from the chat UI. |
If you need to customize HTTP transport or headers, provide a fetcher override or extend the HTTP client directly—ChatProvider keeps the config surface minimal (apiUrl, fetcher, accessToken, user).
Labels & Accessibility
The chat UI exposes a labels prop on <Chat /> so hosts can override empty‑state copy, greeting templates, and every aria-label used throughout the experience without editing component logic.
<Chat
labels={{
greetingTemplate: "Hola {{firstName}} 👋",
emptyStateTitle: "¡Bienvenido a tu copiloto!",
chatSettingsButtonAriaLabel: "Preferencias",
}}
/>Under the hood, the ChatLabelsProvider and useChatLabels() hook distribute these strings to all molecules. The hook exposes two helpers:
get(key, fallback)→ returns a plain string, falling back to the provided default when the host didn’t override it.p(key, fallback, values)→ interpolates templates (e.g.{{firstName}}) and trims whitespace. Returnsundefinedwhen the final string is empty.
Available label keys
| Key | Purpose / Example |
|----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------|
| greetingTemplate | Template for the empty-state greeting ("Bonjour {{firstName}} 👋"). |
| emptyStateTitle / emptyStateDescription | Marketing copy for the empty state. |
| assistantThinkingIndicator | Pulsing text while the assistant is streaming. |
| chatSettingsButtonAriaLabel | Settings button aria label. |
| sidebarOpenHistoryAriaLabel, conversationRefreshAriaLabel, conversationCloseHistoryAriaLabel | Sidebar toggle & controls. |
| messageCopyAriaLabel, messageRegenerateAriaLabel, messageOpenCanvasAriaLabel | Message action buttons (aria). |
| messageCopyButtonText, messageCopySuccessText, messageRegenerateButtonText, messageOpenCanvasButtonText | Visible labels beside those buttons. |
| messageThumbsUpAriaLabel, messageThumbsDownAriaLabel, messageCloseFeedbackAriaLabel | Feedback modal controls (aria). |
| messageFeedbackPositiveTitle, messageFeedbackNegativeTitle, messageFeedbackPromptText, messageFeedbackTextareaPlaceholder, messageFeedbackSkipButtonText, messageFeedbackSubmitButtonText, messageFeedbackSubmittingText | Copy rendered inside the feedback modal. |
| messageCopyToastTitle, messageCopyToastDescription, messageCopyErrorTitle, messageCopyErrorDescription, messageFeedbackToastTitle, messageFeedbackToastDescription, messageFeedbackToastErrorTitle, messageFeedbackToastErrorDescription | Toast notifications for copy/feedback flows. |
| canvasReduceAriaLabel, canvasExpandAriaLabel, canvasCloseAriaLabel | Canvas panel controls. |
| branchPreviousAriaLabel, branchNextAriaLabel | Multi-branch navigation buttons. |
| promptSubmitAriaLabel, promptComposerPlaceholder | Prompt composer button aria + placeholder text. |
Implementation convention: All new user-facing strings or aria labels must use
useChatLabels()(const {get, p} = useChatLabels();) instead of hard-coded literals. Declare the key insideChatLabelsConfigwith a short JSDoc example, then consume it viaget/pwith a sensible fallback so the UI remains resilient when a host doesn’t override that value yet.
Storybook
Storybook v10 is configured at the workspace root (usg-ui/.storybook). Run yarn storybook from usg-ui/ to browse molecules and verify appearance tokens in isolation. The build output (storybook-static) can be published alongside the npm package for visual regression if desired.
