From de7afad5b00adb83ab7549d36db0a2be652f0f9c Mon Sep 17 00:00:00 2001
From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com>
Date: Thu, 13 Jun 2024 23:34:30 +0200
Subject: [PATCH] Short Cartouches (#5925)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
**Problem:**
The cartouches in the navigator and the inspector don't currently have a
max width and they can be overlong.
**Fix:**
For property and element accessors, only show the last bit.
**Commit Details:**
- Added `shortLabel` to `getTextContentOfElement`
- If the DataReferenceCartouche has a non-null shortLabel, it is used
- The tooltip always shows the long label
**Bonus**
The PR also changes when do we hide the cartouche icon – the new ruleset
only hides the cartouche icon for inline value literals such as
`myProp="value"` and `
{'myValue'}
`
---
.../component-section/cartouche-control.tsx | 9 +++-
.../component-section/cartouche-ui.tsx | 15 ++----
.../component-section-children.tsx | 4 +-
.../component-section/component-section.tsx | 5 +-
.../data-reference-cartouche.tsx | 53 ++++++++++++-------
.../data-selector-cartouche.tsx | 7 ++-
.../navigator-condensed-entry.tsx | 1 -
7 files changed, 55 insertions(+), 39 deletions(-)
diff --git a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx
index b8dc71b89fba..725643c4285f 100644
--- a/editor/src/components/inspector/sections/component-section/cartouche-control.tsx
+++ b/editor/src/components/inspector/sections/component-section/cartouche-control.tsx
@@ -2,6 +2,7 @@
/** @jsx jsx */
import React from 'react'
import { jsx } from '@emotion/react'
+import type { DataReferenceCartoucheContentType } from './data-reference-cartouche'
import { DataCartoucheInner } from './data-reference-cartouche'
import { NO_OP } from '../../../../core/shared/utils'
import type { ElementPath, PropertyPath } from '../../../../core/shared/project-file-types'
@@ -12,7 +13,11 @@ import type { CartoucheDataType } from './cartouche-ui'
import { useColorTheme } from '../../../../uuiui'
interface IdentifierExpressionCartoucheControlProps {
- contents: string
+ contents: {
+ type: DataReferenceCartoucheContentType
+ label: string | null
+ shortLabel: string | null
+ }
icon: React.ReactChild
matchType: 'full' | 'partial'
onOpenDataPicker: () => void
@@ -42,7 +47,7 @@ export const IdentifierExpressionCartoucheControl = React.memo(
return (
- {source === 'literal' ? null : (
+ {source === 'inline-literal' ? null : (
{/* this div prevents the popup form putting padding into the condensed rows */}
@@ -170,16 +168,20 @@ export const DataReferenceCartoucheControl = React.memo(
},
)
+export type DataReferenceCartoucheContentType = 'value-literal' | 'object-literal' | 'reference'
interface DataCartoucheInnerProps {
onClick: (e: React.MouseEvent) => void
onDoubleClick: (e: React.MouseEvent) => void
selected: boolean
- contentsToDisplay: { type: 'literal' | 'reference'; label: string | null }
+ contentsToDisplay: {
+ type: DataReferenceCartoucheContentType
+ label: string | null
+ shortLabel: string | null
+ }
safeToDelete: boolean
onDelete: () => void
testId: string
contentIsComingFromServer: boolean
- hideTooltip?: boolean
datatype: CartoucheDataType
highlight?: CartoucheHighlight | null
badge?: React.ReactNode
@@ -211,8 +213,10 @@ export const DataCartoucheInner = React.forwardRef(
const onDelete = safeToDelete ? onDeleteInner : undefined
const source: CartoucheUIProps['source'] =
- contentsToDisplay.type === 'literal'
- ? 'literal'
+ contentsToDisplay.type === 'value-literal'
+ ? 'inline-literal'
+ : contentsToDisplay.type === 'object-literal'
+ ? 'internal'
: contentIsComingFromServer
? 'external'
: 'internal'
@@ -226,13 +230,13 @@ export const DataCartoucheInner = React.forwardRef(
selected={selected}
highlight={highlight}
testId={testId}
- tooltip={!props.hideTooltip ? contentsToDisplay.label ?? 'DATA' : null}
+ tooltip={contentsToDisplay.label ?? contentsToDisplay.shortLabel ?? 'DATA'}
role='selection'
source={source}
ref={ref}
badge={props.badge}
>
- {contentsToDisplay.label ?? 'DATA'}
+ {contentsToDisplay.shortLabel ?? contentsToDisplay.label ?? 'DATA'}
)
},
@@ -241,46 +245,55 @@ export const DataCartoucheInner = React.forwardRef(
export function getTextContentOfElement(
element: JSXElementChild,
metadata: ElementInstanceMetadata | null,
-): { type: 'literal' | 'reference'; label: string | null } {
+): {
+ type: DataReferenceCartoucheContentType
+ label: string | null
+ shortLabel: string | null
+} {
switch (element.type) {
case 'ATTRIBUTE_VALUE':
- return { type: 'literal', label: `${JSON.stringify(element.value)}` }
+ return { type: 'value-literal', label: `${JSON.stringify(element.value)}`, shortLabel: null }
case 'JSX_TEXT_BLOCK':
- return { type: 'literal', label: element.text.trim() }
+ return { type: 'value-literal', label: element.text.trim(), shortLabel: null }
case 'JS_IDENTIFIER':
- return { type: 'reference', label: element.name.trim() }
+ return { type: 'reference', label: element.name.trim(), shortLabel: null }
case 'JS_ELEMENT_ACCESS':
return {
type: 'reference',
label: `${getTextContentOfElement(element.onValue, null).label}[${
getTextContentOfElement(element.element, null).label
}]`,
+ shortLabel: `${TruncationPrefix}${getTextContentOfElement(element.element, null).label}`,
}
case 'JS_PROPERTY_ACCESS':
return {
type: 'reference',
label: `${getTextContentOfElement(element.onValue, null).label}.${element.property}`,
+ shortLabel: `${TruncationPrefix}${element.property}`,
}
case 'ATTRIBUTE_FUNCTION_CALL':
- return { type: 'reference', label: `${element.functionName}(...` }
+ return { type: 'reference', label: `${element.functionName}(...`, shortLabel: null }
case 'JSX_ELEMENT':
return {
- type: 'literal',
+ type: 'object-literal',
label: metadata?.textContent ?? `${getJSXElementNameLastPart(element.name)}`,
+ shortLabel: null,
}
case 'ATTRIBUTE_NESTED_ARRAY':
- return { type: 'literal', label: '[...]' }
+ return { type: 'object-literal', label: '[...]', shortLabel: null }
case 'ATTRIBUTE_NESTED_OBJECT':
- return { type: 'literal', label: '{...}' }
+ return { type: 'object-literal', label: '{...}', shortLabel: null }
case 'JSX_MAP_EXPRESSION':
- return { type: 'literal', label: 'List' }
+ return { type: 'object-literal', label: 'List', shortLabel: null }
case 'JSX_CONDITIONAL_EXPRESSION':
- return { type: 'literal', label: 'Conditional' }
+ return { type: 'object-literal', label: 'Conditional', shortLabel: null }
case 'ATTRIBUTE_OTHER_JAVASCRIPT':
- return { type: 'literal', label: element.originalJavascript }
+ return { type: 'object-literal', label: element.originalJavascript, shortLabel: null }
case 'JSX_FRAGMENT':
- return { type: 'literal', label: 'Fragment' }
+ return { type: 'object-literal', label: 'Fragment', shortLabel: null }
default:
assertNever(element)
}
}
+
+const TruncationPrefix = `…`
diff --git a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx
index e3b82e694d80..78ecb262cf3b 100644
--- a/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx
+++ b/editor/src/components/inspector/sections/component-section/data-selector-cartouche.tsx
@@ -26,6 +26,7 @@ export const DataPickerCartouche = React.memo(
return (
{
@@ -77,7 +80,7 @@ export function useVariableDataSource(variable: DataPickerOption | null) {
return 'external'
case 'literal-attribute':
case 'literal-assignment':
- return 'literal'
+ return 'literal-assignment'
case 'component-prop':
case 'element-at-scope':
case 'failed':
diff --git a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx
index 16ba8ea481cc..60f9e0afce4e 100644
--- a/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx
+++ b/editor/src/components/navigator/navigator-item/navigator-condensed-entry.tsx
@@ -426,7 +426,6 @@ const CondensedEntryItemContent = React.memo(
highlight={
props.rowRootSelected ? 'strong' : props.wholeRowInsideSelection ? 'subtle' : null
}
- hideTooltip={true}
/>,
)}