feat(ui): add 'Focus mode' option in chat settings to persistently toggle the sidebar auto-collapse (#11750)

Assisted-by: Claude:claude-fable-5

Signed-off-by: Plamen K. Kosseff <p.kosseff@gmail.com>
This commit is contained in:
Plamen K. Kosseff authored and GitHub committed 2026-08-27 22:32:32 +02:00
1 parent 1070cb1245
commit e58dabf75f
2 files changed
+28 -2

No files matched your search

@@ -33,6 +33,8 @@
"title": "Chat Settings",
"manageMode": "Manage mode",
"manageModeDesc": "Let this chat install models, switch backends, and edit configs by talking to LocalAI.",
"focusMode": "Focus mode",
"focusModeDesc": "Collapse the sidebar and slim the header while a conversation is active. Esc restores them temporarily; turn this off to keep the full layout.",
"systemPrompt": "System Prompt",
"systemPromptPlaceholder": "You are a helpful assistant...",
"temperature": "Temperature",
+26 -2
View File
@@ -21,6 +21,8 @@ import { useOperations } from '../hooks/useOperations'
import { relativeTime } from '../utils/format'
import { copyToClipboard } from '../utils/clipboard'
const FOCUS_MODE_KEY = 'localai_chat_focus_mode'
function getLastMessagePreview(chat) {
if (!chat.history || chat.history.length === 0) return ''
for (let i = chat.history.length - 1; i >= 0; i--) {
@@ -405,12 +407,20 @@ export default function Chat() {
// Focus mode: once a conversation has at least one message we slim the
// surrounding chrome (collapse the global app rail, fade non-essential
// header items). Esc gives the user back the full chrome for the rest of
// this session.
// this session. The settings drawer offers a persistent opt-out.
const isInConversation = (activeChat?.history?.length || 0) > 0
const [focusOverride, setFocusOverride] = useState(false)
const focusActive = isInConversation && !focusOverride
const [focusModeEnabled, setFocusModeEnabled] = useState(() => {
try { return localStorage.getItem(FOCUS_MODE_KEY) !== 'false' } catch (_) { return true }
})
const focusActive = focusModeEnabled && isInConversation && !focusOverride
const prevAppCollapseRef = useRef(null)
const toggleFocusMode = (next) => {
setFocusModeEnabled(next)
try { localStorage.setItem(FOCUS_MODE_KEY, String(next)) } catch (_) {}
}
const artifacts = useMemo(
() => canvasMode ? extractCodeArtifacts(activeChat?.history, 'role', 'assistant') : [],
[activeChat?.history, canvasMode]
@@ -1110,6 +1120,20 @@ export default function Chat() {
/>
</div>
)}
<div className="form-group chat-settings-toggle-row">
<div className="chat-settings-toggle-text">
<span className="chat-settings-toggle-title">
<i className="fas fa-compress" /> {t('settings.focusMode')}
</span>
<span className="chat-settings-toggle-desc">
{t('settings.focusModeDesc')}
</span>
</div>
<Toggle
checked={focusModeEnabled}
onChange={toggleFocusMode}
/>
</div>
<div className="form-group">
<label className="form-label">{t('settings.systemPrompt')}</label>
<textarea