## 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/zfb/zudo-react`, not React/Preact node types.

### Server-rendered components

```tsx title="src/components/my-badge.tsx"
/** @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](https://zudo-doc.takazudomodular.com/docs/guides/custom-components#interactive-islands-experimental) for scanner reachability and lifecycle requirements.

```tsx title="src/components/counter.tsx"
/** @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](https://zudo-doc.takazudomodular.com/docs/reference/design-system) and [Color](https://zudo-doc.takazudomodular.com/docs/reference/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

1. Compose components and use typed variant props.
2. Use supported utilities with semantic tokens.
3. Use scoped authored CSS where required by the compiler contract.
4. Keep state and browser cleanup within the owning scope.
5. Check generated CSS and real interactions after customization.