feat: floating glass navigation and action bars in modals

Replace inline Save/Discard/Reset buttons with sticky glass-bubble pills
that float at the bottom of scrollable modal content. Make SpaceSettings
tab sidebar sticky with glass material. Convert RoleEditView "Back to
roles" into a sticky glass pill at the top. UserSettings Log Out + Save
always visible in a glass pill with separator. Also includes floating
position hook and popover/tooltip improvements from prior work.
This commit is contained in:
Jannis Braun
2026-03-09 01:31:35 +01:00
parent 31db1a7bd3
commit 37f199e544
15 changed files with 389 additions and 145 deletions
@@ -1,10 +1,13 @@
import React, { useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
import { useTrackStats, AudioTrackStat, VideoTrackStat } from '../../hooks/useTrackStats';
import { getActiveRoom } from '../../hooks/useLiveKit';
import { useFloatingPosition } from '../../hooks/useFloatingPosition';
interface ConnectionInfoPopoverProps {
open: boolean;
onClose: () => void;
anchorRef: React.RefObject<HTMLElement | null>;
}
function formatBitrate(kbps: number): string {
@@ -110,10 +113,16 @@ function VideoTrackRow({ track }: { track: VideoTrackStat }) {
);
}
export function ConnectionInfoPopover({ open, onClose }: ConnectionInfoPopoverProps) {
export function ConnectionInfoPopover({ open, onClose, anchorRef }: ConnectionInfoPopoverProps) {
const popoverRef = useRef<HTMLDivElement>(null);
const stats = useTrackStats(open);
const { style } = useFloatingPosition(anchorRef, popoverRef, {
placement: 'top',
offset: 12,
enabled: open,
});
// Click-outside to close
useEffect(() => {
if (!open) return;
@@ -130,16 +139,17 @@ export function ConnectionInfoPopover({ open, onClose }: ConnectionInfoPopoverPr
const room = getActiveRoom();
return (
return createPortal(
<div
ref={popoverRef}
className="absolute bottom-full left-1/2 -translate-x-1/2 mb-3 w-[300px] glass rounded-lg z-50 overflow-hidden"
style={style}
className="w-[300px] glass rounded-lg overflow-hidden"
>
<div className="px-3 py-2 border-b border-border-hard">
<span className="text-[14px] font-bold text-txt-primary">Connection Info</span>
</div>
<div className="px-3 py-2">
<div className="px-3 py-2 max-h-[calc(100vh-32px)] overflow-y-auto scrollbar-thin">
{!room ? (
<div className="text-[12px] text-txt-tertiary py-2 text-center">Not connected</div>
) : !stats ? (
@@ -197,6 +207,7 @@ export function ConnectionInfoPopover({ open, onClose }: ConnectionInfoPopoverPr
</>
)}
</div>
</div>
</div>,
document.body,
);
}