mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 08:21:49 +03:00
Fix dashboard modal bugs (#6833)
* Fix rename modal disappearing; scroll context menu into view * Fix modal not closing when input is selected
This commit is contained in:
parent
c6cb937c0a
commit
aba5e0f18c
@ -8,6 +8,7 @@ import * as modalProvider from '../../providers/modal'
|
||||
import * as svg from '../../components/svg'
|
||||
import * as validation from '../validation'
|
||||
|
||||
import Input from './input'
|
||||
import Modal from './modal'
|
||||
|
||||
// ==========================
|
||||
@ -64,7 +65,7 @@ function ChangePasswordModal() {
|
||||
{svg.LOCK}
|
||||
</div>
|
||||
|
||||
<input
|
||||
<Input
|
||||
autoFocus
|
||||
required
|
||||
id="old_password"
|
||||
@ -72,9 +73,7 @@ function ChangePasswordModal() {
|
||||
name="old_password"
|
||||
placeholder="Old Password"
|
||||
value={oldPassword}
|
||||
onChange={event => {
|
||||
setOldPassword(event.target.value)
|
||||
}}
|
||||
setValue={setOldPassword}
|
||||
className="text-sm sm:text-base placeholder-gray-500 pl-10 pr-4 rounded-lg border border-gray-400 w-full py-2 focus:outline-none focus:border-blue-400"
|
||||
/>
|
||||
</div>
|
||||
@ -91,7 +90,7 @@ function ChangePasswordModal() {
|
||||
{svg.LOCK}
|
||||
</div>
|
||||
|
||||
<input
|
||||
<Input
|
||||
required
|
||||
id="new_password"
|
||||
type="password"
|
||||
@ -100,9 +99,7 @@ function ChangePasswordModal() {
|
||||
pattern={validation.PASSWORD_PATTERN}
|
||||
title={validation.PASSWORD_TITLE}
|
||||
value={newPassword}
|
||||
onChange={event => {
|
||||
setNewPassword(event.target.value)
|
||||
}}
|
||||
setValue={setNewPassword}
|
||||
className="text-sm sm:text-base placeholder-gray-500 pl-10 pr-4 rounded-lg border border-gray-400 w-full py-2 focus:outline-none focus:border-blue-400"
|
||||
/>
|
||||
</div>
|
||||
@ -119,16 +116,14 @@ function ChangePasswordModal() {
|
||||
{svg.LOCK}
|
||||
</div>
|
||||
|
||||
<input
|
||||
<Input
|
||||
required
|
||||
id="confirm_new_password"
|
||||
type="password"
|
||||
name="confirm_new_password"
|
||||
placeholder="Confirm New Password"
|
||||
value={confirmNewPassword}
|
||||
onChange={event => {
|
||||
setConfirmNewPassword(event.target.value)
|
||||
}}
|
||||
setValue={setConfirmNewPassword}
|
||||
className="text-sm sm:text-base placeholder-gray-500 pl-10 pr-4 rounded-lg border border-gray-400 w-full py-2 focus:outline-none focus:border-blue-400"
|
||||
/>
|
||||
</div>
|
||||
|
@ -3,9 +3,16 @@
|
||||
import * as react from 'react'
|
||||
|
||||
// =================
|
||||
// === Component ===
|
||||
// === Constants ===
|
||||
// =================
|
||||
|
||||
/** The margin around the context menu, so that it is not at the edge of the screen. */
|
||||
const SCROLL_MARGIN = 12
|
||||
|
||||
// ===================
|
||||
// === ContextMenu ===
|
||||
// ===================
|
||||
|
||||
/** Props for a {@link ContextMenu}. */
|
||||
export interface ContextMenuProps {
|
||||
// `left: number` and `top: number` may be more correct,
|
||||
@ -17,10 +24,23 @@ export interface ContextMenuProps {
|
||||
/** A context menu that opens at the current mouse position. */
|
||||
function ContextMenu(props: react.PropsWithChildren<ContextMenuProps>) {
|
||||
const { children, event } = props
|
||||
const contextMenuRef = react.useRef<HTMLDivElement>(null)
|
||||
|
||||
react.useEffect(() => {
|
||||
if (contextMenuRef.current != null) {
|
||||
const boundingBox = contextMenuRef.current.getBoundingClientRect()
|
||||
const scrollBy = boundingBox.bottom - innerHeight + SCROLL_MARGIN
|
||||
if (scrollBy > 0) {
|
||||
scroll(scrollX, scrollY + scrollBy)
|
||||
}
|
||||
}
|
||||
}, [children])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={contextMenuRef}
|
||||
style={{ left: event.pageX, top: event.pageY }}
|
||||
className="absolute bg-white rounded-lg shadow-soft flex flex-col flex-nowrap"
|
||||
className="absolute bg-white rounded-lg shadow-soft flex flex-col flex-nowrap m-2"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
@ -711,9 +711,11 @@ function Dashboard(props: DashboardProps) {
|
||||
tab === Tab.dashboard ? '' : 'hidden'
|
||||
}`}
|
||||
onClick={event => {
|
||||
unsetModal()
|
||||
if (!event.shiftKey) {
|
||||
setSelectedAssets([])
|
||||
if (getSelection()?.type !== 'Range') {
|
||||
unsetModal()
|
||||
if (!event.shiftKey) {
|
||||
setSelectedAssets([])
|
||||
}
|
||||
}
|
||||
}}
|
||||
onKeyDown={handleEscapeKey}
|
||||
|
@ -0,0 +1,29 @@
|
||||
/** @file Input element with default event handlers. */
|
||||
import * as react from 'react'
|
||||
|
||||
// =============
|
||||
// === Input ===
|
||||
// =============
|
||||
|
||||
/** Props for an {@link Input}. */
|
||||
export interface InputProps extends react.InputHTMLAttributes<HTMLInputElement> {
|
||||
setValue: (value: string) => void
|
||||
}
|
||||
|
||||
/** A component for authentication from inputs, with preset styles. */
|
||||
function Input(props: InputProps) {
|
||||
const { setValue, ...passThrough } = props
|
||||
return (
|
||||
<input
|
||||
{...passThrough}
|
||||
onChange={event => {
|
||||
setValue(event.target.value)
|
||||
}}
|
||||
onBlur={() => {
|
||||
getSelection()?.empty()
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Input
|
@ -27,7 +27,8 @@ function Modal(props: ModalProps) {
|
||||
centered ? 'fixed w-screen h-screen grid place-items-center ' : ''
|
||||
}${className ?? ''}`}
|
||||
onClick={event => {
|
||||
if (event.currentTarget === event.target) {
|
||||
if (event.currentTarget === event.target && getSelection()?.type !== 'Range') {
|
||||
event.stopPropagation()
|
||||
unsetModal()
|
||||
}
|
||||
}}
|
||||
|
@ -5,6 +5,7 @@ import toast from 'react-hot-toast'
|
||||
import * as modalProvider from '../../providers/modal'
|
||||
import * as svg from '../../components/svg'
|
||||
|
||||
import Input from './input'
|
||||
import Modal from './modal'
|
||||
|
||||
// ===================
|
||||
@ -62,7 +63,7 @@ function RenameModal(props: RenameModalProps) {
|
||||
<label className="w-1/3" htmlFor="renamed_file_name">
|
||||
File name
|
||||
</label>
|
||||
<input
|
||||
<Input
|
||||
autoFocus
|
||||
id="renamed_file_name"
|
||||
type="text"
|
||||
@ -70,10 +71,8 @@ function RenameModal(props: RenameModalProps) {
|
||||
pattern={namePattern}
|
||||
title={title}
|
||||
className="border-primary bg-gray-200 rounded-full w-2/3 px-2 mx-2"
|
||||
onChange={event => {
|
||||
setNewName(event.target.value)
|
||||
}}
|
||||
defaultValue={newName ?? name}
|
||||
setValue={setNewName}
|
||||
/>
|
||||
</div>
|
||||
<div className="m-1">
|
||||
|
Loading…
Reference in New Issue
Block a user