mirror of
https://github.com/luxfi/forum.git
synced 2026-09-24 00:24:25 +00:00
Tailwind 4 out — the engine import, the `@custom-variant`, and the `@theme inline` wrapper. The tokens inside it were always plain custom properties and are untouched; what goes is the thing that was reading them. Every class attribute now reaches a converter rather than the document: Box for an element, css for an icon, the component itself for anything from @hanzo/ui. The body's ground moves into the sheet, since <body> sits outside the provider and reads no classes. The library's sheets are imported from the LAYOUT rather than @import-ed from the app's CSS: a bare package specifier does not resolve in this pipeline and the failure is silent — the whole file is dropped, so every token goes missing and the page renders on browser defaults. Also on the current toolchain: React 19.2.8, Next 16.3.3, TypeScript 7. Measured at 390px and 1280px: 4/4 page-widths clean, nothing unread. Co-authored-by: Hanzo Dev <[email protected]>
50 lines
1.7 KiB
TypeScript
50 lines
1.7 KiB
TypeScript
'use client';
|
|
|
|
import { useTheme } from 'next-themes';
|
|
import { Box } from '@hanzo/ui'
|
|
import { useEffect, useState } from 'react';
|
|
|
|
export function ThemeToggle() {
|
|
const { setTheme, resolvedTheme } = useTheme();
|
|
const [mounted, setMounted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
}, []);
|
|
|
|
if (!mounted) {
|
|
return (
|
|
<Box tag="button"
|
|
className="rounded-lg p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
aria-label="Toggle theme"
|
|
>
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="12" cy="12" r="5" />
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
|
</svg>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
const isDark = resolvedTheme === 'dark';
|
|
|
|
return (
|
|
<Box tag="button"
|
|
onClick={() => setTheme(isDark ? 'light' : 'dark')}
|
|
className="rounded-lg p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
|
aria-label={`Switch to ${isDark ? 'light' : 'dark'} theme`}
|
|
>
|
|
{isDark ? (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="12" cy="12" r="5" />
|
|
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" />
|
|
</svg>
|
|
) : (
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
|
|
</svg>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|