initial
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
import type { ConversationMember } from '@chat-app/shared/chat';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Props {
|
||||
typingUserIds: string[];
|
||||
members: ConversationMember[];
|
||||
}
|
||||
|
||||
export function TypingIndicator({ typingUserIds, members }: Props) {
|
||||
const { t } = useTranslation(['app']);
|
||||
if (typingUserIds.length === 0) return null;
|
||||
|
||||
const names = typingUserIds
|
||||
.map((id) => members.find((m) => m.userId === id)?.profile?.displayName)
|
||||
.filter((n): n is string => typeof n === 'string' && n.length > 0);
|
||||
|
||||
const text =
|
||||
names.length === 1
|
||||
? t('app:chats.typing_one', { name: names[0] })
|
||||
: t('app:chats.typing_many', { count: typingUserIds.length });
|
||||
|
||||
return (
|
||||
<div className="px-6 pb-1 pt-0 text-xs text-neutral-400">
|
||||
<span className="inline-flex items-center gap-2">
|
||||
<TypingDots />
|
||||
<span>{text}</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function TypingDots() {
|
||||
return (
|
||||
<span aria-hidden="true" className="inline-flex items-center gap-0.5">
|
||||
<span className="h-1 w-1 rounded-full bg-neutral-500 [animation:pulse_1.2s_ease-in-out_infinite]" />
|
||||
<span className="h-1 w-1 rounded-full bg-neutral-500 [animation:pulse_1.2s_ease-in-out_infinite] [animation-delay:0.15s]" />
|
||||
<span className="h-1 w-1 rounded-full bg-neutral-500 [animation:pulse_1.2s_ease-in-out_infinite] [animation-delay:0.3s]" />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user