Files
Termix/src/main.tsx
Peet McKinney e6a70e3a02 feat: Complete light mode implementation with semantic theme system (#450)
- Add comprehensive light/dark mode CSS variables with semantic naming
- Implement theme-aware scrollbars using CSS variables
- Add light mode backgrounds: --bg-base, --bg-elevated, --bg-surface, etc.
- Add theme-aware borders: --border-base, --border-panel, --border-subtle
- Add semantic text colors: --foreground-secondary, --foreground-subtle
- Convert oklch colors to hex for better compatibility
- Add theme awareness to CodeMirror editors
- Update dark mode colors for consistency (background, sidebar, card, muted, input)
- Add Tailwind color mappings for semantic classes

Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com>
2025-12-23 16:35:49 -06:00

117 lines
3.2 KiB
TypeScript

/* eslint-disable react-refresh/only-export-components */
import { StrictMode, useEffect, useState, useRef } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import DesktopApp from "@/ui/desktop/DesktopApp.tsx";
import { MobileApp } from "@/ui/mobile/MobileApp.tsx";
import { ThemeProvider } from "@/components/theme-provider";
import { ElectronVersionCheck } from "@/ui/desktop/user/ElectronVersionCheck.tsx";
import "./i18n/i18n";
import { isElectron } from "./ui/main-axios.ts";
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
const lastSwitchTime = useRef(0);
const isCurrentlyMobile = useRef(window.innerWidth < 768);
const hasSwitchedOnce = useRef(false);
useEffect(() => {
let timeoutId: NodeJS.Timeout;
const handleResize = () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
const newWidth = window.innerWidth;
const newIsMobile = newWidth < 768;
const now = Date.now();
if (hasSwitchedOnce.current && now - lastSwitchTime.current < 10000) {
setWidth(newWidth);
return;
}
if (
newIsMobile !== isCurrentlyMobile.current &&
now - lastSwitchTime.current > 5000
) {
lastSwitchTime.current = now;
isCurrentlyMobile.current = newIsMobile;
hasSwitchedOnce.current = true;
setWidth(newWidth);
} else {
setWidth(newWidth);
}
}, 2000);
};
window.addEventListener("resize", handleResize);
return () => {
clearTimeout(timeoutId);
window.removeEventListener("resize", handleResize);
};
}, []);
return width;
}
function RootApp() {
const width = useWindowWidth();
const isMobile = width < 768;
const [showVersionCheck, setShowVersionCheck] = useState(true);
const userAgent =
navigator.userAgent || navigator.vendor || (window as any).opera || "";
const isTermixMobile = /Termix-Mobile/.test(userAgent);
const renderApp = () => {
if (isElectron()) {
return <DesktopApp />;
}
if (isTermixMobile) {
return <MobileApp key="mobile" />;
}
return isMobile ? <MobileApp key="mobile" /> : <DesktopApp key="desktop" />;
};
return (
<>
<div
className="fixed inset-0 pointer-events-none"
style={{
backgroundColor: "var(--bg-base)",
backgroundImage: `linear-gradient(
135deg,
transparent 0%,
transparent 49%,
rgba(128, 128, 128, 0.03) 49%,
rgba(128, 128, 128, 0.03) 51%,
transparent 51%,
transparent 100%
)`,
backgroundSize: "80px 80px",
zIndex: 0,
}}
/>
<div className="relative min-h-screen" style={{ zIndex: 1 }}>
{isElectron() && showVersionCheck ? (
<ElectronVersionCheck
onContinue={() => setShowVersionCheck(false)}
isAuthenticated={false}
/>
) : (
renderApp()
)}
</div>
</>
);
}
createRoot(document.getElementById("root")!).render(
<StrictMode>
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<RootApp />
</ThemeProvider>
</StrictMode>,
);