merge: upstream Element Call v0.28.0 (cinny #201) #61

Merged
jared merged 197 commits from lotus-upstream-v0.28.0 into lotus 2026-10-24 01:14:32 -04:00
4 changed files with 250 additions and 183 deletions
Showing only changes of commit db0f6837ce - Show all commits
+8
View File
@@ -22,3 +22,11 @@ using an iframe. */
-moz-osx-font-smoothing: grayscale;
-webkit-tap-highlight-color: transparent;
}
/* Compound's overlay container, which holds tooltips and popovers, has to fill
the container for the elements inside it to be positioned against it. The
standalone page does the same for the container under `#root`. */
.root > [data-overlay-container] {
position: relative;
block-size: 100%;
}
+30 -1
View File
@@ -17,6 +17,18 @@ Please see LICENSE in the repository root for full details.
* host instead, or is confined to the container it is mounted in.
*/
// The design tokens, fonts and element defaults every Element Call stylesheet
// builds on.
//
// Where these land relative to the component stylesheets is the bundler's
// choice — the standalone app puts them first, this build puts them in the
// middle — so nothing in base.css may depend on winning or losing against a
// component's own rules at equal specificity. It currently does not: what it
// declares unlayered is custom properties on Element Call's root, which
// components inherit rather than compete with, and everything from Compound
// sits in a `@layer`, which loses to unlayered rules either way.
import "../src/base.css";
import { type FC, type JSX, type ReactNode, useMemo, useState } from "react";
import { type MatrixClient } from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
@@ -26,6 +38,7 @@ import { TooltipProvider } from "@vector-im/compound-web";
import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill.js";
import EN from "../locales/en/app.json";
import { ElementCallView } from "../src/ElementCallView";
import { ClientProvider } from "../src/ClientContext";
import {
@@ -50,7 +63,17 @@ import { useTheme } from "../src/useTheme";
import { useInitial } from "../src/useInitial";
import styles from "./ElementCall.module.css";
export { type HostBridge } from "../src/HostBridge";
// Everything needed to implement a HostBridge, not just the interface itself
export {
type DeviceMuteRequest,
type DeviceMuteState,
type HostBridge,
type HostRequest,
} from "../src/HostBridge";
export { type JoinCallData } from "../src/widget";
// The deployment-wide configuration, as distinct from ElementCallConfiguration
// above, which is per call
export { type ConfigOptions } from "../src/config/ConfigOptions";
/**
* How Element Call should behave. Everything is optional; anything left out
@@ -102,6 +125,12 @@ export async function initializeElementCall(
contextSeparator: "|",
lng: "en",
interpolation: { escapeValue: false },
// English only, bundled in. The standalone app fetches its locale files at
// runtime from URLs its own build emits, which a host serving the library
// from elsewhere could not resolve; bundling one language at least keeps
// the component self-contained. Letting a host supply the rest, or its own
// translations, is still to do.
resources: { en: { app: EN } },
});
}
+203
View File
@@ -0,0 +1,203 @@
/*
Copyright 2021-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
/* The styles Element Call needs wherever it is shown: the design tokens, fonts
and element defaults its own stylesheets build on top of.
Split out from index.css so that Element Call embedded in a host application
can have these without also being given the standalone page's layout, which
would style the host's own document. What remains here does still reach outside
Element Call's container — normalize.css and the typography below use bare
element selectors, and the custom properties are declared on `:root` — so a
host gets those too. Narrowing them needs a real host to check against, so it
waits for the Element Web integration rather than being guessed at here.
Nothing here should depend on where it lands relative to Element Call's
component stylesheets: the bundler decides that, and it decides differently for
the app and for the component build. */
@layer normalize, compound-legacy, compound;
@import url("@fontsource/inter/400.css");
@import url("@fontsource/inter/500.css");
@import url("@fontsource/inter/600.css");
@import url("@fontsource/inter/700.css");
@import url("@fontsource/inconsolata/400.css");
@import url("@fontsource/inconsolata/700.css");
@import url("normalize.css/normalize.css") layer(normalize);
@import url("@vector-im/compound-design-tokens/assets/web/css/compound-design-tokens.css") layer(compound);
@import url("@vector-im/compound-web/dist/style.css") layer(compound.components);
:root {
--font-scale: 1;
--font-size-micro: calc(10px * var(--font-scale));
--font-size-caption: calc(12px * var(--font-scale));
--font-size-body: calc(15px * var(--font-scale));
--font-size-subtitle: calc(18px * var(--font-scale));
--font-size-title: calc(24px * var(--font-scale));
--font-size-headline: calc(32px * var(--font-scale));
--cpd-color-border-accent: var(--cpd-color-green-800);
/* The distance to inset non-full-width content from the edge of the window
along the inline axis. This ramps up from 16px for typical mobile windows, to
96px for typical desktop windows, and accounts for the safe area. */
--content-inset-left: calc(
env(safe-area-inset-left) +
min(
var(--cpd-space-24x),
max(var(--cpd-space-4x), calc((100vw - 900px) / 3))
)
);
--content-inset-right: calc(
env(safe-area-inset-right) +
min(
var(--cpd-space-24x),
max(var(--cpd-space-4x), calc((100vw - 900px) / 3))
)
);
--small-drop-shadow: 0px 1.2px 2.4px 0px rgba(0, 0, 0, 0.15);
--big-drop-shadow: 0px 0px 24px 0px #1b1d221a;
--subtle-drop-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
--call-view-overlay-layer: 1;
--call-view-header-footer-layer: 2;
}
:root,
[class*="cpd-theme-"] {
--video-tile-background: var(--cpd-color-bg-subtle-secondary);
}
.cpd-theme-dark {
--cpd-color-border-accent: var(--cpd-color-green-1100);
--stopgap-color-on-solid-accent: var(--cpd-color-text-primary);
--stopgap-background-85: rgba(16, 19, 23, 0.85);
}
@media (min-height: 330px) {
[data-element-call-root][data-background="gradient"]::before {
content: "";
position: fixed;
/* Chromium abruptly fades our images to fully transparent at the edge of
the element. If we just make the element a little bigger than the viewport,
this is no longer visible. */
inset: -20px;
background-image: url("graphics/mobile-gradient.png");
background-size: 1400px 305px;
background-position: bottom;
background-repeat: no-repeat;
}
[data-element-call-root][data-background="gradient"][data-platform="desktop"]::before {
background-image: url("graphics/desktop-gradient.png");
background-size: max(1440px, 100vw) max(1440px, 100vh);
background-position: center;
}
}
/* We use this to not render the page at all until we know the theme.*/
.no-theme {
opacity: 0;
}
/* On Android and iOS, prefer native system fonts. The global.css file of
Compound Web is where these variables ultimately get consumed to set the page's
font-family. */
[data-element-call-root][data-platform="android"] {
--cpd-font-family-sans: "Roboto", "Noto", "Inter", sans-serif;
}
[data-element-call-root][data-platform="ios"] {
--cpd-font-family-sans:
-apple-system, BlinkMacSystemFont, "Inter", sans-serif;
}
@layer compound-legacy {
h1,
h2,
h3,
h4,
h5,
h6,
p,
a {
margin-top: 0;
}
/* Headline Semi Bold */
h1 {
font-weight: 600;
font-size: var(--font-size-headline);
}
/* Title */
h2 {
font-weight: 600;
font-size: var(--font-size-title);
}
/* Subtitle */
h3 {
font-weight: 600;
font-size: var(--font-size-subtitle);
}
/* Body Semi Bold */
h4 {
font-weight: 600;
font-size: var(--font-size-body);
}
h1,
h2,
h3 {
line-height: 1.2;
}
/* Body */
p {
font-size: var(--font-size-body);
line-height: var(--font-size-title);
}
hr {
width: calc(100% - 24px);
border: none;
border-top: 1px solid var(--cpd-color-border-interactive-secondary);
color: var(--cpd-color-border-interactive-secondary);
overflow: visible;
text-align: center;
height: 5px;
font-weight: 600;
font-size: var(--font-size-body);
line-height: 24px;
margin: 0 12px;
}
summary {
font-size: var(--font-size-body);
}
details > :not(summary) {
margin-left: var(--font-size-body);
}
details[open] > summary {
margin-bottom: var(--font-size-body);
}
}
/* normalize.css sets the focus rings on buttons in Firefox to an unusual custom
outline, which is inconsistent with our other components and is not sufficiently
visible to be accessible. This resets it back to 'auto'. */
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: auto;
}
+9 -182
View File
@@ -5,64 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
@layer normalize, compound-legacy, compound;
/* Styles for Element Call as a page of its own. The parts that apply wherever
Element Call is shown live in base.css; these are about owning the document,
and are not loaded when a host embeds Element Call as a component. */
@import url("@fontsource/inter/400.css");
@import url("@fontsource/inter/500.css");
@import url("@fontsource/inter/600.css");
@import url("@fontsource/inter/700.css");
@import url("@fontsource/inconsolata/400.css");
@import url("@fontsource/inconsolata/700.css");
@import url("normalize.css/normalize.css") layer(normalize);
@import url("@vector-im/compound-design-tokens/assets/web/css/compound-design-tokens.css") layer(compound);
@import url("@vector-im/compound-web/dist/style.css") layer(compound.components);
:root {
--font-scale: 1;
--font-size-micro: calc(10px * var(--font-scale));
--font-size-caption: calc(12px * var(--font-scale));
--font-size-body: calc(15px * var(--font-scale));
--font-size-subtitle: calc(18px * var(--font-scale));
--font-size-title: calc(24px * var(--font-scale));
--font-size-headline: calc(32px * var(--font-scale));
--cpd-color-border-accent: var(--cpd-color-green-800);
/* The distance to inset non-full-width content from the edge of the window
along the inline axis. This ramps up from 16px for typical mobile windows, to
96px for typical desktop windows, and accounts for the safe area. */
--content-inset-left: calc(
env(safe-area-inset-left) +
min(
var(--cpd-space-24x),
max(var(--cpd-space-4x), calc((100vw - 900px) / 3))
)
);
--content-inset-right: calc(
env(safe-area-inset-right) +
min(
var(--cpd-space-24x),
max(var(--cpd-space-4x), calc((100vw - 900px) / 3))
)
);
--small-drop-shadow: 0px 1.2px 2.4px 0px rgba(0, 0, 0, 0.15);
--big-drop-shadow: 0px 0px 24px 0px #1b1d221a;
--subtle-drop-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
--call-view-overlay-layer: 1;
--call-view-header-footer-layer: 2;
}
:root,
[class*="cpd-theme-"] {
--video-tile-background: var(--cpd-color-bg-subtle-secondary);
}
.cpd-theme-dark {
--cpd-color-border-accent: var(--cpd-color-green-1100);
--stopgap-color-on-solid-accent: var(--cpd-color-text-primary);
--stopgap-background-85: rgba(16, 19, 23, 0.85);
}
@import url("./base.css");
body {
background-color: var(--cpd-color-bg-canvas-default);
@@ -74,39 +21,16 @@ body {
-webkit-tap-highlight-color: transparent;
}
@media (min-height: 330px) {
[data-element-call-root][data-background="gradient"]::before {
content: "";
position: fixed;
/* Chromium abruptly fades our images to fully transparent at the edge of
the element. If we just make the element a little bigger than the viewport,
this is no longer visible. */
inset: -20px;
background-image: url("graphics/mobile-gradient.png");
background-size: 1400px 305px;
background-position: bottom;
background-repeat: no-repeat;
}
[data-element-call-root][data-background="gradient"][data-platform="desktop"]::before {
background-image: url("graphics/desktop-gradient.png");
background-size: max(1440px, 100vw) max(1440px, 100vh);
background-position: center;
}
}
/* This prohibits the view to scroll for pages smaller than 122px in width
we use this for mobile pip webviews */
.no-scroll-body {
we use this for mobile pip webviews. Element Call adds this class to whatever
it treats as its root, but it is only ever the page that should be pinned like
this — done to a container inside a host application it would take that
container out of the host's layout — so the selector says so. */
body.no-scroll-body {
position: fixed;
width: 100%;
}
/* We use this to not render the page at all until we know the theme.*/
.no-theme {
opacity: 0;
}
html,
body,
#root {
@@ -123,104 +47,7 @@ body,
isolation: isolate;
}
/* On Android and iOS, prefer native system fonts. The global.css file of
Compound Web is where these variables ultimately get consumed to set the page's
font-family. */
[data-element-call-root][data-platform="android"] {
--cpd-font-family-sans: "Roboto", "Noto", "Inter", sans-serif;
}
[data-element-call-root][data-platform="ios"] {
--cpd-font-family-sans:
-apple-system, BlinkMacSystemFont, "Inter", sans-serif;
}
@layer compound-legacy {
h1,
h2,
h3,
h4,
h5,
h6,
p,
a {
margin-top: 0;
}
/* Headline Semi Bold */
h1 {
font-weight: 600;
font-size: var(--font-size-headline);
}
/* Title */
h2 {
font-weight: 600;
font-size: var(--font-size-title);
}
/* Subtitle */
h3 {
font-weight: 600;
font-size: var(--font-size-subtitle);
}
/* Body Semi Bold */
h4 {
font-weight: 600;
font-size: var(--font-size-body);
}
h1,
h2,
h3 {
line-height: 1.2;
}
/* Body */
p {
font-size: var(--font-size-body);
line-height: var(--font-size-title);
}
hr {
width: calc(100% - 24px);
border: none;
border-top: 1px solid var(--cpd-color-border-interactive-secondary);
color: var(--cpd-color-border-interactive-secondary);
overflow: visible;
text-align: center;
height: 5px;
font-weight: 600;
font-size: var(--font-size-body);
line-height: 24px;
margin: 0 12px;
}
summary {
font-size: var(--font-size-body);
}
details > :not(summary) {
margin-left: var(--font-size-body);
}
details[open] > summary {
margin-bottom: var(--font-size-body);
}
}
#root > [data-overlay-container] {
position: relative;
height: 100%;
}
/* normalize.css sets the focus rings on buttons in Firefox to an unusual custom
outline, which is inconsistent with our other components and is not sufficiently
visible to be accessible. This resets it back to 'auto'. */
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: auto;
}