From 8b82dd1408934148cb7927d27d3eddd912b68412 Mon Sep 17 00:00:00 2001 From: Kenneth Date: Wed, 21 May 2025 15:47:07 +0100 Subject: [PATCH] fix keyboard shortcut not working in add dialog --- packages/web/src/app/bookmarks.tsx | 87 +----------------- .../-dialogs/add-bookmark-dialog.tsx | 13 +-- .../-dialogs/delete-bookmark-dialog.tsx | 89 +++++++++++++++++++ 3 files changed, 98 insertions(+), 91 deletions(-) create mode 100644 packages/web/src/app/bookmarks/-dialogs/delete-bookmark-dialog.tsx diff --git a/packages/web/src/app/bookmarks.tsx b/packages/web/src/app/bookmarks.tsx index bea6bd4..e7c0c6d 100644 --- a/packages/web/src/app/bookmarks.tsx +++ b/packages/web/src/app/bookmarks.tsx @@ -1,11 +1,7 @@ import { Outlet, createFileRoute } from "@tanstack/react-router" import { useEffect } from "react" -import { useDeleteBookmark } from "~/bookmark/api" -import { Button } from "~/components/button" -import { Dialog, DialogActionRow, DialogBody, DialogTitle } from "~/components/dialog" -import { LoadingSpinner } from "~/components/loading-spinner" -import { useMnemonics } from "~/hooks/use-mnemonics" import { AddBookmarkDialog } from "./bookmarks/-dialogs/add-bookmark-dialog" +import { DeleteBookmarkDialog } from "./bookmarks/-dialogs/delete-bookmark-dialog" import { ActiveDialog, LayoutMode, useBookmarkPageStore } from "./bookmarks/-store" export const Route = createFileRoute("/bookmarks")({ @@ -53,84 +49,3 @@ function PageDialog() { return } } - -function DeleteBookmarkDialog() { - // biome-ignore lint/style/noNonNullAssertion: this cannot be null when delete bookmark dialog is visible - const bookmark = useBookmarkPageStore((state) => state.bookmarkToBeDeleted!) - const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog) - const deleteBookmarkMutation = useDeleteBookmark() - - useMnemonics( - { - y: proceed, - n: cancel, - }, - { ignore: () => false }, - ) - - async function proceed() { - try { - await deleteBookmarkMutation.mutateAsync({ bookmark }) - setActiveDialog(ActiveDialog.None) - } catch (error) { - console.error(error) - } - } - - function cancel() { - setActiveDialog(ActiveDialog.None) - } - - function body() { - switch (deleteBookmarkMutation.status) { - case "pending": - return ( -

- Deleting -

- ) - case "idle": - return ( -

- The bookmark titled: -
-
- - "{bookmark.title}" - -
-
- will be deleted. Proceed? -

- ) - case "error": - return

Failed to delete the bookmark!

- } - } - - function title() { - switch (deleteBookmarkMutation.status) { - case "pending": - return "PLEASE WAIT" - case "idle": - return "CONFIRM" - case "error": - return "ERROR OCCURRED" - } - } - - return ( - - {title()} - {body()} - - - - - - ) -} 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 e5eb4d5..33df9c3 100644 --- a/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx +++ b/packages/web/src/app/bookmarks/-dialogs/add-bookmark-dialog.tsx @@ -3,7 +3,7 @@ import type { BookmarkTag } from "@markone/core/bookmark" import clsx from "clsx" import { atom, useAtom } from "jotai" import { useAtomCallback } from "jotai/utils" -import { useCallback, useEffect, useId, useRef, useState } from "react" +import { useCallback, useEffect, useId, useImperativeHandle, useRef, useState } from "react" import { ApiErrorCode, BadRequestError } from "~/api" import { useCreateBookmark, useTags } from "~/bookmark/api" import { Button } from "~/components/button" @@ -36,6 +36,7 @@ function AddBookmarkDialog() { const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog) const formId = useId() const linkInputRef = useRef(null) + const tagsInputRef = useRef(null) const getTags = useAtomCallback( useCallback((get) => { const value = get(tagsInputValueAtom) @@ -46,7 +47,7 @@ function AddBookmarkDialog() { useMnemonics( { c: () => { - if (!document.activeElement) { + if (linkInputRef.current !== document.activeElement && tagsInputRef.current !== document.activeElement) { cancel() } }, @@ -127,7 +128,7 @@ function AddBookmarkDialog() { className="w-full" labelClassName="bg-stone-300 dark:bg-stone-800" /> - + @@ -142,11 +143,11 @@ function AddBookmarkDialog() { ) } -function TagsInput() { +function TagsInput({ ref }: { ref: React.Ref }) { const [value, setValue] = useAtom(tagsInputValueAtom) const [isInputFocused, setIsInputFocused] = useState(false) const [lastTag] = useAtom(lastTagAtom) - const { refs, floatingStyles } = useFloating({ + const { refs, floatingStyles } = useFloating({ whileElementsMounted: autoUpdate, middleware: [ size({ @@ -160,6 +161,8 @@ function TagsInput() { open: isInputFocused && lastTag !== "", }) + useImperativeHandle(ref, () => refs.reference.current) + return ( <> state.bookmarkToBeDeleted!) + const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog) + const deleteBookmarkMutation = useDeleteBookmark() + + useMnemonics( + { + y: proceed, + n: cancel, + }, + { ignore: () => false }, + ) + + async function proceed() { + try { + await deleteBookmarkMutation.mutateAsync({ bookmark }) + setActiveDialog(ActiveDialog.None) + } catch (error) { + console.error(error) + } + } + + function cancel() { + setActiveDialog(ActiveDialog.None) + } + + function body() { + switch (deleteBookmarkMutation.status) { + case "pending": + return ( +

+ Deleting +

+ ) + case "idle": + return ( +

+ The bookmark titled: +
+
+ + "{bookmark.title}" + +
+
+ will be deleted. Proceed? +

+ ) + case "error": + return

Failed to delete the bookmark!

+ } + } + + function title() { + switch (deleteBookmarkMutation.status) { + case "pending": + return "PLEASE WAIT" + case "idle": + return "CONFIRM" + case "error": + return "ERROR OCCURRED" + } + } + + return ( + + {title()} + {body()} + + + + + + ) +} + +export { DeleteBookmarkDialog }