ui: voice recorder pulse + TDS styling, wire mic denied error to input bar

- VoiceMessageRecorder recording dot now pulses (reuses pttLivePulse keyframe)
- Added data-voice-recorder / data-voice-rec-dot / data-voice-waveform attributes
  for TDS targeting: green pulsing dot, cyan waveform bars, subtle border in TDS dark
- Wire VoiceMessageRecorder onError to the same input-bar error display used by
  location errors (mic denied, media error surfaces to user instead of silent fail)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-24 00:30:12 -04:00
parent d58c445d74
commit 5d10afb7a6
3 changed files with 40 additions and 1 deletions
@@ -185,6 +185,7 @@ export function VoiceMessageRecorder({ onSend, onError }: VoiceRecorderProps) {
if (state === 'recording') {
return (
<Box
data-voice-recorder="recording"
alignItems="Center"
gap="200"
style={{
@@ -194,18 +195,21 @@ export function VoiceMessageRecorder({ onSend, onError }: VoiceRecorderProps) {
}}
>
<Box
data-voice-rec-dot
style={{
width: toRem(8),
height: toRem(8),
borderRadius: '50%',
background: 'var(--tc-danger-normal)',
flexShrink: 0,
animation: 'pttLivePulse 900ms ease-in-out infinite',
}}
/>
<Text size="T200" style={{ minWidth: toRem(32), fontVariantNumeric: 'tabular-nums' }}>
{formatDuration(durationMs)}
</Text>
<Box
data-voice-waveform
alignItems="Center"
gap="100"
style={{ height: toRem(20), overflow: 'hidden', flexShrink: 0 }}
+7 -1
View File
@@ -902,7 +902,13 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
<Icon src={Icons.SpaceGlobe} size="100" />
)}
</IconButton>
<VoiceMessageRecorder onSend={handleVoiceSend} />
<VoiceMessageRecorder
onSend={handleVoiceSend}
onError={(err) => {
setLocationError(err);
setTimeout(() => setLocationError(null), 4000);
}}
/>
<IconButton
onClick={submit}
variant="SurfaceVariant"