std-components
v0.1.0
Published
Standard HTML components as functions
Maintainers
Readme
std-components
🧩 Standard HTML components as functions
- 🌳 Composable, typed, tree shakeable functions that create standard DOM components.
- ⚡ No build step required.
- 🚀 Speed up the development of dynamic, performant, component-based front-end applications with vanilla JS/TS.
Install
pnpm i std-componentsExample
Let's say that a users table like this...
...
<table>
<thead>
<tr>
<th>User Name</th>
<th>E-mail</th>
<th>Actions</th>
</tr>
</thead>
<tbody></tbody>
</table>...need to be fulfilled with rows like this, from user objects:
<tr>
<td>John Doe</td>
<td><a href="mailto:[email protected]" >[email protected]</a></td>
<td><button class="btn btn-danger" onclick="removeUser" >Remove</button></td>
</tr>Using std-components, you can create these rows like this:
import { tr, td, a, button, fragment } from 'std-components';
function removeUser() { /*...*/ }
function userRow( user: { name: string, email: string } ): HTMLTableRowElement {
return tr( {},
td( {}, user.name ),
td( {}, a( { href: `mailto: ${user.email}` }, user.email ),
td( {},
button( {
class: 'btn btn-danger',
events: { click: removeUser }
}, 'Remove' )
)
);
}
const users = await getUsers();
const rows = users.map( u => userRow( u ) );
document.querySelector( 'tbody' ).append( fragment( ...rows ) ); // Fragment avoids DOM reflowThe example above without using std-components would be:
function removeUser() { /*...*/ }
function userRow( user: { name: string, email: string } ): HTMLTableRowElement {
const tdName = document.createElement( 'td' );
tdName.textContent = name;
const emailAnchor = document.createElement( 'a' );
emailAnchor.href = `mailto: ${user.email}`;
emailAnchor.textContent = user.email;
const tdEmail = document.createElement( 'td' );
tdEmail.append( emailAnchor );
const removeButton = document.createElement( 'button' );
removeButton.classList.add( 'btn btn-danger' );
removeButton.textContent = 'Remove';
removeButton.addEventListener( 'click', removeUser );
const tdActions = document.createElement( 'td' );
tdActions.append( removeButton );
const tr = document.createElement( 'tr' );
tr.append( tdName, tdEmail, tdActions );
return tr;
}
const users = await getUsers();
const rows = users.map( u => userRow( u ) );
const fragment = document.createDocumentFragment(); // Avoids DOM reflow
fragment.append( ...rows );
document.querySelector( 'tbody' ).append( fragment );API
- The API covers almost all standard DOM elements , except deprecated ones.
- The functions have the same name as the HTML tags (except for
var_, sincevaris a reserved word in JavaScript). - Just import the desired functions and use them like in the example above.
Basic overall syntax:
function tag( props: {[key: string]: any} = {}, ...children: Array<string|Node|HTMLElement> ): HTMLElementwhere:
tagis the desired tag (function), likebutton;props(optional) is an object with DOM attributes you want to define in the tag;- Example:
div( { class: 'card' } )
- Example:
children(optional) are all child elements, separated by comma.- Example:
article( { class: 'post' }, header( {}, title( {}, 'First Post' ) ), p( {}, 'Hello, world!' ) )
- Example:
Special properties
eventsis an object that allows to define standard DOM events for the element.- Example:
button( { events: { click: () => alert('Hi') } }, 'Say Hi' )
- Example:
isis a special property that makes a standard HTML element behave like a defined customized built-in element. See MDN for more.
Extra functions
fragment( ...children: Array<string|Node|HTMLElement> ): DocumentFragmentcreates a DocumentFragment.text( value: string = '' ): Textcreates a text node.component< T extends HTMLElement >( tag: string, props: {[key: string]: any} = {}, ...children: Array<string|Node|HTMLElement> ): Tcreates any DOM component. You probably won't need to use it.
