From 9d45484fce2af2e2b6b9551032ad9e8f8031ff9b Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Tue, 24 Mar 2026 16:52:01 -0300 Subject: [PATCH] feat: enhance EditorToolbar with always-visible Libraries button and missing library hint; remove overflow collapse logic --- .../src/components/editor/EditorToolbar.css | 75 ++++++- .../src/components/editor/EditorToolbar.tsx | 189 ++++++++---------- 2 files changed, 155 insertions(+), 109 deletions(-) diff --git a/frontend/src/components/editor/EditorToolbar.css b/frontend/src/components/editor/EditorToolbar.css index 3e017c35..9a35d565 100644 --- a/frontend/src/components/editor/EditorToolbar.css +++ b/frontend/src/components/editor/EditorToolbar.css @@ -88,7 +88,34 @@ color: #ccc; } -/* Libraries */ +/* Libraries button (always visible, with label) */ +.tb-btn-libraries { + display: flex; + align-items: center; + gap: 5px; + padding: 4px 10px 4px 8px; + border: 1px solid rgba(0, 184, 212, 0.3); + border-radius: 6px; + cursor: pointer; + background: rgba(0, 184, 212, 0.08); + color: #00e5ff; + font-size: 12px; + font-weight: 500; + font-family: inherit; + white-space: nowrap; + transition: background 0.15s, border-color 0.15s, color 0.15s; + flex-shrink: 0; +} +.tb-btn-libraries:hover { + background: rgba(0, 184, 212, 0.18); + border-color: rgba(0, 184, 212, 0.5); + color: #fff; +} +.tb-libraries-label { + line-height: 1; +} + +/* Legacy lib icon-only button (for overflow items) */ .tb-btn-lib { color: #00b8d4; } @@ -97,6 +124,52 @@ color: #00e5ff; } +/* Missing library hint banner */ +.tb-lib-hint { + display: flex; + align-items: center; + gap: 6px; + padding: 5px 12px; + background: rgba(255, 152, 0, 0.1); + border-bottom: 1px solid rgba(255, 152, 0, 0.25); + color: #ffb74d; + font-size: 12px; + font-family: inherit; +} +.tb-lib-hint svg { + flex-shrink: 0; + color: #ffa726; +} +.tb-lib-hint-btn { + background: rgba(0, 184, 212, 0.15); + border: 1px solid rgba(0, 184, 212, 0.4); + border-radius: 4px; + color: #00e5ff; + font-size: 12px; + font-weight: 600; + font-family: inherit; + padding: 2px 8px; + cursor: pointer; + transition: background 0.12s; +} +.tb-lib-hint-btn:hover { + background: rgba(0, 184, 212, 0.3); + color: #fff; +} +.tb-lib-hint-close { + margin-left: auto; + background: none; + border: none; + color: #888; + font-size: 16px; + cursor: pointer; + padding: 0 4px; + line-height: 1; +} +.tb-lib-hint-close:hover { + color: #ccc; +} + /* Output Console toggle */ .tb-btn-output { color: #9d9d9d; diff --git a/frontend/src/components/editor/EditorToolbar.tsx b/frontend/src/components/editor/EditorToolbar.tsx index f9ee3c42..c94d1744 100644 --- a/frontend/src/components/editor/EditorToolbar.tsx +++ b/frontend/src/components/editor/EditorToolbar.tsx @@ -67,20 +67,12 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi const [installModalOpen, setInstallModalOpen] = useState(false); const importInputRef = useRef(null); const toolbarRef = useRef(null); - const [overflowCollapsed, setOverflowCollapsed] = useState(false); const [overflowOpen, setOverflowOpen] = useState(false); const overflowMenuRef = useRef(null); + const [missingLibHint, setMissingLibHint] = useState(false); - // Collapse secondary buttons when toolbar is too narrow - useEffect(() => { - const el = toolbarRef.current; - if (!el) return; - const ro = new ResizeObserver(([entry]) => { - setOverflowCollapsed(entry.contentRect.width < 500); - }); - ro.observe(el); - return () => ro.disconnect(); - }, []); + // (ResizeObserver removed — Library Manager is always visible now, + // only import/export live in the overflow menu) // Close overflow dropdown on outside click useEffect(() => { @@ -143,8 +135,14 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi compileBoardProgram(activeBoardId, program); } setMessage({ type: 'success', text: 'Compiled successfully' }); + setMissingLibHint(false); } else { - setMessage({ type: 'error', text: result.error || result.stderr || 'Compile failed' }); + const errText = result.error || result.stderr || 'Compile failed'; + setMessage({ type: 'error', text: errText }); + // Detect missing library errors — common patterns: + // "No such file or directory" for #include, "fatal error: XXX.h" + const looksLikeMissingLib = /No such file or directory|fatal error:.*\.h|library not found/i.test(errText); + setMissingLibHint(looksLikeMissingLib); } } catch (err) { const errMsg = err instanceof Error ? err.message : 'Compile failed'; @@ -428,104 +426,61 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi onChange={handleImportFile} /> - {/* Secondary buttons — hidden when toolbar is narrow */} - {!overflowCollapsed && ( - <> - {/* Import Wokwi zip */} - + {/* Library Manager — always visible with label */} + - {/* Export Wokwi zip */} - + {/* Import / Export — overflow menu */} +
+ - {/* Libraries */} - - - )} - - {/* Overflow (…) button — shown when toolbar is narrow */} - {overflowCollapsed && ( -
- - - {overflowOpen && ( -
- - - -
- )} -
- )} + {overflowOpen && ( +
+ + +
+ )} +
@@ -549,6 +504,24 @@ export const EditorToolbar = ({ consoleOpen, setConsoleOpen, compileLogs: _compi
{message.text}
)} + {/* Missing library hint */} + {missingLibHint && ( +
+ + + + + + Missing library? Install it from the + + +
+ )} + setLibManagerOpen(false)} />