From 9ba3fe191f1fa700368aa6dbaf376546afafb97e Mon Sep 17 00:00:00 2001 From: Sean Parsons <217400+seanparsons@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:54:41 +0100 Subject: [PATCH] fix(inspector) Grid Template Field Dropdowns (#6498) - Integrated some similar logic into `GridExpressionInput` that is in `NumberOrKeywordControl`. - Resurrected `gridDimensionDropdownKeywords` from the previous code so that it can be passed to `GridExpressionInput`. --- .../src/components/inspector/flex-section.tsx | 35 ++++- .../uuiui/inputs/grid-expression-input.tsx | 147 ++++++++++++++++-- 2 files changed, 165 insertions(+), 17 deletions(-) diff --git a/editor/src/components/inspector/flex-section.tsx b/editor/src/components/inspector/flex-section.tsx index 8afca94bc45f..811c3bdd8b67 100644 --- a/editor/src/components/inspector/flex-section.tsx +++ b/editor/src/components/inspector/flex-section.tsx @@ -30,6 +30,7 @@ import { SquareButton, Subdued, Tooltip, + UtopiaTheme, } from '../../uuiui' import type { CSSKeyword, @@ -513,6 +514,12 @@ const TemplateDimensionControl = React.memo( ) TemplateDimensionControl.displayName = 'TemplateDimensionControl' +const gridDimensionDropdownKeywords = [ + { label: 'Auto', value: cssKeyword('auto') }, + { label: 'Min-Content', value: cssKeyword('min-content') }, + { label: 'Max-Content', value: cssKeyword('max-content') }, +] + function AxisDimensionControl({ value, index, @@ -574,10 +581,21 @@ function AxisDimensionControl({ }, }} > -
+
+ {unless( + gridExpressionInputFocused.focused, + + + , + )}
- {unless( - gridExpressionInputFocused.focused, - - - , - )}
) } diff --git a/editor/src/uuiui/inputs/grid-expression-input.tsx b/editor/src/uuiui/inputs/grid-expression-input.tsx index b5a5bf3a1830..ddbfe783de5a 100644 --- a/editor/src/uuiui/inputs/grid-expression-input.tsx +++ b/editor/src/uuiui/inputs/grid-expression-input.tsx @@ -1,3 +1,7 @@ +/** @jsxRuntime classic */ +/** @jsx jsx */ +import { jsx } from '@emotion/react' +import type { CSSProperties } from 'react' import React from 'react' import { cssKeyword, @@ -13,6 +17,16 @@ import { } from '../../components/inspector/common/css-utils' import { isRight } from '../../core/shared/either' import { StringInput } from './string-input' +import type { DropdownMenuItem } from '../radix-components' +import { + DropdownMenu, + regularDropdownMenuItem, + separatorDropdownMenuItem, +} from '../radix-components' +import { Icons, SmallerIcons } from '../icons' +import { NO_OP } from '../../core/shared/utils' +import { unless } from '../../utils/react-conditionals' +import { useColorTheme } from '../styles/theme' interface GridExpressionInputProps { testId: string @@ -21,8 +35,12 @@ interface GridExpressionInputProps { onUpdateDimension: (v: GridDimension) => void onFocus: () => void onBlur: () => void + keywords: Array<{ label: string; value: CSSKeyword }> + style?: CSSProperties } +const DropdownWidth = 25 + export const GridExpressionInput = React.memo( ({ testId, @@ -31,7 +49,11 @@ export const GridExpressionInput = React.memo( onUpdateDimension, onFocus, onBlur, + keywords, + style = {}, }: GridExpressionInputProps) => { + const colorTheme = useColorTheme() + const [printValue, setPrintValue] = React.useState(stringifyGridDimension(value)) React.useEffect(() => setPrintValue(stringifyGridDimension(value)), [value]) @@ -71,16 +93,123 @@ export const GridExpressionInput = React.memo( [printValue, onUpdateNumberOrKeyword, onUpdateDimension, value], ) + const [hover, setHover] = React.useState(false) + const [dropdownOpen, setDropdownOpen] = React.useState(false) + const onMouseOver = React.useCallback(() => { + setHover(true) + }, []) + const onMouseOut = React.useCallback(() => { + setHover(false) + }, []) + + const dropdownButtonId = `${testId}-dropdown` + + const dropdownButton = React.useCallback( + () => ( + + ), + [dropdownButtonId, hover, dropdownOpen], + ) + + const dropdownItems = React.useMemo((): DropdownMenuItem[] => { + let items: DropdownMenuItem[] = [] + items.push( + regularDropdownMenuItem({ + id: 'dropdown-input-value', + icon: , + label: printValue, + disabled: true, + onSelect: NO_OP, + }), + ) + if (keywords.length > 0) { + items.push(separatorDropdownMenuItem('dropdown-separator')) + } + items.push( + ...keywords.map((keyword, idx): DropdownMenuItem => { + return regularDropdownMenuItem({ + id: `dropdown-label-${keyword.value.value}`, + icon:
, + label: keyword.label, + onSelect: () => onUpdateNumberOrKeyword(keyword.value), + }) + }), + ) + return items + }, [keywords, printValue, onUpdateNumberOrKeyword]) + + const [inputFocused, setInputFocused] = React.useState(false) + + const inputOnFocus = React.useCallback(() => { + setInputFocused(true) + onFocus() + }, [onFocus]) + + const inputOnBlur = React.useCallback(() => { + setInputFocused(false) + onBlur() + }, [onBlur]) + return ( - +
+ + {unless( + inputFocused, +
+ +
, + )} +
) }, )