From fe86b355a911ea986cd059c12f74512d50a5f35d Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Mon, 21 Oct 2024 20:25:09 +0200 Subject: [PATCH 1/3] open menu with right click on title --- .../src/components/inspector/flex-section.tsx | 39 ++++++++++++++++--- editor/src/uuiui/radix-components.tsx | 15 ++++++- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/editor/src/components/inspector/flex-section.tsx b/editor/src/components/inspector/flex-section.tsx index 5114495c30a3..ea9ef2d445ad 100644 --- a/editor/src/components/inspector/flex-section.tsx +++ b/editor/src/components/inspector/flex-section.tsx @@ -4,7 +4,7 @@ import { jsx } from '@emotion/react' import React from 'react' import { createSelector } from 'reselect' -import { unless, when } from '../../utils/react-conditionals' +import { when } from '../../utils/react-conditionals' import { Substores, useEditorState, useRefEditorState } from '../editor/store/store-hook' import { AddRemoveLayoutSystemControl } from './add-remove-layout-system-control' import { FlexDirectionToggle } from './flex-direction-control' @@ -554,9 +554,15 @@ function AxisDimensionControl({ opener: (isOpen: boolean) => React.ReactElement }) { const testId = `grid-dimension-${axis}-${index}` - const [isOpen, setIsOpen] = React.useState(false) - const onOpenChange = React.useCallback((isDropdownOpen: boolean) => { - setIsOpen(isDropdownOpen) + const [isDotsMenuOpen, setDotsMenuOpen] = React.useState(false) + const [isTitleMenuOpen, setTitleMenuOpen] = React.useState(false) + + const onOpenChangeDotsMenu = React.useCallback((isDropdownOpen: boolean) => { + setDotsMenuOpen(isDropdownOpen) + }, []) + + const onOpenChangeTitleMenu = React.useCallback(() => { + setTitleMenuOpen(false) }, []) const isDynamic = React.useMemo(() => { @@ -584,6 +590,14 @@ function AxisDimensionControl({ setIsHovered(false) }, []) + const onContextMenuTitle = React.useCallback((e: React.MouseEvent) => { + e.preventDefault() + e.stopPropagation() + setTitleMenuOpen(true) + }, []) + + const invisibleOpener = React.useCallback(() => null, []) + return (
{title} + {when( - (isHovered && !gridExpressionInputFocused.focused) || isOpen, + (isHovered && !gridExpressionInputFocused.focused) || isDotsMenuOpen, - + , )}
diff --git a/editor/src/uuiui/radix-components.tsx b/editor/src/uuiui/radix-components.tsx index 86ed787124af..00568db5e82f 100644 --- a/editor/src/uuiui/radix-components.tsx +++ b/editor/src/uuiui/radix-components.tsx @@ -90,6 +90,7 @@ export interface DropdownMenuProps { alignOffset?: number onOpenChange?: (open: boolean) => void style?: CSSProperties + isOpen?: boolean } export const ItemContainerTestId = (id: string) => `item-container-${id}` @@ -103,7 +104,7 @@ export const DropdownMenu = React.memo((props) => { }, []) const onEscapeKeyDown = React.useCallback((e: KeyboardEvent) => e.stopPropagation(), []) - const [open, setOpen] = React.useState(false) + const [open, setOpen] = useIsDropdownMenuOpen(props.isOpen ?? null) const shouldShowCheckboxes = props.items.some( (i) => !isSeparatorDropdownMenuItem(i) && i.checked != null, @@ -408,3 +409,15 @@ export const RadixSelect = React.memo( }, ) RadixSelect.displayName = 'RadixSelect' + +function useIsDropdownMenuOpen(isOpenFromProps: boolean | null) { + const state = React.useState(isOpenFromProps || false) + const [, setOpen] = state + + // If the `isOpen` value coming from props changes, update the state. + React.useEffect(() => { + setOpen(isOpenFromProps || false) + }, [setOpen, isOpenFromProps]) + + return state +} From beccf7216a3b11ab9815a8cf2e3ed1cdf223972c Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:02:17 +0200 Subject: [PATCH 2/3] usePropControlledStateV2 --- editor/src/uuiui/radix-components.tsx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/editor/src/uuiui/radix-components.tsx b/editor/src/uuiui/radix-components.tsx index 00568db5e82f..d68472776ba8 100644 --- a/editor/src/uuiui/radix-components.tsx +++ b/editor/src/uuiui/radix-components.tsx @@ -11,6 +11,7 @@ import { Icons, SmallerIcons } from './icons' import { when } from '../utils/react-conditionals' import { Icn, type IcnProps } from './icn' import { forceNotNull } from '../core/shared/optional-utils' +import { usePropControlledStateV2 } from '../components/inspector/common/inspector-utils' // Keep this in sync with the radix-components-portal div in index.html. export const RadixComponentsPortalId = 'radix-components-portal' @@ -104,7 +105,7 @@ export const DropdownMenu = React.memo((props) => { }, []) const onEscapeKeyDown = React.useCallback((e: KeyboardEvent) => e.stopPropagation(), []) - const [open, setOpen] = useIsDropdownMenuOpen(props.isOpen ?? null) + const [open, setOpen] = usePropControlledStateV2(props.isOpen || false) const shouldShowCheckboxes = props.items.some( (i) => !isSeparatorDropdownMenuItem(i) && i.checked != null, @@ -409,15 +410,3 @@ export const RadixSelect = React.memo( }, ) RadixSelect.displayName = 'RadixSelect' - -function useIsDropdownMenuOpen(isOpenFromProps: boolean | null) { - const state = React.useState(isOpenFromProps || false) - const [, setOpen] = state - - // If the `isOpen` value coming from props changes, update the state. - React.useEffect(() => { - setOpen(isOpenFromProps || false) - }, [setOpen, isOpenFromProps]) - - return state -} From a21a685b0579b30c8fab2a38d736582c4d67e6ba Mon Sep 17 00:00:00 2001 From: Federico Ruggi <1081051+ruggi@users.noreply.github.com> Date: Tue, 22 Oct 2024 12:13:19 +0200 Subject: [PATCH 3/3] rename --- editor/src/components/inspector/flex-section.tsx | 2 +- editor/src/uuiui/radix-components.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/editor/src/components/inspector/flex-section.tsx b/editor/src/components/inspector/flex-section.tsx index ea9ef2d445ad..5d27487c3357 100644 --- a/editor/src/components/inspector/flex-section.tsx +++ b/editor/src/components/inspector/flex-section.tsx @@ -633,7 +633,7 @@ function AxisDimensionControl({ items={items} opener={invisibleOpener} onOpenChange={onOpenChangeTitleMenu} - isOpen={isTitleMenuOpen} + forceOpen={isTitleMenuOpen} /> void style?: CSSProperties - isOpen?: boolean + forceOpen?: boolean } export const ItemContainerTestId = (id: string) => `item-container-${id}` @@ -105,7 +105,7 @@ export const DropdownMenu = React.memo((props) => { }, []) const onEscapeKeyDown = React.useCallback((e: KeyboardEvent) => e.stopPropagation(), []) - const [open, setOpen] = usePropControlledStateV2(props.isOpen || false) + const [open, setOpen] = usePropControlledStateV2(props.forceOpen || false) const shouldShowCheckboxes = props.items.some( (i) => !isSeparatorDropdownMenuItem(i) && i.checked != null,