🚸 Remove dialog expansion, instead expand popover

This commit is contained in:
Baptiste Arnaud 2025-06-05 18:25:28 +02:00
parent 47d1bee4ce
commit 000495d3aa
No known key found for this signature in database
6 changed files with 46 additions and 81 deletions

View File

@ -748,3 +748,12 @@ export const CircleXIcon = (props: IconProps) => (
<path d="m9 9 6 6" />
</Icon>
);
export const MinimizeIcon = (props: IconProps) => (
<Icon viewBox="0 0 24 24" {...featherIconsBaseProps} {...props}>
<path d="m14 10 7-7" />
<path d="M20 10h-6V4" />
<path d="m3 21 7-7" />
<path d="M4 14h6v6" />
</Icon>
);

View File

@ -1,15 +1,10 @@
import { ContextMenu } from "@/components/ContextMenu";
import { useEditor } from "@/features/editor/providers/EditorProvider";
import { useTypebot } from "@/features/editor/providers/TypebotProvider";
import { SettingsModal } from "@/features/graph/components/nodes/block/SettingsModal";
import {
NodeSettings,
SettingsPopoverContent,
} from "@/features/graph/components/nodes/block/SettingsPopoverContent";
import { SettingsPopoverContent } from "@/features/graph/components/nodes/block/SettingsPopoverContent";
import { eventWidth } from "@/features/graph/constants";
import { useSelectionStore } from "@/features/graph/hooks/useSelectionStore";
import { useGraph } from "@/features/graph/providers/GraphProvider";
import { ParentModalProvider } from "@/features/graph/providers/ParentModalProvider";
import { setMultipleRefs } from "@/helpers/setMultipleRefs";
import { useRightPanel } from "@/hooks/useRightPanel";
import {
@ -217,23 +212,11 @@ export const EventNode = ({ event, eventIndex }: Props) => {
</Stack>
</PopoverTrigger>
{hasSettingsPopover(event) && (
<>
<SettingsPopoverContent
node={event}
groupId={undefined}
onExpandClick={onModalOpen}
onNodeChange={handleOnNodeChange}
/>
<ParentModalProvider>
<SettingsModal isOpen={isModalOpen} onClose={handleModalClose}>
<NodeSettings
node={event}
groupId={undefined}
onNodeChange={handleOnNodeChange}
/>
</SettingsModal>
</ParentModalProvider>
</>
<SettingsPopoverContent
node={event}
groupId={undefined}
onNodeChange={handleOnNodeChange}
/>
)}
</Popover>
)}

View File

