Marble UI
← Components

Reaction Bar

Preview: Default

Message reactions: toggle chips with live counts, plus an emoji picker to add new ones.

Import

import { ReactionBar } from '@marbleui/ui'

Props

<ReactionBar>

PropTypeDefaultDescription
onChange *required(next: Reaction[]) => void—
reactions *requiredReaction[]—
classNamestring—

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitive: React Aria ToggleButton. Follow the primitive's docs for the full keyboard map.

Usage notes

Emoji reaction chips with counts, plus an “Add reaction” picker, for messages and comments between people. To rate an AI reply use the thumbs in MessageActions.

// comment.reactions: [{ emoji: '🎉', label: 'tada', count: 4, mine: true }, { emoji: '👀', label: 'eyes', count: 2 }]
<ReactionBar reactions={comment.reactions} onChange={(next) => saveReactions(comment.id, next)} />
  • Controlled only: onChange hands back the whole next array and nothing is saved for you. mine marks the current user’s reactions and drives the selected state.
  • Pressing a chip toggles your reaction, and a chip whose count reaches 0 disappears. Picking an emoji you already reacted with from the picker keeps it.
  • Each chip is read as “tada, 4 reactions, including you”, built from label. Reactions added from the picker take their label from the picker’s emoji name (“tada”), falling back to the character.
  • Put it in the message body, not in ChatMessage’s actions, which hide until hover.
Example source · show
import { useState } from 'react'
import { Avatar } from '../avatar'
import { ReactionBar, type Reaction } from './reaction-bar'

function Demo() {
  const [r, setR] = useState<Reaction[]>([{ emoji: '🎉', label: 'tada', count: 4, mine: true }, { emoji: '👀', label: 'eyes', count: 2 }, { emoji: '🚀', label: 'rocket', count: 1 }])
  return (
    <div className="flex w-96 gap-3 rounded-xl border border-border bg-surface p-4">
      <Avatar size="sm" name="Ada Park" />
      <div className="flex flex-col gap-2"><p className="text-sm text-fg"><span className="font-medium">Ada Park</span> · Shipped the new data grid 🎉</p><ReactionBar reactions={r} onChange={setR} /></div>
    </div>
  )
}
export const styles = { Default: Demo }

Source: packages/ui/src/reaction-bar/reaction-bar.tsx

Catalog

Category
ai-agents
Priority
Extra
Primitive
composed
React Aria
ToggleButtonGroup
Base UI
Toggle Group