mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-10 23:25:52 +00:00
Route Element Call's DOM decoration through an injectable root element
Element Call writes its theme classes, background and layout attributes straight onto document.body, and portals its modals there too. That is only correct while it owns the page; embedded in a host application it has to confine itself to the container it was mounted into. Add a RootElementContext, defaulting to document.body so that the standalone and widget builds are unaffected, and point the theme classes, data-background, no-scroll-body and the fullscreen target at it. Give the Modal and Toast portals an explicit container as well. Radix and vaul both default to document.body, so without this every modal, drawer and toast would render outside the container and lose the theme and platform attributes set on it. No functional change: the root element is document.body until an embedder provides otherwise.
This commit is contained in:
@@ -54,6 +54,7 @@ import { Slider } from "../Slider";
|
||||
import { platform } from "../Platform";
|
||||
import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel";
|
||||
import { RingingStatus } from "./RingingStatus";
|
||||
import { useRootElement } from "../RootElementContext";
|
||||
|
||||
interface SpotlightItemBaseProps {
|
||||
ref?: Ref<HTMLDivElement>;
|
||||
@@ -414,6 +415,7 @@ export const SpotlightTile: FC<Props> = ({
|
||||
style,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const rootElement = useRootElement();
|
||||
const [ourRef, root$] = useObservableRef<HTMLDivElement | null>(null);
|
||||
const ref = useMergedRefs(ourRef, theirRef);
|
||||
const maximised = useBehavior(vm.maximised$);
|
||||
@@ -428,24 +430,22 @@ export const SpotlightTile: FC<Props> = ({
|
||||
const canGoToNext = visibleIndex !== -1 && visibleIndex < media.length - 1;
|
||||
|
||||
const isFullscreen = useCallback((): boolean => {
|
||||
const rootElement = document.body;
|
||||
if (rootElement && document.fullscreenElement) return true;
|
||||
return false;
|
||||
}, []);
|
||||
}, [rootElement]);
|
||||
|
||||
const FullScreenIcon = isFullscreen()
|
||||
? FullScreenMinimiseIcon
|
||||
: FullScreenMaximiseIcon;
|
||||
|
||||
const onToggleFullscreen = useCallback(() => {
|
||||
const rootElement = document.body;
|
||||
if (!rootElement) return;
|
||||
if (isFullscreen()) {
|
||||
void document?.exitFullscreen();
|
||||
} else {
|
||||
void rootElement.requestFullscreen();
|
||||
}
|
||||
}, [isFullscreen]);
|
||||
}, [isFullscreen, rootElement]);
|
||||
|
||||
// To keep track of which item is visible, we need an intersection observer
|
||||
// hooked up to the root element and the items. Because the items will run
|
||||
|
||||
Reference in New Issue
Block a user