Skip to content

Commit

Permalink
Design: data selector rearrange (#5911)
Browse files Browse the repository at this point in the history
Target design:
<img width="846" alt="image"
src="https://github.com/concrete-utopia/utopia/assets/2226774/19167ba2-3fff-4137-8e37-20d103868e39">

Result on branch:
<img width="865" alt="image"
src="https://github.com/concrete-utopia/utopia/assets/2226774/3c4979d1-dc77-47b9-bda6-ecee4a49abcd">

**Commit Details:**

- Rearranged the basic layout: search bar lives at the top, apply button
moved to the bottom. the "output input field" has been replaced by a
"Selection: [cartouche]" row.
- Left sidebar options are now checkboxes (BUT they still behave like
radio buttons / tabs)
- Added fake source filtering options to the left sidebar
- minor tweaks to paddings etc
- MASSIVE cleanup of code in data-selector-modal
- instead of storing `selectedPath`, we store `selectedVariableOption`
which allowed further simplification of code
- useProcessVariablesInScope no longer necessary

**Manual Tests:**
I hereby swear that:

- [x] I opened a hydrogen project and it loaded
- [ ] I could navigate to various routes in Preview mode
  • Loading branch information
balazsbajorics authored Jun 13, 2024
1 parent 5289026 commit df11d08
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 313 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export function getEnclosingScopes(
MetadataUtils.isJSXMapExpression(parentOfCurrent, metadata) ||
EP.isRootElementOfInstance(current)
) {
result.unshift({
result.push({
insertionCeiling: current,
label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current),
hasContent: buckets.includes(insertionCeilingToString(current)),
Expand All @@ -118,7 +118,7 @@ export function getEnclosingScopes(

// we also add anything that has content in scope even if it's not a component or map
if (buckets.includes(insertionCeilingToString(current))) {
result.unshift({
result.push({
insertionCeiling: current,
label: outletNameHack(metadata, allElementProps, elementPathTree, projectContents, current),
hasContent: true,
Expand All @@ -128,7 +128,7 @@ export function getEnclosingScopes(
}

// Add file root
result.unshift({
result.push({
insertionCeiling: { type: 'file-root' },
label: 'File',
hasContent: buckets.includes(insertionCeilingToString({ type: 'file-root' })),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import type { DataPickerOption } from './data-picker-utils'
interface DataPickerCartoucheProps {
data: DataPickerOption
selected: boolean
forcedRole?: CartoucheUIProps['role']
onClick?: CartoucheUIProps['onClick']
}

export const DataPickerCartouche = React.memo(
(props: React.PropsWithChildren<DataPickerCartoucheProps>) => {
const { data, selected } = props
const { data, selected, forcedRole: forceRole } = props
const dataSource = useVariableDataSource(data)
const children = props.children ?? data.variableInfo.expressionPathPart
return (
Expand All @@ -28,7 +29,7 @@ export const DataPickerCartouche = React.memo(
datatype={childTypeToCartoucheDataType(data.type)}
selected={!data.disabled && selected}
highlight={data.disabled ? 'disabled' : null}
role={data.disabled ? 'information' : 'selection'}
role={forceRole ?? (data.disabled ? 'information' : 'selection')}
testId={`data-selector-option-${data.variableInfo.expression}`}
badge={
data.type === 'array' ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { DataPickerCartouche } from './data-selector-cartouche'
interface DataSelectorColumnsProps {
activeScope: Array<DataPickerOption>
targetPathInsideScope: ObjectPath
onTargetPathChange: (newTargetPath: ObjectPath) => void
onTargetPathChange: (newTargetVariable: DataPickerOption) => void
}

export const DataSelectorColumns = React.memo((props: DataSelectorColumnsProps) => {
Expand Down Expand Up @@ -38,7 +38,7 @@ interface DataSelectorColumnProps {
activeScope: Array<DataPickerOption>
currentlyShowingScopeForArray: boolean
targetPathInsideScope: ObjectPath
onTargetPathChange: (newTargetPath: ObjectPath) => void
onTargetPathChange: (newTargetVariable: DataPickerOption) => void
}

const DataSelectorColumn = React.memo((props: DataSelectorColumnProps) => {
Expand Down Expand Up @@ -156,18 +156,17 @@ interface RowWithCartoucheProps {
onActivePath: boolean
forceShowArrow: boolean
isLeaf: boolean
onTargetPathChange: (newTargetPath: ObjectPath) => void
onTargetPathChange: (newTargetVariable: DataPickerOption) => void
}
const RowWithCartouche = React.memo((props: RowWithCartoucheProps) => {
const { onTargetPathChange, data, isLeaf, selected, onActivePath, forceShowArrow } = props
const targetPath = data.valuePath

const onClick: React.MouseEventHandler<HTMLDivElement> = React.useCallback(
(e) => {
e.stopPropagation()
onTargetPathChange(targetPath)
onTargetPathChange(data)
},
[targetPath, onTargetPathChange],
[data, onTargetPathChange],
)

const ref = useScrollIntoView(selected)
Expand Down Expand Up @@ -204,13 +203,14 @@ const DataSelectorFlexColumn = styled(FlexColumn)({
overflowY: 'scroll',
scrollbarWidth: 'auto',
scrollbarColor: 'gray transparent',
paddingTop: 8,
paddingRight: 10, // to account for scrollbar
paddingLeft: 6,
paddingBottom: 10,
borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`,
})

export const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({
const DataPickerRow = styled(FlexRow)((props: { disabled: boolean }) => ({
alignSelf: 'stretch',
justifyContent: 'space-between',
fontSize: 10,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react'
import type { ElementPath } from 'utopia-shared/src/types'
import { FlexColumn, FlexRow, LargerIcons, colorTheme } from '../../../../uuiui'
import { CheckboxInput, FlexColumn, FlexRow, LargerIcons, colorTheme } from '../../../../uuiui'
import {
insertionCeilingToString,
insertionCeilingsEqual,
type FileRootPath,
} from '../../../canvas/ui-jsx-canvas'
import { stopPropagation } from '../../common/inspector-utils'
import { DataPickerRow } from './data-selector-columns'
import { NO_OP } from '../../../../core/shared/utils'

interface SelectableScope {
label: string
Expand All @@ -24,10 +24,19 @@ interface DataSelectorLeftSidebarProps {
export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSidebarProps) => {
const { scopes, setSelectedScope, activeScope } = props
return (
<>
<span style={{ fontSize: 10, fontWeight: 'bold', color: colorTheme.fg4.cssValue }}>
Sources
</span>
<FlexColumn
onClick={stopPropagation}
style={{
alignSelf: 'stretch',
minWidth: 150,
paddingLeft: 16,
paddingTop: 8,
paddingRight: 8,
borderRight: `1px solid ${colorTheme.subduedBorder.cssValue}`,
contain: 'layout',
}}
>
<span style={{ fontSize: 10, fontWeight: 500, color: colorTheme.fg5.cssValue }}>Sources</span>
<FlexColumn>
{scopes.map((scope) => {
return (
Expand All @@ -41,7 +50,33 @@ export const DataSelectorLeftSidebar = React.memo((props: DataSelectorLeftSideba
)
})}
</FlexColumn>
</>
<span
style={{
marginTop: 32,
fontSize: 10,
fontWeight: 500,
color: colorTheme.fg5.cssValue,
}}
>
Origin
</span>
<FlexColumn>
<RowWithCheckbox
label={'Local'}
color={colorTheme.selectionBlue.value}
selected={true}
disabled={false}
onClick={NO_OP}
/>
<RowWithCheckbox
label={'Loader'}
color={colorTheme.green.value}
selected={true}
disabled={false}
onClick={NO_OP}
/>
</FlexColumn>
</FlexColumn>
)
})

Expand All @@ -65,16 +100,46 @@ const ScopeRow = React.memo(
)

return (
<DataPickerRow
style={{
backgroundColor: selected ? colorTheme.bg4.value : undefined,
color: disabled ? colorTheme.fg6.value : colorTheme.neutralForeground.value,
}}
onClick={onClick}
<RowWithCheckbox
label={scope.label}
selected={selected}
disabled={disabled}
>
{scope.label}
</DataPickerRow>
onClick={onClick}
/>
)
},
)

interface RowWithCheckboxProps {
label: string
color?: string
selected: boolean
disabled: boolean
onClick: (e: React.MouseEvent<HTMLDivElement>) => void
}

const RowWithCheckbox = React.memo((props: RowWithCheckboxProps) => {
const { label, color, selected, disabled, onClick } = props
return (
<FlexRow
style={{
justifyContent: 'flex-start',
gap: 8,
fontSize: 11,
fontWeight: 400,
color: color ?? (disabled ? colorTheme.fg6.value : colorTheme.fg2.value),
}}
onClick={onClick}
>
<CheckboxInput
style={{
backgroundColor: colorTheme.bg0.value,
border: `1px solid ${colorTheme.fg4.cssValue}`,
}}
checked={selected}
onChange={stopPropagation}
/>
{label}
</FlexRow>
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('data selector modal', () => {

expect(editor.renderedDOM.getByText('Apply')).not.toBeNull()
expect(editor.renderedDOM.getByTestId(DataSelectorPopupBreadCrumbsTestId).innerText).toEqual(
['header', '.title'].join('\n'),
expect.stringContaining('Selection:'),
)
})
})
Expand Down
Loading

0 comments on commit df11d08

Please sign in to comment.