Skip to content

Commit

Permalink
🐛 Create & edit modals not autofocusing first input
Browse files Browse the repository at this point in the history
  • Loading branch information
homostellaris committed Aug 5, 2024
1 parent 8adcc11 commit 25de832
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,24 @@ import {
IonTitle,
IonToolbar,
} from '@ionic/react'
import { ComponentProps, ReactNode, useEffect, useRef } from 'react'
import { ComponentProps, MutableRefObject, ReactNode } from 'react'
import { StarRole } from '../db'

export default function StarRoleModal({
dismiss,
title,
titleInput,
starRole = {},
toolbarSlot,
...props
}: {
dismiss: (data?: any, role?: string) => void
title: string
starRole?: Partial<StarRole>
titleInput: MutableRefObject<HTMLIonInputElement | null>
toolbarSlot?: ReactNode
} & ComponentProps<typeof IonPage>) {
const input = useRef<HTMLIonInputElement>(null)

// Might cause problems that this runs on every render but seems fine atm...
useEffect(() => {
input.current?.setFocus()
})

console.log('RENDER')
return (
<IonPage
{...props}
Expand All @@ -40,7 +36,7 @@ export default function StarRoleModal({
dismiss(
{
...starRole,
title: input.current?.value,
title: titleInput.current?.value,
},
'confirm',
)
Expand All @@ -55,8 +51,9 @@ export default function StarRoleModal({
</IonHeader>
<IonContent className="space-y-4 ion-padding">
<IonInput
autofocus
fill="outline"
ref={input}
ref={titleInput}
type="text"
label="Title"
labelPlacement="floating"
Expand All @@ -79,7 +76,7 @@ export default function StarRoleModal({
dismiss(
{
...starRole,
title: input.current?.value,
title: titleInput.current?.value,
},
'confirm',
)
Expand Down
10 changes: 5 additions & 5 deletions components/starRoles/create/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import StarRoleModal from '../RoleModal'
import { ComponentProps } from 'react'
import StarRoleModal from '../StarRoleModal'

export function CreateStarRoleModal({
dismiss,
title,
...props
}: {
dismiss: (data?: any, role?: string) => void
title: string
}) {
} & ComponentProps<typeof StarRoleModal>) {
return (
<StarRoleModal
dismiss={(data?: any, role?: string) => {
Expand All @@ -17,7 +17,7 @@ export function CreateStarRoleModal({
role,
)
}}
title={title}
{...props}
/>
)
}
8 changes: 6 additions & 2 deletions components/starRoles/create/useCreateStarRoleModal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useIonModal } from '@ionic/react'
import { HookOverlayOptions } from '@ionic/react/dist/types/hooks/HookOverlayOptions'
import { useCallback } from 'react'
import { useCallback, useRef } from 'react'
import { db } from '../../db'
import { CreateStarRoleModal } from './modal'

Expand All @@ -12,18 +12,22 @@ export function useCreateStarRoleModal(): [
}) => void,
(data?: any, role?: string) => void,
] {
const titleInput = useRef<HTMLIonInputElement>(null)
const [present, dismiss] = useIonModal(CreateStarRoleModal, {
dismiss: (data: string, role: string) => dismiss(data, role),
title: 'Create star role',
titleInput,
})

const createStarRole = useCallback(async ({ title }: { title: any }) => {
db.starRoles.add({ title })
}, [])

return [
({ onWillDismiss }: HookOverlayOptions) => {
present({
onDidPresent: _event => {
titleInput.current?.setFocus()
},
onWillDismiss: event => {
if (event.detail.role === 'confirm') {
const { starRole } = event.detail.data
Expand Down
14 changes: 5 additions & 9 deletions components/starRoles/edit/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import { StarRole } from '../../db'
import StarRoleModal from '../RoleModal'
import { ComponentProps } from 'react'
import StarRoleModal from '../StarRoleModal'

export function EditStarRoleModal({
dismiss,
starRole,
title,
...props
}: {
dismiss: (data?: any, role?: string) => void
starRole: StarRole
title: string
}) {
} & ComponentProps<typeof StarRoleModal>) {
return (
<StarRoleModal
dismiss={(data?: any, role?: string) => {
Expand All @@ -20,8 +17,7 @@ export function EditStarRoleModal({
role,
)
}}
starRole={starRole}
title={title}
{...props}
/>
)
}
7 changes: 6 additions & 1 deletion components/starRoles/edit/useEditStarRoleModal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useIonModal } from '@ionic/react'
import { useCallback, useState } from 'react'
import { useCallback, useRef, useState } from 'react'
import { StarRole, db } from '../../db'
import { EditStarRoleModal } from './modal'

Expand All @@ -8,10 +8,12 @@ export function useEditStarRoleModal(): [
(data?: any, role?: string) => void,
] {
const [starRole, setStarRole] = useState<StarRole | null>(null)
const titleInput = useRef<HTMLIonInputElement>(null)
const [present, dismiss] = useIonModal(EditStarRoleModal, {
dismiss: (data: string, role: string) => dismiss(data, role),
starRole,
title: 'Edit star role',
titleInput,
})

const editStarRole = useCallback(async (updatedStarRole: StarRole) => {
Expand All @@ -23,6 +25,9 @@ export function useEditStarRoleModal(): [
return [
(starRole: StarRole) => {
present({
onDidPresent: _event => {
titleInput.current?.setFocus()
},
onWillPresent: () => {
setStarRole(starRole)
},
Expand Down
12 changes: 4 additions & 8 deletions components/todos/TodoModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
import { openOutline } from 'ionicons/icons'
import {
ComponentProps,
MutableRefObject,
ReactNode,
useCallback,
useEffect,
Expand All @@ -28,26 +29,22 @@ import { useLiveQuery } from 'dexie-react-hooks'
export default function TodoModal({
dismiss,
title,
titleInput,
todo = {},
toolbarSlot,
...props
}: {
dismiss: (data?: any, role?: string) => void
title: string
titleInput: MutableRefObject<HTMLIonInputElement | null>
todo?: Partial<Todo>
toolbarSlot?: ReactNode
} & ComponentProps<typeof IonPage>) {
const noteInput = useRef<HTMLIonTextareaElement>(null)
const starRoleInput = useRef<HTMLIonSelectElement>(null)
const titleInput = useRef<HTMLIonInputElement>(null)

const starRoles = useLiveQuery(() => db.starRoles.toArray(), [], [])

// Might cause problems that this runs on every render but seems fine atm...
useEffect(() => {
titleInput.current?.setFocus()
})

const noteProvider = useNoteProvider()
const emitTodo = useCallback(() => {
dismiss(
Expand All @@ -59,7 +56,7 @@ export default function TodoModal({
},
'confirm',
)
}, [dismiss, todo])
}, [dismiss, todo, titleInput])

return (
<IonPage
Expand All @@ -79,7 +76,6 @@ export default function TodoModal({
</IonHeader>
<IonContent className="space-y-4 ion-padding">
<IonInput
autoFocus
fill="outline"
ref={titleInput}
type="text"
Expand Down
9 changes: 4 additions & 5 deletions components/todos/create/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { IonSelect, IonSelectOption, useIonModal } from '@ionic/react'
import { HookOverlayOptions } from '@ionic/react/dist/types/hooks/HookOverlayOptions'
import { useCallback, useRef } from 'react'
import { ComponentProps, useCallback, useRef } from 'react'
import { db, ListType } from '../../db'
import useNoteProvider from '../../notes/useNoteProvider'
import TodoModal from '../TodoModal'

export function CreateTodoModal({
dismiss,
title,
...props
}: {
dismiss: (data?: any, role?: string) => void
title: string
}) {
} & ComponentProps<typeof TodoModal>) {
const locationSelect = useRef<HTMLIonSelectElement>(null)

return (
Expand All @@ -35,7 +34,6 @@ export function CreateTodoModal({
locationSelect.current!.value = ListType.icebox
}
}}
title={title}
toolbarSlot={
<IonSelect
className="p-2"
Expand All @@ -50,6 +48,7 @@ export function CreateTodoModal({
</IonSelectOption>
</IonSelect>
}
{...props}
/>
)
}
7 changes: 6 additions & 1 deletion components/todos/create/useCreateTodoModal.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useIonModal } from '@ionic/react'
import { HookOverlayOptions } from '@ionic/react/dist/types/hooks/HookOverlayOptions'
import { useCallback } from 'react'
import { useCallback, useRef } from 'react'
import { db, ListType, Todo } from '../../db'
import useNoteProvider from '../../notes/useNoteProvider'
import { CreateTodoModal } from './modal'
Expand All @@ -13,9 +13,11 @@ export function useCreateTodoModal(): [
}) => void,
(data?: any, role?: string) => void,
] {
const titleInput = useRef<HTMLIonInputElement>(null)
const [present, dismiss] = useIonModal(CreateTodoModal, {
dismiss: (data: string, role: string) => dismiss(data, role),
title: 'Create todo',
titleInput,
})

const noteProvider = useNoteProvider()
Expand Down Expand Up @@ -48,6 +50,9 @@ export function useCreateTodoModal(): [
return [
({ onWillDismiss }: HookOverlayOptions) => {
present({
onDidPresent: _event => {
titleInput.current?.setFocus()
},
onWillDismiss: event => {
if (event.detail.role === 'confirm') {
const { todo, location } = event.detail.data
Expand Down
24 changes: 3 additions & 21 deletions components/todos/edit/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,6 @@
import { useIonModal } from '@ionic/react'
import { useCallback } from 'react'
import { Todo, db } from '../../db'
import useNoteProvider from '../../notes/useNoteProvider'
import useSelectedTodo from '../SelectedTodo'
import { ComponentProps } from 'react'
import TodoModal from '../TodoModal'

export function EditTodoModal({
dismiss,
title,
todo,
}: {
dismiss: (data?: any, role?: string) => void
title: string
todo: Todo
}) {
return (
<TodoModal
title={title}
todo={todo}
dismiss={dismiss}
/>
)
export function EditTodoModal({ ...props }: ComponentProps<typeof TodoModal>) {
return <TodoModal {...props} />
}
7 changes: 6 additions & 1 deletion components/todos/edit/useEditTodoModal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useIonModal } from '@ionic/react'
import { useCallback } from 'react'
import { useCallback, useRef } from 'react'
import { Todo, db } from '../../db'
import useNoteProvider from '../../notes/useNoteProvider'
import useSelectedTodo from '../SelectedTodo'
Expand All @@ -10,9 +10,11 @@ export function useEditTodoModal(): [
(data?: any, role?: string) => void,
] {
const [todo, setTodo] = useSelectedTodo()
const titleInput = useRef<HTMLIonInputElement>(null)
const [present, dismiss] = useIonModal(EditTodoModal, {
dismiss: (data: string, role: string) => dismiss(data, role),
title: 'Edit todo',
titleInput,
todo,
})
const noteProvider = useNoteProvider()
Expand All @@ -37,6 +39,9 @@ export function useEditTodoModal(): [
return [
(todo: Todo) => {
present({
onDidPresent: _event => {
titleInput.current?.setFocus()
},
onWillPresent: () => {
setTodo(todo)
},
Expand Down

0 comments on commit 25de832

Please sign in to comment.