Add FullscreenExitIcon component; refactor Popover to PopoverWrapper for better functionality; update ChatPopup and ControlsPopover to utilize new PopoverWrapper; enhance NewSessionPage with fullscreen toggle functionality and improved button interactions.

This commit is contained in:
2025-10-15 23:41:15 +05:00
parent 9fd61562a0
commit 9e19a6e03f
6 changed files with 118 additions and 32 deletions
@@ -0,0 +1,15 @@
function FullscreenExitIcon() {
return (
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="m7 13-5 5m5-5v5m0-5H2m11-6 5-5m-5 5V2m0 5h5"
stroke="currentColor"
strokeWidth={1.2}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
export default FullscreenExitIcon;
+1 -1
View File
@@ -32,7 +32,7 @@ export default function ChatPopup() {
}
return (
<PopupWrapper title="Чат" draggable className="max-h-[40]">
<PopupWrapper title="Чат" draggable className="max-h-[40] overflow-hidden">
<div className="flex flex-col h-[27.778vw] relative -m-[1.389vw]">
<MessageFeed messages={messages} />
<MessageInput onMessageSend={onMessageSend} />
+4 -4
View File
@@ -1,7 +1,7 @@
import { useState, useRef, useEffect } from "react";
import Button from "./Button";
import MoreIcon from "../icons/MoreIcon";
import Popover from "./Popover";
import PopoverWrapper from "./PopoverWrapper";
interface ActionsPopoverProps {
options: {
@@ -47,7 +47,7 @@ export default function ActionsPopover({ options }: ActionsPopoverProps) {
<MoreIcon />
</div>
</button>
<Popover
<PopoverWrapper
isOpened={isOpened}
buttonRef={buttonRef}
className="w-[17.222vw]"
@@ -55,7 +55,7 @@ export default function ActionsPopover({ options }: ActionsPopoverProps) {
{options.map((option) => (
<Button
variant="tertiary"
className="p-[0.833vw] button-s w-full flex items-center !rounded-none !justify-start gap-[0.556vw]"
className="w-full !justify-start"
key={option.label}
onClick={option.onClick}
disabled={option.disabled}
@@ -64,7 +64,7 @@ export default function ActionsPopover({ options }: ActionsPopoverProps) {
{option.label}
</Button>
))}
</Popover>
</PopoverWrapper>
</div>
);
}
+37 -9
View File
@@ -1,5 +1,5 @@
import FloatingActionButton from "./FloatingActionButton";
import Popover from "./Popover";
import PopoverWrapper from "./PopoverWrapper";
import MoreIcon from "../icons/MoreIcon";
import { useEffect, useRef, useState } from "react";
import Button from "./Button";
@@ -7,9 +7,16 @@ import ChatFilledIcon from "../icons/ChatFilledIcon";
import UsersFilledIcon from "../icons/UsersFilledIcon";
import ShareFilledIcon from "../icons/ShareFilledIcon";
import CogFilledIcon from "../icons/CogFilledIcon";
import usePopupStore from "../../store/popupStore";
import useModalStore from "../../store/modalStore";
import ChatPopup from "../popups/ChatPopup";
import ParticipantsPopup from "../popups/ParticipantsPopup";
import SharePopup from "../popups/SharePopup";
import SettingsModal from "../modals/SettingsModal";
function ControlsPopover() {
const [isOpened, setIsOpened] = useState(false);
const buttonRef = useRef<HTMLButtonElement>(null);
useEffect(() => {
@@ -30,8 +37,11 @@ function ControlsPopover() {
};
}, []);
const { setPopup } = usePopupStore();
const { setModal } = useModalStore();
return (
<div className="2xl:hidden order-3 relative">
<div className="2xl:hidden order-3 relative ah-full">
<FloatingActionButton
ref={buttonRef}
className="!bg-[#7B60F3]"
@@ -41,36 +51,54 @@ function ControlsPopover() {
<MoreIcon />
</div>
</FloatingActionButton>
<Popover
<PopoverWrapper
isOpened={isOpened}
buttonRef={buttonRef}
className="w-[248px] bottom-[72px]"
className="w-[248px] !bottom-[72px] min-h-full !fixed left-1/2 -translate-x-1/2"
>
<Button variant="tertiary" className="w-full !justify-start">
<Button
variant="tertiary"
className="w-full !justify-start"
onClick={() => setPopup(<ChatPopup />)}
>
<div className="size-4">
<ChatFilledIcon />
</div>
Чат
</Button>
<Button variant="tertiary" className="w-full !justify-start">
<Button
variant="tertiary"
className="w-full !justify-start"
onClick={() => setPopup(<ParticipantsPopup />)}
>
<div className="size-4">
<UsersFilledIcon />
</div>
Участники
</Button>
<Button variant="tertiary" className="w-full !justify-start">
<Button
variant="tertiary"
className="w-full !justify-start"
onClick={() =>
setPopup(<SharePopup link="https://estate.stream/ahdy12jdco1" />)
}
>
<div className="size-4">
<ShareFilledIcon />
</div>
Пригласить
</Button>
<Button variant="tertiary" className="w-full !justify-start">
<Button
variant="tertiary"
className="w-full !justify-start"
onClick={() => setModal(<SettingsModal />)}
>
<div className="size-4">
<CogFilledIcon />
</div>
Настройки
</Button>
</Popover>
</PopoverWrapper>
</div>
);
}
@@ -9,7 +9,12 @@ interface PopoverProps {
className?: string;
}
function Popover({ isOpened, buttonRef, children, className }: PopoverProps) {
function PopoverWrapper({
isOpened,
buttonRef,
children,
className,
}: PopoverProps) {
const [openUpwards, setOpenUpwards] = useState(false);
const [menuHeight, setMenuHeight] = useState(0);
@@ -30,19 +35,19 @@ function Popover({ isOpened, buttonRef, children, className }: PopoverProps) {
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
ref={(el) => {
setMenuHeight(el?.offsetHeight || 0);
if (el) setMenuHeight(el.offsetHeight);
}}
className={clsx(
"absolute z-10 right-0 bg-white 2xl:rounded-[1.111vw] shadow-[0_4px_40px_0_rgba(15,16,17,0.1)] overflow-hidden rounded-2xl 2xl:p-[0.278vw] p-1",
"absolute z-10 right-0 shadow-[0_4px_40px_0_rgba(15,16,17,0.1)] overflow-hidden bg-white 2xl:rounded-[1.111vw] rounded-2xl",
openUpwards ? "bottom-full" : "top-full",
className
)}
>
{children}
<div className="2xl:p-[0.278vw] p-1">{children}</div>
</motion.div>
)}
</AnimatePresence>
);
}
export default Popover;
export default PopoverWrapper;
+51 -13
View File
@@ -2,6 +2,7 @@ import ActionsSidebarWrapper from "../components/ActionsSidebarWrapper";
import ChatFilledIcon from "../components/icons/ChatFilledIcon";
import CogFilledIcon from "../components/icons/CogFilledIcon";
import ExitFilledIcon from "../components/icons/ExitFilledIcon";
import FullscreenExitIcon from "../components/icons/FullscreenExitIcon";
import FullscreenIcon from "../components/icons/FullscreenIcon";
import MicrophoneFilledIcon from "../components/icons/MicrophoneFilledIcon";
import ShareFilledIcon from "../components/icons/ShareFilledIcon";
@@ -11,33 +12,67 @@ import FloatingActionButton from "../components/ui/FloatingActionButton";
import ParticipantsPopup from "../components/popups/ParticipantsPopup";
import usePopupStore from "../store/popupStore";
import ControlsPopover from "../components/ui/ControlsPopover";
import ChatPopup from "../components/popups/ChatPopup";
import SharePopup from "../components/popups/SharePopup";
import SettingsModal from "../components/modals/SettingsModal";
import useModalStore from "../store/modalStore";
import { useEffect, useState } from "react";
function NewSessionPage() {
const { setPopup } = usePopupStore();
const { setModal } = useModalStore();
const [isFullscreen, setIsFullscreen] = useState(false);
function toggleFullscreen() {
if (document.fullscreenElement) document.exitFullscreen();
else document.documentElement.requestFullscreen();
}
useEffect(() => {
document.addEventListener("fullscreenchange", () =>
setIsFullscreen(!!document.fullscreenElement)
);
return () =>
document.removeEventListener("fullscreenchange", () =>
setIsFullscreen(!!document.fullscreenElement)
);
}, []);
return (
<div className="relative w-screen h-screen bg-[#DADADA] order-3">
<div className="relative w-screen h-screen bg-[#DADADA] order-3 overflow-hidden">
<ActionsSidebarWrapper>
<FloatingActionButton
className="max-2xl:hidden"
onClick={() => setPopup(<ChatPopup />)}
>
<div className="size-[1.111vw] text-white">
<ChatFilledIcon />
</div>
</FloatingActionButton>
<FloatingActionButton
className="max-2xl:hidden"
onClick={() => setPopup(<ParticipantsPopup />)}
>
<div className="2xl:size-[1.111vw] text-white">
<ChatFilledIcon />
</div>
</FloatingActionButton>
<FloatingActionButton className="max-2xl:hidden">
<div className="2xl:size-[1.111vw] text-white">
<div className="size-[1.111vw] text-white">
<UsersFilledIcon />
</div>
</FloatingActionButton>
<FloatingActionButton className="max-2xl:hidden">
<div className="2xl:size-[1.111vw] text-white">
<FloatingActionButton
className="max-2xl:hidden"
onClick={() =>
setPopup(<SharePopup link="https://estate.stream/ahdy12jdco1" />)
}
>
<div className="size-[1.111vw] text-white">
<ShareFilledIcon />
</div>
</FloatingActionButton>
<FloatingActionButton className="max-2xl:hidden">
<div className="2xl:size-[1.111vw] text-white">
<FloatingActionButton
className="max-2xl:hidden"
onClick={() => setModal(<SettingsModal />)}
>
<div className="size-[1.111vw] text-white">
<CogFilledIcon />
</div>
</FloatingActionButton>
@@ -51,9 +86,12 @@ function NewSessionPage() {
<VideoOffFilledIcon />
</div>
</FloatingActionButton>
<FloatingActionButton className="max-2xl:order-2">
<FloatingActionButton
className="max-2xl:order-2"
onClick={toggleFullscreen}
>
<div className="2xl:size-[1.111vw] size-4 text-white">
<FullscreenIcon />
{isFullscreen ? <FullscreenExitIcon /> : <FullscreenIcon />}
</div>
</FloatingActionButton>
<FloatingActionButton variant="critical" className="max-2xl:order-1">