From 60c1540744583e47ae757ae9dc856280c868ce4d Mon Sep 17 00:00:00 2001 From: Richard R Date: Sat, 30 May 2026 15:13:15 -0600 Subject: [PATCH] refactor(ui): decouple settings modal trigger from modal logic extract SettingsTrigger component to separate modal open control from SettingsModal. update HomeContent to manage modal state and pass open/onOpenChange props. remove redundant trigger button from SettingsModal for improved composability. removes embedded trigger logic from SettingsModal, enabling external state management and better integration with various UI layouts. also cleans up playwright config by centralizing testIgnore for unit tests. --- playwright.config.ts | 3 +-- src/components/HomeContent.tsx | 29 ++++++++++++--------- src/components/SettingsModal.tsx | 44 ++++++++++++++++++++------------ 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/playwright.config.ts b/playwright.config.ts index 6cd95e5..07b27bb 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -16,6 +16,7 @@ if (process.env.CI === 'true') { */ export default defineConfig({ testDir: './tests', + testIgnore: '**/unit/**', tsconfig: './tsconfig.json', timeout: 30 * 1000, outputDir: './tests/results', @@ -60,7 +61,6 @@ export default defineConfig({ { name: 'firefox', - testIgnore: '**/unit/**', use: { ...devices['Desktop Firefox'], extraHTTPHeaders: { 'x-openreader-test-namespace': 'firefox' }, @@ -69,7 +69,6 @@ export default defineConfig({ { name: 'webkit', - testIgnore: '**/unit/**', use: { ...devices['Desktop Safari'], extraHTTPHeaders: { 'x-openreader-test-namespace': 'webkit' }, diff --git a/src/components/HomeContent.tsx b/src/components/HomeContent.tsx index 8e9240f..e548230 100644 --- a/src/components/HomeContent.tsx +++ b/src/components/HomeContent.tsx @@ -1,7 +1,8 @@ 'use client'; +import { useState } from 'react'; import { DocumentList } from '@/components/doclist/DocumentList'; -import { SettingsModal } from '@/components/SettingsModal'; +import { SettingsModal, SettingsTrigger } from '@/components/SettingsModal'; import { UserMenu } from '@/components/auth/UserMenu'; const Brand = () => ( @@ -14,20 +15,24 @@ const Brand = () => ( ); -const AppActions = () => ( -
- - -
-); - export function HomeContent() { + const [settingsOpen, setSettingsOpen] = useState(false); + + const appActions = ( +
+ setSettingsOpen(true)} + /> + +
+ ); + return (
- } appActions={} /> + } appActions={appActions} /> +
); } diff --git a/src/components/SettingsModal.tsx b/src/components/SettingsModal.tsx index 50fee42..330f452 100644 --- a/src/components/SettingsModal.tsx +++ b/src/components/SettingsModal.tsx @@ -130,19 +130,42 @@ const SIDEBAR_SECTIONS: SidebarSection[] = [ type AdminSubTab = 'providers' | 'features'; -export function SettingsModal({ +export function SettingsTrigger({ className = '', triggerLabel, + onOpen, }: { className?: string; triggerLabel?: string; + onOpen: () => void; +}) { + return ( + + ); +} + +export function SettingsModal({ + open, + onOpenChange, +}: { + open: boolean; + onOpenChange: (open: boolean) => void; }) { const runtimeConfig = useRuntimeConfig(); const enableDestructiveDelete = runtimeConfig.enableDestructiveDeleteActions; const showAllProviderModels = runtimeConfig.showAllProviderModels; const enableTTSProvidersTab = runtimeConfig.enableTtsProvidersTab; const restrictUserApiKeys = runtimeConfig.restrictUserApiKeys; - const [isOpen, setIsOpen] = useState(false); + const isOpen = open; + const setIsOpen = onOpenChange; const [isChangelogOpen, setIsChangelogOpen] = useState(false); const [activeSection, setActiveSection] = useState(enableTTSProvidersTab ? 'api' : 'theme'); @@ -215,7 +238,7 @@ export function SettingsModal({ if (changelogOpenSignal <= 0) return; setIsOpen(true); setIsChangelogOpen(true); - }, [changelogOpenSignal]); + }, [changelogOpenSignal, setIsOpen]); useEffect(() => { setLocalApiKey(apiKey); @@ -409,7 +432,7 @@ export function SettingsModal({ } else { setCustomModelInput(''); } - }, [apiKey, baseUrl, providerRef, providerType, ttsModel, ttsInstructions, ttsModels]); + }, [apiKey, baseUrl, providerRef, providerType, ttsModel, ttsInstructions, ttsModels, setIsOpen]); const [systemIsDark, setSystemIsDark] = useState( typeof window !== 'undefined' && window.matchMedia('(prefers-color-scheme: dark)').matches @@ -489,19 +512,6 @@ export function SettingsModal({ return ( <> - -