feat(v3): redesign SettingsTab global settings with split font controls

Split single font setting into separate UI font (sans-serif options)
and Terminal font (monospace options), each with custom themed dropdown
and size stepper (8-24px). Single-column layout with Appearance and
Defaults subsections. All native <select> replaced with custom themed
dropdowns. Font previews render in their own typeface. New CSS vars:
--term-font-family, --term-font-size. Setting keys changed from
font_family/font_size to ui_font_family/ui_font_size +
term_font_family/term_font_size.
This commit is contained in:
Hibryda 2026-03-07 23:23:33 +01:00
parent fa7d0bd915
commit 36af9dd1d2
3 changed files with 360 additions and 223 deletions

View file

@ -29,21 +29,40 @@
// Global settings // Global settings
let defaultShell = $state(''); let defaultShell = $state('');
let defaultCwd = $state(''); let defaultCwd = $state('');
let fontFamily = $state(''); let uiFont = $state('');
let fontSize = $state(''); let uiFontSize = $state('');
let termFont = $state('');
let termFontSize = $state('');
let selectedTheme = $state<ThemeId>(getCurrentTheme()); let selectedTheme = $state<ThemeId>(getCurrentTheme());
let themeDropdownOpen = $state(false);
const FONT_OPTIONS = [ // Dropdown open states
'JetBrains Mono', let themeDropdownOpen = $state(false);
'Fira Code', let uiFontDropdownOpen = $state(false);
'Cascadia Code', let termFontDropdownOpen = $state(false);
'Source Code Pro',
'IBM Plex Mono', const UI_FONTS = [
'Hack', { value: '', label: 'System Default' },
'Inconsolata', { value: 'Inter', label: 'Inter' },
'Ubuntu Mono', { value: 'IBM Plex Sans', label: 'IBM Plex Sans' },
'monospace', { value: 'Noto Sans', label: 'Noto Sans' },
{ value: 'Roboto', label: 'Roboto' },
{ value: 'Source Sans 3', label: 'Source Sans 3' },
{ value: 'Ubuntu', label: 'Ubuntu' },
{ value: 'JetBrains Mono', label: 'JetBrains Mono' },
{ value: 'Fira Code', label: 'Fira Code' },
];
const TERM_FONTS = [
{ value: '', label: 'Default (JetBrains Mono)' },
{ value: 'JetBrains Mono', label: 'JetBrains Mono' },
{ value: 'Fira Code', label: 'Fira Code' },
{ value: 'Cascadia Code', label: 'Cascadia Code' },
{ value: 'Source Code Pro', label: 'Source Code Pro' },
{ value: 'IBM Plex Mono', label: 'IBM Plex Mono' },
{ value: 'Hack', label: 'Hack' },
{ value: 'Inconsolata', label: 'Inconsolata' },
{ value: 'Ubuntu Mono', label: 'Ubuntu Mono' },
{ value: 'monospace', label: 'monospace' },
]; ];
// Group themes by category // Group themes by category
@ -60,25 +79,33 @@
THEME_LIST.find(t => t.id === selectedTheme)?.label ?? selectedTheme, THEME_LIST.find(t => t.id === selectedTheme)?.label ?? selectedTheme,
); );
let uiFontLabel = $derived(
UI_FONTS.find(f => f.value === uiFont)?.label ?? 'System Default',
);
let termFontLabel = $derived(
TERM_FONTS.find(f => f.value === termFont)?.label ?? 'Default (JetBrains Mono)',
);
onMount(async () => { onMount(async () => {
const [shell, cwd, font, size] = await Promise.all([ const [shell, cwd, font, size, tfont, tsize] = await Promise.all([
getSetting('default_shell'), getSetting('default_shell'),
getSetting('default_cwd'), getSetting('default_cwd'),
getSetting('font_family'), getSetting('ui_font_family'),
getSetting('font_size'), getSetting('ui_font_size'),
getSetting('term_font_family'),
getSetting('term_font_size'),
]); ]);
defaultShell = shell ?? ''; defaultShell = shell ?? '';
defaultCwd = cwd ?? ''; defaultCwd = cwd ?? '';
fontFamily = font ?? ''; uiFont = font ?? '';
fontSize = size ?? ''; uiFontSize = size ?? '';
termFont = tfont ?? '';
termFontSize = tsize ?? '';
selectedTheme = getCurrentTheme(); selectedTheme = getCurrentTheme();
// Apply saved font settings
if (font) applyFont('--ui-font-family', `'${font}', monospace`);
if (size) applyFont('--ui-font-size', `${size}px`);
}); });
function applyFont(prop: string, value: string) { function applyCssProp(prop: string, value: string) {
document.documentElement.style.setProperty(prop, value); document.documentElement.style.setProperty(prop, value);
} }
@ -90,18 +117,40 @@
} }
} }
async function handleFontFamilyChange(family: string) { async function handleUiFontChange(family: string) {
fontFamily = family; uiFont = family;
applyFont('--ui-font-family', family ? `'${family}', monospace` : "'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace"); uiFontDropdownOpen = false;
await saveGlobalSetting('font_family', family); const val = family
? `'${family}', sans-serif`
: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace";
applyCssProp('--ui-font-family', val);
await saveGlobalSetting('ui_font_family', family);
} }
async function handleFontSizeChange(size: string) { async function handleUiFontSizeChange(size: string) {
const num = parseInt(size, 10); const num = parseInt(size, 10);
if (isNaN(num) || num < 8 || num > 24) return; if (isNaN(num) || num < 8 || num > 24) return;
fontSize = size; uiFontSize = size;
applyFont('--ui-font-size', `${num}px`); applyCssProp('--ui-font-size', `${num}px`);
await saveGlobalSetting('font_size', size); await saveGlobalSetting('ui_font_size', size);
}
async function handleTermFontChange(family: string) {
termFont = family;
termFontDropdownOpen = false;
const val = family
? `'${family}', monospace`
: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace";
applyCssProp('--term-font-family', val);
await saveGlobalSetting('term_font_family', family);
}
async function handleTermFontSizeChange(size: string) {
const num = parseInt(size, 10);
if (isNaN(num) || num < 8 || num > 24) return;
termFontSize = size;
applyCssProp('--term-font-size', `${num}px`);
await saveGlobalSetting('term_font_size', size);
} }
async function handleThemeChange(themeId: ThemeId) { async function handleThemeChange(themeId: ThemeId) {
@ -110,16 +159,20 @@
await setTheme(themeId); await setTheme(themeId);
} }
function handleDropdownKeydown(e: KeyboardEvent) { function handleClickOutside(e: MouseEvent) {
if (e.key === 'Escape') { const target = e.target as HTMLElement;
if (!target.closest('.custom-dropdown')) {
themeDropdownOpen = false; themeDropdownOpen = false;
uiFontDropdownOpen = false;
termFontDropdownOpen = false;
} }
} }
function handleClickOutside(e: MouseEvent) { function handleKeydown(e: KeyboardEvent) {
const target = e.target as HTMLElement; if (e.key === 'Escape') {
if (!target.closest('.theme-dropdown')) {
themeDropdownOpen = false; themeDropdownOpen = false;
uiFontDropdownOpen = false;
termFontDropdownOpen = false;
} }
} }
@ -157,16 +210,16 @@
<!-- svelte-ignore a11y_click_events_have_key_events --> <!-- svelte-ignore a11y_click_events_have_key_events -->
<!-- svelte-ignore a11y_no_static_element_interactions --> <!-- svelte-ignore a11y_no_static_element_interactions -->
<div class="settings-tab" onclick={handleClickOutside}> <div class="settings-tab" onclick={handleClickOutside} onkeydown={handleKeydown}>
<section class="settings-section"> <section class="settings-section">
<h2>Global</h2> <h2>Appearance</h2>
<div class="global-grid"> <div class="settings-list">
<div class="setting-field"> <div class="setting-field">
<span class="setting-label">Theme</span> <span class="setting-label">Theme</span>
<div class="theme-dropdown" onkeydown={handleDropdownKeydown}> <div class="custom-dropdown">
<button <button
class="theme-trigger" class="dropdown-trigger"
onclick={() => (themeDropdownOpen = !themeDropdownOpen)} onclick={() => { themeDropdownOpen = !themeDropdownOpen; uiFontDropdownOpen = false; termFontDropdownOpen = false; }}
aria-haspopup="listbox" aria-haspopup="listbox"
aria-expanded={themeDropdownOpen} aria-expanded={themeDropdownOpen}
> >
@ -174,16 +227,16 @@
class="theme-swatch" class="theme-swatch"
style="background: {getPalette(selectedTheme).base}; border-color: {getPalette(selectedTheme).surface1};" style="background: {getPalette(selectedTheme).base}; border-color: {getPalette(selectedTheme).surface1};"
></span> ></span>
<span class="theme-trigger-label">{selectedThemeLabel}</span> <span class="dropdown-label">{selectedThemeLabel}</span>
<span class="theme-arrow">{themeDropdownOpen ? '\u25B4' : '\u25BE'}</span> <span class="dropdown-arrow">{themeDropdownOpen ? '\u25B4' : '\u25BE'}</span>
</button> </button>
{#if themeDropdownOpen} {#if themeDropdownOpen}
<div class="theme-menu" role="listbox"> <div class="dropdown-menu" role="listbox">
{#each themeGroups() as [groupName, themes]} {#each themeGroups() as [groupName, themes]}
<div class="theme-group-label">{groupName}</div> <div class="dropdown-group-label">{groupName}</div>
{#each themes as t} {#each themes as t}
<button <button
class="theme-option" class="dropdown-option"
class:active={t.id === selectedTheme} class:active={t.id === selectedTheme}
role="option" role="option"
aria-selected={t.id === selectedTheme} aria-selected={t.id === selectedTheme}
@ -193,7 +246,7 @@
class="theme-swatch" class="theme-swatch"
style="background: {getPalette(t.id).base}; border-color: {getPalette(t.id).surface1};" style="background: {getPalette(t.id).base}; border-color: {getPalette(t.id).surface1};"
></span> ></span>
<span class="theme-option-label">{t.label}</span> <span class="dropdown-option-label">{t.label}</span>
<span class="theme-colors"> <span class="theme-colors">
<span class="color-dot" style="background: {getPalette(t.id).red};"></span> <span class="color-dot" style="background: {getPalette(t.id).red};"></span>
<span class="color-dot" style="background: {getPalette(t.id).green};"></span> <span class="color-dot" style="background: {getPalette(t.id).green};"></span>
@ -209,47 +262,120 @@
</div> </div>
<div class="setting-field"> <div class="setting-field">
<label for="font-family" class="setting-label">Font family</label> <span class="setting-label">UI Font</span>
<select <div class="setting-row">
id="font-family" <div class="custom-dropdown dropdown-grow">
class="setting-select" <button
onchange={e => handleFontFamilyChange((e.target as HTMLSelectElement).value)} class="dropdown-trigger"
> onclick={() => { uiFontDropdownOpen = !uiFontDropdownOpen; themeDropdownOpen = false; termFontDropdownOpen = false; }}
<option value="" selected={!fontFamily}>Default (JetBrains Mono)</option> aria-haspopup="listbox"
{#each FONT_OPTIONS as font} aria-expanded={uiFontDropdownOpen}
<option value={font} selected={fontFamily === font}>{font}</option> >
{/each} <span class="dropdown-label" style={uiFont ? `font-family: '${uiFont}', sans-serif` : ''}>{uiFontLabel}</span>
</select> <span class="dropdown-arrow">{uiFontDropdownOpen ? '\u25B4' : '\u25BE'}</span>
</div> </button>
{#if uiFontDropdownOpen}
<div class="setting-field"> <div class="dropdown-menu" role="listbox">
<label for="font-size" class="setting-label">Font size</label> {#each UI_FONTS as f}
<div class="size-control"> <button
<button class="dropdown-option"
class="size-btn" class:active={f.value === uiFont}
onclick={() => handleFontSizeChange(String((parseInt(fontSize, 10) || 13) - 1))} role="option"
disabled={parseInt(fontSize, 10) <= 8} aria-selected={f.value === uiFont}
></button> style={f.value ? `font-family: '${f.value}', sans-serif` : ''}
<input onclick={() => handleUiFontChange(f.value)}
id="font-size" >
type="number" <span class="dropdown-option-label">{f.label}</span>
min="8" </button>
max="24" {/each}
value={fontSize || '13'} </div>
class="size-input" {/if}
onchange={e => handleFontSizeChange((e.target as HTMLInputElement).value)} </div>
/> <div class="size-control">
<span class="size-unit">px</span> <button
<button class="size-btn"
class="size-btn" onclick={() => handleUiFontSizeChange(String((parseInt(uiFontSize, 10) || 13) - 1))}
onclick={() => handleFontSizeChange(String((parseInt(fontSize, 10) || 13) + 1))} disabled={(parseInt(uiFontSize, 10) || 13) <= 8}
disabled={parseInt(fontSize, 10) >= 24} >&minus;</button>
>+</button> <input
type="number"
min="8"
max="24"
value={uiFontSize || '13'}
class="size-input"
onchange={e => handleUiFontSizeChange((e.target as HTMLInputElement).value)}
/>
<span class="size-unit">px</span>
<button
class="size-btn"
onclick={() => handleUiFontSizeChange(String((parseInt(uiFontSize, 10) || 13) + 1))}
disabled={(parseInt(uiFontSize, 10) || 13) >= 24}
>+</button>
</div>
</div> </div>
</div> </div>
<div class="setting-field"> <div class="setting-field">
<label for="default-shell" class="setting-label">Default shell</label> <span class="setting-label">Terminal Font</span>
<div class="setting-row">
<div class="custom-dropdown dropdown-grow">
<button
class="dropdown-trigger"
onclick={() => { termFontDropdownOpen = !termFontDropdownOpen; themeDropdownOpen = false; uiFontDropdownOpen = false; }}
aria-haspopup="listbox"
aria-expanded={termFontDropdownOpen}
>
<span class="dropdown-label" style={termFont ? `font-family: '${termFont}', monospace` : ''}>{termFontLabel}</span>
<span class="dropdown-arrow">{termFontDropdownOpen ? '\u25B4' : '\u25BE'}</span>
</button>
{#if termFontDropdownOpen}
<div class="dropdown-menu" role="listbox">
{#each TERM_FONTS as f}
<button
class="dropdown-option"
class:active={f.value === termFont}
role="option"
aria-selected={f.value === termFont}
style={f.value ? `font-family: '${f.value}', monospace` : ''}
onclick={() => handleTermFontChange(f.value)}
>
<span class="dropdown-option-label">{f.label}</span>
</button>
{/each}
</div>
{/if}
</div>
<div class="size-control">
<button
class="size-btn"
onclick={() => handleTermFontSizeChange(String((parseInt(termFontSize, 10) || 13) - 1))}
disabled={(parseInt(termFontSize, 10) || 13) <= 8}
>&minus;</button>
<input
type="number"
min="8"
max="24"
value={termFontSize || '13'}
class="size-input"
onchange={e => handleTermFontSizeChange((e.target as HTMLInputElement).value)}
/>
<span class="size-unit">px</span>
<button
class="size-btn"
onclick={() => handleTermFontSizeChange(String((parseInt(termFontSize, 10) || 13) + 1))}
disabled={(parseInt(termFontSize, 10) || 13) >= 24}
>+</button>
</div>
</div>
</div>
</div>
</section>
<section class="settings-section">
<h2>Defaults</h2>
<div class="settings-list">
<div class="setting-field">
<label for="default-shell" class="setting-label">Shell</label>
<input <input
id="default-shell" id="default-shell"
value={defaultShell} value={defaultShell}
@ -257,9 +383,8 @@
onchange={e => { defaultShell = (e.target as HTMLInputElement).value; saveGlobalSetting('default_shell', defaultShell); }} onchange={e => { defaultShell = (e.target as HTMLInputElement).value; saveGlobalSetting('default_shell', defaultShell); }}
/> />
</div> </div>
<div class="setting-field"> <div class="setting-field">
<label for="default-cwd" class="setting-label">Default CWD</label> <label for="default-cwd" class="setting-label">Working directory</label>
<input <input
id="default-cwd" id="default-cwd"
value={defaultCwd} value={defaultCwd}
@ -356,24 +481,26 @@
padding: 16px 24px; padding: 16px 24px;
overflow-y: auto; overflow-y: auto;
height: 100%; height: 100%;
max-width: 900px; max-width: 560px;
} }
h2 { h2 {
font-size: 1rem; font-size: 0.85rem;
font-weight: 600; font-weight: 600;
color: var(--ctp-text); color: var(--ctp-text);
margin: 0 0 12px; margin: 0 0 10px;
padding-bottom: 6px;
border-bottom: 1px solid var(--ctp-surface0);
} }
.settings-section { .settings-section {
margin-bottom: 24px; margin-bottom: 20px;
} }
.global-grid { .settings-list {
display: grid; display: flex;
grid-template-columns: 1fr 1fr; flex-direction: column;
gap: 12px; gap: 10px;
} }
.setting-field { .setting-field {
@ -389,7 +516,7 @@
letter-spacing: 0.03em; letter-spacing: 0.03em;
} }
.setting-field input:not([type="number"]) { .setting-field > input {
padding: 6px 10px; padding: 6px 10px;
background: var(--ctp-surface0); background: var(--ctp-surface0);
border: 1px solid var(--ctp-surface1); border: 1px solid var(--ctp-surface1);
@ -398,7 +525,27 @@
font-size: 0.8rem; font-size: 0.8rem;
} }
.setting-select { .setting-row {
display: flex;
gap: 8px;
align-items: stretch;
}
/* Reusable custom dropdown */
.custom-dropdown {
position: relative;
}
.dropdown-grow {
flex: 1;
min-width: 0;
}
.dropdown-trigger {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 6px 10px; padding: 6px 10px;
background: var(--ctp-surface0); background: var(--ctp-surface0);
border: 1px solid var(--ctp-surface1); border: 1px solid var(--ctp-surface1);
@ -406,12 +553,112 @@
color: var(--ctp-text); color: var(--ctp-text);
font-size: 0.8rem; font-size: 0.8rem;
cursor: pointer; cursor: pointer;
text-align: left;
height: 100%;
} }
.dropdown-trigger:hover {
border-color: var(--ctp-surface2);
}
.dropdown-label {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dropdown-arrow {
color: var(--ctp-overlay0);
font-size: 0.7rem;
flex-shrink: 0;
}
.dropdown-menu {
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 100%;
width: max-content;
max-height: 360px;
overflow-y: auto;
background: var(--ctp-mantle);
border: 1px solid var(--ctp-surface1);
border-radius: 4px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
z-index: 100;
padding: 4px 0;
}
.dropdown-group-label {
padding: 6px 10px 2px;
font-size: 0.65rem;
font-weight: 700;
color: var(--ctp-overlay0);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.dropdown-option {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 5px 10px;
background: transparent;
border: none;
color: var(--ctp-subtext1);
font-size: 0.8rem;
cursor: pointer;
text-align: left;
white-space: nowrap;
}
.dropdown-option:hover {
background: var(--ctp-surface0);
color: var(--ctp-text);
}
.dropdown-option.active {
background: var(--ctp-surface0);
color: var(--ctp-text);
font-weight: 600;
}
.dropdown-option-label {
flex: 1;
}
/* Theme-specific dropdown extras */
.theme-swatch {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 3px;
border: 1px solid;
flex-shrink: 0;
}
.theme-colors {
display: flex;
gap: 3px;
flex-shrink: 0;
}
.color-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
}
/* Size control (shared by UI and Terminal font) */
.size-control { .size-control {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 4px; gap: 2px;
flex-shrink: 0;
} }
.size-btn { .size-btn {
@ -438,8 +685,8 @@
} }
.size-input { .size-input {
width: 48px; width: 40px;
padding: 4px 6px; padding: 4px 2px;
background: var(--ctp-surface0); background: var(--ctp-surface0);
border: 1px solid var(--ctp-surface1); border: 1px solid var(--ctp-surface1);
border-radius: 4px; border-radius: 4px;
@ -455,122 +702,9 @@
} }
.size-unit { .size-unit {
font-size: 0.75rem;
color: var(--ctp-overlay0);
}
/* Custom theme dropdown */
.theme-dropdown {
position: relative;
}
.theme-trigger {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 4px 8px;
background: var(--ctp-base);
border: 1px solid var(--ctp-surface1);
border-radius: 3px;
color: var(--ctp-text);
font-size: 0.8rem;
cursor: pointer;
text-align: left;
}
.theme-trigger:hover {
border-color: var(--ctp-surface2);
}
.theme-trigger-label {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.theme-arrow {
color: var(--ctp-overlay0);
font-size: 0.7rem; font-size: 0.7rem;
flex-shrink: 0;
}
.theme-swatch {
display: inline-block;
width: 14px;
height: 14px;
border-radius: 3px;
border: 1px solid;
flex-shrink: 0;
}
.theme-menu {
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 280px;
max-height: 400px;
overflow-y: auto;
background: var(--ctp-mantle);
border: 1px solid var(--ctp-surface1);
border-radius: 4px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
z-index: 100;
padding: 4px 0;
}
.theme-group-label {
padding: 6px 10px 2px;
font-size: 0.65rem;
font-weight: 700;
color: var(--ctp-overlay0); color: var(--ctp-overlay0);
text-transform: uppercase; margin-right: 2px;
letter-spacing: 0.05em;
}
.theme-option {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 5px 10px;
background: transparent;
border: none;
color: var(--ctp-subtext1);
font-size: 0.8rem;
cursor: pointer;
text-align: left;
}
.theme-option:hover {
background: var(--ctp-surface0);
color: var(--ctp-text);
}
.theme-option.active {
background: var(--ctp-surface0);
color: var(--ctp-text);
font-weight: 600;
}
.theme-option-label {
flex: 1;
white-space: nowrap;
}
.theme-colors {
display: flex;
gap: 3px;
flex-shrink: 0;
}
.color-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
} }
/* Groups & Projects */ /* Groups & Projects */

View file

@ -81,16 +81,17 @@ export async function initTheme(): Promise<void> {
// Apply saved font settings // Apply saved font settings
try { try {
const [fontFamily, fontSize] = await Promise.all([ const [uiFont, uiSize, termFont, termSize] = await Promise.all([
getSetting('font_family'), getSetting('ui_font_family'),
getSetting('font_size'), getSetting('ui_font_size'),
getSetting('term_font_family'),
getSetting('term_font_size'),
]); ]);
if (fontFamily) { const root = document.documentElement.style;
document.documentElement.style.setProperty('--ui-font-family', `'${fontFamily}', monospace`); if (uiFont) root.setProperty('--ui-font-family', `'${uiFont}', sans-serif`);
} if (uiSize) root.setProperty('--ui-font-size', `${uiSize}px`);
if (fontSize) { if (termFont) root.setProperty('--term-font-family', `'${termFont}', monospace`);
document.documentElement.style.setProperty('--ui-font-size', `${fontSize}px`); if (termSize) root.setProperty('--term-font-size', `${termSize}px`);
}
} catch { } catch {
// Font settings are optional — defaults from catppuccin.css apply // Font settings are optional — defaults from catppuccin.css apply
} }

View file

@ -46,6 +46,8 @@
/* Typography */ /* Typography */
--ui-font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace; --ui-font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
--ui-font-size: 13px; --ui-font-size: 13px;
--term-font-family: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
--term-font-size: 13px;
/* Layout */ /* Layout */
--sidebar-width: 260px; --sidebar-width: 260px;