no utility engine

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]>
This commit is contained in:
2026-09-08 02:37:59 -07:00
co-authored by Hanzo Dev
parent c8f558792b
commit 17bd239f2a
9 changed files with 5541 additions and 587 deletions
+18 -5
View File
@@ -1,13 +1,15 @@
/**
* Lux Forum Theme
* Tailwind CSS 4
* No utility engine: tokens and rules, read straight by the browser
*/
@import "tailwindcss";
/* The library's sheets are imported from the LAYOUT, not here: a bare package
specifier in a plain @import does not resolve in this pipeline, and the
failure is silent — the whole file is dropped, so the tokens below never
reach the document and every link renders browser-default blue. */
@custom-variant dark (&:is(.dark *));
@theme inline {
:root {
--font-sans: var(--font-inter), system-ui, sans-serif;
--font-mono: ui-monospace, monospace;
--radius: 0.5rem;
@@ -73,7 +75,7 @@
--ring: 0 0% 36%;
}
@layer base {
* {
border-color: hsl(var(--border));
}
@@ -95,4 +97,15 @@
.dark ::selection {
background: rgba(255, 255, 255, 0.20);
}
/* The body's ground. Stated here rather than as classes on <body>, which sits
outside the provider and so reads none of them. */
body {
display: grid;
grid-template-columns: minmax(0, 1fr);
min-height: 100vh;
background: hsl(var(--background));
color: hsl(var(--foreground));
-webkit-font-smoothing: antialiased;
}
+6 -1
View File
@@ -1,6 +1,9 @@
import type { Metadata } from 'next';
import { Hanzo } from '@hanzo/ui'
import { Inter } from 'next/font/google';
import { ThemeProvider } from 'next-themes';
import '@hanzo/ui/theme.css';
import '@hanzo/ui/styles.css';
import './global.css';
const inter = Inter({
@@ -32,7 +35,8 @@ export default function RootLayout({
}) {
return (
<html lang="en" suppressHydrationWarning className={inter.variable}>
<body className="min-h-screen bg-background text-foreground antialiased">
<body>
<Hanzo>
<ThemeProvider
attribute="class"
defaultTheme="system"
@@ -41,6 +45,7 @@ export default function RootLayout({
>
{children}
</ThemeProvider>
</Hanzo>
</body>
</html>
);
+127 -126
View File
@@ -1,4 +1,5 @@
import Link from 'next/link';
import { Box, css } from '@hanzo/ui'
import {
MessageSquare,
Lightbulb,
@@ -107,204 +108,204 @@ const colorClasses: Record<string, string> = {
export default function ForumPage() {
return (
<div className="min-h-screen flex flex-col">
<Box className="min-h-screen flex flex-col">
{/* Header */}
<header className="sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<div className="container flex h-16 items-center justify-between px-4 md:px-6 mx-auto max-w-6xl">
<Link href="/" className="flex items-center gap-2">
<Box tag="header" className="sticky top-0 z-50 w-full border-b border-border/40 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
<Box className="container flex h-16 items-center justify-between px-4 md:px-6 mx-auto max-w-6xl">
<Link href="/" style={css('flex items-center gap-2')}>
<Logo size={28} />
<span className="font-semibold text-lg">Forum</span>
<Box tag="span" className="font-semibold text-lg">Forum</Box>
</Link>
<div className="flex items-center gap-4">
<a
<Box className="flex items-center gap-4">
<Box tag="a"
href="https://lux.help"
className="hidden sm:flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
Help
<ExternalLink className="h-3 w-3" />
</a>
<a
<ExternalLink style={css('h-3 w-3')} />
</Box>
<Box tag="a"
href="https://github.com/luxfi/lps/discussions"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github className="h-5 w-5" />
</a>
<Github style={css('h-5 w-5')} />
</Box>
<ThemeToggle />
</div>
</div>
</header>
</Box>
</Box>
</Box>
{/* Main Content */}
<main className="flex-1">
<Box tag="main" className="flex-1">
{/* Hero */}
<section className="py-16 md:py-24 px-4 md:px-6 border-b border-border/50">
<div className="container mx-auto max-w-4xl text-center">
<div className="inline-flex items-center justify-center p-3 bg-primary/5 rounded-full mb-6">
<Users className="h-8 w-8 text-primary" />
</div>
<h1 className="text-4xl md:text-5xl font-bold tracking-tight mb-4">
<Box tag="section" className="py-16 md:py-24 px-4 md:px-6 border-b border-border/50">
<Box className="container mx-auto max-w-4xl text-center">
<Box className="inline-flex items-center justify-center p-3 bg-primary/5 rounded-full mb-6">
<Users style={css('h-8 w-8 text-primary')} />
</Box>
<Box tag="h1" className="text-4xl md:text-5xl font-bold tracking-tight mb-4">
Lux Community
</h1>
<p className="text-lg text-muted-foreground max-w-2xl mx-auto mb-8">
</Box>
<Box tag="p" className="text-lg text-muted-foreground max-w-2xl mx-auto mb-8">
Join the conversation. Share ideas, ask questions, and connect with developers
building on Lux Network.
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<a
</Box>
<Box className="flex flex-col sm:flex-row gap-4 justify-center">
<Box tag="a"
href="https://github.com/luxfi/lps/discussions"
className="inline-flex items-center justify-center gap-2 h-12 px-8 rounded-lg bg-primary text-primary-foreground font-medium hover:opacity-90 transition-opacity"
>
<MessageSquare className="h-5 w-5" />
<MessageSquare style={css('h-5 w-5')} />
Open Discussions
<ExternalLink className="h-4 w-4" />
</a>
<a
<ExternalLink style={css('h-4 w-4')} />
</Box>
<Box tag="a"
href="https://github.com/luxfi/lps/discussions/new/choose"
className="inline-flex items-center justify-center gap-2 h-12 px-8 rounded-lg border border-border font-medium hover:bg-muted transition-colors"
>
<Zap className="h-5 w-5" />
<Zap style={css('h-5 w-5')} />
Start a Discussion
</a>
</div>
</div>
</section>
</Box>
</Box>
</Box>
</Box>
{/* Categories */}
<section className="py-16 px-4 md:px-6">
<div className="container mx-auto max-w-6xl">
<h2 className="text-2xl font-bold mb-8 text-center">Discussion Categories</h2>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
<Box tag="section" className="py-16 px-4 md:px-6">
<Box className="container mx-auto max-w-6xl">
<Box tag="h2" className="text-2xl font-bold mb-8 text-center">Discussion Categories</Box>
<Box className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{discussionCategories.map((category) => {
const Icon = category.icon;
return (
<a
<Box tag="a"
key={category.title}
href={category.href}
className="group p-6 rounded-xl border border-border/50 bg-background hover:border-primary/30 hover:shadow-lg transition-all"
>
<div className={`inline-flex p-3 rounded-lg ${colorClasses[category.color]} mb-4`}>
<Icon className="h-6 w-6" />
</div>
<h3 className="text-lg font-semibold mb-2 group-hover:text-primary transition-colors">
<Box className={`inline-flex p-3 rounded-lg ${colorClasses[category.color]} mb-4`}>
<Icon style={css('h-6 w-6')} />
</Box>
<Box tag="h3" className="text-lg font-semibold mb-2 group-hover:text-primary transition-colors">
{category.title}
</h3>
<p className="text-sm text-muted-foreground mb-4">
</Box>
<Box tag="p" className="text-sm text-muted-foreground mb-4">
{category.description}
</p>
<span className="inline-flex items-center gap-1 text-sm font-medium text-primary opacity-0 group-hover:opacity-100 transition-opacity">
</Box>
<Box tag="span" className="inline-flex items-center gap-1 text-sm font-medium text-primary opacity-0 group-hover:opacity-100 transition-opacity">
View discussions
<ArrowRight className="h-4 w-4" />
</span>
</a>
<ArrowRight style={css('h-4 w-4')} />
</Box>
</Box>
);
})}
</div>
</div>
</section>
</Box>
</Box>
</Box>
{/* Resources */}
<section className="py-16 px-4 md:px-6 bg-muted/30 border-y border-border/50">
<div className="container mx-auto max-w-4xl">
<h2 className="text-2xl font-bold mb-8 text-center">Resources</h2>
<div className="grid gap-4 sm:grid-cols-2">
<Box tag="section" className="py-16 px-4 md:px-6 bg-muted/30 border-y border-border/50">
<Box className="container mx-auto max-w-4xl">
<Box tag="h2" className="text-2xl font-bold mb-8 text-center">Resources</Box>
<Box className="grid gap-4 sm:grid-cols-2">
{resources.map((resource) => {
const Icon = resource.icon;
return (
<a
<Box tag="a"
key={resource.title}
href={resource.href}
className="flex items-center gap-4 p-4 rounded-lg border border-border/50 bg-background hover:border-primary/30 hover:shadow-md transition-all"
>
<div className="p-2 rounded-lg bg-muted">
<Icon className="h-5 w-5" />
</div>
<div className="flex-1">
<span className="font-medium block">{resource.title}</span>
<span className="text-sm text-muted-foreground">{resource.description}</span>
</div>
<ExternalLink className="h-4 w-4 text-muted-foreground" />
</a>
<Box className="p-2 rounded-lg bg-muted">
<Icon style={css('h-5 w-5')} />
</Box>
<Box className="flex-1">
<Box tag="span" className="font-medium block">{resource.title}</Box>
<Box tag="span" className="text-sm text-muted-foreground">{resource.description}</Box>
</Box>
<ExternalLink style={css('h-4 w-4 text-muted-foreground')} />
</Box>
);
})}
</div>
</div>
</section>
</Box>
</Box>
</Box>
{/* Guidelines */}
<section className="py-16 px-4 md:px-6">
<div className="container mx-auto max-w-3xl">
<h2 className="text-2xl font-bold mb-8 text-center">Community Guidelines</h2>
<div className="space-y-6">
<div className="p-6 rounded-xl border border-border/50 bg-background">
<h3 className="font-semibold mb-2">Be Respectful</h3>
<p className="text-sm text-muted-foreground">
<Box tag="section" className="py-16 px-4 md:px-6">
<Box className="container mx-auto max-w-3xl">
<Box tag="h2" className="text-2xl font-bold mb-8 text-center">Community Guidelines</Box>
<Box className="space-y-6">
<Box className="p-6 rounded-xl border border-border/50 bg-background">
<Box tag="h3" className="font-semibold mb-2">Be Respectful</Box>
<Box tag="p" className="text-sm text-muted-foreground">
Treat everyone with respect. Healthy discussions require diverse perspectives.
</p>
</div>
<div className="p-6 rounded-xl border border-border/50 bg-background">
<h3 className="font-semibold mb-2">Stay On Topic</h3>
<p className="text-sm text-muted-foreground">
</Box>
</Box>
<Box className="p-6 rounded-xl border border-border/50 bg-background">
<Box tag="h3" className="font-semibold mb-2">Stay On Topic</Box>
<Box tag="p" className="text-sm text-muted-foreground">
Keep discussions relevant to Lux Network and the broader ecosystem.
</p>
</div>
<div className="p-6 rounded-xl border border-border/50 bg-background">
<h3 className="font-semibold mb-2">Share Knowledge</h3>
<p className="text-sm text-muted-foreground">
</Box>
</Box>
<Box className="p-6 rounded-xl border border-border/50 bg-background">
<Box tag="h3" className="font-semibold mb-2">Share Knowledge</Box>
<Box tag="p" className="text-sm text-muted-foreground">
Help others by sharing your experience and expertise. We grow together.
</p>
</div>
</div>
</div>
</section>
</Box>
</Box>
</Box>
</Box>
</Box>
{/* CTA */}
<section className="py-16 px-4 md:px-6 bg-muted/30 border-t border-border/50">
<div className="container mx-auto max-w-4xl text-center">
<MessageSquare className="h-10 w-10 mx-auto mb-4 text-primary" />
<h2 className="text-2xl font-bold mb-4">Ready to join the conversation?</h2>
<p className="text-muted-foreground mb-6 max-w-xl mx-auto">
<Box tag="section" className="py-16 px-4 md:px-6 bg-muted/30 border-t border-border/50">
<Box className="container mx-auto max-w-4xl text-center">
<MessageSquare style={css('h-10 w-10 mx-auto mb-4 text-primary')} />
<Box tag="h2" className="text-2xl font-bold mb-4">Ready to join the conversation?</Box>
<Box tag="p" className="text-muted-foreground mb-6 max-w-xl mx-auto">
All discussions happen on GitHub. Sign in with your GitHub account to participate.
</p>
<a
</Box>
<Box tag="a"
href="https://github.com/luxfi/lps/discussions"
className="inline-flex items-center justify-center gap-2 h-12 px-8 rounded-lg bg-primary text-primary-foreground font-medium hover:opacity-90 transition-opacity"
>
<Github className="h-5 w-5" />
<Github style={css('h-5 w-5')} />
Go to Discussions
<ExternalLink className="h-4 w-4" />
</a>
</div>
</section>
</main>
<ExternalLink style={css('h-4 w-4')} />
</Box>
</Box>
</Box>
</Box>
{/* Footer */}
<footer className="border-t border-border/50 py-8 px-4 md:px-6">
<div className="container mx-auto max-w-6xl">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
<div className="flex items-center gap-2">
<Box tag="footer" className="border-t border-border/50 py-8 px-4 md:px-6">
<Box className="container mx-auto max-w-6xl">
<Box className="flex flex-col md:flex-row items-center justify-between gap-4">
<Box className="flex items-center gap-2">
<Logo size={20} />
<span className="text-sm text-muted-foreground">
<Box tag="span" className="text-sm text-muted-foreground">
BSD-3-Clause &copy; 2020 - {new Date().getFullYear()} Lux Industries Inc.
</span>
</div>
<div className="flex items-center gap-6">
<a
</Box>
</Box>
<Box className="flex items-center gap-6">
<Box tag="a"
href="https://github.com/luxfi"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Github className="h-5 w-5" />
</a>
<a
<Github style={css('h-5 w-5')} />
</Box>
<Box tag="a"
href="https://twitter.com/luxfi"
className="text-muted-foreground hover:text-foreground transition-colors"
>
<Twitter className="h-5 w-5" />
</a>
</div>
</div>
</div>
</footer>
</div>
<Twitter style={css('h-5 w-5')} />
</Box>
</Box>
</Box>
</Box>
</Box>
</Box>
);
}
+13 -12
View File
@@ -1,6 +1,7 @@
'use client';
import { getMenuBarSVG, getWhiteSVG, getMonoSVG, getColorSVG } from '@luxfi/logo';
import { Box } from '@hanzo/ui'
interface LogoProps {
size?: number;
@@ -25,7 +26,7 @@ export function Logo({ size = 24, className = '', variant = 'default' }: LogoPro
}
return (
<div
<Box
className={`logo-container inline-block ${className}`}
style={{ width: size, height: size }}
dangerouslySetInnerHTML={{ __html: svg }}
@@ -35,28 +36,28 @@ export function Logo({ size = 24, className = '', variant = 'default' }: LogoPro
export function LogoWithText({ size = 24, text = 'Forum' }: { size?: number; text?: string }) {
return (
<div className="flex items-center gap-2 group logo-with-text">
<Box className="flex items-center gap-2 group logo-with-text">
<Logo
size={size}
className="transition-transform duration-200 group-hover:scale-110"
/>
<div className="relative h-6">
<span className="font-bold text-lg inline-block transition-all duration-300 ease-out group-hover:opacity-0 group-hover:-translate-y-full">
<Box className="relative h-6">
<Box tag="span" className="font-bold text-lg inline-block transition-all duration-300 ease-out group-hover:opacity-0 group-hover:-translate-y-full">
{text}
</span>
<span className="font-bold text-lg absolute left-0 top-0 opacity-0 translate-y-full transition-all duration-300 ease-out group-hover:opacity-100 group-hover:translate-y-0 whitespace-nowrap">
</Box>
<Box tag="span" className="font-bold text-lg absolute left-0 top-0 opacity-0 translate-y-full transition-all duration-300 ease-out group-hover:opacity-100 group-hover:translate-y-0 whitespace-nowrap">
Lux {text}
</span>
</div>
</div>
</Box>
</Box>
</Box>
);
}
export function LogoStatic({ size = 24, text = 'Forum' }: { size?: number; text?: string }) {
return (
<div className="flex items-center gap-2">
<Box className="flex items-center gap-2">
<Logo size={size} />
<span className="font-bold text-lg">{text}</span>
</div>
<Box tag="span" className="font-bold text-lg">{text}</Box>
</Box>
);
}
+5 -4
View File
@@ -1,6 +1,7 @@
'use client';
import { useTheme } from 'next-themes';
import { Box } from '@hanzo/ui'
import { useEffect, useState } from 'react';
export function ThemeToggle() {
@@ -13,7 +14,7 @@ export function ThemeToggle() {
if (!mounted) {
return (
<button
<Box tag="button"
className="rounded-lg p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
aria-label="Toggle theme"
>
@@ -21,14 +22,14 @@ export function ThemeToggle() {
<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>
</button>
</Box>
);
}
const isDark = resolvedTheme === 'dark';
return (
<button
<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`}
@@ -43,6 +44,6 @@ export function ThemeToggle() {
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />
</svg>
)}
</button>
</Box>
);
}
+5 -8
View File
@@ -13,21 +13,18 @@
"@luxfi/logo": "^1.0.0",
"clsx": "^2.1.1",
"lucide-react": "^0.468.0",
"next": "16.0.1",
"next": "16.3.3",
"next-themes": "^0.4.6",
"react": "19.2.0",
"react-dom": "19.2.0",
"react": "19.2.8",
"react-dom": "19.2.8",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.16"
"@hanzo/ui": "^8.23.2"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.16",
"@types/node": "^22.10.2",
"@types/react": "^19.0.1",
"@types/react-dom": "^19.0.2",
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"typescript": "^5.7.2"
"typescript": "^7.0.2"
},
"packageManager": "[email protected]"
}
+5367 -393
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
-33
View File
@@ -1,33 +0,0 @@
import type { Config } from 'tailwindcss';
const config: Config = {
darkMode: 'class',
content: [
'./app/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
],
theme: {
extend: {
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
border: 'hsl(var(--border))',
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
},
},
},
plugins: [],
};
export default config;