LevelChatLevelChatDocs
ReactionBar

Components

ReactionBar

The send half of the reaction surface — a row of emoji buttons.

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/web

Basic 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.

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

PropTypeDefaultNotes
reactionsReactionChoice[]DEFAULT_REACTIONSThe emoji + label pairs to render.
surface'glass' | 'plain'glassTranslucent over-video bar, or opaque on-surface card.
disabledbooleanfalseDisable every button.
onReact(emoji: string) => voidCalled on every tap, alongside the room send.