CxJS

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:

<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>
Mixing Widgets and HTML
Visibility Control
 
Show message

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:

<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:

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

Key Differences from React

FeatureReactCxJS
Class namesclassName onlyclass or className
Two-way bindingManualBuilt-in via accessor chains
State managementuseState, ReduxStore with typed models
Component wrapperNone<cx> (optional)