Files
dumpsterChat/web/src/components/ReactionBar.tsx
T
hobokenchicken b3b5ff495d fix: DM message ordering, consolidate input toolbar, add rich text/WYSIWYG, file upload with drag-drop
- Fix DM backend ListMessages to use DESC + reverse (match channel handler)
- Remove spurious .reverse() from frontend message/conversation stores
- Create shared MessageInput component with Slack-style single toolbar row
- Add file upload via + button with progress bar and drag-and-drop
- Add markdown/rich text toggle with full WYSIWYG block formatting
  (lists, blockquotes, links, headings, code blocks)
- Add frontend+backend security for file uploads (extension + content-type guards)
2026-07-06 17:33:20 +00:00

56 lines
1.4 KiB
TypeScript

import { useState } from 'react';
interface Reaction {
emoji: string;
count: number;
users: string[];
reacted: boolean;
}
interface ReactionBarProps {
reactions: Reaction[];
onToggle: (emoji: string, isReacted: boolean) => Promise<void>;
}
export function ReactionBar({ reactions, onToggle }: ReactionBarProps) {
const [loading, setLoading] = useState(false);
const toggleReaction = async (emoji: string) => {
if (loading) return;
setLoading(true);
try {
const existing = reactions.find(r => r.emoji === emoji);
await onToggle(emoji, !!existing?.reacted);
} catch (error) {
console.error('Failed to toggle reaction:', error);
} finally {
setLoading(false);
}
};
if (reactions.length === 0) return null;
return (
<div className="flex flex-wrap gap-1 mt-1">
{reactions.map((reaction) => (
<button
key={reaction.emoji}
onClick={() => toggleReaction(reaction.emoji)}
disabled={loading}
className={`
px-1.5 py-0.5 text-xs font-mono border rounded-sm
transition-colors duration-100
${reaction.reacted
? 'border-gb-orange bg-gb-bg-t text-gb-orange'
: 'border-gb-bg-t bg-gb-bg-s text-gb-fg-f hover:border-gb-fg-f'
}
`}
title={reaction.users.join(', ')}
>
{reaction.emoji} {reaction.count}
</button>
))}
</div>
);
}