diff --git a/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/DetailCompoundPropEditor.tsx b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/DetailCompoundPropEditor.tsx index 4136bef2e..22a9558b0 100644 --- a/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/DetailCompoundPropEditor.tsx +++ b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/DetailCompoundPropEditor.tsx @@ -29,10 +29,11 @@ import {usePrism} from '@theatre/react' import {val} from '@theatre/dataverse' import {HiOutlineChevronRight} from 'react-icons/all' import memoizeFn from '@theatre/utils/memoizeFn' +import {collapsedMap} from './collapsedMap' const Container = styled.div` --step: 15px; - --left-pad: 15px; + --left-pad: 10px; ${pointerEventsAutoInNormalMode}; --right-width: 60%; ` @@ -193,8 +194,11 @@ function DetailCompoundPropEditor< propConfig, ) + const label = propName || 'Props' + const [contextMenu] = useContextMenu(propNameContainer, { menuItems: tools.contextMenuItems, + displayName: `${label}`, }) const lastSubPropIsComposite = compositeSubs.length > 0 @@ -241,7 +245,7 @@ function DetailCompoundPropEditor< isHighlighted={isPropHighlightedD} ref={propNameContainerRef} > - {propName || 'Props'} + {label} >() diff --git a/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/SingleRowPropEditor.tsx b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/SingleRowPropEditor.tsx index e79e3d66a..7abaa1b98 100644 --- a/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/SingleRowPropEditor.tsx +++ b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/SingleRowPropEditor.tsx @@ -111,6 +111,7 @@ export function SingleRowPropEditor({ useRefAndState(null) const [contextMenu] = useContextMenu(propNameContainer, { + displayName: `${label}`, menuItems: editingTools.contextMenuItems, }) diff --git a/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/collapsedMap.tsx b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/collapsedMap.tsx new file mode 100644 index 000000000..bca84901f --- /dev/null +++ b/theatre/studio/src/panels/DetailPanel/DeterminePropEditorForDetail/collapsedMap.tsx @@ -0,0 +1,3 @@ +import type {Atom} from '@theatre/dataverse' + +export const collapsedMap = new Map>() diff --git a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx index 536ae6145..cbda75796 100644 --- a/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx +++ b/theatre/studio/src/panels/SequenceEditorPanel/GraphEditor/BasicKeyframedTrack/BasicKeyframedTrack.tsx @@ -16,7 +16,10 @@ import { import type {PropTypeConfig_AllSimples} from '@theatre/core/propTypes' import {useVal} from '@theatre/react' import type {GraphEditorColors} from '@theatre/sync-server/state/types' -import {keyframeUtils} from '@theatre/sync-server/state/schema' +import { + graphEditorColors, + keyframeUtils, +} from '@theatre/sync-server/state/schema' export type ExtremumSpace = { fromValueSpace: (v: number) => number @@ -121,11 +124,13 @@ const BasicKeyframedTrack: React.VFC<{ /> )) + const iconColor = graphEditorColors[color].iconColor + return ( {keyframeEditors} diff --git a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/BaseMenu.tsx b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/BaseMenu.tsx index c393db0bd..f0eb9bf25 100644 --- a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/BaseMenu.tsx +++ b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/BaseMenu.tsx @@ -14,23 +14,26 @@ const MenuContainer = styled.ul` position: absolute; min-width: ${minWidth}px; z-index: 10000; - background: ${transparentize(0.2, '#111')}; - backdrop-filter: blur(2px); + background: ${transparentize(0.8, '#000000')}; + backdrop-filter: blur(8px) saturate(300%) contrast(65%) brightness(70%); color: white; + border: 0.5px solid #6262622c; + box-sizing: border-box; + box-shadow: ${transparentize(0.75, '#000000')} 0px 4px 20px; list-style-type: none; - padding: 2px 0; + padding: 0; margin: 0; - border-radius: 1px; + border-radius: 3px; cursor: default; ${pointerEventsAutoInNormalMode}; - border-radius: 3px; + border-radius: 4px; ` const MenuTitle = styled.div` - padding: 4px 10px; - border-bottom: 1px solid #6262626d; - color: #adadadb3; - font-size: 11px; + padding: 8px 10px; + border-bottom: 1px solid #6262621b; + color: #d1d1d1; + font-size: 10px; font-weight: 500; ` diff --git a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/ContextMenu.tsx b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/ContextMenu.tsx index 7c5b960a8..6c0bc33f1 100644 --- a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/ContextMenu.tsx +++ b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/ContextMenu.tsx @@ -9,6 +9,7 @@ import {height as itemHeight} from './Item' import {PortalContext} from 'reakit' import useOnKeyDown from '@theatre/studio/uiComponents/useOnKeyDown' import BaseMenu from './BaseMenu' +import type {$IntentionalAny} from '@theatre/utils/types' /** * How far from the menu should the pointer travel to auto close the menu @@ -17,7 +18,7 @@ const pointerDistanceThreshold = 20 export type IContextMenuItemCustomNodeRenderFn = (controls: { closeMenu(): void -}) => React.ReactChild +}) => React.ReactElement export type IContextMenuItem = { label: string | ElementType @@ -38,6 +39,26 @@ export type ContextMenuProps = { clientY: number } onRequestClose: () => void + // default: true + closeOnPointerLeave?: boolean +} + +/** + * Useful helper in development to prevent the context menu from auto-closing, + * so its easier to inspect the DOM / change the styles, etc. + * + * Call window.$disableAutoCloseContextMenu() in the console to disable auto-close + */ +const shouldAutoCloseByDefault = + process.env.NODE_ENV === 'development' + ? (): boolean => + (window as $IntentionalAny).__autoCloseContextMenuByDefault ?? true + : (): boolean => true + +if (process.env.NODE_ENV === 'development') { + ;(window as $IntentionalAny).$disableAutoCloseContextMenu = () => { + ;(window as $IntentionalAny).__autoCloseContextMenuByDefault = false + } } /** @@ -86,7 +107,8 @@ const ContextMenu: React.FC = (props) => { e.clientY < pos.top - pointerDistanceThreshold || e.clientY > pos.top + rect.height + pointerDistanceThreshold ) { - props.onRequestClose() + if (props.closeOnPointerLeave !== false && shouldAutoCloseByDefault()) + props.onRequestClose() } } @@ -95,7 +117,14 @@ const ContextMenu: React.FC = (props) => { return () => { window.removeEventListener('mousemove', onMouseMove) } - }, [rect, container, props.clickPoint, windowSize, props.onRequestClose]) + }, [ + rect, + container, + props.clickPoint, + windowSize, + props.onRequestClose, + props.closeOnPointerLeave, + ]) const portalLayer = useContext(PortalContext) useOnKeyDown((ev) => { diff --git a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/Item.tsx b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/Item.tsx index b2cb0d5ea..de66fa953 100644 --- a/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/Item.tsx +++ b/theatre/studio/src/uiComponents/simpleContextMenu/ContextMenu/Item.tsx @@ -3,7 +3,7 @@ import type {ElementType} from 'react' import React from 'react' import styled from 'styled-components' -export const height = 26 +export const height = 30 const ItemContainer = styled.li<{enabled: boolean}>` height: ${height}px; @@ -11,25 +11,24 @@ const ItemContainer = styled.li<{enabled: boolean}>` margin: 0; display: flex; align-items: center; - font-size: 11px; font-weight: 400; position: relative; color: ${(props) => (props.enabled ? 'white' : '#8f8f8f')}; - cursor: ${(props) => (props.enabled ? 'normal' : 'not-allowed')}; + cursor: ${(props) => (props.enabled ? 'default' : 'not-allowed')}; &:after { position: absolute; - inset: 2px 1px; + inset: 2px; display: block; content: ' '; pointer-events: none; z-index: -1; - border-radius: 3px; + border-radius: 4px; } &:hover:after { background-color: ${(props) => - props.enabled ? 'rgba(63, 174, 191, 0.75)' : 'initial'}; + props.enabled ? 'rgba(255, 255, 255, 0.075)' : 'initial'}; } `