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,
+
+
+
,
+ )}
+
)
},
)