Options.tsx 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { useState, useEffect } from 'react';
  2. import '@src/Options.css';
  3. import { Button } from '@extension/ui';
  4. import { withErrorBoundary, withSuspense } from '@extension/shared';
  5. import { GeneralSettings } from './components/GeneralSettings';
  6. import { ModelSettings } from './components/ModelSettings';
  7. type TabTypes = 'general' | 'models' | 'help';
  8. const TABS: { id: TabTypes; icon: string; label: string }[] = [
  9. { id: 'general', icon: '⚙️', label: 'General' },
  10. { id: 'models', icon: '📊', label: 'Models' },
  11. { id: 'help', icon: '📚', label: 'Help' },
  12. ];
  13. const Options = () => {
  14. const [activeTab, setActiveTab] = useState<TabTypes>('models');
  15. const [isDarkMode, setIsDarkMode] = useState(false);
  16. // Check for dark mode preference
  17. useEffect(() => {
  18. const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
  19. setIsDarkMode(darkModeMediaQuery.matches);
  20. const handleChange = (e: MediaQueryListEvent) => {
  21. setIsDarkMode(e.matches);
  22. };
  23. darkModeMediaQuery.addEventListener('change', handleChange);
  24. return () => darkModeMediaQuery.removeEventListener('change', handleChange);
  25. }, []);
  26. const handleTabClick = (tabId: TabTypes) => {
  27. if (tabId === 'help') {
  28. window.location.href = 'https://nanobrowser.ai/docs';
  29. } else {
  30. setActiveTab(tabId);
  31. }
  32. };
  33. const renderTabContent = () => {
  34. switch (activeTab) {
  35. case 'general':
  36. return <GeneralSettings isDarkMode={isDarkMode} />;
  37. case 'models':
  38. return <ModelSettings isDarkMode={isDarkMode} />;
  39. default:
  40. return null;
  41. }
  42. };
  43. return (
  44. <div
  45. className={`flex min-h-screen min-w-[768px] ${isDarkMode ? 'bg-slate-900' : "bg-[url('/bg.jpg')] bg-cover bg-center"} ${isDarkMode ? 'text-gray-200' : 'text-gray-900'}`}>
  46. {/* Vertical Navigation Bar */}
  47. <nav
  48. className={`w-48 border-r ${isDarkMode ? 'border-slate-700 bg-slate-800/80' : 'border-white/20 bg-[#0EA5E9]/10'} backdrop-blur-sm`}>
  49. <div className="p-4">
  50. <h1 className={`mb-6 text-xl font-bold ${isDarkMode ? 'text-gray-200' : 'text-gray-800'}`}>Settings</h1>
  51. <ul className="space-y-2">
  52. {TABS.map(item => (
  53. <li key={item.id}>
  54. <Button
  55. onClick={() => handleTabClick(item.id)}
  56. className={`flex w-full items-center space-x-2 rounded-lg px-4 py-2 text-left text-base
  57. ${
  58. activeTab !== item.id
  59. ? `${isDarkMode ? 'bg-slate-700/70 text-gray-300 hover:text-white' : 'bg-[#0EA5E9]/15 font-medium text-gray-700 hover:text-white'} backdrop-blur-sm`
  60. : `${isDarkMode ? 'bg-sky-800/50' : ''} text-white backdrop-blur-sm`
  61. }`}>
  62. <span>{item.icon}</span>
  63. <span>{item.label}</span>
  64. </Button>
  65. </li>
  66. ))}
  67. </ul>
  68. </div>
  69. </nav>
  70. {/* Main Content Area */}
  71. <main className={`flex-1 ${isDarkMode ? 'bg-slate-800/50' : 'bg-white/10'} p-8 backdrop-blur-sm`}>
  72. <div className="mx-auto min-w-[512px] max-w-screen-lg">{renderTabContent()}</div>
  73. </main>
  74. </div>
  75. );
  76. };
  77. export default withErrorBoundary(withSuspense(Options, <div>Loading...</div>), <div>Error Occurred</div>);