JSX
JSX is a syntax extension for JavaScript that allows writing HTML-like markup inside JavaScript.
It has been popularized by React, and then adopted by many other libraries/frameworks.
By default, when running JSX in LiveCodes, React runtime is used.
However, other libraries like Preact, nano JSX and others can be used as well (see Custom JSX Runtimes).
Please note that TSX is also supported in LiveCodes and is documented here.
Demo:
show code
import { createPlayground } from 'livecodes';
const options = {
"template": "react"
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"template": "react"
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"template": "react"
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"template": "react"
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
const options = {
"template": "react"
};
let container;
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
Usage
The easiest way is to auto-render a component by exporting it as the default export:
You may, however, be more explicit and render the component yourself using React DOM:
React's new JSX transform is utilized. So there is no need to import React.
export default function App() {
return <h1>Hello World!</h1>;
}
Auto-rendering
A component is rendered automatically as a React component (without having to manually use React Dom to render it) if the following conditions are met:
Root Element
To render the React components to a specific root DOM element use "livecodes-app"
as the element id
. Otherwise, if that element is not found, a new div
element is added to document.body
and is used as the root.
Example:
Disabling Auto-rendering
To disable auto-rendering, set the custom settings disableAutoRender
property to true
.
Importing Modules
npm modules can be imported as described in the section about module resolution, including bare module imports and importing from different CDNs. Stylesheet imports are added as <link rel="stylesheet">
tags in the page head
.
Example:
Module imports can be customized using import maps as described in module resolution documentations.
Types for Imported Modules
Types for imported modules are loaded automatically (if available) to provide Intellisense, auto-completion and type information.
Moreover, you can provide custom type definitions for modules that do not have types available on npm. See Custom Types for details.
Exports
Values exported from script editor (default or named) can be imported in the markup editor by importing from "./script"
(with no extension).
This can be useful, for example, when using MDX to import components exported form JSX.
Demo:
show code
import { createPlayground } from 'livecodes';
const options = {
"params": {
"mdx": "import Greeting from \"./script\";\n\n<Greeting name=\"MDX\" />\n",
"jsx": "export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n"
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"params": {
"mdx": "import Greeting from \"./script\";\n\n<Greeting name=\"MDX\" />\n",
"jsx": "export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n"
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"params": {
"mdx": "import Greeting from \"./script\";\n\n<Greeting name=\"MDX\" />\n",
"jsx": "export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n"
}
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"params": {
"mdx": "import Greeting from \"./script\";\n\n<Greeting name=\"MDX\" />\n",
"jsx": "export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n"
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
const options = {
"params": {
"mdx": "import Greeting from \"./script\";\n\n<Greeting name=\"MDX\" />\n",
"jsx": "export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n"
}
};
let container;
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
When values are imported from "./script"
, auto-rendering is disabled, because it is assumed that you want to take control over component rendering.
Styles
CSS can be applied to the component using various ways:
Style Editor
Styles added in the style editor is applied globally to the result page. This can use different languages/processors supported in LiveCodes including CSS, SCSS, Less, Stylus, ..etc. See style documentation for more details.
And of course, styles and stylesheets added in markup editor are also applied globally.
Importing Stylesheets
Stylesheets imported in script editor are added as <link rel="stylesheet">
tags in the page head
.
The stylesheet URL can be an absolute URL or a path in the npm package. The URL has to end with ".css"
.
example:
CSS Modules
CSS modules are supported and are documented separately. Make sure to enable CSS modules (from style editor menu or in processors
property of configuration object).
Demo:
show code
import { createPlayground } from 'livecodes';
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": ".title {\n color: green;\n font-family: sans-serif;\n}\n"
},
"script": {
"language": "jsx",
"content": "import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n"
},
"processors": [
"cssmodules"
]
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": ".title {\n color: green;\n font-family: sans-serif;\n}\n"
},
"script": {
"language": "jsx",
"content": "import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n"
},
"processors": [
"cssmodules"
]
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": ".title {\n color: green;\n font-family: sans-serif;\n}\n"
},
"script": {
"language": "jsx",
"content": "import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n"
},
"processors": [
"cssmodules"
]
}
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": ".title {\n color: green;\n font-family: sans-serif;\n}\n"
},
"script": {
"language": "jsx",
"content": "import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n"
},
"processors": [
"cssmodules"
]
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": ".title {\n color: green;\n font-family: sans-serif;\n}\n"
},
"script": {
"language": "jsx",
"content": "import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n"
},
"processors": [
"cssmodules"
]
}
};
let container;
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
CSS Frameworks
CSS Frameworks supported in LiveCodes (e.g. Tailwind CSS, UnoCSS, WindiCSS) can detect class names added in JSX. Make sure that the required utility is enabled (from style editor menu or in processors
property of configuration object) and that required directives are added to the style editor.
Demo:
show code
import { createPlayground } from 'livecodes';
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
"script": {
"language": "jsx",
"content": "export default function() {\n return <h1 className=\"text-3xl font-bold text-gray-500 text-center m-4\">Hello, Tailwind CSS!</h1>;\n}\n"
},
"processors": [
"tailwindcss"
]
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
"script": {
"language": "jsx",
"content": "export default function() {\n return <h1 className=\"text-3xl font-bold text-gray-500 text-center m-4\">Hello, Tailwind CSS!</h1>;\n}\n"
},
"processors": [
"tailwindcss"
]
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
"script": {
"language": "jsx",
"content": "export default function() {\n return <h1 className=\"text-3xl font-bold text-gray-500 text-center m-4\">Hello, Tailwind CSS!</h1>;\n}\n"
},
"processors": [
"tailwindcss"
]
}
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
"script": {
"language": "jsx",
"content": "export default function() {\n return <h1 className=\"text-3xl font-bold text-gray-500 text-center m-4\">Hello, Tailwind CSS!</h1>;\n}\n"
},
"processors": [
"tailwindcss"
]
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
const options = {
"config": {
"activeEditor": "script",
"style": {
"language": "css",
"content": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n"
},
"script": {
"language": "jsx",
"content": "export default function() {\n return <h1 className=\"text-3xl font-bold text-gray-500 text-center m-4\">Hello, Tailwind CSS!</h1>;\n}\n"
},
"processors": [
"tailwindcss"
]
}
};
let container;
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
CSS-in-JS
CSS-in-JS libraries can be imported and used as usual.
Demo:
show code
import { createPlayground } from 'livecodes';
const options = {
"params": {
"jsx": "import styled from 'styled-components';\n\nconst Title = styled.h1`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n"
}
};
createPlayground('#container', options);
import { createPlayground, type EmbedOptions } from 'livecodes';
const options: EmbedOptions = {
"params": {
"jsx": "import styled from 'styled-components';\n\nconst Title = styled.h1`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n"
}
};
createPlayground('#container', options);
import LiveCodes from 'livecodes/react';
export default function App() {
const options = {
"params": {
"jsx": "import styled from 'styled-components';\n\nconst Title = styled.h1`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n"
}
};
return (<LiveCodes {...options}></LiveCodes>);
}
<script setup>
import LiveCodes from "livecodes/vue";
const options = {
"params": {
"jsx": "import styled from 'styled-components';\n\nconst Title = styled.h1`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n"
}
};
</script>
<template>
<LiveCodes v-bind="options" />
</template>
<script>
import { onMount } from 'svelte';
import { createPlayground } from 'livecodes';
const options = {
"params": {
"jsx": "import styled from 'styled-components';\n\nconst Title = styled.h1`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n"
}
};
let container;
onMount(() => {
createPlayground(container, options);
});
</script>
<div bind:this="{container}"></div>
Custom JSX Runtimes
LiveCodes allows using other libraries (like Preact and nano JSX) as the JSX runtime.
JSX is compiled to JavaScript using the TypeScript compiler, which allows multiple configuration options for JSX, including jsx
, jsxFactory
, jsxFragmentFactory
and jsxImportSource
.
These can be configured using in-code pragmas or in custom settings.
Example for using Preact:
Language Info
Name
jsx
Extension
.jsx
Editor
script
Compiler
TypeScript compiler
Using Prettier.
Custom Settings
Custom settings added to the property jsx
are passed to the TypeScript compiler as compiler options while compiling JSX.
In addition, the option disableAutoRender
can be set to true
to disable auto-rendering.
Please note that custom settings should be valid JSON (i.e. functions are not allowed).
Example:
Custom Settings
{
"jsx": {
"disableAutoRender": true,
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment"
}
}
Starter Template
https://livecodes.io/?template=react
Links