diff --git a/frontend/src/components/common/tiptap-customized.tsx b/frontend/src/components/common/tiptap-customized.tsx index 284ef63..8c08ac1 100644 --- a/frontend/src/components/common/tiptap-customized.tsx +++ b/frontend/src/components/common/tiptap-customized.tsx @@ -3,6 +3,7 @@ import { useEditor, EditorContent } from '@tiptap/react' import { FloatingMenu, BubbleMenu } from '@tiptap/react/menus' import { BatteryFull, List } from 'lucide-react' import TiptapToolbar from '@/components/common/tiptap-toolbar' +import { useState, useEffect, useRef } from 'react' interface Props { @@ -12,6 +13,10 @@ interface Props { const Tiptap = (props: Props) => { const { value, onValueUpdate } = props + const [isFocused, setIsFocused] = useState(false) + const [isMobile, setIsMobile] = useState(false) + const containerRef = useRef(null) + const editor = useEditor({ extensions: [StarterKit], // define your extension array content: value, @@ -19,23 +24,66 @@ const Tiptap = (props: Props) => { const { editor: newEditor } = updates const html = newEditor.getHTML() onValueUpdate(html) + }, + onFocus: () => { + setIsFocused(true) + }, + onBlur: () => { + // Delay to allow toolbar clicks + setTimeout(() => setIsFocused(false), 200) } }) + // Detect mobile and keyboard + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 768 || /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) + } + + checkMobile() + window.addEventListener('resize', checkMobile) + + // Use visualViewport API to detect keyboard + let viewport = window.visualViewport + if (viewport) { + const handleViewportChange = () => { + if (isMobile && viewport) { + // Keyboard is open when viewport height is significantly less than window height + const keyboardOpen = viewport.height < window.innerHeight * 0.75 + // This will be handled by CSS using env(keyboard-inset-height) + } + } + viewport.addEventListener('resize', handleViewportChange) + return () => { + window.removeEventListener('resize', checkMobile) + viewport?.removeEventListener('resize', handleViewportChange) + } + } + + return () => { + window.removeEventListener('resize', checkMobile) + } + }, [isMobile]) + return ( -
{/* IMPORTANT */} - - - {/* This is the floating menu - This is the bubble menu */} +
+ +
) } diff --git a/frontend/src/components/common/tiptap-toolbar.tsx b/frontend/src/components/common/tiptap-toolbar.tsx index 64762e3..c5baf3b 100644 --- a/frontend/src/components/common/tiptap-toolbar.tsx +++ b/frontend/src/components/common/tiptap-toolbar.tsx @@ -41,9 +41,11 @@ import { useEditorState } from '@tiptap/react' interface Props { editor: Editor + isMobile?: boolean + isFocused?: boolean } -export default function TiptapToolbar({ editor }: Props) { +export default function TiptapToolbar({ editor, isMobile = false, isFocused = false }: Props) { const state = useEditorState({ editor, selector: ({ editor }) => ({ @@ -72,7 +74,14 @@ export default function TiptapToolbar({ editor }: Props) { }) return ( - + {/* TEXT MARKS */}