diff --git a/locales/en/app.json b/locales/en/app.json index 5398930f..b51c6ed9 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -145,6 +145,7 @@ }, "layout_grid_label": "Grid", "layout_spotlight_label": "Spotlight", + "layout_switch_label": "Layout", "lobby": { "ask_to_join": "Request to join call", "join_as_guest": "Join as guest", diff --git a/src/components/CallFooter.tsx b/src/components/CallFooter.tsx index fdedf36c..9d59d2d1 100644 --- a/src/components/CallFooter.tsx +++ b/src/components/CallFooter.tsx @@ -8,6 +8,12 @@ Please see LICENSE in the repository root for full details. import { type FC, type JSX, type Ref, useMemo } from "react"; import classNames from "classnames"; import { BehaviorSubject } from "rxjs"; +import { Switch } from "@vector-im/compound-web"; +import { t } from "i18next"; +import { + SpotlightIcon, + GridIcon, +} from "@vector-im/compound-design-tokens/assets/web/icons"; import LogoMark from "../icons/LogoMark.svg?react"; import LogoType from "../icons/LogoType.svg?react"; @@ -23,7 +29,6 @@ import { type ReactionData, } from "../button"; import styles from "./CallFooter.module.css"; -import { LayoutToggle } from "../room/LayoutToggle"; import { type GridMode } from "../state/CallViewModel/CallViewModel"; export interface AudioOutputSwitcher { @@ -232,10 +237,18 @@ export const CallFooter: FC = ({ {!hideControls &&
{buttons}
} {setLayoutMode && layoutMode && showLayoutSwitcher && ( - + name="layoutMode" + aria-label={t("layout_switch_label")} + leftLabel={t("layout_spotlight_label")} + leftValue="spotlight" + leftIcon={SpotlightIcon} + rightLabel={t("layout_grid_label")} + rightValue="grid" + rightIcon={GridIcon} className={styles.layout} - layout={layoutMode} - setLayout={setLayoutMode} + value={layoutMode} + onChange={setLayoutMode} /> )} diff --git a/src/room/LayoutToggle.module.css b/src/room/LayoutToggle.module.css deleted file mode 100644 index d9ae5813..00000000 --- a/src/room/LayoutToggle.module.css +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2023, 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. -*/ - -.toggle { - padding: 2px; - border: 1px solid var(--cpd-color-border-interactive-secondary); - border-radius: var(--cpd-radius-pill-effect); - background: var(--cpd-color-bg-canvas-default); - display: flex; - position: relative; -} - -.toggle input { - appearance: none; - /* Safari puts a margin on these, which is not removed via appearance: none */ - margin: 0; - block-size: var(--cpd-space-11x); - inline-size: var(--cpd-space-11x); - cursor: pointer; - border-radius: var(--cpd-radius-pill-effect); - background: var(--cpd-color-bg-action-secondary-rest); - box-shadow: var(--small-drop-shadow); - transition: background-color 0.1s; -} - -.toggle svg { - display: block; - position: absolute; - padding: calc(2.5 * var(--cpd-space-1x)); - pointer-events: none; - color: var(--cpd-color-icon-primary); - transition: color 0.1s; -} - -.toggle svg:nth-child(2) { - inset-inline-start: 2px; -} - -.toggle svg:nth-child(4) { - inset-inline-end: 2px; -} - -@media (hover: hover) { - .toggle input:hover { - background: var(--cpd-color-bg-action-secondary-hovered); - box-shadow: none; - } -} - -.toggle input:active { - background: var(--cpd-color-bg-action-secondary-pressed); - box-shadow: none; -} - -.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:hover { - background: var(--cpd-color-bg-action-primary-hovered); - } -} - -.toggle input:checked:active { - background: var(--cpd-color-bg-action-primary-pressed); -} - -.toggle input:first-child { - margin-inline-end: 5px; -} diff --git a/src/room/LayoutToggle.stories.tsx b/src/room/LayoutToggle.stories.tsx deleted file mode 100644 index 72a2ffad..00000000 --- a/src/room/LayoutToggle.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* -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. -*/ - -import { fn } from "storybook/test"; - -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { LayoutToggle } from "./LayoutToggle"; - -const meta = { - component: LayoutToggle, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - layout: "grid", - setLayout: fn(), - }, -}; diff --git a/src/room/LayoutToggle.tsx b/src/room/LayoutToggle.tsx deleted file mode 100644 index 98ed91d3..00000000 --- a/src/room/LayoutToggle.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2023, 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. -*/ - -import { type ChangeEvent, type FC, useCallback } from "react"; -import { useTranslation } from "react-i18next"; -import { Tooltip } from "@vector-im/compound-web"; -import { - SpotlightIcon, - GridIcon, -} from "@vector-im/compound-design-tokens/assets/web/icons"; -import classNames from "classnames"; - -import styles from "./LayoutToggle.module.css"; - -export type Layout = "spotlight" | "grid"; - -type Props = { - layout: Layout; - setLayout: (layout: Layout) => void; - className?: string; -}; - -export const LayoutToggle: FC = ({ layout, setLayout, className }) => { - const { t } = useTranslation(); - - const onChange = useCallback( - (e: ChangeEvent) => setLayout(e.target.value as Layout), - [setLayout], - ); - - return ( -
- - - - - - - - - - ); -}; diff --git a/src/room/__snapshots__/InCallView.test.tsx.snap b/src/room/__snapshots__/InCallView.test.tsx.snap index 3ad3dcfa..d9f768e7 100644 --- a/src/room/__snapshots__/InCallView.test.tsx.snap +++ b/src/room/__snapshots__/InCallView.test.tsx.snap @@ -396,21 +396,23 @@ exports[`InCallView > rendering > renders 1`] = ` -