Component First Strategy
Why zudo-doc uses components with utility classes instead of custom CSS class names.
The Rule
The component is the UI abstraction. Compose zudo-react .tsx components with the supported zudo-wind utilities and semantic design tokens. Use props for variants. For a feature the utility compiler does not support, add narrowly scoped authored CSS with a zd- name and register its authored-class coverage; do not invent a utility spelling and assume it emits CSS.
In zudo-doc
Server components return Child/Description and produce HTML without client JavaScript. Client components add "use client" and use scope-owned signals. Both use class and the JSX source @takazudo/, not React/Preact node types.
Server-rendered components
/** @jsxRuntime automatic */
/** @jsxImportSource @takazudo/zfb/zudo-react */
import type { Child } from "@takazudo/zfb/zudo-react";
export function MyBadge({ children }: { children?: Child }) {
return (
<span class="rounded-full bg-surface px-hsp-sm py-vsp-2xs text-caption text-fg">
{children}
</span>
);
}Client-hydrated islands
Use a fixed-target server boundary and serializable props. Follow Custom Components for scanner reachability and lifecycle requirements.
/** @jsxRuntime automatic */
/** @jsxImportSource @takazudo/zfb/zudo-react */
"use client";
import { computed, getScope, signal } from "@takazudo/zfb/zudo-react";
export default function Counter() {
const scope = getScope();
const count = signal(0);
const label = computed(() => `Count: ${count.value}`);
scope.onActivate(() => {
// Browser-only setup belongs here. Return cleanup when needed.
});
return (
<button
type="button"
class="rounded-full bg-surface px-hsp-sm py-vsp-2xs text-caption text-fg"
on:click={() => { count.value += 1; }}
>
{label}
</button>
);
}Component Variants via Props
Keep variants typed. A static class lookup inside a presentational component is sufficient; a signal-dependent variant needs computed so it updates after setup.
Component Composition
Compose small components. For changing lists use keyed For; ordinary array mapping is appropriate for fixed server content. A retained Show(true) child does not reset its local state on unrelated value changes. Keep structural boundaries outside restricted table parents.
Using zudo-doc's Design Tokens
Use text-fg, bg-surface, p-hsp-md, and text-small. Defining a CSS custom property changes an existing token value. Adding a new utility name also requires wind.tokens configuration. See Design System and Color.
When Custom CSS Is Acceptable
The package owns .zd-content typography, reset patches, and component seams. Projects import public stylesheets rather than copying them. Put custom-property overrides in :root after the package imports. Use scoped authored CSS for unsupported utility families or explicit component details, and validate cascade winners: generated utilities are unlayered and follow authored CSS, so layers alone cannot put an authored override after them. Prefer a component-scoped selector over global !important.
Rules Summary
Compose components and use typed variant props.
Use supported utilities with semantic tokens.
Use scoped authored CSS where required by the compiler contract.
Keep state and browser cleanup within the owning scope.
Check generated CSS and real interactions after customization.