Files
glchat/web/src/components/voice/SoundboardNotice.tsx
T

53 lines
2.0 KiB
TypeScript
Raw Normal View History

import { useTranslation } from 'react-i18next';
import { useAuthorDirectory } from '@/components/chat/useAuthorDirectory';
import { useSoundboardStore } from '@/stores/soundboard';
/**
* Всплывающая подпись «{имя} включил звук {name}» (AGENT.md 7.13).
*
* Живёт в оболочке приложения — рядом с подсказкой о выключенном микрофоне,
* поэтому её видно с любого экрана. Гаснет сама: время жизни держит
* `stores/soundboard` (3 секунды), компонент только рисует текст.
*/
export function SoundboardNotice() {
const { t } = useTranslation();
const notice = useSoundboardStore((state) => state.notice);
const clear = useSoundboardStore((state) => state.clearNotice);
// Имя того, кто сыграл звук, резолвит общий справочник авторов.
const authors = useAuthorDirectory(
notice?.guildId ?? null,
notice === null ? [] : [notice.userId],
);
if (notice === null) {
return null;
}
return (
<div
role="status"
aria-live="polite"
data-testid="soundboard-notice"
className="pointer-events-auto fixed bottom-40 left-1/2 z-50 flex -translate-x-1/2 items-center gap-2 rounded-[var(--radius-md)] border border-border/60 bg-surface-2 px-3 py-2 text-sm shadow-[var(--shadow-3)]"
>
<span aria-hidden="true">🔊</span>
<p>
{t('voice.soundboard.playedBy', {
name: authors.resolve(notice.userId).name,
sound: notice.soundName,
})}
</p>
<button
type="button"
aria-label={t('common.dismiss')}
title={t('common.dismiss')}
onClick={clear}
className="rounded-[var(--radius-sm)] px-1 text-fg-muted transition-colors duration-[var(--duration-fast)] hover:bg-surface-3 hover:text-fg"
>
<span aria-hidden="true">✕</span>
</button>
</div>
);
}