Let page background shine through spotlight tiles

By giving spotlight tiles a transparent background in certain layouts.
This commit is contained in:
Robin
2026-06-25 18:22:43 +02:00
parent 360a4ff026
commit 8fa3f33f37
9 changed files with 71 additions and 11 deletions

View File

@@ -41,13 +41,16 @@ Please see LICENSE in the repository root for full details.
.bg {
grid-area: content;
background-color: var(--video-tile-background);
inline-size: 100%;
block-size: 100%;
border-radius: inherit;
contain: strict;
}
.media[data-bg-style="solid"] .bg {
background-color: var(--video-tile-background);
}
.avatar {
position: absolute;
top: 50%;

View File

@@ -43,6 +43,7 @@ interface Props extends ComponentProps<typeof animated.div> {
displayName: string;
mxcAvatarUrl: string | undefined;
avatarStyle?: "solid" | "translucent";
bgStyle?: "solid" | "transparent";
focusable: boolean;
primaryButton?: ReactNode;
raisedHandTime?: Date;
@@ -73,6 +74,7 @@ export const MediaView: FC<Props> = ({
displayName,
mxcAvatarUrl,
avatarStyle = "solid",
bgStyle = "solid",
focusable,
primaryButton,
status,
@@ -118,6 +120,7 @@ export const MediaView: FC<Props> = ({
ref={ref}
data-testid="videoTile"
data-video-fit={videoFit}
data-bg-style={bgStyle}
{...props}
>
<div className={styles.bg}>

View File

@@ -58,7 +58,13 @@ test("SpotlightTile is accessible", async () => {
const toggleExpanded = vi.fn();
const { container } = render(
<SpotlightTile
vm={new SpotlightTileViewModel(constant([vm1, vm2]), constant(false))}
vm={
new SpotlightTileViewModel(
constant([vm1, vm2]),
constant(false),
constant("solid"),
)
}
targetWidth={300}
targetHeight={200}
expanded={false}
@@ -101,7 +107,13 @@ test("Screen share volume UI is shown when screen share has audio", async () =>
const { container } = render(
<TooltipProvider>
<SpotlightTile
vm={new SpotlightTileViewModel(constant([vm]), constant(false))}
vm={
new SpotlightTileViewModel(
constant([vm]),
constant(false),
constant("solid"),
)
}
targetWidth={300}
targetHeight={200}
expanded={false}
@@ -132,7 +144,13 @@ test("Screen share volume UI is hidden when screen share has no audio", async ()
const toggleExpanded = vi.fn();
const { container } = render(
<SpotlightTile
vm={new SpotlightTileViewModel(constant([vm]), constant(false))}
vm={
new SpotlightTileViewModel(
constant([vm]),
constant(false),
constant("solid"),
)
}
targetWidth={300}
targetHeight={200}
expanded={false}
@@ -168,7 +186,13 @@ test("SpotlightTile displays ringing media", async () => {
const toggleExpanded = vi.fn();
const { container } = render(
<SpotlightTile
vm={new SpotlightTileViewModel(constant([vm]), constant(false))}
vm={
new SpotlightTileViewModel(
constant([vm]),
constant(false),
constant("solid"),
)
}
targetWidth={300}
targetHeight={200}
expanded={false}

View File

@@ -65,6 +65,7 @@ interface SpotlightItemBaseProps {
displayName: string;
mxcAvatarUrl: string | undefined;
showNameTags: boolean;
bgStyle: "solid" | "transparent";
focusable: boolean;
"aria-hidden"?: boolean;
}
@@ -243,6 +244,7 @@ interface SpotlightItemProps {
targetHeight: number;
showNameTags: boolean;
showRingingStatus: boolean;
bgStyle: "solid" | "transparent";
focusable: boolean;
intersectionObserver$: Observable<IntersectionObserver>;
/**
@@ -259,6 +261,7 @@ const SpotlightItem: FC<SpotlightItemProps> = ({
targetHeight,
showNameTags,
showRingingStatus,
bgStyle,
focusable,
intersectionObserver$,
snap,
@@ -295,6 +298,7 @@ const SpotlightItem: FC<SpotlightItemProps> = ({
displayName,
mxcAvatarUrl,
showNameTags,
bgStyle,
focusable,
"aria-hidden": ariaHidden,
};
@@ -412,6 +416,7 @@ export const SpotlightTile: FC<Props> = ({
const [ourRef, root$] = useObservableRef<HTMLDivElement | null>(null);
const ref = useMergedRefs(ourRef, theirRef);
const maximised = useBehavior(vm.maximised$);
const bgStyle = useBehavior(vm.bgStyle$);
const media = useBehavior(vm.media$);
const [visibleId, setVisibleId] = useState<string | undefined>(media[0]?.id);
const latestMedia = useLatest(media);
@@ -516,6 +521,7 @@ export const SpotlightTile: FC<Props> = ({
targetHeight={targetHeight}
showRingingStatus={showRingingStatus}
showNameTags={showNameTags}
bgStyle={bgStyle}
focusable={focusable}
intersectionObserver$={intersectionObserver$}
// This is how we get the container to scroll to the right media