From 18af8d1de5c7d12af674018ce819cc91480cf51a Mon Sep 17 00:00:00 2001 From: xXJSONDeruloXx Date: Fri, 11 Sep 2026 09:09:29 -0400 Subject: fix tab change jutter --- src/components/ConfigurationTab.tsx | 1 - src/components/Content.tsx | 30 +++++++++++------------------- src/styles.ts | 13 +++++++++++++ 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/components/ConfigurationTab.tsx b/src/components/ConfigurationTab.tsx index a6d4c2a..12f36a5 100644 --- a/src/components/ConfigurationTab.tsx +++ b/src/components/ConfigurationTab.tsx @@ -88,7 +88,6 @@ export function ConfigurationTab({ diff --git a/src/components/Content.tsx b/src/components/Content.tsx index 0d49f89..dc8c54f 100644 --- a/src/components/Content.tsx +++ b/src/components/Content.tsx @@ -1,5 +1,5 @@ -import { Field, PanelSection, PanelSectionRow, Tabs } from "@decky/ui"; -import { useEffect, useRef, useState } from "react"; +import { Tabs } from "@decky/ui"; +import { useEffect, useRef, useState, type FocusEvent } from "react"; import { FaCube, FaFileAlt, FaGamepad, FaList, FaTools } from "react-icons/fa"; import { ConfigurationData } from "../config/configSchema"; import { useFlatpakConfiguration } from "../hooks/useFlatpakConfiguration"; @@ -79,6 +79,7 @@ export function Content() { const flatpak = useFlatpakConfiguration(setupComplete); const [tab, setTab] = useState("Setup"); const [showDebugTab, setShowDebugTab] = usePersistentBoolean(DEBUG_TAB_VISIBILITY_KEY, true); + const [contentFocused, setContentFocused] = useState(false); const previousRunningWorkload = useRef(null); const runningFlatpak = flatpak.runningApp; const nowPlayingTarget = resolveNowPlayingTarget(runningGame, runningFlatpak); @@ -154,13 +155,11 @@ export function Content() { launcher={nowPlayingTarget.launcher} onConfigChange={flatpak.updateConfig} /> - ) : ( - - ); + ) : null; const tabs = setupComplete ? [ - { id: "NowPlaying", title: tabIcons.nowPlaying, content: nowPlaying }, + ...(nowPlaying ? [{ id: "NowPlaying", title: tabIcons.nowPlaying, content: nowPlaying }] : []), { id: "Games", title: tabIcons.games, @@ -205,11 +204,16 @@ export function Content() { const availableTabIds = new Set(tabs.map(({ id }) => id)); const activeTab = availableTabIds.has(tab) ? tab : setupComplete ? "Games" : "Setup"; + const handleFocusCapture = (event: FocusEvent) => { + const focusedElement = event.target as HTMLElement | null; + setContentFocused(!focusedElement?.closest?.('[role="tab"]')); + }; return (
); } - -function NowPlayingTabPlaceholder() { - return ( -
- - - - - -
- ); -} diff --git a/src/styles.ts b/src/styles.ts index 1bc089b..d197451 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -31,4 +31,17 @@ export const tabStyles = ` display: block; margin: 0; } + + .lsfg-vk-tabs--content-focused [role="tablist"][aria-orientation="horizontal"], + .lsfg-vk-tabs--content-focused [role="tablist"][aria-orientation="horizontal"] > div, + .lsfg-vk-tabs--content-focused [role="tablist"][aria-orientation="horizontal"] > div > div, + .lsfg-vk-tabs--content-focused [role="tablist"][aria-orientation="horizontal"] [role="tab"] { + animation: none !important; + transition: none !important; + } + + .lsfg-vk-tabs--content-focused [role="tablist"][aria-orientation="horizontal"] > div > div { + scroll-behavior: auto !important; + scroll-snap-type: none !important; + } `; -- cgit v1.2.3