Skip to content

Commit 4f7bc8c

Browse files
fix: transcript z index (#47)
* rename avatar tile video tile * fix transcript padding * fix transcript z-index and initial empty actionbar * fix action bar buttons pop-in during init * remove unecessary VideoTile component
1 parent a17be87 commit 4f7bc8c

File tree

7 files changed

+72
-129
lines changed

7 files changed

+72
-129
lines changed

components/embed-popup/action-bar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ export function ActionBar({
8585
<div
8686
aria-label="Voice assistant controls"
8787
className={cn(
88-
'bg-background border-separator1 dark:border-separator1 relative z-20 mx-2 mb-1 flex flex-col rounded-[24px] border p-1 drop-shadow-md',
88+
'bg-background border-separator1 dark:border-separator1 relative z-20 mx-2 mb-2 flex flex-col rounded-[24px] border p-1 drop-shadow-md',
8989
className
9090
)}
9191
{...props}

components/embed-popup/popup-view.tsx

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { AnimatePresence, motion } from 'motion/react';
66
import {
77
type AgentState,
88
type TrackReference,
9+
VideoTrack,
910
useLocalParticipant,
1011
useRoomContext,
1112
useTracks,
@@ -14,7 +15,6 @@ import {
1415
import { ActionBar } from '@/components/embed-popup/action-bar';
1516
import { AudioVisualizer } from '@/components/embed-popup/audio-visualizer';
1617
import { Transcript } from '@/components/embed-popup/transcript';
17-
import { AvatarTile } from '@/components/livekit/avatar-tile';
1818
import useChatAndTranscription from '@/hooks/use-chat-and-transcription';
1919
import { useDebugMode } from '@/hooks/useDebug';
2020
import type { AppConfig, EmbedErrorDetails } from '@/lib/types';
@@ -109,8 +109,25 @@ export const PopupView = ({
109109

110110
return (
111111
<div ref={ref} inert={disabled} className="flex h-full w-full flex-col overflow-hidden">
112-
<div className="relative flex h-full shrink-1 grow-1 flex-col py-1">
113-
<div className="absolute top-0 left-0 h-full w-1/2" />
112+
<div className="relative flex h-full shrink-1 grow-1 flex-col">
113+
{/* Transcript */}
114+
<TranscriptMotion
115+
initial={{
116+
y: 10,
117+
opacity: 0,
118+
}}
119+
animate={{
120+
y: chatOpen ? 0 : 10,
121+
opacity: chatOpen ? 1 : 0,
122+
}}
123+
transition={{
124+
type: 'spring',
125+
duration: 0.5,
126+
bounce: 0,
127+
}}
128+
messages={messages}
129+
/>
130+
114131
{/* Audio Visualizer */}
115132
<AnimatePresence>
116133
{!agentVideoTrack && (
@@ -133,7 +150,7 @@ export const PopupView = ({
133150
}}
134151
transition={TILE_TRANSITION}
135152
className={cn(
136-
'bg-bg1 dark:bg-bg2 pointer-events-none absolute z-10 flex aspect-square w-64 items-center justify-center rounded-2xl border border-transparent transition-colors',
153+
'bg-bg1 dark:bg-bg2 pointer-events-none absolute flex aspect-square w-64 items-center justify-center rounded-2xl border border-transparent transition-colors',
137154
chatOpen && 'border-separator1 dark:border-separator2 drop-shadow-2xl'
138155
)}
139156
>
@@ -172,9 +189,14 @@ export const PopupView = ({
172189
duration: 1,
173190
},
174191
}}
175-
className="pointer-events-none absolute inset-1 z-10 overflow-hidden rounded-[24px]"
192+
className="border-separator1 dark:border-separator2 pointer-events-none absolute inset-1 drop-shadow-lg/20"
176193
>
177-
<AvatarTile videoTrack={agentVideoTrack} className="h-full bg-black object-cover" />
194+
<VideoTrack
195+
trackRef={agentVideoTrack}
196+
width={agentVideoTrack?.publication.dimensions?.width ?? 0}
197+
height={agentVideoTrack?.publication.dimensions?.height ?? 0}
198+
className="h-full rounded-[24px] bg-black object-cover"
199+
/>
178200
</motion.div>
179201
)}
180202
</AnimatePresence>
@@ -198,11 +220,13 @@ export const PopupView = ({
198220
left: isCameraEnabled || isScreenShareEnabled ? '37.5%' : '50%',
199221
}}
200222
transition={TILE_TRANSITION}
201-
className="pointer-events-none absolute z-10 overflow-hidden rounded-md"
223+
className="border-separator1 dark:border-separator2 pointer-events-none absolute drop-shadow-lg/20"
202224
>
203-
<AvatarTile
204-
videoTrack={agentVideoTrack}
205-
className="aspect-square w-[70px] bg-black object-cover"
225+
<VideoTrack
226+
trackRef={agentVideoTrack}
227+
width={agentVideoTrack?.publication.dimensions?.width ?? 0}
228+
height={agentVideoTrack?.publication.dimensions?.height ?? 0}
229+
className="aspect-square w-[70px] rounded-md bg-black object-cover"
206230
/>
207231
</motion.div>
208232
)}
@@ -218,7 +242,6 @@ export const PopupView = ({
218242
opacity: 0,
219243
right: '12px',
220244
top: '346px',
221-
222245
transformOrigin: 'center bottom',
223246
}}
224247
animate={{
@@ -233,41 +256,38 @@ export const PopupView = ({
233256
opacity: 0,
234257
}}
235258
transition={TILE_TRANSITION}
236-
className="pointer-events-none absolute z-10 overflow-hidden rounded-md"
259+
className="border-separator1 dark:border-separator2 pointer-events-none absolute drop-shadow-lg/20"
237260
>
238-
<AvatarTile
239-
videoTrack={cameraTrack || screenShareTrack}
240-
className="aspect-square w-[70px] bg-black object-cover"
261+
<VideoTrack
262+
trackRef={cameraTrack || screenShareTrack}
263+
width={(cameraTrack || screenShareTrack)?.publication.dimensions?.width ?? 0}
264+
height={(cameraTrack || screenShareTrack)?.publication.dimensions?.height ?? 0}
265+
className="aspect-square w-[70px] rounded-md bg-black object-cover"
241266
/>
242267
</motion.div>
243268
)}
244269
</AnimatePresence>
245270

246-
{/* Transcript */}
247-
<TranscriptMotion
271+
{/* Action Bar */}
272+
<motion.div
248273
initial={{
249-
y: 10,
250274
opacity: 0,
275+
translateY: 8,
251276
}}
252277
animate={{
253-
y: chatOpen ? 0 : 10,
254-
opacity: chatOpen ? 1 : 0,
278+
opacity: sessionStarted ? 1 : 0,
279+
translateY: sessionStarted ? 0 : 8,
255280
}}
256281
transition={{
257-
type: 'spring',
258-
duration: 0.5,
259-
bounce: 0,
282+
delay: 0.5,
260283
}}
261-
messages={messages}
262-
className="relative z-30"
263-
/>
264-
265-
{/* Action Bar */}
266-
<ActionBar
267-
onSendMessage={onSendMessage}
268-
capabilities={capabilities}
269-
onChatOpenChange={setChatOpen}
270-
/>
284+
>
285+
<ActionBar
286+
capabilities={capabilities}
287+
onSendMessage={onSendMessage}
288+
onChatOpenChange={setChatOpen}
289+
/>
290+
</motion.div>
271291
</div>
272292
</div>
273293
);

components/embed-popup/transcript.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ export function Transcript({
5656
<div
5757
ref={handleRef}
5858
className={cn(
59-
'scrollbar-on-hover flex grow flex-col overflow-x-hidden overflow-y-scroll py-2 pr-3 pl-1',
59+
'scrollbar-on-hover flex grow flex-col overflow-x-hidden overflow-y-scroll py-3 pr-3 pl-1',
6060
'[mask-image:linear-gradient(0deg,rgba(0,0,0,0.2)_0%,rgba(0,0,0,1)_5%,rgba(0,0,0,1)_95%,rgba(0,0,0,0)_100%)]',
6161
className
6262
)}
6363
>
64-
<div className="flex flex-1 flex-col justify-end gap-2 pt-12">
64+
<div className="flex flex-1 flex-col justify-end gap-2 pt-16">
6565
<AnimatePresence>
6666
{messages.map((message) => (
6767
<ChatEntryMotion

components/livekit/agent-tile.tsx

Lines changed: 0 additions & 35 deletions
This file was deleted.

components/livekit/avatar-tile.tsx

Lines changed: 0 additions & 23 deletions
This file was deleted.

components/livekit/video-tile.tsx

Lines changed: 0 additions & 23 deletions
This file was deleted.

hooks/use-agent-control-bar.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,26 @@ export interface UseAgentControlBarReturn {
3434
handleVideoDeviceChange: (deviceId: string) => void;
3535
}
3636

37-
export function useAgentControlBar(props: UseAgentControlBarProps = {}): UseAgentControlBarReturn {
38-
const { controls, saveUserChoices = true } = props;
39-
const visibleControls = {
40-
leave: true,
41-
...controls,
42-
};
37+
export function useAgentControlBar({
38+
controls,
39+
saveUserChoices = true,
40+
onDeviceError,
41+
}: UseAgentControlBarProps = {}): UseAgentControlBarReturn {
4342
const { microphoneTrack, localParticipant } = useLocalParticipant();
4443
const publishPermissions = usePublishPermissions();
4544
const room = useRoomContext();
4645

4746
const microphoneToggle = useTrackToggle({
4847
source: Track.Source.Microphone,
49-
onDeviceError: (error) => props.onDeviceError?.({ source: Track.Source.Microphone, error }),
48+
onDeviceError: (error) => onDeviceError?.({ source: Track.Source.Microphone, error }),
5049
});
5150
const cameraToggle = useTrackToggle({
5251
source: Track.Source.Camera,
53-
onDeviceError: (error) => props.onDeviceError?.({ source: Track.Source.Camera, error }),
52+
onDeviceError: (error) => onDeviceError?.({ source: Track.Source.Camera, error }),
5453
});
5554
const screenShareToggle = useTrackToggle({
5655
source: Track.Source.ScreenShare,
57-
onDeviceError: (error) => props.onDeviceError?.({ source: Track.Source.ScreenShare, error }),
56+
onDeviceError: (error) => onDeviceError?.({ source: Track.Source.ScreenShare, error }),
5857
});
5958

6059
const micTrackRef = React.useMemo(() => {
@@ -65,6 +64,11 @@ export function useAgentControlBar(props: UseAgentControlBarProps = {}): UseAgen
6564
};
6665
}, [localParticipant, microphoneTrack]);
6766

67+
const visibleControls = {
68+
leave: true,
69+
...controls,
70+
};
71+
6872
visibleControls.microphone ??= publishPermissions.microphone;
6973
visibleControls.screenShare ??= publishPermissions.screenShare;
7074
visibleControls.camera ??= publishPermissions.camera;
@@ -108,7 +112,7 @@ export function useAgentControlBar(props: UseAgentControlBarProps = {}): UseAgen
108112
// persist video input enabled preference
109113
saveVideoInputEnabled(!cameraToggle.enabled);
110114
},
111-
[cameraToggle.enabled, screenShareToggle.enabled]
115+
[screenShareToggle.enabled, screenShareToggle.toggle, cameraToggle.toggle]
112116
);
113117

114118
const handleToggleMicrophone = React.useCallback(
@@ -117,7 +121,7 @@ export function useAgentControlBar(props: UseAgentControlBarProps = {}): UseAgen
117121
// persist audio input enabled preference
118122
saveAudioInputEnabled(!microphoneToggle.enabled);
119123
},
120-
[microphoneToggle.enabled]
124+
[microphoneToggle.enabled, microphoneToggle.toggle]
121125
);
122126

123127
const handleToggleScreenShare = React.useCallback(
@@ -127,7 +131,7 @@ export function useAgentControlBar(props: UseAgentControlBarProps = {}): UseAgen
127131
}
128132
await screenShareToggle.toggle(enabled);
129133
},
130-
[screenShareToggle.enabled, cameraToggle.enabled]
134+
[cameraToggle.enabled, cameraToggle.toggle, screenShareToggle.toggle]
131135
);
132136

133137
return {

0 commit comments

Comments
 (0)