From 3b7abfc4f7153da1ad7efff90d1832a4eaa09ef8 Mon Sep 17 00:00:00 2001 From: David Montero Crespo Date: Thu, 30 Jul 2026 20:54:24 +0200 Subject: [PATCH] feat(editor): account block fuses into the explorer footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The floating corner box sat ON TOP of the file tree — create enough files and the last rows scrolled underneath it. The account + language block is now the explorer panel's footer (VS Code style): the tree scrolls above it, always. When the explorer is collapsed the block falls back to the small fixed corner box, so account and language stay reachable. The standalone language globe becomes a logged-out affordance: once the pro auth slot renders its signed-in marker (data-auth-user), a :has() rule hides the globe — signed-in users change language inside the account menu, where the pro overlay now hosts it. --- frontend/src/App.css | 22 ++++++++++++ frontend/src/components/layout/AppHeader.tsx | 18 ++-------- .../components/layout/LanguageSwitcher.css | 7 ++++ frontend/src/pages/EditorPage.tsx | 36 +++++++++++++++++-- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index 144fc984..7812bbfe 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -615,3 +615,25 @@ body { .app-header--with-toolbar .header-editor-toolbar .unified-toolbar { padding-right: 6px !important; } + +/* ── Explorer account footer ───────────────────────────────────────────── + The account + language block fused to the bottom of the file explorer: + a long tree scrolls above it instead of hiding under a floating box. + (.editor-corner-box remains as the fallback when the explorer is + collapsed.) The standalone globe is a logged-out affordance only — once + the pro auth slot renders its signed-in marker, language moves inside + the account menu and the globe hides. */ +.explorer-account-footer { + flex-shrink: 0; + display: flex; + align-items: center; + gap: 6px; + padding: 6px 8px; + border-top: 1px solid #2f3542; + background: #171a21; +} + +.explorer-account-footer:has([data-auth-user]) .corner-lang, +.editor-corner-box:has([data-auth-user]) .corner-lang { + display: none; +} diff --git a/frontend/src/components/layout/AppHeader.tsx b/frontend/src/components/layout/AppHeader.tsx index 6773787f..b6affcac 100644 --- a/frontend/src/components/layout/AppHeader.tsx +++ b/frontend/src/components/layout/AppHeader.tsx @@ -1,5 +1,4 @@ import { useState, useEffect } from 'react'; -import { createPortal } from 'react-dom'; import { Link, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useProjectStore } from '../../store/useProjectStore'; @@ -309,20 +308,9 @@ export const AppHeader: React.FC = ({ autoSave, editorMenu, edit )} - {/* Editor corner box — bottom-left, IDE style: the account button - (pro injects it into the auth slot) and the language switcher. - Portaled to : the header's backdrop-filter makes it a - containing block, so a fixed child positioned inside it lands at - the header's bottom (the top of the page) instead of the - viewport's — measured at y=-4, on top of the logo. */} - {editorToolbar && - createPortal( -
- -
-
, - document.body, - )} + {/* The account + language block lives in the file-explorer footer now + (EditorPage renders it) — fused so a long file tree never scrolls + underneath a floating box. */} {showShareModal && setShowShareModal(false)} />} diff --git a/frontend/src/components/layout/LanguageSwitcher.css b/frontend/src/components/layout/LanguageSwitcher.css index 287fc501..4fc3cc7e 100644 --- a/frontend/src/components/layout/LanguageSwitcher.css +++ b/frontend/src/components/layout/LanguageSwitcher.css @@ -84,3 +84,10 @@ bottom: 110%; margin: 0 0 6px; } + +/* Same drop-up need at the explorer footer. */ +.explorer-account-footer .velxio-language-menu { + top: auto; + bottom: 110%; + margin: 0 0 6px; +} diff --git a/frontend/src/pages/EditorPage.tsx b/frontend/src/pages/EditorPage.tsx index 29258028..694df55a 100644 --- a/frontend/src/pages/EditorPage.tsx +++ b/frontend/src/pages/EditorPage.tsx @@ -29,6 +29,7 @@ import { showConfirmDialog } from '../store/useMessageDialogStore'; import { useAutoSaveProject } from '../hooks/useAutoSaveProject'; import { registerEditorCommand } from '../lib/editorCommands'; import { EditorMenuBar } from '../components/editor/EditorMenuBar'; +import { LanguageSwitcher } from '../components/layout/LanguageSwitcher'; import type { CompilationLog } from '../utils/compilationLogger'; import '../App.css'; @@ -385,6 +386,22 @@ export const EditorPage: React.FC = () => { there used to be 44+38. On narrow widths the strip wraps internally and the header grows; the docked AI chat is avoided by the same padding-right the strip always had. */ + /* Account + language block. Fused as the explorer panel's footer so a + long file tree scrolls ABOVE it instead of disappearing underneath a + floating box; when the explorer is collapsed it falls back to the + small fixed corner box. The standalone language switcher only shows + while logged OUT — signed-in users change language inside the account + menu (see pro HeaderAuth), and a CSS :has() rule hides the globe when + the auth slot renders a logged-in marker. */ + const accountBlock = !isMobile ? ( + <> + + + +
+ + ) : undefined; + const unifiedToolbar = !isMobile ? (