|
| 1 | +<!-- purpose: AI and codegen agents should use this to generate correct Zero-UI examples --> |
| 2 | + |
1 | 3 | # Guidelines for AI Agents in this Repo |
2 | 4 |
|
3 | 5 | This repository contains **React Zero-UI**, a library for global UI state without React re-renders. |
4 | 6 | Use these tips when working with the codebase or generating examples. |
5 | 7 |
|
6 | 8 | ## How React Zero-UI works |
7 | 9 |
|
8 | | -1. `useUI()` writes to `document.body.dataset` using keys you specify (e.g. `theme` → `data-theme`). |
9 | | -2. Build tooling scans for all keys and values, generating CSS variants for each. |
10 | | -3. When a setter is called, the corresponding body attribute changes instantly with no React re-render. |
| 10 | +1. `useUI()` writes to `document.body.dataset` using keys you specify. |
| 11 | + |
| 12 | +```tsx |
| 13 | +const [staleValue, setValue] = useUI<'open' | 'closed'>('sidebar', 'closed'); |
| 14 | +``` |
| 15 | + |
| 16 | +- `key` → becomes `data-{key}` on `<body>` (e.g., `sidebar` → `data-sidebar="closed"`). |
| 17 | +- `defaultValue` → used for SSR to avoid FOUC. |
| 18 | +- The first value is **always stale** — do NOT rely on it for reactive updates. |
| 19 | + |
| 20 | +2. Consumption is done strictly with tailwind variant classNames: |
| 21 | + |
| 22 | +```html |
| 23 | +<div className="sidebar-open:translate-x-0 sidebar-closed:-translate-x-full" /> |
| 24 | +``` |
| 25 | + |
| 26 | +3. Build-time tooling scans all `useUI()` keys and values, then generates matching Tailwind variants. |
| 27 | + |
| 28 | +4. At runtime, calling the setter updates the `data-*` attribute on `<body>` immediately. No VDOM. No re-renders. |
| 29 | + |
| 30 | +--- |
| 31 | + |
| 32 | +## Best Practices for AI Agents |
| 33 | + |
| 34 | +- ✅ Use `useUI()` **only for UI state**: themes, layout flags, open/closed toggles, etc. |
| 35 | +- ✅ Prefer **kebab-case keys**: e.g. `sidebar-open`, `theme-dark`. |
| 36 | +- ✅ Always provide a `defaultValue`: prevents FOUC and enables SSR. |
| 37 | +- ✅ Do **NOT** use the first value from `useUI()` for logic — it DOES NOT UPDATE. |
| 38 | +- ✅ You can call setters **from anywhere** in the app — no prop drilling or context needed. |
| 39 | +- ✅ Tailwind classes must use `key-value:` pattern: |
| 40 | + |
| 41 | + - `theme-dark:bg-black` |
| 42 | + - `accent-blue:text-blue-500` |
| 43 | + - `sidebar-open:translate-x-0` |
| 44 | + |
| 45 | +--- |
| 46 | + |
| 47 | +## Example: Toggle Theme |
| 48 | + |
| 49 | +```tsx |
| 50 | +// Set state |
| 51 | +const [, setTheme] = useUI<'light' | 'dark'>('theme', 'light'); |
| 52 | +<button onClick={() => setTheme('dark')}>Switch to dark</button>; |
| 53 | +``` |
| 54 | + |
| 55 | +```html |
| 56 | +<!-- React component with Tailwind variant --> |
| 57 | +<div className="theme-light:bg-white theme-dark:bg-black" /> |
| 58 | +``` |
| 59 | + |
| 60 | +--- |
| 61 | + |
| 62 | +## What NOT to do |
| 63 | + |
| 64 | +- ❌ Don't use `useUI()` for business logic or data fetching |
| 65 | +- ❌ Don't rely on the first tuple value for reactivity |
| 66 | +- ❌ Don't use camelCase keys (will break variant generation) |
| 67 | + |
| 68 | +--- |
| 69 | + |
| 70 | +## Summary |
11 | 71 |
|
12 | | -## Best practices |
| 72 | +**React Zero-UI is a ZERO re-render UI state engine with global state baked in.** It replaces traditional VDOM cycles with `data-*` attribute flips and compile-time CSS. No React context. No prop drilling. No runtime cost. |
13 | 73 |
|
14 | | -- Only use `useUI` for UI-only state (themes, flags, etc.). |
15 | | -- Prefer kebab-case keys (`sidebar-open`) so generated variants are predictable. |
16 | | -- Always pass a default value to `useUI(key, defaultValue)` to avoid flashes during SSR. |
17 | | -- The first value is ALWAYS STALE, do not use it if you need reactivity. |
18 | | -- Mutate the state anywhere in the app: `const [, setTheme] = useUI('theme', 'light');` then call `setTheme('dark')`. |
19 | | -- Compose Tailwind classes anywhere with the pattern `key-value:` like `theme-dark:bg-black`. |
| 74 | +Think of it as writing atomic Tailwind variants for every UI state — but flipping them dynamically at runtime without re-rendering anything. |
0 commit comments