Linear Rendering Replaces JSX Returns for Readability
Write UI components as sequential statements without a return keyword: use component instead of function, and place JSX markup directly where it renders, top-to-bottom. This creates a linear flow matching execution order, unlike React's single return tree. Early returns skip remaining UI/logic with a bare return. Drop paragraphs or elements anywhere they appear in source, and they render in place—ideal for colocating structure, logic, and styling. Text requires double quotes (e.g., <p>"Hello"</p>), with dynamic values concatenating seamlessly or via template literals. For HTML strings, text keyword escapes safely (XSS-proof), while html injects raw markup (Ripple fully, Vue partially).
Control flow uses vanilla JS: if/else-if/else for conditions (avoids nested ternaries), switch cases directly, for-of loops for lists (with built-in index and key for stability, continue to skip). Only for-of works—no for, while, etc. Errors use try/catch; async adds pending block for loading (compiles to lazy in React/Preact/Solid, Ripple equivalent). This reduces verbosity for complex logic but may add lines for simple cases.
Hoisted Hooks and Scoping Eliminate React Rules Friction
Hooks work after conditions, early returns, or loops—the compiler hoists them to the function top, preserving React's stable order without breaking rules. Place useState inline where needed for colocation, not rigidly at top. Lexical scoping per block (nested elements, if, for, switch, try) prevents variable leaks: declare const label in sibling divs or top-level without conflicts.
Scoped styles via <style> blocks attach unique hashes to classes (e.g., .card only styles its component). Share via style keyword prop (passes hash). Global selectors escape scoping but risk mess. Lazy destructuring (&{prop}) preserves reactivity in Solid/Vue/Ripple by compiling to property lookups, avoiding snapshot issues. Prop shorthand (e.g., onChange={onChange}) mirrors JS objects.
Trade-offs: Niche Wins vs. Muscle Memory and AI
TSRX requires .tsrx files and Vite plugin (or equivalents), adding compiler magic that obscures debugging (e.g., hoisted hooks, linear-to-tree transforms). Cleaner for vanilla JS fans (ex-Svelte users, Ripple adopters) but verbose for lists (for-of vs. map), breaks JSX text muscle memory, and lags AI codegen optimized for JSX/React. Sticks to Tailwind over scoped CSS for most. Backward-compatible with TypeScript, targets readability/colocation over framework conventions—try if linear code trumps familiarity.