Make the footer display more nicely on narrow screens
It needed a bit of tweaking now that we have up to 6 buttons in the footer. I tried to do everything in CSS this time.
This commit is contained in:
@@ -53,7 +53,8 @@ const InnerButton: FC<InnerButtonProps> = ({ raised, ...props }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface RaisedHandToggleButtonProps {
|
interface RaisedHandToggleButtonProps
|
||||||
|
extends ComponentPropsWithoutRef<"button"> {
|
||||||
rtcSession: MatrixRTCSession;
|
rtcSession: MatrixRTCSession;
|
||||||
client: MatrixClient;
|
client: MatrixClient;
|
||||||
}
|
}
|
||||||
@@ -61,6 +62,7 @@ interface RaisedHandToggleButtonProps {
|
|||||||
export function RaiseHandToggleButton({
|
export function RaiseHandToggleButton({
|
||||||
client,
|
client,
|
||||||
rtcSession,
|
rtcSession,
|
||||||
|
...props
|
||||||
}: RaisedHandToggleButtonProps): ReactNode {
|
}: RaisedHandToggleButtonProps): ReactNode {
|
||||||
const { raisedHands, lowerHand } = useReactions();
|
const { raisedHands, lowerHand } = useReactions();
|
||||||
const [busy, setBusy] = useState(false);
|
const [busy, setBusy] = useState(false);
|
||||||
@@ -121,6 +123,7 @@ export function RaiseHandToggleButton({
|
|||||||
disabled={busy}
|
disabled={busy}
|
||||||
onClick={toggleRaisedHand}
|
onClick={toggleRaisedHand}
|
||||||
raised={isHandRaised}
|
raised={isHandRaised}
|
||||||
|
{...props}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,12 +36,14 @@ Please see LICENSE in the repository root for full details.
|
|||||||
inset-block-end: 0;
|
inset-block-end: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto 1fr;
|
grid-template-columns: minmax(0, var(--inline-content-inset)) 1fr auto 1fr minmax(
|
||||||
grid-template-areas: "logo buttons layout";
|
0,
|
||||||
|
var(--inline-content-inset)
|
||||||
|
);
|
||||||
|
grid-template-areas: ". logo buttons layout .";
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--cpd-space-3x);
|
gap: var(--cpd-space-3x);
|
||||||
padding-block: var(--cpd-space-4x);
|
padding-block: var(--cpd-space-10x);
|
||||||
padding-inline: var(--inline-content-inset);
|
|
||||||
background: linear-gradient(
|
background: linear-gradient(
|
||||||
180deg,
|
180deg,
|
||||||
rgba(0, 0, 0, 0) 0%,
|
rgba(0, 0, 0, 0) 0%,
|
||||||
@@ -83,6 +85,7 @@ Please see LICENSE in the repository root for full details.
|
|||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
grid-area: buttons;
|
grid-area: buttons;
|
||||||
|
justify-self: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: var(--cpd-space-3x);
|
gap: var(--cpd-space-3x);
|
||||||
}
|
}
|
||||||
@@ -92,15 +95,49 @@ Please see LICENSE in the repository root for full details.
|
|||||||
justify-self: end;
|
justify-self: end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-height: 400px) {
|
@media (max-width: 660px) {
|
||||||
.footer {
|
.footer {
|
||||||
padding-block: var(--cpd-space-8x);
|
grid-template-areas: ". buttons buttons buttons .";
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layout {
|
||||||
|
display: none !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-height: 800px) {
|
@media (max-width: 370px) {
|
||||||
|
.raiseHand {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 340px) {
|
||||||
|
.invite,
|
||||||
|
.switchCamera,
|
||||||
|
.shareScreen {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-height: 400px) {
|
||||||
|
.footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-height: 400px) {
|
||||||
.footer {
|
.footer {
|
||||||
padding-block: var(--cpd-space-10x);
|
padding-block: var(--cpd-space-4x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-height: 800px) {
|
||||||
|
.footer {
|
||||||
|
padding-block: var(--cpd-space-8x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,6 @@ export const InCallView: FC<InCallViewProps> = ({
|
|||||||
|
|
||||||
const containerRef1 = useRef<HTMLDivElement | null>(null);
|
const containerRef1 = useRef<HTMLDivElement | null>(null);
|
||||||
const [containerRef2, bounds] = useMeasure();
|
const [containerRef2, bounds] = useMeasure();
|
||||||
const boundsValid = bounds.height > 0;
|
|
||||||
// Merge the refs so they can attach to the same element
|
// Merge the refs so they can attach to the same element
|
||||||
const containerRef = useMergedRefs(containerRef1, containerRef2);
|
const containerRef = useMergedRefs(containerRef1, containerRef2);
|
||||||
|
|
||||||
@@ -226,10 +225,6 @@ export const InCallView: FC<InCallViewProps> = ({
|
|||||||
(muted) => muteStates.audio.setEnabled?.(!muted),
|
(muted) => muteStates.audio.setEnabled?.(!muted),
|
||||||
);
|
);
|
||||||
|
|
||||||
const mobile = boundsValid && bounds.width <= 660;
|
|
||||||
const reducedControls = boundsValid && bounds.width <= 340;
|
|
||||||
const noControls = reducedControls && bounds.height <= 400;
|
|
||||||
|
|
||||||
const windowMode = useObservableEagerState(vm.windowMode);
|
const windowMode = useObservableEagerState(vm.windowMode);
|
||||||
const layout = useObservableEagerState(vm.layout);
|
const layout = useObservableEagerState(vm.layout);
|
||||||
const gridMode = useObservableEagerState(vm.gridMode);
|
const gridMode = useObservableEagerState(vm.gridMode);
|
||||||
@@ -511,95 +506,94 @@ export const InCallView: FC<InCallViewProps> = ({
|
|||||||
.catch(logger.error);
|
.catch(logger.error);
|
||||||
}, [localParticipant, isScreenShareEnabled]);
|
}, [localParticipant, isScreenShareEnabled]);
|
||||||
|
|
||||||
let footer: JSX.Element | null;
|
const buttons: JSX.Element[] = [];
|
||||||
|
|
||||||
if (noControls) {
|
|
||||||
footer = null;
|
|
||||||
} else {
|
|
||||||
const buttons: JSX.Element[] = [];
|
|
||||||
|
|
||||||
|
buttons.push(
|
||||||
|
<MicButton
|
||||||
|
key="audio"
|
||||||
|
muted={!muteStates.audio.enabled}
|
||||||
|
onClick={toggleMicrophone}
|
||||||
|
disabled={muteStates.audio.setEnabled === null}
|
||||||
|
data-testid="incall_mute"
|
||||||
|
/>,
|
||||||
|
<VideoButton
|
||||||
|
key="video"
|
||||||
|
muted={!muteStates.video.enabled}
|
||||||
|
onClick={toggleCamera}
|
||||||
|
disabled={muteStates.video.setEnabled === null}
|
||||||
|
data-testid="incall_videomute"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
if (switchCamera !== null)
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<MicButton
|
<SwitchCameraButton
|
||||||
key="audio"
|
key="switch_camera"
|
||||||
muted={!muteStates.audio.enabled}
|
className={styles.switchCamera}
|
||||||
onClick={toggleMicrophone}
|
onClick={switchCamera}
|
||||||
disabled={muteStates.audio.setEnabled === null}
|
|
||||||
data-testid="incall_mute"
|
|
||||||
/>,
|
|
||||||
<VideoButton
|
|
||||||
key="video"
|
|
||||||
muted={!muteStates.video.enabled}
|
|
||||||
onClick={toggleCamera}
|
|
||||||
disabled={muteStates.video.setEnabled === null}
|
|
||||||
data-testid="incall_videomute"
|
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
if (!reducedControls) {
|
if (canScreenshare && !hideScreensharing) {
|
||||||
if (switchCamera !== null)
|
|
||||||
buttons.push(
|
|
||||||
<SwitchCameraButton key="switch_camera" onClick={switchCamera} />,
|
|
||||||
);
|
|
||||||
if (canScreenshare && !hideScreensharing) {
|
|
||||||
buttons.push(
|
|
||||||
<ShareScreenButton
|
|
||||||
key="share_screen"
|
|
||||||
enabled={isScreenShareEnabled}
|
|
||||||
onClick={toggleScreensharing}
|
|
||||||
data-testid="incall_screenshare"
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (supportsReactions) {
|
|
||||||
buttons.push(
|
|
||||||
<RaiseHandToggleButton
|
|
||||||
client={client}
|
|
||||||
rtcSession={rtcSession}
|
|
||||||
key="4"
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
buttons.push(<SettingsButton key="settings" onClick={openSettings} />);
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons.push(
|
buttons.push(
|
||||||
<EndCallButton
|
<ShareScreenButton
|
||||||
key="end_call"
|
key="share_screen"
|
||||||
onClick={function (): void {
|
className={styles.shareScreen}
|
||||||
onLeave();
|
enabled={isScreenShareEnabled}
|
||||||
}}
|
onClick={toggleScreensharing}
|
||||||
data-testid="incall_leave"
|
data-testid="incall_screenshare"
|
||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
footer = (
|
|
||||||
<div
|
|
||||||
ref={footerRef}
|
|
||||||
className={classNames(styles.footer, {
|
|
||||||
[styles.overlay]: windowMode === "flat",
|
|
||||||
[styles.hidden]: !showFooter || (!showControls && hideHeader),
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{!mobile && !hideHeader && (
|
|
||||||
<div className={styles.logo}>
|
|
||||||
<LogoMark width={24} height={24} aria-hidden />
|
|
||||||
<LogoType
|
|
||||||
width={80}
|
|
||||||
height={11}
|
|
||||||
aria-label={import.meta.env.VITE_PRODUCT_NAME || "Element Call"}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{showControls && <div className={styles.buttons}>{buttons}</div>}
|
|
||||||
{!mobile && showControls && (
|
|
||||||
<LayoutToggle
|
|
||||||
className={styles.layout}
|
|
||||||
layout={gridMode}
|
|
||||||
setLayout={setGridMode}
|
|
||||||
onTouchEnd={onLayoutToggleTouchEnd}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if (supportsReactions) {
|
||||||
|
buttons.push(
|
||||||
|
<RaiseHandToggleButton
|
||||||
|
key="raise_hand"
|
||||||
|
className={styles.raiseHand}
|
||||||
|
client={client}
|
||||||
|
rtcSession={rtcSession}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (layout.type !== "pip")
|
||||||
|
buttons.push(<SettingsButton key="settings" onClick={openSettings} />);
|
||||||
|
|
||||||
|
buttons.push(
|
||||||
|
<EndCallButton
|
||||||
|
key="end_call"
|
||||||
|
onClick={function (): void {
|
||||||
|
onLeave();
|
||||||
|
}}
|
||||||
|
data-testid="incall_leave"
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
const footer = (
|
||||||
|
<div
|
||||||
|
ref={footerRef}
|
||||||
|
className={classNames(styles.footer, {
|
||||||
|
[styles.overlay]: windowMode === "flat",
|
||||||
|
[styles.hidden]: !showFooter || (!showControls && hideHeader),
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{!hideHeader && (
|
||||||
|
<div className={styles.logo}>
|
||||||
|
<LogoMark width={24} height={24} aria-hidden />
|
||||||
|
<LogoType
|
||||||
|
width={80}
|
||||||
|
height={11}
|
||||||
|
aria-label={import.meta.env.VITE_PRODUCT_NAME || "Element Call"}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{showControls && <div className={styles.buttons}>{buttons}</div>}
|
||||||
|
{showControls && (
|
||||||
|
<LayoutToggle
|
||||||
|
className={styles.layout}
|
||||||
|
layout={gridMode}
|
||||||
|
setLayout={setGridMode}
|
||||||
|
onTouchEnd={onLayoutToggleTouchEnd}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -631,8 +625,11 @@ export const InCallView: FC<InCallViewProps> = ({
|
|||||||
/>
|
/>
|
||||||
</LeftNav>
|
</LeftNav>
|
||||||
<RightNav>
|
<RightNav>
|
||||||
{!reducedControls && showControls && onShareClick !== null && (
|
{showControls && onShareClick !== null && (
|
||||||
<InviteButton onClick={onShareClick} />
|
<InviteButton
|
||||||
|
className={styles.invite}
|
||||||
|
onClick={onShareClick}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</RightNav>
|
</RightNav>
|
||||||
</Header>
|
</Header>
|
||||||
@@ -644,15 +641,19 @@ export const InCallView: FC<InCallViewProps> = ({
|
|||||||
<source src={handSoundMp3} type="audio/mpeg" />
|
<source src={handSoundMp3} type="audio/mpeg" />
|
||||||
</audio>
|
</audio>
|
||||||
{footer}
|
{footer}
|
||||||
{!noControls && <RageshakeRequestModal {...rageshakeRequestModalProps} />}
|
{layout.type !== "pip" && (
|
||||||
<SettingsModal
|
<>
|
||||||
client={client}
|
<RageshakeRequestModal {...rageshakeRequestModalProps} />
|
||||||
roomId={rtcSession.room.roomId}
|
<SettingsModal
|
||||||
open={settingsModalOpen}
|
client={client}
|
||||||
onDismiss={closeSettings}
|
roomId={rtcSession.room.roomId}
|
||||||
tab={settingsTab}
|
open={settingsModalOpen}
|
||||||
onTabChange={setSettingsTab}
|
onDismiss={closeSettings}
|
||||||
/>
|
tab={settingsTab}
|
||||||
|
onTabChange={setSettingsTab}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user