@fieldstate/atrium-sdk
v0.2.0
Published
Fieldstate ERM chat widget — embeddable 'Start a project' conversation powered by Monday.
Readme
@fieldstate/atrium-sdk
Embeddable chat widget for Fieldstate. Powered by Monday, the Fieldstate concierge agent.
Installation
npm install @fieldstate/atrium-sdkReact 18 or 19 is required as a peer dependency.
Usage
Import the component and its stylesheet:
import { ERMWidget } from '@fieldstate/atrium-sdk';
import '@fieldstate/atrium-sdk/style.css';The widget fills whatever container you place it in — it has no fixed positioning of its own. Mount and unmount it to control visibility:
export function MyPage() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>Start a project</button>
{open && (
<div className="my-sidebar">
<ERMWidget
gatewayUrl="https://api.fieldstate.io/api/gateway"
onClose={() => setOpen(false)}
/>
</div>
)}
</>
);
}The widget auto-starts the conversation when it mounts. When the conversation ends or the close button is clicked, onClose fires so you can unmount it.
Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| gatewayUrl | string | Yes | Base URL of the erm-gateway API (no trailing slash), e.g. https://api.fieldstate.io/api/gateway. |
| onClose | () => void | No | Called when the close button is clicked or the conversation ends. |
| className | string | No | Extra CSS class applied to the widget root div. |
Headless usage
For full control over layout and open/close behaviour, use the exported hook and sub-components directly:
import {
useConversation,
ChatMessage,
ChatInput,
TypingIndicator,
} from '@fieldstate/atrium-sdk';
import '@fieldstate/atrium-sdk/style.css';
export function SidebarConversation({ onClose }: { onClose: () => void }) {
const { status, messages, sendMessage } = useConversation({
gatewayUrl: 'https://api.fieldstate.io/api/gateway',
autoStart: true,
});
return (
<div className="my-sidebar-layout">
<MyHeader onClose={onClose} /> {/* your own header component */}
<div className="messages">
{messages.map((m) => <ChatMessage key={m.id} message={m} />)}
{status === 'sending' && <TypingIndicator />}
</div>
<ChatInput onSend={sendMessage} disabled={status !== 'active'} />
</div>
);
}Use <ChatPanel> when you want the full panel UI in your own container. Use the individual primitives when you want a completely custom shell — your own header, your own message list layout, your own input styling.
Exported primitives
| Export | Type | Description |
|--------|------|-------------|
| useConversation(opts) | Hook | Manages conversation state. Returns { status, conversationId, messages, error, start, sendMessage, reset }. |
| ChatPanel | Component | Full panel UI (header, messages, input). Fills its container. |
| ChatMessage | Component | Single message bubble. |
| ChatInput | Component | Textarea + send button. |
| TypingIndicator | Component | Animated typing dots. |
Theming
All colours and geometry are controlled via CSS custom properties. No defaults are provided — all values must be set by the consuming application:
:root {
--atrium-primary: /* primary action colour */
--atrium-primary-fg: /* text on primary colour */
--atrium-bg: /* panel background */
--atrium-surface: /* input and secondary surface */
--atrium-border: /* borders and dividers */
--atrium-text: /* primary text */
--atrium-muted: /* secondary / placeholder text */
--atrium-agent-bubble: /* agent message bubble background */
--atrium-agent-bubble-fg: /* agent message bubble text */
--atrium-radius: /* panel and bubble border radius */
--atrium-font: /* font family */
}Escape key
The widget does not handle the Escape key itself. Most drawer and modal components already close on Escape — if you're placing the widget in a plain div, wire it up in your container:
useEffect(() => {
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') setOpen(false); };
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, []);TypeScript
import type {
ERMWidgetProps,
GatewayMessage,
ConversationStatus,
UseConversationOptions,
UseConversationResult,
ChatPanelProps,
ChatMessageProps,
ChatInputProps,
} from '@fieldstate/atrium-sdk';