Implement new designs for in-call footer buttons
This basically amounts to swapping out some CSS, the icons, and the Tooltip component.
This commit is contained in:
@@ -63,6 +63,7 @@ limitations under the License.
|
||||
|
||||
.toolbarButton:disabled {
|
||||
background-color: var(--cpd-color-bg-action-primary-disabled);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.toolbarButton,
|
||||
@@ -70,33 +71,39 @@ limitations under the License.
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50px;
|
||||
background-color: var(--cpd-color-bg-subtle-secondary);
|
||||
}
|
||||
|
||||
.toolbarButton:hover,
|
||||
.toolbarButtonSecondary:hover {
|
||||
background-color: var(--cpd-color-bg-action-secondary-hovered);
|
||||
}
|
||||
|
||||
.toolbarButton:active,
|
||||
.toolbarButtonSecondary:active {
|
||||
background-color: var(--cpd-color-bg-action-secondary-pressed);
|
||||
background-color: var(--cpd-color-bg-canvas-default);
|
||||
color: var(--cpd-color-icon-primary);
|
||||
border: 1px solid var(--cpd-color-gray-400);
|
||||
box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05);
|
||||
}
|
||||
|
||||
.toolbarButton.on,
|
||||
.toolbarButton.off {
|
||||
background-color: var(--cpd-color-bg-action-primary-rest);
|
||||
color: var(--cpd-color-icon-on-solid-primary);
|
||||
}
|
||||
|
||||
.toolbarButtonSecondary.on {
|
||||
background-color: var(--cpd-color-text-success-primary);
|
||||
}
|
||||
|
||||
.toolbarButton:active,
|
||||
.toolbarButtonSecondary:active {
|
||||
background-color: var(--cpd-color-bg-subtle-primary);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.toolbarButton.on:active,
|
||||
.toolbarButton.off:active {
|
||||
background-color: var(--cpd-color-bg-action-primary-pressed);
|
||||
}
|
||||
|
||||
.iconButton:not(.stroke) svg * {
|
||||
fill: var(--cpd-color-bg-action-primary-rest);
|
||||
}
|
||||
|
||||
.iconButton:not(.stroke):hover svg * {
|
||||
.iconButton:not(.stroke):tertiary svg * {
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
@@ -110,31 +117,12 @@ limitations under the License.
|
||||
|
||||
.hangupButton {
|
||||
background-color: var(--cpd-color-bg-critical-primary);
|
||||
border-color: var(--cpd-color-border-critical-subtle);
|
||||
color: var(--stopgap-color-on-solid-accent);
|
||||
}
|
||||
|
||||
.hangupButton:hover {
|
||||
background-color: var(--cpd-color-bg-critical-hovered);
|
||||
}
|
||||
|
||||
.toolbarButton.hangupButton svg * {
|
||||
fill: var(--stopgap-color-on-solid-accent);
|
||||
}
|
||||
|
||||
.toolbarButton svg *,
|
||||
.toolbarButtonSecondary svg * {
|
||||
fill: var(--cpd-color-icon-primary);
|
||||
}
|
||||
|
||||
.toolbarButton.on svg * {
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
.toolbarButton.off svg * {
|
||||
fill: var(--cpd-color-icon-on-solid-primary);
|
||||
}
|
||||
|
||||
.toolbarButtonSecondary.on svg * {
|
||||
fill: var(--stopgap-color-on-solid-accent);
|
||||
.hangupButton:active {
|
||||
background-color: var(--cpd-color-bg-critical-pressed);
|
||||
}
|
||||
|
||||
.secondary,
|
||||
@@ -196,10 +184,6 @@ limitations under the License.
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
.iconCopyButton:hover svg * {
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
.iconCopyButton.on svg *,
|
||||
.iconCopyButton.on:hover svg * {
|
||||
fill: transparent;
|
||||
@@ -212,10 +196,6 @@ limitations under the License.
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.dropdownButton:hover {
|
||||
background-color: var(--cpd-color-bg-action-secondary-hovered);
|
||||
}
|
||||
|
||||
.dropdownButton:active,
|
||||
.dropdownButton.on {
|
||||
background-color: var(--cpd-color-bg-action-secondary-pressed);
|
||||
@@ -239,3 +219,33 @@ limitations under the License.
|
||||
color: var(--cpd-color-text-action-accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
.toolbarButton:hover,
|
||||
.toolbarButtonSecondary:hover {
|
||||
background-color: var(--cpd-color-bg-subtle-primary);
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.toolbarButton.on:hover,
|
||||
.toolbarButton.off:hover {
|
||||
background-color: var(--cpd-color-bg-action-primary-hovered);
|
||||
}
|
||||
|
||||
.iconButton:not(.stroke):hover svg * {
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
.hangupButton:hover {
|
||||
background-color: var(--cpd-color-bg-critical-hovered);
|
||||
}
|
||||
|
||||
.iconCopyButton:hover svg * {
|
||||
fill: var(--cpd-color-icon-accent-tertiary);
|
||||
}
|
||||
|
||||
.dropdownButton:hover {
|
||||
background-color: var(--cpd-color-bg-action-secondary-hovered);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,17 +19,18 @@ import classNames from "classnames";
|
||||
import { useButton } from "@react-aria/button";
|
||||
import { mergeProps, useObjectRef } from "@react-aria/utils";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Tooltip } from "@vector-im/compound-web";
|
||||
import { ReactComponent as MicOnSolidIcon } from "@vector-im/compound-design-tokens/icons/mic-on-solid.svg";
|
||||
import { ReactComponent as MicOffSolidIcon } from "@vector-im/compound-design-tokens/icons/mic-off-solid.svg";
|
||||
import { ReactComponent as VideoCallIcon } from "@vector-im/compound-design-tokens/icons/video-call.svg";
|
||||
import { ReactComponent as VideoCallOffIcon } from "@vector-im/compound-design-tokens/icons/video-call-off.svg";
|
||||
import { ReactComponent as EndCallIcon } from "@vector-im/compound-design-tokens/icons/end-call.svg";
|
||||
import { ReactComponent as ShareScreenSolidIcon } from "@vector-im/compound-design-tokens/icons/share-screen-solid.svg";
|
||||
import { ReactComponent as SettingsSolidIcon } from "@vector-im/compound-design-tokens/icons/settings-solid.svg";
|
||||
import { ReactComponent as UserAddSolidIcon } from "@vector-im/compound-design-tokens/icons/user-add-solid.svg";
|
||||
import { ReactComponent as ChevronDownIcon } from "@vector-im/compound-design-tokens/icons/chevron-down.svg";
|
||||
|
||||
import styles from "./Button.module.css";
|
||||
import { ReactComponent as MicIcon } from "../icons/Mic.svg";
|
||||
import { ReactComponent as MuteMicIcon } from "../icons/MuteMic.svg";
|
||||
import { ReactComponent as VideoIcon } from "../icons/Video.svg";
|
||||
import { ReactComponent as DisableVideoIcon } from "../icons/DisableVideo.svg";
|
||||
import { ReactComponent as HangupIcon } from "../icons/Hangup.svg";
|
||||
import { ReactComponent as ScreenshareIcon } from "../icons/Screenshare.svg";
|
||||
import { ReactComponent as SettingsIcon } from "../icons/Settings.svg";
|
||||
import { ReactComponent as AddUserIcon } from "../icons/AddUser.svg";
|
||||
import { ReactComponent as ArrowDownIcon } from "../icons/ArrowDown.svg";
|
||||
import { ReactComponent as Fullscreen } from "../icons/Fullscreen.svg";
|
||||
import { ReactComponent as FullscreenExit } from "../icons/FullscreenExit.svg";
|
||||
import { TooltipTrigger } from "../Tooltip";
|
||||
@@ -129,7 +130,7 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
|
||||
>
|
||||
<>
|
||||
{children}
|
||||
{variant === "dropdown" && <ArrowDownIcon />}
|
||||
{variant === "dropdown" && <ChevronDownIcon />}
|
||||
</>
|
||||
</button>
|
||||
);
|
||||
@@ -147,13 +148,11 @@ export function MicButton({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<TooltipTrigger
|
||||
tooltip={() => (muted ? t("Unmute microphone") : t("Mute microphone"))}
|
||||
>
|
||||
<Button variant="toolbar" {...rest} off={muted}>
|
||||
{muted ? <MuteMicIcon /> : <MicIcon />}
|
||||
<Tooltip label={muted ? t("Microphone off") : t("Microphone on")}>
|
||||
<Button variant="toolbar" {...rest} on={!muted}>
|
||||
{muted ? <MicOffSolidIcon /> : <MicOnSolidIcon />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -168,13 +167,11 @@ export function VideoButton({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<TooltipTrigger
|
||||
tooltip={() => (muted ? t("Turn on camera") : t("Turn off camera"))}
|
||||
>
|
||||
<Button variant="toolbar" {...rest} off={muted}>
|
||||
{muted ? <DisableVideoIcon /> : <VideoIcon />}
|
||||
<Tooltip label={muted ? t("Video off") : t("Video on")}>
|
||||
<Button variant="toolbar" {...rest} on={!muted}>
|
||||
{muted ? <VideoCallOffIcon /> : <VideoCallIcon />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -191,13 +188,11 @@ export function ScreenshareButton({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<TooltipTrigger
|
||||
tooltip={() => (enabled ? t("Stop sharing screen") : t("Share screen"))}
|
||||
>
|
||||
<Button variant="toolbarSecondary" {...rest} on={enabled}>
|
||||
<ScreenshareIcon />
|
||||
<Tooltip label={enabled ? t("Sharing screen") : t("Share screen")}>
|
||||
<Button variant="toolbar" {...rest} on={enabled}>
|
||||
<ShareScreenSolidIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -210,18 +205,17 @@ export function HangupButton({
|
||||
[index: string]: unknown;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const tooltip = useCallback(() => t("Leave"), [t]);
|
||||
|
||||
return (
|
||||
<TooltipTrigger tooltip={tooltip}>
|
||||
<Tooltip label={t("End call")}>
|
||||
<Button
|
||||
variant="toolbar"
|
||||
className={classNames(styles.hangupButton, className)}
|
||||
{...rest}
|
||||
>
|
||||
<HangupIcon />
|
||||
<EndCallIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -234,14 +228,13 @@ export function SettingsButton({
|
||||
[index: string]: unknown;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const tooltip = useCallback(() => t("Settings"), [t]);
|
||||
|
||||
return (
|
||||
<TooltipTrigger tooltip={tooltip}>
|
||||
<Tooltip label={t("Settings")}>
|
||||
<Button variant="toolbar" {...rest}>
|
||||
<SettingsIcon width={20} height={20} />
|
||||
<SettingsSolidIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -256,14 +249,13 @@ export function InviteButton({
|
||||
[index: string]: unknown;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const tooltip = useCallback(() => t("Invite"), [t]);
|
||||
|
||||
return (
|
||||
<TooltipTrigger tooltip={tooltip}>
|
||||
<Tooltip label={t("Invite")}>
|
||||
<Button variant={variant} {...rest}>
|
||||
<AddUserIcon />
|
||||
<UserAddSolidIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ limitations under the License.
|
||||
|
||||
@import "normalize.css/normalize.css";
|
||||
@import "@vector-im/compound-design-tokens/assets/web/css/compound-design-tokens.css";
|
||||
@import "@vector-im/compound-web/dist/style.css";
|
||||
|
||||
:root {
|
||||
--font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI",
|
||||
|
||||
@@ -52,6 +52,7 @@ limitations under the License.
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: var(--footerPadding) 0;
|
||||
/* TODO: Un-hardcode these colors */
|
||||
background: linear-gradient(
|
||||
@@ -68,14 +69,6 @@ limitations under the License.
|
||||
);
|
||||
}
|
||||
|
||||
.footer > * {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.footer > :last-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.maximised .footer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
@@ -84,12 +77,16 @@ limitations under the License.
|
||||
|
||||
@media (min-height: 300px) {
|
||||
.inRoom {
|
||||
--footerPadding: 24px;
|
||||
--footerPadding: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
.inRoom {
|
||||
--footerPadding: 32px;
|
||||
--footerPadding: 60px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
gap: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,19 +381,19 @@ export function InCallView({
|
||||
const buttons: JSX.Element[] = [];
|
||||
|
||||
buttons.push(
|
||||
<MicButton
|
||||
key="1"
|
||||
muted={!muteStates.audio.enabled}
|
||||
onPress={toggleMicrophone}
|
||||
disabled={muteStates.audio.setEnabled === null}
|
||||
data-testid="incall_mute"
|
||||
/>,
|
||||
<VideoButton
|
||||
key="2"
|
||||
muted={!muteStates.video.enabled}
|
||||
onPress={toggleCamera}
|
||||
disabled={muteStates.video.setEnabled === null}
|
||||
data-testid="incall_videomute"
|
||||
/>,
|
||||
<MicButton
|
||||
key="1"
|
||||
muted={!muteStates.audio.enabled}
|
||||
onPress={toggleMicrophone}
|
||||
disabled={muteStates.audio.setEnabled === null}
|
||||
data-testid="incall_mute"
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@@ -131,16 +131,16 @@ export const VideoPreview: FC<Props> = ({ matrixInfo, muteStates }) => {
|
||||
</div>
|
||||
)}
|
||||
<div className={styles.previewButtons}>
|
||||
<MicButton
|
||||
muted={!muteStates.audio.enabled}
|
||||
onPress={onAudioPress}
|
||||
disabled={muteStates.audio.setEnabled === null}
|
||||
/>
|
||||
<VideoButton
|
||||
muted={!muteStates.video.enabled}
|
||||
onPress={onVideoPress}
|
||||
disabled={muteStates.video.setEnabled === null}
|
||||
/>
|
||||
<MicButton
|
||||
muted={!muteStates.audio.enabled}
|
||||
onPress={onAudioPress}
|
||||
disabled={muteStates.audio.setEnabled === null}
|
||||
/>
|
||||
<SettingsButton onPress={openSettings} />
|
||||
</div>
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user