Skip to content

Commit

Permalink
Duplicate cursor when alt is pressed (#6115)
Browse files Browse the repository at this point in the history
**Problem:**
We should show the duplicate mouse cursor when alt is pressed, even
before the interaction starts (so the user knows what is going to
happen).

**Fix:**
Set the canvas control cursor to the duplicate cursor when alt is
pressed.

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

- [x] I opened a hydrogen project and it loaded
- [x] I could navigate to various routes in Preview mode

Fixes #6083
  • Loading branch information
gbalint authored Jul 24, 2024
1 parent 1789889 commit a43854d
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { BakedInStoryboardUID } from '../../../core/model/scene-utils'
import * as EP from '../../../core/shared/element-path'
import { altModifier } from '../../../utils/modifiers'
import {
makeTestProjectCodeWithSnippet,
renderTestEditorWithCode,
TestAppUID,
TestSceneUID,
} from '../../canvas//ui-jsx.test-utils'
import { selectComponents } from '../../editor/actions/meta-actions'
import { keyDown } from '../event-helpers.test-utils'

describe('Canvas Controls', () => {
it('absolute children outline only included for non-group absolutely positioned elements', async () => {
Expand Down Expand Up @@ -106,3 +108,27 @@ describe('Canvas Controls', () => {
expect(possibleAbsoluteControlForDiv).not.toBeNull()
})
})

describe('Mouse Cursor', () => {
it('Uses the default cursor in select mode', async () => {
const renderResult = await renderTestEditorWithCode(
makeTestProjectCodeWithSnippet('<div/>'),
'await-first-dom-report',
)

const canvasControls = renderResult.renderedDOM.getByTestId('canvas-controls')

expect(canvasControls.style.cursor).toContain('cursor-default.png')
})
it('Uses the duplicate cursor in select mode when ALT is pressed', async () => {
const renderResult = await renderTestEditorWithCode(
makeTestProjectCodeWithSnippet('<div/>'),
'await-first-dom-report',
)

await keyDown('Alt', { modifiers: altModifier })
const canvasControls = renderResult.renderedDOM.getByTestId('canvas-controls')

expect(canvasControls.style.cursor).toContain('cursor-duplicate.png')
})
})
14 changes: 12 additions & 2 deletions editor/src/components/canvas/controls/new-canvas-controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import type {
} from '../../editor/store/editor-state'
import { getMetadata } from '../../editor/store/editor-state'
import type { ElementPath, NodeModules } from '../../../core/shared/project-file-types'
import type { CanvasPositions, CSSCursor } from '../canvas-types'
import type { CanvasPositions } from '../canvas-types'
import { CSSCursor } from '../canvas-types'
import { HighlightControl } from './highlight-control'
import { Substores, useEditorState } from '../../editor/store/store-hook'
import type { ElementInstanceMetadataMap } from '../../../core/shared/element-template'
Expand Down Expand Up @@ -181,6 +182,14 @@ export const NewCanvasControls = React.memo((props: NewCanvasControlsProps) => {

const ref = React.useRef<HTMLDivElement | null>(null)

const selectModeCursor = React.useMemo(() => {
const altKeyPressed = canvasControlProps.keysPressed.alt ?? false
if (altKeyPressed) {
return CSSCursor.Duplicate
}
return props.cursor
}, [props.cursor, canvasControlProps.keysPressed.alt])

if (isLiveMode(canvasControlProps.editorMode) && !canvasControlProps.keysPressed.cmd) {
return (
<div
Expand Down Expand Up @@ -219,6 +228,7 @@ export const NewCanvasControls = React.memo((props: NewCanvasControlsProps) => {
: ' canvas-controls '
}
id='canvas-controls'
data-testid='canvas-controls'
style={{
pointerEvents: 'initial',
position: 'absolute',
Expand All @@ -228,7 +238,7 @@ export const NewCanvasControls = React.memo((props: NewCanvasControlsProps) => {
width: `100%`,
height: `100%`,
zoom: canvasControlProps.scale >= 1 ? `${canvasControlProps.scale * 100}%` : 1,
cursor: props.cursor,
cursor: selectModeCursor,
visibility: canvasControlProps.canvasScrollAnimation ? 'hidden' : 'initial',
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Array [
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)()",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)()",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div:data-testid='canvas-controls'",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)(MultiplayerPresence)",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)(MultiplayerWrapper)",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/UtopiaSpiedExoticType(Symbol(react.fragment))",
Expand Down Expand Up @@ -734,7 +734,7 @@ Array [
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)()",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)()",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/div:data-testid='canvas-controls'",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)(MultiplayerPresence)",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/Symbol(react.memo)(MultiplayerWrapper)",
"/UtopiaSpiedClass(EditorCanvas)/div/NewCanvasControls/UtopiaSpiedExoticType(Symbol(react.fragment))",
Expand Down

0 comments on commit a43854d

Please sign in to comment.