mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-22 22:29:30 +00:00
- Bound the scrolling device list by the measured height of the call area. It was capped with a viewport unit and a Radix variable, both of which measure the window: as a component in a corner of a host's page, the menu would have been sized against the whole page. The menu is portalled outside the root, so no container query reaches it and it has to be measured. - Leave a single divider between the two lists, as the design has. Compound underlines every menu heading, so the headings drop theirs, and the line closing the microphone section goes: the section wrapper already bounds the meter's stickiness without one. - Cover device persistence, hot-plug, fallback when the device in use is removed, fallback to a default when a remembered device is gone, numbered labels before permission, "Default" listed as its own entry, one device kind not disturbing another, and camera parity. Their acceptance criteria named check commands for tests that did not exist, which makes the criteria unenforceable and blocks the next drift check. Spec: FEATURES_SPEC/2026-09_Quick_Audio_Menu.md — AC3, AC4, AC5, AC8, AC9, AC10, AC11, AC19, AC20
80 lines
2.4 KiB
CSS
80 lines
2.4 KiB
CSS
/*
|
|
Copyright 2026 Element Creations Ltd.
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
Please see LICENSE in the repository root for full details.
|
|
*/
|
|
|
|
.container {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
background-color: var(--cpd-color-bg-subtle-secondary);
|
|
border-radius: 32px;
|
|
transition: background-color 0.2s ease-in-out;
|
|
}
|
|
.containerOpen {
|
|
background-color: var(--cpd-color-bg-action-primary-pressed);
|
|
}
|
|
.chevronIconOpen > svg {
|
|
color: var(--cpd-color-icon-on-solid-primary);
|
|
}
|
|
.menuButton {
|
|
width: 40px;
|
|
background-color: transparent !important;
|
|
}
|
|
.itemIcon {
|
|
color: var(--cpd-color-text-secondary);
|
|
}
|
|
|
|
.rotate {
|
|
animation: spinner 1.5s linear infinite;
|
|
}
|
|
@keyframes spinner {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
.menu {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* Compound underlines every menu heading. The design has a single line, the
|
|
one dividing the speaker list from the microphone list, so the headings
|
|
carry none and that divider is drawn explicitly. */
|
|
.menu h3 {
|
|
border-block-end: none;
|
|
padding-block-end: var(--cpd-space-2x);
|
|
}
|
|
|
|
/* Only the device lists scroll; the level meter stays put beneath them.
|
|
The bound comes from the measured height of the call area, set by the
|
|
component: the menu is portalled outside the root, so neither a container
|
|
query nor a viewport unit describes the space it is allowed to fill. */
|
|
.deviceList {
|
|
overflow-y: auto;
|
|
min-block-size: 0;
|
|
max-block-size: var(--device-list-max-height);
|
|
}
|
|
|
|
/* The meter belongs to the microphone section: it stays at the bottom of the
|
|
scrollport while that section is in view, and leaves with it when the list
|
|
is scrolled up to the speakers. The wrapper is deliberately unpositioned —
|
|
a positioned one paints above the menu's outline and swallows the frame
|
|
along this whole section. Sticky is resolved against the scroll container,
|
|
so it does not need one. */
|
|
|
|
.stickyMeter {
|
|
position: sticky;
|
|
inset-block-end: 0;
|
|
/* Opaque, so the list does not show through it as it scrolls past. The menu
|
|
draws its frame as an outline inset by one border width, and the device
|
|
rows are transparent at rest, so this is the only thing that can cover it:
|
|
hold it clear on the sides and the bottom. */
|
|
background: var(--cpd-color-bg-canvas-default);
|
|
margin-inline: var(--cpd-border-width-1);
|
|
margin-block-end: var(--cpd-border-width-1);
|
|
}
|