+ {/* Font Family */}
+
+
+
+ {t('terminalFonts.fontConfig.fontFamilyDescription', {
+ defaultValue: 'Primary monospace font for terminal text',
+ })}
+
+
+
+
+ {/* Current font chain display */}
+
+ {t('terminalFonts.fontConfig.fontChain', { defaultValue: 'Font chain:' })}{' '}
+
+ {settings.fontFamily.join(', ')}
+
+
+
+
+ {/* Font Size */}
+
+
+
+
+
+ {settings.fontSize}px
+
+
+
+
+
+
+
+
+ {t('terminalFonts.fontConfig.fontSizeDescription', {
+ defaultValue: 'Base font size in pixels (10-24px)',
+ })}
+
+
handleFontSizeChange(parseInt(e.target.value, 10))}
+ aria-label={t('terminalFonts.fontConfig.fontSize', { defaultValue: 'Font Size' })}
+ aria-valuemin={FONT_SIZE_MIN}
+ aria-valuemax={FONT_SIZE_MAX}
+ aria-valuenow={settings.fontSize}
+ aria-valuetext={`${settings.fontSize} ${t('terminalFonts.fontConfig.pixels', { defaultValue: 'pixels' })}`}
+ className={cn(...SLIDER_INPUT_CLASSES)}
+ />
+
+ {FONT_SIZE_MIN}px
+ {FONT_SIZE_MAX}px
+
+
+
+ {/* Font Weight */}
+
+
+
+ {t('terminalFonts.fontConfig.fontWeightDescription', {
+ defaultValue: 'Font weight from 100 (thin) to 900 (black), in steps of 100',
+ })}
+
+
+
handleFontWeightChange(e.target.value)}
+ className={cn(
+ 'w-24 h-10 px-3 rounded-lg',
+ 'border border-border bg-card',
+ 'text-sm text-foreground',
+ 'focus:outline-none focus:ring-2 focus:ring-ring focus:border-primary',
+ 'disabled:cursor-not-allowed disabled:opacity-50',
+ 'transition-colors duration-200'
+ )}
+ />
+
+
+
+
+
+
+ {t('terminalFonts.fontConfig.commonWeights', {
+ defaultValue: 'Common: 400 (normal), 600 (semi-bold), 700 (bold)',
+ })}
+
+
+
+ {/* Line Height */}
+
+
+
+
+ {numberFormatter.format(settings.lineHeight)}
+
+
+
+ {t('terminalFonts.fontConfig.lineHeightDescription', {
+ defaultValue: 'Line height as a multiple of font size (1.0-2.0)',
+ })}
+
+
handleLineHeightChange(parseFloat(e.target.value))}
+ aria-label={t('terminalFonts.fontConfig.lineHeight', { defaultValue: 'Line Height' })}
+ aria-valuemin={LINE_HEIGHT_MIN}
+ aria-valuemax={LINE_HEIGHT_MAX}
+ aria-valuenow={settings.lineHeight}
+ aria-valuetext={numberFormatter.format(settings.lineHeight)}
+ className={cn(...SLIDER_INPUT_CLASSES)}
+ />
+
+ {LINE_HEIGHT_MIN.toFixed(1)}
+ {LINE_HEIGHT_MAX.toFixed(1)}
+
+
+
+ {/* Letter Spacing */}
+
+
+
+
+ {settings.letterSpacing > 0 ? `+${numberFormatter.format(settings.letterSpacing)}` : numberFormatter.format(settings.letterSpacing)}px
+
+
+
+ {t('terminalFonts.fontConfig.letterSpacingDescription', {
+ defaultValue: 'Horizontal spacing between characters (-2 to 5px)',
+ })}
+
+
handleLetterSpacingChange(parseFloat(e.target.value))}
+ aria-label={t('terminalFonts.fontConfig.letterSpacing', { defaultValue: 'Letter Spacing' })}
+ aria-valuemin={LETTER_SPACING_MIN}
+ aria-valuemax={LETTER_SPACING_MAX}
+ aria-valuenow={settings.letterSpacing}
+ aria-valuetext={`${settings.letterSpacing > 0 ? '+' : ''}${numberFormatter.format(settings.letterSpacing)} ${t('terminalFonts.fontConfig.pixels', { defaultValue: 'pixels' })}`}
+ className={cn(...SLIDER_INPUT_CLASSES)}
+ />
+
+ {LETTER_SPACING_MIN}px
+ +{LETTER_SPACING_MAX}px
+
+
+
+ );
+}
diff --git a/apps/frontend/src/renderer/components/settings/terminal-font-settings/LivePreviewTerminal.tsx b/apps/frontend/src/renderer/components/settings/terminal-font-settings/LivePreviewTerminal.tsx
new file mode 100644
index 00000000..c44e1524
--- /dev/null
+++ b/apps/frontend/src/renderer/components/settings/terminal-font-settings/LivePreviewTerminal.tsx
@@ -0,0 +1,248 @@
+import { useEffect, useRef } from 'react';
+import { Terminal as XTerm } from '@xterm/xterm';
+import { FitAddon } from '@xterm/addon-fit';
+import type { TerminalFontSettings } from '../../../stores/terminal-font-settings-store';
+import { useTranslation } from 'react-i18next';
+import { debounce } from '../../../lib/debounce';
+import { DEFAULT_TERMINAL_THEME } from '../../../lib/terminal-theme';
+
+interface LivePreviewTerminalProps {
+ settings: TerminalFontSettings;
+}
+
+/**
+ * LivePreviewTerminal component
+ *
+ * Renders a mock xterm.js terminal instance showing sample output.
+ * Updates in real-time (300ms debounced) as font settings change.
+ *
+ * Features:
+ * - Realistic terminal prompt and colored output
+ * - Applies all font settings (family, size, weight, line height, letter spacing)
+ * - Applies cursor settings (style, blink, accent color)
+ * - Debounced updates prevent UI lag during slider drag
+ * - Read-only terminal (no user input allowed)
+ *
+ * Sample output includes:
+ * - Shell prompt with username and hostname
+ * - Command examples (ls, git status, npm run dev)
+ * - Colored output (directories, errors, warnings)
+ * - Multi-line output demonstration
+ */
+export function LivePreviewTerminal({ settings }: LivePreviewTerminalProps) {
+ const { t } = useTranslation('settings');
+ const terminalRef = useRef