From 9306a9c23b6916cad0d5c2885b7a37bf15efe99a Mon Sep 17 00:00:00 2001 From: Amit Haridas Date: Fri, 5 Jun 2026 19:41:18 +0530 Subject: [PATCH] feat(renderer): SettingsSheet (5 tabs: editor, theme, export, plugins, about) --- .../components/modals/SettingsSheet.tsx | 45 ++++++++++++++ tests/component/modals/SettingsSheet.test.tsx | 58 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 src/renderer/components/modals/SettingsSheet.tsx create mode 100644 tests/component/modals/SettingsSheet.test.tsx diff --git a/src/renderer/components/modals/SettingsSheet.tsx b/src/renderer/components/modals/SettingsSheet.tsx new file mode 100644 index 0000000..6d2f436 --- /dev/null +++ b/src/renderer/components/modals/SettingsSheet.tsx @@ -0,0 +1,45 @@ +import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle } from '@/components/ui/sheet'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { Button } from '@/components/ui/button'; +import { useAppStore } from '@/stores/app-store'; +import { useSettingsStore } from '@/stores/settings-store'; +import { EditorSettings } from './EditorSettings'; +import { ThemeSettings } from './ThemeSettings'; +import { ExportSettings } from './ExportSettings'; +import { PluginsSettings } from './PluginsSettings'; +import { AboutSettings } from './AboutSettings'; + +export function SettingsSheet() { + const closeModal = useAppStore((s) => s.closeModal); + const resetToDefaults = useSettingsStore((s) => s.resetToDefaults); + + return ( + !o && closeModal()}> + + + Settings + Editor, theme, and export preferences + + + + Editor + Theme + Export + Plugins + About + +
+ + + + + +
+
+
+ +
+
+
+ ); +} \ No newline at end of file diff --git a/tests/component/modals/SettingsSheet.test.tsx b/tests/component/modals/SettingsSheet.test.tsx new file mode 100644 index 0000000..3c24324 --- /dev/null +++ b/tests/component/modals/SettingsSheet.test.tsx @@ -0,0 +1,58 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { SettingsSheet } from '@/components/modals/SettingsSheet'; +import { useSettingsStore } from '@/stores/settings-store'; + +describe('SettingsSheet', () => { + beforeEach(() => { + localStorage.clear(); + useSettingsStore.setState(useSettingsStore.getInitialState()); + }); + + it('renders 5 tab triggers', () => { + render(); + expect(screen.getByRole('tab', { name: /editor/i })).toBeInTheDocument(); + expect(screen.getByRole('tab', { name: /theme/i })).toBeInTheDocument(); + expect(screen.getByRole('tab', { name: /export/i })).toBeInTheDocument(); + expect(screen.getByRole('tab', { name: /plugins/i })).toBeInTheDocument(); + expect(screen.getByRole('tab', { name: /about/i })).toBeInTheDocument(); + }); + + it('editor tab is open by default and shows font size', () => { + render(); + expect(screen.getByText(/font size/i)).toBeInTheDocument(); + }); + + it('theme tab shows theme radio group', async () => { + render(); + await userEvent.click(screen.getByRole('tab', { name: /theme/i })); + expect(screen.getByText(/accent color/i)).toBeInTheDocument(); + }); + + it('export tab shows ascii toggle and template picker', async () => { + render(); + await userEvent.click(screen.getByRole('tab', { name: /export/i })); + expect(screen.getByText(/render tables as ascii by default/i)).toBeInTheDocument(); + expect(screen.getByText(/default docx template/i)).toBeInTheDocument(); + }); + + it('plugins tab shows coming soon message', async () => { + render(); + await userEvent.click(screen.getByRole('tab', { name: /plugins/i })); + expect(screen.getByText(/coming soon/i)).toBeInTheDocument(); + }); + + it('about tab shows version', async () => { + render(); + await userEvent.click(screen.getByRole('tab', { name: /about/i })); + expect(screen.getByText(/markdownconverter/i)).toBeInTheDocument(); + }); + + it('reset to defaults button clears all settings', async () => { + useSettingsStore.getState().setSetting('fontSize', 22); + render(); + await userEvent.click(screen.getByRole('button', { name: /reset/i })); + expect(useSettingsStore.getState().fontSize).toBe(14); + }); +}); \ No newline at end of file