mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-10 21:55:19 +00:00
Opening settings in an embedded call put the dialog in the middle of the host's window, spilling outside the container, and with two calls on a page the second drew over the first's dialog. The container established a stacking context but not a containing block, which are two different things and only the first had been done. `position: fixed` resolves against the viewport unless an ancestor makes itself the containing block, so the modal scrim and dialog in Overlay.module.css — `fixed`, `inset: 0`, centred, because in the standalone app they are meant to cover the page — were positioned and sized against the window. Layout and paint containment makes the container the containing block for those descendants and clips what we paint to our own box. The second-call-on-top symptom goes with it, since the dialog now stays inside the first call's box and there is nothing to overlap. Two sibling components still cannot draw over one another by construction, neither being able to leave its own stacking context, but that only shows if a host overlaps them. Containment clips a box measured in viewport units but cannot resize it, so anything positioned that way is simply put somewhere outside the container and disappears. That applied to the reactions overlay, a `100vw` by `100vh` box, and to the reaction picker, which sits at `82vh` so as to appear near the footer it belongs to. Both are positioned against whatever Element Call treats as its root — `[data-overlay-container]` in the app, which is the size of the page, and the host's container when embedded — so percentages mean the same thing there and the right thing here. The earpiece overlay is `inset: 0` with no viewport units, so containment is enough for it. Three viewport-relative sizes remain, all of which need more than a change of unit: the lobby's video preview is `50vh` on a flex item with an aspect ratio, `--content-inset-*` ramps up to a desktop inset from the window width, and the picker's `max-width` cap is the window's. The clipping cuts both ways: a menu near the edge of a small container is trimmed rather than overflowing into the host. That is the trade an embedded component makes.
58 lines
1.1 KiB
CSS
58 lines
1.1 KiB
CSS
.container {
|
|
position: absolute;
|
|
display: inline;
|
|
z-index: 2;
|
|
pointer-events: none;
|
|
/* Percentages, not viewport units: the containing block is the element
|
|
Element Call treats as its root, which is the page in the standalone app but
|
|
the container a host gave us when embedded. */
|
|
width: 100%;
|
|
height: 100%;
|
|
left: 0;
|
|
top: 0;
|
|
}
|
|
|
|
.reaction {
|
|
font-size: 32pt;
|
|
/* Reactions are "active" for 3 seconds (as per REACTION_ACTIVE_TIME_MS), give a bit more time for it to fade out. */
|
|
animation-duration: 4s;
|
|
animation-name: reaction-up;
|
|
width: fit-content;
|
|
position: relative;
|
|
top: 80%;
|
|
}
|
|
|
|
@keyframes reaction-up {
|
|
from {
|
|
opacity: 1;
|
|
translate: 0 0;
|
|
scale: 200%;
|
|
top: 80%;
|
|
}
|
|
|
|
to {
|
|
top: 0;
|
|
opacity: 0;
|
|
scale: 100%;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion) {
|
|
@keyframes reaction-up-reduced {
|
|
from {
|
|
opacity: 1;
|
|
}
|
|
|
|
to {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
.reaction {
|
|
font-size: 48pt;
|
|
animation-name: reaction-up-reduced;
|
|
top: calc(-50% + (48pt / 2));
|
|
left: calc(50% - (48pt / 2)) !important;
|
|
}
|
|
}
|