Skip to main content

User Presence & Typing Indicators

Show user online status and real-time typing indicators for better engagement.

User Presence

Set Your Status

// Set online
await sdk.updatePresence({ status: 'online' });

// Set away
await sdk.updatePresence({ status: 'away' });

// Set custom status
await sdk.updatePresence({
status: 'online',
customStatus: 'In a meeting',
emoji: '📅',
});

Get User Status

const presence = await sdk.getUserPresence({ userId: 'user-123' });
console.log(presence.status); // 'online', 'away', 'busy', 'offline'
console.log(presence.lastSeenAt); // Timestamp

Subscribe to Presence Updates

sdk.on('user.presence', ({ userId, status, customStatus }) => {
console.log(`${userId} is now ${status}`);
});

React Component

function UserPresence({ userId }) {
const { status, customStatus, emoji } = usePresence({ userId });

return (
<div className="presence">
<div className={`status-dot status-${status}`} />
{customStatus && (
<span>
{emoji} {customStatus}
</span>
)}
</div>
);
}

Typing Indicators

Send Typing Event

// User starts typing
sdk.sendTypingIndicator({ channelId: 'ch-abc123', isTyping: true });

// User stops typing
sdk.sendTypingIndicator({ channelId: 'ch-abc123', isTyping: false });

// Auto-stop after 5s
sdk.sendTypingIndicator({ channelId: 'ch-abc123', timeout: 5000 });

Listen for Typing

sdk.on('typing.start', ({ userId, userName, channelId }) => {
console.log(`${userName} is typing in ${channelId}`);
});

sdk.on('typing.stop', ({ userId, channelId }) => {
console.log(`User stopped typing`);
});

Auto Typing (React)

function MessageInput({ channelId }) {
const [text, setText] = useState('');
const { sendTyping } = useTyping();

const handleChange = (e) => {
setText(e.target.value);

// Auto-send typing indicator
sendTyping({ channelId });
};

return (
<input
value={text}
onChange={handleChange}
placeholder="Type a message..."
/>
);
}

Typing Indicator UI

function TypingIndicator({ channelId }) {
const { typingUsers } = useTyping({ channelId });

if (typingUsers.length === 0) return null;

const names = typingUsers.map((u) => u.name);

return (
<div className="typing-indicator">
<div className="typing-dots">
<span></span>
<span></span>
<span></span>
</div>
<span>
{names.length === 1
? `${names[0]} is typing...`
: names.length === 2
? `${names[0]} and ${names[1]} are typing...`
: `${names.length} people are typing...`}
</span>
</div>
);
}

Best Practices

1. Debounce Typing Events

import { debounce } from 'lodash';

const sendTyping = debounce((channelId) => {
sdk.sendTypingIndicator({ channelId });
}, 300);

2. Stop Typing on Blur

<input
onFocus={() => sdk.sendTypingIndicator({ channelId, isTyping: true })}
onBlur={() => sdk.sendTypingIndicator({ channelId, isTyping: false })}
/>

3. Auto-Cleanup

useEffect(() => {
const timer = setTimeout(() => {
sdk.sendTypingIndicator({ channelId, isTyping: false });
}, 5000);

return () => clearTimeout(timer);
}, [text]);

Next Steps