Give the component what the app shell was providing

The component built and typechecked in the previous commit, but only because
nothing had rendered it. Everything Element Call needs that `src/main.tsx`
side-loads was missing from it.

Its stylesheet: only main.tsx imported index.css, so the library build emitted
CSS-module styles with every `--cpd-*` and `--font-size-*` unresolved. Split
into base.css, which both the app and the component import, and the rules that
are about owning a page, which only the app does. The split is a straight move
— comment-stripped and sorted, the old file and the two new ones differ by
exactly one line — and that line is the deliberate part: `.no-scroll-body`
becomes `body.no-scroll-body`. Element Call adds that class to whatever it
treats as its root, and since the root can now be a container, `position:
fixed` would have taken that container out of the host's layout. Pinning the
page is what it always meant.

Its translations: `initializeElementCall` called `i18n.init` with neither
resources nor a backend, so every key would have rendered as itself. English is
bundled in. The app fetches locale files from URLs its own build emits, which a
host serving the library from somewhere else could not resolve, so how a host
picks a language is left open.

And the types a host needs: `HostBridge` alone is not enough to implement
`HostBridge` — `HostRequest`, `DeviceMuteState`, `DeviceMuteRequest` and
`JoinCallData` all appear in its signatures, and `ConfigOptions` in
`initializeElementCall`'s.
This commit is contained in:
Valere
2026-09-03 16:10:26 +02:00
parent 979b521563
commit db0f6837ce
4 changed files with 250 additions and 183 deletions
+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;
}