ReactionBar is the picker a participant taps to send a reaction. ReactionOverlay renders reactions coming the other way — together they are the full round-trip. The bar auto-wires to the active room; pass onReact to use it without one.
Install
pnpm add @levelchat/react-components @levelchat/webBasic usage
Drop it inside a <LevelChatProvider> and every tap calls room.reactions.send(). The glass surface floats over the video stage; plain sits on a light card.
import { ReactionBar } from '@levelchat/react-components';
<ReactionBar surface="glass" />Pairing with ReactionOverlay
The two reaction components share one hook (useReactions), so wiring both gives you the complete loop — picker in, floating emoji out:
<div className="relative">
<ParticipantGrid />
<ReactionOverlay /> {/* incoming reactions */}
<div className="absolute bottom-4 inset-x-0 flex justify-center">
<ReactionBar surface="glass" /> {/* outgoing reactions */}
</div>
</div>Custom reaction set
The default set is six reactions. Pass reactions to curate your own — each entry needs an emoji and a human-readable label (the label drives the button's accessible name).
<ReactionBar
reactions={[
{ emoji: '👍', label: 'Agree' },
{ emoji: '🙌', label: 'Celebrate' },
{ emoji: '🤔', label: 'Thinking' },
]}
/>Headless hook
useReactions is the headless layer — build a wholly custom picker against its send action.
import { useReactions } from '@levelchat/react-components';
function MyPicker() {
const { send, supported } = useReactions();
if (!supported) return null;
return <button onClick={() => send('🎉')}>Celebrate</button>;
}Accessibility
- The bar is a
role="group"labelled "Send a reaction". - Each button has a real
aria-label("React with Applause") so the reaction is announced by name, never as a bare emoji glyph. - The tap-pop animation is suppressed under `prefers-reduced-motion`.
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
reactions | ReactionChoice[] | DEFAULT_REACTIONS | The emoji + label pairs to render. |
surface | 'glass' | 'plain' | glass | Translucent over-video bar, or opaque on-surface card. |
disabled | boolean | false | Disable every button. |
onReact | (emoji: string) => void | — | Called on every tap, alongside the room send. |