From d2edc31460d9b379390c7295033b3921c2dfa712 Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Mon, 22 Jun 2026 23:45:04 +0000 Subject: [PATCH] T23: Add dropdown outside-click and Escape close for RibbonBar --- frontend/src/components/RibbonBar.tsx | 55 +++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/RibbonBar.tsx b/frontend/src/components/RibbonBar.tsx index f106d3a..4cffb49 100644 --- a/frontend/src/components/RibbonBar.tsx +++ b/frontend/src/components/RibbonBar.tsx @@ -1,4 +1,4 @@ -import React, { useState, useRef, useCallback } from 'react'; +import React, { useState, useRef, useCallback, useEffect } from 'react'; import type { YjsDocument } from '../crdt/YjsDocument'; import { exportDrawing, type ExportFormat } from '../services/exportService'; import { importDrawing, type ImportFormat, type ImportResult } from '../services/importService'; @@ -19,6 +19,12 @@ const RibbonBar: React.FC = ({ onTabChange, yjsDoc }) => { const fileInputRef = useRef(null); const pendingImportFormat = useRef('json'); + // Refs for dropdown wrappers (for outside-click detection) + const exportDropdownRef = useRef(null); + const importDropdownRef = useRef(null); + // Ref to track the trigger button that opened the print preview (for focus restoration) + const printTriggerRef = useRef(null); + const tabs = [ { id: 'draw', label: 'Draw', icon: '✏️' }, { id: 'modify', label: 'Modify', icon: '🔧' }, @@ -82,6 +88,40 @@ const RibbonBar: React.FC = ({ onTabChange, yjsDoc }) => { } }, [yjsDoc]); + // Outside-click and Escape close for dropdowns + useEffect(() => { + const handleClickOutside = (e: MouseEvent) => { + const target = e.target as Node; + if (showExportMenu && exportDropdownRef.current && !exportDropdownRef.current.contains(target)) { + setShowExportMenu(false); + } + if (showImportMenu && importDropdownRef.current && !importDropdownRef.current.contains(target)) { + setShowImportMenu(false); + } + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + if (showExportMenu) { + setShowExportMenu(false); + } + if (showImportMenu) { + setShowImportMenu(false); + } + } + }; + + if (showExportMenu || showImportMenu) { + document.addEventListener('mousedown', handleClickOutside); + document.addEventListener('keydown', handleKeyDown); + } + + return () => { + document.removeEventListener('mousedown', handleClickOutside); + document.removeEventListener('keydown', handleKeyDown); + }; + }, [showExportMenu, showImportMenu]); + return (
{tabs.map((tab) => ( @@ -99,7 +139,7 @@ const RibbonBar: React.FC = ({ onTabChange, yjsDoc }) => {