@ -9,7 +9,6 @@ import {
useDragDistance,
} from "@/features/graph/providers/GraphDndProvider";
import { useGraph } from "@/features/graph/providers/GraphProvider";
import { ParentModalProvider } from "@/features/graph/providers/ParentModalProvider";
import { hasDefaultConnector } from "@/features/typebot/helpers/hasDefaultConnector";
import { setMultipleRefs } from "@/helpers/setMultipleRefs";
import {
@ -51,8 +50,7 @@ import { TargetEndpoint } from "../../endpoints/TargetEndpoint";
import { BlockNodeContent } from "./BlockNodeContent";
import { BlockNodeContextMenu } from "./BlockNodeContextMenu";
import { MediaBubblePopoverContent } from "./MediaBubblePopoverContent";
import { SettingsModal } from "./SettingsModal";
import { NodeSettings, SettingsPopoverContent } from "./SettingsPopoverContent";
import { SettingsPopoverContent } from "./SettingsPopoverContent";
export const BlockNode = ({
block,
@ -329,23 +327,12 @@ export const BlockNode = ({
</Flex>
</PopoverTrigger>
{hasSettingsPopover(block) && (
<>
<SettingsPopoverContent
node={block}
groupId={groupId}
onExpandClick={handleExpandClick}
onNodeChange={handleBlockUpdate}
/>
<ParentModalProvider>
<SettingsModal isOpen={isModalOpen} onClose={handleModalClose}>
<NodeSettings
node={block}
groupId={groupId}
onNodeChange={handleBlockUpdate}
/>
</SettingsModal>
</ParentModalProvider>
</>
<SettingsPopoverContent
node={block}
groupId={groupId}
onNodeChange={handleBlockUpdate}
isOpen={openedBlockId === block.id}
/>
)}
{typebot && isMediaBubbleBlock(block) && (
<MediaBubblePopoverContent

View File

@ -1,4 +1,4 @@
import { BuoyIcon, ExpandIcon } from "@/components/icons";
import { BuoyIcon, ExpandIcon, MinimizeIcon } from "@/components/icons";
import { getHelpDocUrl } from "@/features/graph/helpers/getHelpDocUrl";
import { VideoOnboardingPopover } from "@/features/onboarding/components/VideoOnboardingPopover";
import {
@ -17,6 +17,7 @@ type Props = {
nodeType: BlockWithOptions["type"] | TEventWithOptions["type"];
blockDef?: (typeof forgedBlocks)[keyof typeof forgedBlocks];
isVideoOnboardingItemDisplayed: boolean;
isExpanded: boolean;
onExpandClick: () => void;
onVideoOnboardingClick: () => void;
};
@ -25,6 +26,7 @@ export const SettingsHoverBar = ({
nodeType,
blockDef,
isVideoOnboardingItemDisplayed,
isExpanded,
onExpandClick,
onVideoOnboardingClick,
}: Props) => {
@ -39,7 +41,7 @@ export const SettingsHoverBar = ({
shadow="md"
>
<IconButton
icon={<ExpandIcon />}
icon={isExpanded ? <MinimizeIcon /> : <ExpandIcon />}
borderRightWidth="1px"
borderRightRadius="none"
borderLeftRadius="none"

View File

@ -1,30 +0,0 @@
import { useParentModal } from "@/features/graph/providers/ParentModalProvider";
import { Portal } from "@ark-ui/react";
import { Dialog } from "@ark-ui/react/dialog";
import { dialogClassNames } from "@typebot.io/ui/components/Dialog";
import type React from "react";
type Props = {
isOpen: boolean;
onClose: () => void;
children: React.ReactNode;
};
export const SettingsModal = ({ isOpen, onClose, children }: Props) => {
const { ref } = useParentModal();
return (
<Dialog.Root
open={isOpen}
onOpenChange={(e) => (e.open ? undefined : onClose())}
>
<Portal>
<Dialog.Backdrop className={dialogClassNames.backdrop} />
<Dialog.Positioner className={dialogClassNames.positioner}>
<Dialog.Content className={dialogClassNames.content} ref={ref}>
{children}
</Dialog.Content>
</Dialog.Positioner>
</Portal>
</Dialog.Root>
);
};

View File

@ -52,28 +52,36 @@ import { IntegrationBlockType } from "@typebot.io/blocks-integrations/constants"
import { LogicBlockType } from "@typebot.io/blocks-logic/constants";
import { EventType } from "@typebot.io/events/constants";
import type { TEventWithOptions } from "@typebot.io/events/schemas";
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { ForgedBlockSettings } from "../../../../forge/components/ForgedBlockSettings";
import { SettingsHoverBar } from "./SettingsHoverBar";
type Props = {
node: BlockWithOptions | TEventWithOptions;
groupId: string | undefined;
onExpandClick: () => void;
onNodeChange: (
updates: Partial<BlockWithOptions | TEventWithOptions>,
) => void;
isOpen?: boolean;
};
export const SettingsPopoverContent = ({ onExpandClick, ...props }: Props) => {
export const SettingsPopoverContent = ({ isOpen, ...props }: Props) => {
const [isHovering, setIsHovering] = useState(false);
const arrowColor = useColorModeValue("white", "gray.900");
const { blockDef } = useForgedBlock({
nodeType: props.node.type,
});
const [isExpanded, setIsExpanded] = useState(false);
const ref = useRef<HTMLDivElement | null>(null);
const handleMouseDown = (e: React.MouseEvent) => e.stopPropagation();
useEffect(() => {
if (!isExpanded || isOpen) return;
setTimeout(() => {
setIsExpanded(false);
}, 300);
}, [isOpen, isExpanded]);
const handleMouseWheel = (e: WheelEvent) => {
e.stopPropagation();
};
@ -81,7 +89,13 @@ export const SettingsPopoverContent = ({ onExpandClick, ...props }: Props) => {
return (
<Portal>
<PopoverContent onMouseDown={handleMouseDown} pos="relative">
<PopoverContent
onMouseDown={handleMouseDown}
pos="relative"
w={isExpanded ? "650px" : undefined}
maxH={isExpanded ? "70vh" : "400px"}
h="full"
>
<PopoverArrow bgColor={arrowColor} />
<VideoOnboardingPopover.Root type={props.node.type} blockDef={blockDef}>
@ -89,7 +103,6 @@ export const SettingsPopoverContent = ({ onExpandClick, ...props }: Props) => {
<PopoverBody
py="3"
overflowY="auto"
maxH="400px"
ref={ref}
shadow="md"
onMouseEnter={() => setIsHovering(true)}
@ -107,7 +120,8 @@ export const SettingsPopoverContent = ({ onExpandClick, ...props }: Props) => {
>
<SlideFade in={isHovering} unmountOnExit>
<SettingsHoverBar
onExpandClick={onExpandClick}
isExpanded={isExpanded}
onExpandClick={() => setIsExpanded(!isExpanded)}
onVideoOnboardingClick={onOpen}
nodeType={props.node.type}
blockDef={blockDef}