Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Floating panel v2 #4613

Merged
merged 43 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7698746
wip
kof Dec 17, 2024
086566f
finish positioning logic
kof Dec 18, 2024
1e6ebd6
use floating panel in editor and css value editor
kof Dec 18, 2024
57bc208
position floating panel above the container in case of value editor d…
kof Dec 18, 2024
da5ffc7
deprecate old api
kof Dec 18, 2024
ec8fe0e
better semantics
kof Dec 18, 2024
e9e6a71
remove effect
kof Dec 18, 2024
1e761ae
semantics
kof Dec 18, 2024
c9b2066
move floating panel to the design system
kof Dec 18, 2024
266f3a9
migrating to dialog
kof Dec 18, 2024
9756d47
floatingPanelStyle
kof Dec 18, 2024
95f436b
move TitleSlot
kof Dec 18, 2024
a7b19df
delete floating-panel file from the builder
kof Dec 18, 2024
58431ef
use floating panel in binding popover
kof Dec 18, 2024
aa42113
use floatingPanel from variable-popover
kof Dec 18, 2024
3447030
delete useSideOffset
kof Dec 18, 2024
bcba312
use popover in publish
kof Dec 18, 2024
31e9abd
use popover in share dialog
kof Dec 18, 2024
6dcf6ef
use popover in image info
kof Dec 18, 2024
df79cf4
use popover in the stories
kof Dec 18, 2024
67478a6
delete floating panel popover
kof Dec 18, 2024
45e589f
unused stories
kof Dec 18, 2024
69d3fad
use layout effect
kof Dec 18, 2024
d54a1f0
lint
kof Dec 18, 2024
9d461ab
use the right shadow, use inline position for object position
kof Dec 18, 2024
deec61b
offset position below the button
kof Dec 18, 2024
068f939
use inline position for advanced typography
kof Dec 18, 2024
a2f479f
use inline position for advanced settings of flex child and transforms
kof Dec 18, 2024
6465f67
position adjustment with resize observer
kof Dec 18, 2024
0ccfc1e
fix position calculation
kof Dec 18, 2024
f76a72a
fix html embed external editor, move maximize button to the dialog
kof Dec 18, 2024
9b8a457
allow centered dialog to be opened together with the inline/left alig…
kof Dec 18, 2024
303c4a3
min dialog height
kof Dec 18, 2024
8b978fd
rewrite the positioning logic
kof Dec 19, 2024
9774c3f
fix custom code in project settings not having top bar
kof Dec 19, 2024
6106650
project settings dialog now draggable
kof Dec 19, 2024
654d0dd
fix page settings binding panel position
kof Dec 19, 2024
8d950ac
Merge branch 'main' into floating-panel-v2
kof Dec 19, 2024
61107ed
fix share dialog border radius
kof Dec 19, 2024
dd25b51
fix stories
kof Dec 19, 2024
5648c73
fix popover corners
kof Dec 19, 2024
519b369
Merge branch 'main' into floating-panel-v2
kof Dec 19, 2024
32de542
add stories
kof Dec 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
use floating panel in editor and css value editor
  • Loading branch information
