# JSX Syntax



CxJS uses JSX to define user interfaces declaratively. If you're familiar with React,
you'll find the syntax familiar — with some CxJS-specific extensions.

## Widgets vs HTML Elements

CxJS follows a simple naming convention — widgets start with an uppercase letter (`Button`, `TextField`, `Grid`) while HTML elements start with a lowercase letter (`div`, `span`, `section`). You can freely mix them in the same component.

CxJS widgets also support common attributes for controlling behavior and appearance. Use `visible` to conditionally render widgets, `class` or `className` for CSS classes, and `style` for inline styles:

```tsx
import { createModel } from "cx/data";
import { Button, Switch, TextField } from "cx/widgets";

interface PageModel {
  name: string;
  showMessage: boolean;
}

const m = createModel<PageModel>();

export default (
  <div class="flex flex-col gap-4">
    <div class="p-4 border border-border rounded">
      <strong>Mixing Widgets and HTML</strong>
      <div class="flex gap-2 items-center mt-2">
        <TextField value={m.name} placeholder="Your name" />
        <Button>Greet</Button>
      </div>
    </div>

    <div class="p-4 border border-border rounded min-h-24">
      <strong>Visibility Control</strong>
      <div class="mt-2">
        <Switch value={m.showMessage}>Show message</Switch>
      </div>
      <div visible={m.showMessage} class="mt-2 text-primary">
        This text is conditionally visible!
      </div>
    </div>
  </div>
);

```

## The `<cx>` Wrapper

In earlier versions of CxJS, widget trees had to be wrapped in a `<cx>` element to instruct
the Babel compiler to process them as CxJS configuration. With TypeScript and the new
`jsxImportSource: "cx"` configuration, this wrapper is no longer required:

```tsx
import { createModel } from "cx/data";
import { Button, TextField } from "cx/widgets";

interface PageModel {
  name: string;
}

const m = createModel<PageModel>();

export default (
  <div class="flex gap-2 p-4">
    <TextField value={m.name} placeholder="Your name" />
    <Button>Submit</Button>
  </div>
);

```

The legacy `<cx>` syntax is still supported for backwards compatibility:

```tsx
import { createModel } from "cx/data";
import { Button, TextField } from "cx/widgets";

interface PageModel {
  name: string;
}

const m = createModel<PageModel>();

export default (
  <cx>
    <div class="flex gap-2 p-4">
      <TextField value={m.name} placeholder="Your name" />
      <Button>Submit</Button>
    </div>
  </cx>
);

```

## Key Differences from React

| Feature           | React             | CxJS                         |
| ----------------- | ----------------- | ---------------------------- |
| Class names       | `className` only  | `class` or `className`       |
| Two-way binding   | Manual            | Built-in via accessor chains |
| State management  | `useState`, Redux | Store with typed models      |
| Component wrapper | None              | `<cx>` (optional)            |