diff --git a/src/button/Button.tsx b/src/button/Button.tsx
index 63e29420..10c4dfd0 100644
--- a/src/button/Button.tsx
+++ b/src/button/Button.tsx
@@ -151,7 +151,7 @@ export const MicButton: FC<{
return (
);
@@ -171,7 +171,7 @@ export const VideoButton: FC<{
return (
);
@@ -191,7 +191,7 @@ export const ScreenshareButton: FC<{
return (
);
@@ -211,11 +211,7 @@ export const HangupButton: FC<{
className={classNames(styles.hangupButton, className)}
{...rest}
>
-
+
);
@@ -231,11 +227,7 @@ export const SettingsButton: FC<{
return (
);
diff --git a/src/room/EncryptionLock.tsx b/src/room/EncryptionLock.tsx
index fe60ad30..53b8e430 100644
--- a/src/room/EncryptionLock.tsx
+++ b/src/room/EncryptionLock.tsx
@@ -1,5 +1,5 @@
/*
-Copyright 2023 New Vector Ltd
+Copyright 2023-2024 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,13 +34,13 @@ export const EncryptionLock: FC = ({ encrypted }) => {
const label = encrypted ? t("common.encrypted") : t("common.unencrypted");
return (
-
+
);
diff --git a/src/room/LayoutToggle.module.css b/src/room/LayoutToggle.module.css
index 0f9d614d..e2e592fc 100644
--- a/src/room/LayoutToggle.module.css
+++ b/src/room/LayoutToggle.module.css
@@ -1,5 +1,5 @@
/*
-Copyright 2023 New Vector Ltd
+Copyright 2023-2024 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,22 +21,15 @@ limitations under the License.
background: var(--cpd-color-bg-canvas-default);
box-shadow: 0px 0px 40px 0px rgba(0, 0, 0, 0.5);
display: flex;
+ position: relative;
}
.toggle input {
appearance: none;
- /*
- * Safari puts a margin on these, which is not removed via appearance: none
- * mobile safari also has them take up space in the DOM, so set width 0
- */
+ /* Safari puts a margin on these, which is not removed via appearance: none */
margin: 0;
- width: 0;
- outline: none !important;
-}
-
-.toggle label {
- display: block;
- padding: calc(2.5 * var(--cpd-space-1x));
+ block-size: var(--cpd-space-11x);
+ inline-size: var(--cpd-space-11x);
cursor: pointer;
border-radius: var(--cpd-radius-pill-effect);
color: var(--cpd-color-icon-primary);
@@ -44,41 +37,52 @@ limitations under the License.
box-shadow: var(--small-drop-shadow);
}
+.toggle svg {
+ display: block;
+ position: absolute;
+ padding: calc(2.5 * var(--cpd-space-1x));
+ pointer-events: none;
+ color: var(--cpd-color-icon-primary);
+}
+
+.toggle svg:nth-child(2) {
+ inset-inline-start: 2px;
+}
+
+.toggle svg:nth-child(4) {
+ inset-inline-end: 2px;
+}
+
@media (hover: hover) {
- .toggle label:hover {
+ .toggle input:hover {
background: var(--cpd-color-bg-action-secondary-hovered);
box-shadow: none;
}
}
-.toggle label:active {
+.toggle input:active {
background: var(--cpd-color-bg-action-secondary-hovered);
box-shadow: none;
}
-.toggle input:checked + label {
- color: var(--cpd-color-icon-on-solid-primary);
+.toggle input:checked {
background: var(--cpd-color-bg-action-primary-rest);
}
+.toggle input:checked + svg {
+ color: var(--cpd-color-icon-on-solid-primary);
+}
+
@media (hover: hover) {
- .toggle input:checked + label:hover {
+ .toggle input:checked:hover {
background: var(--cpd-color-bg-action-primary-hovered);
}
}
-.toggle input:checked + label:active {
+.toggle input:checked:active {
background: var(--cpd-color-bg-action-primary-hovered);
}
-.toggle label > svg {
- display: block;
-}
-
-.toggle label:last-child {
- margin-inline-start: 5px;
-}
-
-.toggle input:focus-visible + label {
- outline: auto;
+.toggle input:first-child {
+ margin-inline-end: 5px;
}
diff --git a/src/room/LayoutToggle.tsx b/src/room/LayoutToggle.tsx
index fe3020ed..ed68198c 100644
--- a/src/room/LayoutToggle.tsx
+++ b/src/room/LayoutToggle.tsx
@@ -1,5 +1,5 @@
/*
-Copyright 2023 New Vector Ltd
+Copyright 2023-2024 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import { ChangeEvent, FC, useCallback, useId } from "react";
+import { ChangeEvent, FC, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { Tooltip } from "@vector-im/compound-web";
import {
@@ -41,45 +41,28 @@ export const LayoutToggle: FC = ({ layout, setLayout, className }) => {
[setLayout],
);
- const spotlightId = useId();
- const gridId = useId();
-
return (
-
-
+
-
+
-
+
+
);
};
diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx
index e87c506e..f1e0c72b 100644
--- a/src/tile/GridTile.tsx
+++ b/src/tile/GridTile.tsx
@@ -90,10 +90,12 @@ const UserMediaTile = forwardRef(
const videoEnabled = useObservableEagerState(vm.videoEnabled);
const speaking = useObservableEagerState(vm.speaking);
const cropVideo = useObservableEagerState(vm.cropVideo);
- const onChangeFitContain = useCallback(() => vm.toggleFitContain(), [vm]);
const onSelectFitContain = useCallback(
- (e: Event) => e.preventDefault(),
- [],
+ (e: Event) => {
+ e.preventDefault();
+ vm.toggleFitContain();
+ },
+ [vm],
);
const MicIcon = audioEnabled ? MicOnSolidIcon : MicOffSolidIcon;
@@ -106,7 +108,6 @@ const UserMediaTile = forwardRef(
Icon={ExpandIcon}
label={t("video_tile.change_fit_contain")}
checked={cropVideo}
- onChange={onChangeFitContain}
onSelect={onSelectFitContain}
/>
{menuEnd}
@@ -176,11 +177,10 @@ const LocalUserMediaTile = forwardRef(
const alwaysShow = useObservableEagerState(vm.alwaysShow);
const latestAlwaysShow = useLatest(alwaysShow);
const onSelectAlwaysShow = useCallback(
- (e: Event) => e.preventDefault(),
- [],
- );
- const onChangeAlwaysShow = useCallback(
- () => vm.setAlwaysShow(!latestAlwaysShow.current),
+ (e: Event) => {
+ e.preventDefault();
+ vm.setAlwaysShow(!latestAlwaysShow.current);
+ },
[vm, latestAlwaysShow],
);
@@ -194,7 +194,6 @@ const LocalUserMediaTile = forwardRef(
Icon={VisibilityOnIcon}
label={t("video_tile.always_show")}
checked={alwaysShow}
- onChange={onChangeAlwaysShow}
onSelect={onSelectAlwaysShow}
/>
}
@@ -224,8 +223,13 @@ const RemoteUserMediaTile = forwardRef<
const { t } = useTranslation();
const locallyMuted = useObservableEagerState(vm.locallyMuted);
const localVolume = useObservableEagerState(vm.localVolume);
- const onChangeMute = useCallback(() => vm.toggleLocallyMuted(), [vm]);
- const onSelectMute = useCallback((e: Event) => e.preventDefault(), []);
+ const onSelectMute = useCallback(
+ (e: Event) => {
+ e.preventDefault();
+ vm.toggleLocallyMuted();
+ },
+ [vm],
+ );
const onChangeLocalVolume = useCallback(
(v: number) => vm.setLocalVolume(v),
[vm],
@@ -244,7 +248,6 @@ const RemoteUserMediaTile = forwardRef<
Icon={MicOffIcon}
label={t("video_tile.mute_for_me")}
checked={locallyMuted}
- onChange={onChangeMute}
onSelect={onSelectMute}
/>
{/* TODO: Figure out how to make this slider keyboard accessible */}
diff --git a/src/tile/MediaView.tsx b/src/tile/MediaView.tsx
index e30bdb8c..4d073092 100644
--- a/src/tile/MediaView.tsx
+++ b/src/tile/MediaView.tsx
@@ -103,14 +103,14 @@ export const MediaView = forwardRef(
{unencryptedWarning && (
)}