A DOM creation utility with JSX-like syntax, async support, and reactive integration.
npm install html-tag-js
- Declarative element creation
- Support for async children
- Reactive text integration
- Attribute/event shorthand syntax
- Promise-based dynamic content
import tag from 'html-tag-js/tag';
const element = tag('div', {
id: 'container',
style: { background: 'white' },
children: [
tag('h1', 'Hello World'),
tag('button', {
onclick: [() => console.log('Clicked!')],
children: ['Click me']
})
]
});
document.body.append(element);
Create DOM elements with nested structure
Parameters:
tagName
: String | Function | Nodeoptions
: Object (optional)children
: Array (optional)
Returns: HTMLElement
Property | Description | Example |
---|---|---|
attr |
HTML attributes | { attr: { id: 'main' } } |
style |
CSS styles | { style: { color: 'red' } } |
dataset |
Data attributes | { dataset: { id: '123' } } |
on |
Event listeners | { on: { click: [handler] } } |
child |
Single child element | { child: tag('span') } |
children |
Array of child elements | { children: [ ... ] } |
ref |
Reference to previous Ref class | { ref: myRef } |
All other properties are set directly on the element:
tag('input', { type: 'text', placeholder: 'Enter name' })
tag('div', [
'Text node', // String
tag('span'), // Element
42, // Number
Reactive('Dynamic'), // Reactive text
new Promise(...), // Async content
[tag('li', 'Item 1'), tag('li', 'Item 2')] // Nested arrays
]);
tag('div', [
'Loading...',
fetch('/data').then(data =>
tag('ul', data.map(item =>
tag('li', item.name)
))
)
]);
const count = Reactive(0);
tag('div', [
tag('h1', {
children: ['Count: ', count]
}),
tag('button', {
onclick: [() => count.value++],
style: { color: 'blue' },
children: ['Increment']
})
]);
const header = tag.get('#main-header');
const buttons = tag.getAll('.btn');
const textNode = tag.text('Hello World');
import tag from 'html-tag-js/tag';
import Reactive from 'html-tag-js/reactive';
const user = Reactive('Guest');
const app = tag('main', {
attr: { id: 'app-container' },
children: [
tag('header', {
style: {
padding: '1rem',
background: '#f0f0f0'
},
children: [
tag('h1', 'Welcome ', user)
]
}),
tag('section', {
children: [
tag('input', {
type: 'text',
placeholder: 'Enter name',
on: {
input: [(e) => user.value = e.target.value]
}
}),
tag('div', {
children: [
new Promise(resolve => {
setTimeout(() => resolve(
tag('p', 'Async loaded content!')
), 1000);
})
]
})
]
})
]
});
document.body.append(app);
- Use
children
for multiple elements,child
for single elements - Prefer
attr
for HTML attributes over direct property access - Wrap event handlers in arrays for multiple listeners
- Use
tag.text()
for explicit text node creation - Combine with Reactive for dynamic content updates
- Handle Promise rejections in async children
- Throws error for invalid tag types
- Warns for non-array children in
children
property - Ignores undefined values in children
- Automatically flattens nested arrays
- Async children create placeholder nodes
- Reactive text nodes are automatically cloned
- Batch DOM operations using fragment patterns
- Avoid deep nested Promise chains in children