1- import React , { useState } from 'react' ;
1+ import React , { useState , KeyboardEvent , ChangeEvent , FormEvent } from 'react' ;
22import { useHistory } from 'react-router-dom' ;
33import { useOvermind } from 'app/overmind' ;
44import { sandboxUrl } from '@codesandbox/common/lib/utils/url-generator' ;
5+ import { ESC } from '@codesandbox/common/lib/utils/keycodes' ;
56import {
67 Stack ,
78 Element ,
@@ -26,8 +27,19 @@ export const SandboxCard = ({ sandbox, isTemplate = false, ...props }) => {
2627 alias : sandbox . alias ,
2728 } ) ;
2829
29- const editSandboxTitle = async e => {
30- e . preventDefault ( ) ;
30+ const onChange = ( event : ChangeEvent < HTMLInputElement > ) => {
31+ setNewName ( event . target . value ) ;
32+ } ;
33+ const onKeyDown = ( event : KeyboardEvent < HTMLInputElement > ) => {
34+ if ( event . keyCode === ESC ) {
35+ // Reset value and exit without saving
36+ setNewName ( sandboxTitle ) ;
37+ setEdit ( false ) ;
38+ }
39+ } ;
40+
41+ const onSubmit = async ( event ?: FormEvent < HTMLFormElement > ) => {
42+ if ( event ) event . preventDefault ( ) ;
3143 await actions . dashboard . renameSandbox ( {
3244 id : sandbox . id ,
3345 title : newName ,
@@ -36,6 +48,20 @@ export const SandboxCard = ({ sandbox, isTemplate = false, ...props }) => {
3648 setEdit ( false ) ;
3749 } ;
3850
51+ const onBlur = ( ) => {
52+ // save value when you click outside or tab away
53+ onSubmit ( ) ;
54+ } ;
55+
56+ const inputRef = React . useRef ( null ) ;
57+ const enterEditing = ( ) => {
58+ setEdit ( true ) ;
59+ // Menu defaults to sending focus back to Menu Button
60+ // Send focus to input in the next tick
61+ // after menu is done closing.
62+ setTimeout ( ( ) => inputRef . current . focus ( ) ) ;
63+ } ;
64+
3965 return (
4066 < Stack
4167 direction = "vertical"
@@ -50,13 +76,13 @@ export const SandboxCard = ({ sandbox, isTemplate = false, ...props }) => {
5076 transition : 'all ease-in-out' ,
5177 transitionDuration : theme => theme . speeds [ 4 ] ,
5278 ':hover, :focus, :focus-within' : {
53- cursor : 'pointer' ,
79+ cursor : edit ? 'normal' : 'pointer' ,
5480 transform : 'scale(0.98)' ,
5581 } ,
5682 } ) }
5783 { ...props }
5884 onClick = { event => {
59- if ( isMenuClicked ( event ) ) return ;
85+ if ( edit || isMenuClicked ( event ) ) return ;
6086 history . push ( url ) ;
6187 } }
6288 >
@@ -73,8 +99,14 @@ export const SandboxCard = ({ sandbox, isTemplate = false, ...props }) => {
7399 />
74100 < Stack justify = "space-between" align = "center" marginLeft = { 4 } >
75101 { edit ? (
76- < form onSubmit = { editSandboxTitle } >
77- < Input value = { newName } onChange = { e => setNewName ( e . target . value ) } />
102+ < form onSubmit = { onSubmit } >
103+ < Input
104+ value = { newName }
105+ ref = { inputRef }
106+ onChange = { onChange }
107+ onKeyDown = { onKeyDown }
108+ onBlur = { onBlur }
109+ />
78110 </ form >
79111 ) : (
80112 < Text size = { 3 } weight = "medium" >
@@ -84,7 +116,7 @@ export const SandboxCard = ({ sandbox, isTemplate = false, ...props }) => {
84116 < MenuOptions
85117 sandbox = { sandbox }
86118 isTemplate = { isTemplate }
87- setEdit = { setEdit }
119+ onRename = { enterEditing }
88120 />
89121 </ Stack >
90122 < Stack marginX = { 4 } >
0 commit comments