From ff078fd2bfaa563ad02b3c1dc011cacd125b45ec Mon Sep 17 00:00:00 2001 From: IliesAllali Date: Tue, 20 Oct 2026 13:33:30 +0200 Subject: [PATCH] =?UTF-8?q?onglets=20:=20la=20recherche=20ouvre=20l'onglet?= =?UTF-8?q?=20de=20la=20personne=20;=20barre=20jamais=20cach=C3=A9e=20par?= =?UTF-8?q?=20la=20fiche=20ou=20la=20recherche?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Une personne trouvée par la recherche mais rangée dans un autre onglet : l'onglet s'ouvre et la vue va sur elle (avant, la fiche s'ouvrait et l'arbre ne bougeait pas). - Téléphone : recherche ouverte, la barre passe dessous. Grand écran : fiche ouverte, la barre passe à sa droite ; recherche ouverte, elle s'arrête avant et se fond au bord. Co-Authored-By: Claude Opus 5.5 --- frontend/src/components/Galaxy.css | 10 ++++++++++ frontend/src/components/Galaxy.jsx | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/frontend/src/components/Galaxy.css b/frontend/src/components/Galaxy.css index 56ba59e..e08c47c 100644 --- a/frontend/src/components/Galaxy.css +++ b/frontend/src/components/Galaxy.css @@ -96,8 +96,18 @@ se limite à la moitié gauche sur grand écran et descend sous le message sur téléphone */ .family-tabs--lowered { max-width: calc(50vw - 200px); } +/* Fiche ouverte sur grand écran (à gauche, 384 px depuis 24 px) : la barre passe à sa droite */ +@media (min-width: 769px) { + body:has(.person-card) .family-tabs { left: 424px; max-width: calc(100vw - 424px - 96px); } + /* Recherche ouverte (environ 540 px à droite) : la barre s'arrête avant elle et se fond au bord */ + body:has(.expandable-search.expanded) .family-tabs { max-width: calc(100vw - 16px - 560px); } + body:has(.person-card):has(.expandable-search.expanded) .family-tabs { max-width: calc(100vw - 424px - 560px); } +} + @media (max-width: 768px) { .family-tabs { top: 10px; left: 10px; max-width: calc(100vw - 84px); } .family-tabs--lowered { top: 64px; max-width: calc(100vw - 20px); } + /* Recherche ouverte sur téléphone : elle prend toute la largeur du haut, la barre passe dessous */ + body:has(.expandable-search.expanded) .family-tabs { top: 80px; max-width: calc(100vw - 20px); } .family-tab { font-size: 14px; padding: 6px 12px 7px; } } diff --git a/frontend/src/components/Galaxy.jsx b/frontend/src/components/Galaxy.jsx index 7478c6f..0cbf709 100644 --- a/frontend/src/components/Galaxy.jsx +++ b/frontend/src/components/Galaxy.jsx @@ -51,6 +51,7 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, selectedPersonId, searchHighlig const [tabs, setTabs] = useState([]) const [activeKey, setActiveKey] = useState(focusPersonId != null ? String(focusPersonId) : null) const tabsCacheRef = useRef({ rev: -1, start: undefined, tabs: [] }) + const pendingFocusRef = useRef(null) // personne cherchée dans un autre onglet, visée après le changement const activeTabRef = useRef(null) const familyTabsRef = useRef(familyTabs) useEffect(() => { familyTabsRef.current = familyTabs }, [familyTabs]) @@ -406,6 +407,14 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, selectedPersonId, searchHighlig focusPerson: (personId) => { const canvas = canvasRef.current const node = layoutDataRef.current?.children.find(n => n.id === `p-${personId}`) + // Rangée dans un autre onglet : on ouvre cet onglet, la personne est visée une fois l'arbre posé + if (!node && familyTabsRef.current) { + const id = String(personId) + const all = tabsCacheRef.current.tabs + const home = all.find((tb) => tb.personIds?.has(id) && !(tb.hinges || []).map(String).includes(id)) || all.find((tb) => tb.personIds?.has(id)) || all[0] + if (home && home.key !== activeTabRef.current?.key) { pendingFocusRef.current = id; setActiveKey(home.key) } + return + } if (!canvas || !node) return const rect = canvas.getBoundingClientRect() const pos = getAnimatedPos(node, performance.now()) @@ -618,6 +627,11 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, selectedPersonId, searchHighlig layoutDataRef.current = result needsRedrawRef.current = true setLayoutReady(true) + if (pendingFocusRef.current) { + const id = pendingFocusRef.current + pendingFocusRef.current = null + requestAnimationFrame(() => zoomApiRef?.current?.focusPerson?.(id)) + } }, [graphRevision, activeKey, familyTabs]) // Sync selectedPersonId