From 347451dbbc9a5b7b73379961d36825aa51ba13a6 Mon Sep 17 00:00:00 2001
From: Kenneth
Date: Tue, 27 May 2025 16:47:46 +0100
Subject: [PATCH] implement edit dialog mnemonics
---
.../-dialogs/add-bookmark-dialog.tsx | 3 +
.../-dialogs/edit-bookmark-dialog.tsx | 66 +++++++++++++++++--
2 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx b/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx
index 1d29f9d..4fb6794 100644
--- a/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx
+++ b/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx
@@ -33,6 +33,9 @@ function AddBookmarkDialog() {
{ ignore: () => false },
)
+ // when using autoFocus, it also captures the "a" mnemonic
+ // which appends the "a" to the input
+ // this is to prevent the "a" mnemonic to be captured as input to the text box
useEffect(() => {
setTimeout(() => {
if (linkInputRef.current) {
diff --git a/packages/web/src/app/bookmarks/-dialogs/edit-bookmark-dialog.tsx b/packages/web/src/app/bookmarks/-dialogs/edit-bookmark-dialog.tsx
index a159e91..1cd763e 100644
--- a/packages/web/src/app/bookmarks/-dialogs/edit-bookmark-dialog.tsx
+++ b/packages/web/src/app/bookmarks/-dialogs/edit-bookmark-dialog.tsx
@@ -1,5 +1,5 @@
import type { Bookmark, Tag } from "@markone/core"
-import { useId, useRef } from "react"
+import { useEffect, useId, useImperativeHandle, useRef } from "react"
import { useBookmarkTags, useUpdateBookmark } from "~/bookmark/api"
import { Button } from "~/components/button"
import { Dialog, DialogActionRow, DialogBody, DialogTitle } from "~/components/dialog"
@@ -7,12 +7,47 @@ import { FormField } from "~/components/form-field"
import { LoadingSpinner } from "~/components/loading-spinner"
import { Message, MessageVariant } from "~/components/message.tsx"
import { TagsInput, type TagsInputRef } from "~/components/tags-input"
+import { useMnemonics } from "~/hooks/use-mnemonics.ts"
import { useBookmarkPageStore } from "../-store"
+interface EditFormRef {
+ form: HTMLFormElement | null
+ titleInput: HTMLInputElement | null
+ tagsInput: TagsInputRef | null
+}
+
function EditBookmarkDialog({ bookmark }: { bookmark: Bookmark }) {
const closeDialog = useBookmarkPageStore((state) => state.closeDialog)
const { data: tags, status } = useBookmarkTags(bookmark)
const editFormId = useId()
+ const editFormRef = useRef(null)
+
+ useMnemonics(
+ {
+ s: () => {
+ if (
+ editFormRef.current &&
+ editFormRef.current.titleInput !== document.activeElement &&
+ editFormRef.current.tagsInput?.input !== document.activeElement
+ ) {
+ editFormRef.current.form?.requestSubmit()
+ }
+ },
+ c: () => {
+ if (
+ editFormRef.current?.titleInput !== document.activeElement &&
+ editFormRef.current?.tagsInput?.input !== document.activeElement
+ ) {
+ closeDialog()
+ }
+ },
+ Escape: () => {
+ editFormRef.current?.titleInput?.blur()
+ editFormRef.current?.tagsInput?.input?.blur()
+ },
+ },
+ { ignore: () => false },
+ )
function content() {
switch (status) {
@@ -23,7 +58,7 @@ function EditBookmarkDialog({ bookmark }: { bookmark: Bookmark }) {
)
case "success":
- return
+ return
case "error":
return null
}
@@ -45,11 +80,33 @@ function EditBookmarkDialog({ bookmark }: { bookmark: Bookmark }) {
)
}
-function EditForm({ formId, bookmark, tags }: { formId: string; bookmark: Bookmark; tags: Tag[] }) {
+function EditForm({
+ ref,
+ formId,
+ bookmark,
+ tags,
+}: { ref: React.Ref; formId: string; bookmark: Bookmark; tags: Tag[] }) {
+ const formRef = useRef(null)
+ const titleInputRef = useRef(null)
const tagsInputRef = useRef(null)
const updateBookmarkMutation = useUpdateBookmark(bookmark)
const closeDialog = useBookmarkPageStore((state) => state.closeDialog)
+ useImperativeHandle(ref, () => ({
+ form: formRef.current,
+ titleInput: titleInputRef.current,
+ tagsInput: tagsInputRef.current,
+ }))
+
+ // when using autoFocus, it also captures the "e" mnemonic
+ // which appends the "e" to the input
+ // this is to prevent the "e" mnemonic to be captured as input to the text box
+ useEffect(() => {
+ setTimeout(() => {
+ titleInputRef.current?.focus()
+ }, 0)
+ }, [])
+
async function onSubmit(event: React.FormEvent) {
if (tagsInputRef.current) {
event.preventDefault()
@@ -86,8 +143,9 @@ function EditForm({ formId, bookmark, tags }: { formId: string; bookmark: Bookma
return (
<>
{message()}
-