kof committed Dec 18, 2024
commit 1e6ebd68565b4ce48a2f117d19bd157000051e4c
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,10 @@ export const CssFragmentEditorContent = ({

export const CssFragmentEditor = ({
title,
open,
content,
onOpenChange,
}: {
title?: ReactNode;
open?: boolean;
content: ReactNode;
onOpenChange?: (newOpen: boolean) => void;
}) => {
Expand All @@ -113,7 +111,6 @@ export const CssFragmentEditor = ({
<EditorDialogControl>
{content}
<EditorDialog
open={open}
onOpenChange={onOpenChange}
title={title}
content={content}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import {
NestedInputButton,
rawTheme,
theme,
} from "@webstudio-is/design-system";
import { NestedInputButton, theme } from "@webstudio-is/design-system";
import { MaximizeIcon } from "@webstudio-is/icons";
import { useEffect, useRef, useState } from "react";
import { useEffect, useState } from "react";
import { EditorDialog } from "~/builder/shared/code-editor-base";
import { CssFragmentEditorContent } from "../css-fragment";
import type {
Expand Down Expand Up @@ -39,8 +35,6 @@ export const isComplexValue = (value: CssValueInputValue) => {
return false;
};

const width = parseFloat(rawTheme.sizes.sidebarWidth);

export const ValueEditorDialog = ({
property,
value,
Expand All @@ -58,25 +52,6 @@ export const ValueEditorDialog = ({
setIntermediateValue({ type: "intermediate", value });
}, [value]);

const triggerRef = useRef<HTMLButtonElement>(null);

const [rect, setRect] = useState(() => ({
height: 200,
width,
x: window.innerWidth - width,
y: 0,
}));

const handleOpenChange = (isOpen: boolean) => {
if (isOpen && triggerRef.current) {
const triggerRect = triggerRef.current.getBoundingClientRect();
setRect({
...rect,
y: triggerRect.y,
});
}
};

const handleChange = (value: string) => {
const parsedValue = parseIntermediateOrInvalidValue(property, {
type: "intermediate",
Expand Down Expand Up @@ -111,8 +86,6 @@ export const ValueEditorDialog = ({
return (
<EditorDialog
title="CSS Value"
onOpenChange={handleOpenChange}
{...rect}
content={
<CssFragmentEditorContent
autoFocus
Expand All @@ -133,7 +106,6 @@ export const ValueEditorDialog = ({
display: "block",
},
}}
ref={triggerRef}
>
<MaximizeIcon size={12} />
</NestedInputButton>
Expand Down
87 changes: 19 additions & 68 deletions apps/builder/app/builder/shared/code-editor-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
useEffect,
useRef,
type ReactNode,
useState,
forwardRef,
type ComponentProps,
type RefObject,
Expand Down Expand Up @@ -32,21 +31,16 @@ import {
textVariants,
css,
SmallIconButton,
Dialog,
DialogTrigger,
DialogContent,
Grid,
DialogTitle,
Button,
DialogClose,
Flex,
rawTheme,
globalCss,
Kbd,
Text,
} from "@webstudio-is/design-system";
import { CrossIcon, MaximizeIcon, MinimizeIcon } from "@webstudio-is/icons";
import { MaximizeIcon } from "@webstudio-is/icons";
import { solarizedLight } from "./code-highlight";
import { FloatingPanel } from "./floating-panel";

// This undocumented flag is required to keep contenteditable fields editable after the first activation of EditorView.
// To reproduce the issue, open any Binding dialog and then try to edit a Navigation Item in the Navigation menu.
Expand Down Expand Up @@ -423,42 +417,28 @@ export const EditorDialogButton = forwardRef<
EditorDialogButton.displayName = "EditorDialogButton";

export const EditorDialog = ({
open,
onOpenChange,
title,
content,
children,
width = 640,
height = 480,
x,
y,
open,
onOpenChange,
}: {
open?: boolean;
onOpenChange?: (newOpen: boolean) => void;
title?: ReactNode;
content: ReactNode;
children: ReactNode;
x?: number;
y?: number;
width?: number;
height?: number;
open?: boolean;
onOpenChange?: (newOpen: boolean) => void;
}) => {
const [isMaximized, setIsMaximized] = useState(false);
return (
<Dialog open={open} onOpenChange={onOpenChange} modal={false}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent
resize="auto"
width={width}
height={height}
x={x}
y={y}
minHeight={240}
isMaximized={isMaximized}
onInteractOutside={(event) => {
event.preventDefault();
}}
>
<FloatingPanel
title={title}
onOpenChange={onOpenChange}
width={640}
height={480}
align="center"
maximizable
open={open}
content={
<Grid
align="stretch"
css={{
Expand All @@ -470,38 +450,9 @@ export const EditorDialog = ({
>
{content}
</Grid>
{/* Title is at the end intentionally,
* to make the close button last in the tab order
*/}
<DialogTitle
draggable
suffix={
<Flex
gap="1"
onMouseDown={(event) => {
// Prevent dragging dialog
event.preventDefault();
}}
>
<Button
color="ghost"
prefix={isMaximized ? <MinimizeIcon /> : <MaximizeIcon />}
aria-label="Expand"
onClick={() => setIsMaximized(isMaximized ? false : true)}
/>
<DialogClose asChild>
<Button
color="ghost"
prefix={<CrossIcon />}
aria-label="Close"
/>
</DialogClose>
</Flex>
}
>
{title}
</DialogTitle>
</DialogContent>
</Dialog>
}
>
{children}
</FloatingPanel>
);
};
32 changes: 24 additions & 8 deletions apps/builder/app/builder/shared/floating-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
type JSX,
type ComponentProps,
useEffect,
type ReactNode,
} from "react";
import {
theme,
Expand Down Expand Up @@ -81,11 +82,15 @@ export const FloatingPanelProvider = ({
);

type FloatingPanelProps = {
title: string;
content: JSX.Element;
children: JSX.Element;
title: ReactNode;
content: ReactNode;
children: ReactNode;
maximizable?: boolean;
resize?: ComponentProps<typeof DialogContent>["resize"];
width?: number;
height?: number;
align?: "left" | "center";
open?: boolean;
onOpenChange?: (isOpen: boolean) => void;
};

Expand All @@ -99,6 +104,10 @@ export const FloatingPanel = ({
children,
resize,
maximizable,
width,
height,
align,
open,
onOpenChange,
}: FloatingPanelProps) => {
const { container: containerRef } = useContext(FloatingPanelContext);
Expand All @@ -115,7 +124,12 @@ export const FloatingPanel = ({
}));

useEffect(() => {
kof marked this conversation as resolved.
Show resolved Hide resolved
if (!triggerRef.current || !containerRef.current || !contentElement) {
if (
!triggerRef.current ||
!containerRef.current ||
!contentElement ||
align === "center"
) {
return;
}
const triggerRect = triggerRef.current.getBoundingClientRect();
Expand All @@ -127,19 +141,21 @@ export const FloatingPanel = ({
? window.innerHeight - contentRect.height
: triggerRect.y;
setRect({ x, y });
}, [contentElement, containerRef]);
}, [contentElement, containerRef, align]);

return (
<Dialog modal={false} onOpenChange={onOpenChange}>
<Dialog open={open} modal={false} onOpenChange={onOpenChange}>
<DialogTrigger asChild ref={triggerRef}>
{children}
</DialogTrigger>
<DialogContent
draggable
resize={resize}
className={contentStyle()}
x={rect.x}
y={rect.y}
{...(align === "center" ? {} : rect)}
width={width}
height={height}
isMaximized={isMaximized}
onInteractOutside={(event) => {
event.preventDefault();
}}
Expand Down