mirror of
https://github.com/katanemo/plano.git
synced 2026-06-17 15:25:17 +02:00
added dark mode
This commit is contained in:
parent
4afe5cbdb2
commit
3e69fb6c2d
5 changed files with 107 additions and 41 deletions
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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: {},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue