added dark mode

This commit is contained in:
Salman Paracha 2025-07-03 15:38:13 -07:00
parent 4afe5cbdb2
commit 3e69fb6c2d
5 changed files with 107 additions and 41 deletions

View file

@ -1,17 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-g" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>React App</title>
</head>
<body>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<!-- ✅ External JS to configure Tailwind and set dark mode -->
<script src="%PUBLIC_URL%/init-theme.js"></script>
<title>RouteGPT</title>
</head>
<body class="bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-100">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>

View file

@ -0,0 +1,9 @@
// Apply dark mode based on system preference
if (
localStorage.theme === 'dark' ||
(!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}

View file

@ -3,24 +3,24 @@ import PreferenceBasedModelSelector from './components/PreferenceBasedModelSelec
export default function App() {
return (
<div className="bg-gray-100 min-h-screen flex items-center justify-center p-4">
<div className="bg-gray-100 dark:bg-gray-900 min-h-screen flex items-center justify-center p-4">
<div className="w-full max-w-6xl">
<div className="text-center mb-8">
<div className="flex justify-center items-center gap-3 -ml-12">
<img src="/logo.png" alt="RouteGPT Logo" className="w-10 h-10" />
<h1 className="text-3xl font-bold text-gray-800">RouteGPT</h1>
<div className="text-center mb-8">
<div className="flex justify-center items-center gap-3 -ml-12">
<img src="/logo.png" alt="RouteGPT Logo" className="w-10 h-10" />
<h1 className="text-3xl font-bold text-gray-800 dark:text-gray-100">RouteGPT</h1>
</div>
<p className="text-gray-600 dark:text-gray-300 mt-2">
Dynamically route to GPT models based on usage preferences.
</p>
<a
target="_blank"
href="https://github.com/katanemo/archgw"
className="text-blue-500 dark:text-blue-400 hover:underline"
>
powered by Arch Router
</a>
</div>
<p className="text-gray-600 mt-2">
Dynamically route to GPT models based on usage preferences.
</p>
<a
target="_blank"
href="https://github.com/katanemo/archgw"
className="text-blue-500 hover:underline"
>
powered by Arch Router
</a>
</div>
<PreferenceBasedModelSelector />
</div>
</div>

View file

@ -31,27 +31,74 @@ const PlusCircle = ({ className }) => (
// --- Mocked UI Components ---
const Card = ({ children, className = '' }) => (
<div className={`bg-white border border-gray-200 rounded-lg shadow-sm ${className}`}>{children}</div>
<div className={`bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm ${className}`}>
{children}
</div>
);
const CardContent = ({ children, className = '' }) => (
<div className={`p-4 ${className}`}>{children}</div>
<div className={`p-4 text-gray-800 dark:text-gray-100 ${className}`}>
{children}
</div>
);
const Input = (props) => (
<input
{...props}
className={`w-full h-9 px-3 text-sm text-gray-800 bg-white border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 ${props.className || ''}`}
className={`w-full h-9 px-3 text-sm
text-gray-800 dark:text-white
bg-white dark:bg-gray-700
border border-gray-300 dark:border-gray-600
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500
${props.className || ''}`}
/>
);
const Button = ({ children, variant = 'default', size = 'default', className = '', ...props }) => {
const baseClasses = 'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2';
const baseClasses = `
inline-flex items-center justify-center
rounded-md text-sm font-medium
transition-colors
focus:outline-none focus:ring-2 focus:ring-offset-2
`;
const variantClasses = {
default: 'bg-gray-900 text-white hover:bg-gray-800 focus:ring-gray-900',
outline: 'border border-gray-300 bg-transparent hover:bg-gray-100 focus:ring-gray-400',
ghost: 'hover:bg-gray-100 hover:text-gray-900 focus:ring-gray-400'
default: `
bg-gray-900 text-white
hover:bg-gray-800
focus:ring-gray-900
`,
outline: `
border border-gray-300 dark:border-gray-600
bg-transparent
text-gray-800 dark:text-white
hover:bg-gray-100 dark:hover:bg-gray-700
focus:ring-blue-500
focus:ring-offset-2
dark:focus:ring-offset-gray-900
`,
ghost: `
text-gray-800 dark:text-gray-200
hover:bg-gray-100 dark:hover:bg-gray-700
focus:ring-gray-400
`
};
const sizeClasses = { default: 'h-9 px-3', icon: 'h-9 w-9' };
const sizeClasses = {
default: 'h-9 px-3',
icon: 'h-9 w-9'
};
return (
<button {...props} className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}>
<button
{...props}
className={`
${baseClasses}
${variantClasses[variant]}
${sizeClasses[size]}
${className}
`}
>
{children}
</button>
);
@ -186,7 +233,7 @@ export default function PreferenceBasedModelSelector() {
};
return (
<div className="w-full max-w-[600px] bg-gray-50 p-4 mx-auto">
<div className="w-full max-w-[600px] bg-gray-50 dark:bg-gray-800 p-4 mx-auto">
<div className="space-y-4">
<Card className="w-full">
<CardContent>
@ -195,7 +242,7 @@ export default function PreferenceBasedModelSelector() {
<Switch checked={routingEnabled} onCheckedChange={setRoutingEnabled} />
</div>
{routingEnabled && (
<div className="pt-4 mt-4 space-y-3 border-t border-gray-200">
<div className="pt-4 mt-4 space-y-3 border-t border-gray-200 dark:border-gray-700">
{preferences.map((pref) => (
<div key={pref.id} className="grid grid-cols-[3fr_1.5fr_auto] gap-4 items-center">
<Input
@ -206,7 +253,11 @@ export default function PreferenceBasedModelSelector() {
<select
value={pref.model}
onChange={(e) => updatePreference(pref.id, 'model', e.target.value)}
className="h-9 w-full px-3 text-sm bg-white border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
className="h-9 w-full px-3 text-sm
bg-white dark:bg-gray-700
text-gray-800 dark:text-white
border border-gray-300 dark:border-gray-600
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
<option disabled value="">
Select Model
@ -235,7 +286,11 @@ export default function PreferenceBasedModelSelector() {
<select
value={defaultModel}
onChange={(e) => setDefaultModel(e.target.value)}
className="h-9 w-full mt-2 px-3 text-sm bg-white border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
className="h-9 w-full mt-2 px-3 text-sm
bg-white dark:bg-gray-700
text-gray-800 dark:text-white
border border-gray-300 dark:border-gray-600
rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
>
{modelOptions.map((m) => (
<option key={m} value={m}>
@ -245,7 +300,7 @@ export default function PreferenceBasedModelSelector() {
</select>
</CardContent>
</Card>
<div className="flex justify-end gap-2 pt-4 border-t border-gray-200">
<div className="flex justify-end gap-2 pt-4 border-t border-gray-200 dark:border-gray-700">
<Button variant="ghost" onClick={handleCancel}>
Cancel
</Button>

View file

@ -1,7 +1,9 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
darkMode: 'class', // ✅ Add this line
content: [
"./src/**/*.{js,jsx,ts,tsx}",
"./public/index.html",
],
theme: {
extend: {},