JSX
After all, JSX is just another way to write HTML. JSX is a syntax extension for JavaScript that looks similar to XML.
Learning some syntax gotchas and how to extend types will make your life easier when working with JSX.
Firstly, it’s recommended to read the React JSX in depth and Javascript in JSX with curly braces articles from the Official React documentation.
Fragments
JSX does not allow multiple root elements, but you can use a fragment to group multiple elements:
const html = (
<>
<div>1</div>
<div>2</div>
</>
);
Learn more about JSX syntax here!
Supported HTML
All HTML elements and attributes should be supported.
Missing an element or attribute? Please create an issue or a PR to add it. It’s easy to add.
The tag
tag
The <tag of="">
tag is a custom internal tag that allows you to render any runtime selected tag you want. Possibly reasons to prefer this tag over extending types:
- You want to render a tag that is chosen at runtime.
- You don’t want to mess up with extending globally available types.
- You are writing javascript with typechecking enabled.
- You are writing a library and should not extend types globally.
- You need to use kebab-case tags, which JSX syntax does not support.
<tag of="asd" />
// <asd></asd>
<tag of="my-custom-KEBAB" />
// <my-custom-KEBAB></my-custom-KEBAB>
2
3
4
5
We do recommend using extending types instead, as it will give you intellisense and type checking.
Conditional classes
Kita supports constructing class
attributes conditionally, which is a common use case for many applications.
<div class={['a', true && 'b', false && 'c', 'd']} />
// <div class="a b d"></div>
<div class={['class-a class-b', true && 'class-c']} />
// <div class="class-a class-b class-c"></div>
2
3
4
5
This behavior is pretty similar and inspired from clsx, but we do not support objects as input.
Extending types
Just as exemplified above, you may also want to add custom properties to your elements. You can do this by extending the JSX
namespace.
declare global {
namespace JSX {
// Adds a new element called mathPower
interface IntrinsicElements {
mathPower: HtmlTag & {
// Changes properties to the math-power element
['my-exponential']: number;
// this property becomes the <>{children}</> type
children: number;
};
}
// Adds hxBoost property to all elements native elements (those who extends HtmlTag)
interface HtmlTag {
['hx-boost']: boolean;
// TIP: We already provide HTMX types, check them out!
}
}
}
const element = (
<mathPower my-exponential={2} hx-boost>
{3}
</mathPower>
);
// Becomes <math-power my-exponential="2" hx-boost>3</math-power>
2
3
4
Allow everything!
We also provide a way to allow any tag/attribute combination, altough we do not recommend using it.
Just add this triple slash directive to the top of your file:
/// <reference types="@kitajs/html/all-types.d.ts" />
How it works
This package just aims to be a drop in replacement syntax for JSX, and it works because you tell tsc to transpile JSX syntax to calls to our own JSX-runtime.
<ol start={2}>
{[1, 2].map((i) => (
<li>{i}</li>
))}
</ol>
Gets transpiled by tsc to plain javascript:
const runtime = require('@kitajs/html/jsx-runtime');
runtime.jsx('ol', {
start: 2,
children: [1, 2].map((i) => jsx('li', { children: i }))
});
Which, when called, returns this string:
<ol start="2"><li>1</li><li>2</li></ol>
Format HTML output
This package emits HTML as a compact string, useful for over the wire environments. However, if your use case really needs the output HTML to be pretty printed, you can use an external JS library to do so, like html-prettify.
import prettify from 'html-prettify';
const html = (
<div>
<div>1</div>
<div>2</div>
</div>
);
console.log(html);
// <div><div>1</div><div>2</div></div>
console.log(prettify(html));
// <div>
// <div>1</div>
// <div>2</div>
// </div>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Serialization table
Here is the table that explains how this library handles different types of children, describing the inputs and outputs.
IMPORTANT
Arrays are simply concatenated with no separator.
Input Type | Output Type |
---|---|
<div>{"abc"}</div> | <div>abc</div> |
<div>{10}</div> | <div>10</div> |
<div>{NaN}</div> | <div>NaN</div> |
<div>{Infinity}</div> | <div>Infinity</div> |
<div>{true}</div> | <div>true</div> |
<div>{false}</div> | <div>false</div> |
<div>{null}</div> | <div></div> |
<div>{undefined}</div> | <div></div> |
<div>{[1, 2, 3]}</div> | <div>123</div> |
<div>{BigInt(123)}</div> | <div>123</div> |