UX improvement: Inputs now correctly lose focus on outside gestures

This commit is contained in:
Aria Minaei 2021-11-14 21:40:50 +01:00
parent fb53be8fe6
commit 8ca44085de
3 changed files with 30 additions and 4 deletions

View file

@ -5,6 +5,7 @@ import styled from 'styled-components'
import DraggableArea from '@theatre/studio/uiComponents/DraggableArea' import DraggableArea from '@theatre/studio/uiComponents/DraggableArea'
import mergeRefs from 'react-merge-refs' import mergeRefs from 'react-merge-refs'
import useRefAndState from '@theatre/studio/utils/useRefAndState' import useRefAndState from '@theatre/studio/utils/useRefAndState'
import useOnClickOutside from '@theatre/studio/uiComponents/useOnClickOutside'
const Container = styled.div` const Container = styled.div`
height: 100%; height: 100%;
@ -124,6 +125,14 @@ const BasicNumberInput: React.FC<{
const inputRef = useRef<HTMLInputElement | null>(null) const inputRef = useRef<HTMLInputElement | null>(null)
useOnClickOutside(
inputRef.current,
() => {
inputRef.current!.blur()
},
stateRef.current.mode === 'editingViaKeyboard',
)
const bodyCursorBeforeDrag = useRef<string | null>(null) const bodyCursorBeforeDrag = useRef<string | null>(null)
const callbacks = useMemo(() => { const callbacks = useMemo(() => {

View file

@ -3,6 +3,7 @@ import type {MutableRefObject} from 'react'
import React, {useMemo, useRef} from 'react' import React, {useMemo, useRef} from 'react'
import mergeRefs from 'react-merge-refs' import mergeRefs from 'react-merge-refs'
import useRefAndState from '@theatre/studio/utils/useRefAndState' import useRefAndState from '@theatre/studio/utils/useRefAndState'
import useOnClickOutside from '@theatre/studio/uiComponents/useOnClickOutside'
const Input = styled.input.attrs({type: 'text'})` const Input = styled.input.attrs({type: 'text'})`
background: transparent; background: transparent;
@ -72,6 +73,14 @@ const BasicStringInput: React.FC<{
const inputRef = useRef<HTMLInputElement | null>(null) const inputRef = useRef<HTMLInputElement | null>(null)
useOnClickOutside(
inputRef.current,
() => {
inputRef.current!.blur()
},
stateRef.current.mode === 'editingViaKeyboard',
)
const callbacks = useMemo(() => { const callbacks = useMemo(() => {
const inputChange = (e: React.ChangeEvent) => { const inputChange = (e: React.ChangeEvent) => {
const target = e.target as HTMLInputElement const target = e.target as HTMLInputElement

View file

@ -1,11 +1,13 @@
import type {$IntentionalAny} from '@theatre/shared/utils/types'
import {useEffect} from 'react' import {useEffect} from 'react'
export default function useOnClickOutside( export default function useOnClickOutside(
container: Element | null, container: Element | null,
onOutside: (e: MouseEvent) => void, onOutside: (e: MouseEvent) => void,
enabled?: boolean,
) { ) {
useEffect(() => { useEffect(() => {
if (!container) return if (!container || enabled === false) return
const onMouseDown = (e: MouseEvent) => { const onMouseDown = (e: MouseEvent) => {
if (!e.composedPath().includes(container)) { if (!e.composedPath().includes(container)) {
@ -13,9 +15,15 @@ export default function useOnClickOutside(
} }
} }
window.addEventListener('mousedown', onMouseDown, {capture: true}) window.addEventListener('mousedown', onMouseDown, {
capture: true,
passive: false,
})
return () => { return () => {
window.removeEventListener('mousedown', onMouseDown, {capture: true}) window.removeEventListener('mousedown', onMouseDown, {
capture: true,
passive: false,
} as unknown as $IntentionalAny)
} }
}, [container, onOutside]) }, [container, enabled])
} }