Using with Vite
The design system is fully compatible with Vite, Create React App, and other non-Next.js setups.
Quick Start
Install the package and import styles:
npm install @sourceful-energy/uiBasic Setup
The only difference from Next.js is handling dark mode yourself. Here's a complete example:
// main.tsx or App.tsx
import { useState, useEffect } from "react"
import {
DesignSystemProvider,
Button,
Card,
CardHeader,
CardTitle,
CardContent
} from "@sourceful-energy/ui"
import "@sourceful-energy/ui/styles.css" // Required!
import "./index.css"
function App() {
// Handle dark mode (replaces next-themes)
const [darkMode, setDarkMode] = useState(() =>
window.matchMedia("(prefers-color-scheme: dark)").matches
)
// Toggle .dark class on <html>
useEffect(() => {
document.documentElement.classList.toggle("dark", darkMode)
}, [darkMode])
return (
<DesignSystemProvider defaultTheme="elevated">
<div className="min-h-screen bg-background text-foreground p-8">
<Button onClick={() => setDarkMode(!darkMode)}>
{darkMode ? "Light Mode" : "Dark Mode"}
</Button>
<Card className="mt-4">
<CardHeader>
<CardTitle>Works in Vite!</CardTitle>
</CardHeader>
<CardContent>
All components work exactly the same.
</CardContent>
</Card>
</div>
</DesignSystemProvider>
)
}
export default AppDark Mode
The design system uses a .dark class on the <html> element for dark mode. In Next.js, next-themes handles this automatically. In Vite, you toggle it yourself:
// Toggle dark mode - that's it!
document.documentElement.classList.toggle("dark", isDarkMode)You can use any state management (useState, Zustand, localStorage) to persist the user's preference.
Themes & Accessibility
The DesignSystemProvider handles visual themes and accessibility modes. It's pure React with no framework dependencies:
import {
DesignSystemProvider,
useAccessibility,
Switch
} from "@sourceful-energy/ui"
// Visual themes: "base" (flat) or "elevated" (premium)
<DesignSystemProvider defaultTheme="elevated">
<App />
</DesignSystemProvider>
// Accessibility hooks work in Vite
function AccessibilitySettings() {
const {
fontMode, setFontMode, // "default" | "dyslexic"
colorMode, setColorMode, // color blind modes
spacingMode, setSpacingMode, // "default" | "comfortable"
focusMode, setFocusMode, // "default" | "enhanced"
} = useAccessibility()
return (
<Switch
checked={fontMode === "dyslexic"}
onCheckedChange={(v) => setFontMode(v ? "dyslexic" : "default")}
/>
)
}No Next.js Dependencies
The npm package has zero Next.js dependencies. Only React and React DOM are peer dependencies:
{
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
}
}This means fast installs and no bloat in your Vite project.
Full Example with Persistence
Here's a more complete example with localStorage persistence for dark mode:
import { useState, useEffect } from "react"
function useDarkMode() {
const [darkMode, setDarkMode] = useState(() => {
// Check localStorage first, then system preference
const stored = localStorage.getItem("darkMode")
if (stored !== null) return stored === "true"
return window.matchMedia("(prefers-color-scheme: dark)").matches
})
useEffect(() => {
// Update class and localStorage
document.documentElement.classList.toggle("dark", darkMode)
localStorage.setItem("darkMode", String(darkMode))
}, [darkMode])
return [darkMode, setDarkMode] as const
}
// Use in your app
function App() {
const [darkMode, setDarkMode] = useDarkMode()
return (
<DesignSystemProvider defaultTheme="elevated">
<Button onClick={() => setDarkMode(!darkMode)}>
Toggle Theme
</Button>
</DesignSystemProvider>
)
}