-
Notifications
You must be signed in to change notification settings - Fork 0
Learn By Example
This guide shows practical examples and explanations for the basics of Cardboard.
Every Cardboard app starts by calling init()
. This sets up the framework and creates a root element (by default, the <body>
tag) to which you can append your UI.
import { init } from '@nkeff/cardboard-js';
const root = init(); // The <body> is now your root element
You can also specify a different selector if you want to mount your app to a different element:
const root = init({ selector: '#app-root' });
This is the first step in any Cardboard app. The init
function returns the root element for your UI.
Use the allTags
object to create any HTML tag as a function. This is the core of Cardboard's declarative API.
import { init, allTags } from '@nkeff/cardboard-js';
const { div } = allTags;
init().append(
div() // creates a <div></div>
);
-
allTags
provides factory functions for all standard HTML tags.
You can add text directly as a string, or use the text
function for dynamic or templated text.
import { init, allTags, text } from '@nkeff/cardboard-js';
const { p } = allTags;
init().append(
p('Hello, Cardboard!'), // <p>Hello, Cardboard!</p>
p(text('Hello, ${name}!', { name: 'world!' })), // <p>Hello, world!</p>
);
- Direct string:
p('Hello, Cardboard!')
- Dynamic:
text
for string templates and reactivity.
See: Managing Text
Tags can take other tags as children, allowing you to build complex structures.
import { init, allTags } from '@nkeff/cardboard-js';
const { ul, li } = allTags;
init().append(
ul(
li('Item 1'),
li('Item 2'),
li('Item 3')
)
);
See: Tags
Set HTML attributes using .setAttrs()
.
import { init, allTags } from '@nkeff/cardboard-js';
const { input } = allTags;
init().append(
input().setAttrs({ placeholder: 'Type here', type: 'text' })
);
See: Manipulating Tags
Add or remove CSS classes using .addClass()
and .rmClass()
.
import { init, allTags } from '@nkeff/cardboard-js';
const { div } = allTags;
const box = div('Box').addClass('my-class');
box.rmClass('my-class');
init().append(box);
See: Manipulating Tags
Apply inline styles with .setStyle()
. This is best for quick prototyping or dynamic changes.
import { init, allTags } from '@nkeff/cardboard-js';
const { div } = allTags;
init().append(
div('Styled box').setStyle({
color: 'white',
background: 'blue',
padding: '16px',
borderRadius: '8px',
})
);
See: Styling
Attach event listeners to tags using .on()
or convenience methods like .clicked()
.
import { init, allTags } from '@nkeff/cardboard-js';
const { button } = allTags;
init().append(
button('Click me').on('click', (self, evt) => {
self.text('Clicked!');
})
);
Cardboard's state
function creates reactive values. When you update a state, the UI updates automatically.
import { init, allTags, state } from '@nkeff/cardboard-js';
const { button, p } = allTags;
const count = state(0);
init().append(
p().text('Count: $count', { count }),
button('Increase').clicked(() => count.value++)
);
See: State
Render dynamic lists using each
and a reactive state array.
import { init, allTags, state, each } from '@nkeff/cardboard-js';
const { ul, li, button, input } = allTags;
const items = state(['Apple', 'Banana']);
const addItem = (item) => {
if (item) items.value = [...items.value, item];
};
let inputRef;
init().append(
input().on('input', (self) => (inputRef = self.value)),
button('Add').clicked(() => addItem(inputRef)),
ul(
each(items, (item) => li(item))
)
);
See: Rendering Lists
Show or hide elements based on state using .hideIfNot()
.
import { init, allTags, state } from '@nkeff/cardboard-js';
const { div, button, p } = allTags;
const show = state(true);
init().append(
button('Toggle').clicked(() => (show.value = !show.value)),
div(
p('This is conditionally visible!')
).hideIfNot(show)
);
Bind an input's value to state and reflect changes in the UI.
import { init, allTags, state } from '@nkeff/cardboard-js';
const { input, p } = allTags;
const textValue = state('');
init().append(
input().setAttrs({ placeholder: 'Type...' })
.on('input', (self) => (textValue.value = self.value)),
p().text('You typed: $textValue', { textValue })
);
See: State
Dynamically add or remove classes based on state using .classIf()
.
import { init, allTags, state } from '@nkeff/cardboard-js';
const { button, div } = allTags;
const active = state(false);
init().append(
button('Toggle highlight').clicked(() => (active.value = !active.value)),
div('Highlight me!')
.addClass('highlight')
.classIf(active, ['active'])
.setStyle({ padding: '16px', border: '1px solid #ccc' })
);
// Add your own CSS for .highlight and .active in your stylesheet
See: Styling
Build reusable components by composing tags and state.
import { init, allTags, state } from '@nkeff/cardboard-js';
const { div, button, p } = allTags;
function Counter(label = 'Counter') {
const count = state(0);
return div(
p(`${label}: $count`, count),
button('Increment').clicked(() => count.value++)
);
}
init().append(
Counter('A'),
Counter('B')
);
See: Reusable Components
While inline styles (setStyle
) are convenient for quick prototyping or dynamic changes, it's best to use CSS classes and the .styled()
method or <style>
tags for reusable or large-scale components. This keeps your styles organized, efficient, and avoids unnecessary duplication in the DOM.
import { init, allTags } from '@nkeff/cardboard-js';
const { div } = allTags;
// Define a style object for reuse
const cardStyle = {
backgroundColor: '#466187',
borderRadius: '16px',
color: 'white',
padding: '16px',
margin: '10px',
':hover': {
color: 'lightblue',
}
};
function Card(content: string) {
return div(content).styled(cardStyle, 'my-card');
}
init().append(
Card('Reusable styled card'),
Card('Another card')
);
This example uses the .styled()
method to apply a CSS class with the given styles. The style is injected only once, no matter how many components use it.
See: styled
import { init, allTags } from '@nkeff/cardboard-js';
const { div, style } = allTags;
init().append(
style({
'.fancy': {
background: 'linear-gradient(90deg, #f3ec78, #af4261)',
color: '#222',
padding: '12px 24px',
borderRadius: '8px',
fontWeight: 'bold',
}
}),
div('This uses a global class!').addClass('fancy')
);
Here, a global style is defined using the style
tag and then applied via addClass
. This is the most efficient way to style many elements.
See: style tag
Inline styles (via .setStyle
) are best for dynamic, one-off, or state-driven changes. For static or repeated styles, prefer .styled()
or global classes. This reduces DOM bloat and improves performance, especially with many elements.
import { allTags } from '@nkeff/cardboard-js';
const { div } = allTags;
// BAD: Each instance gets its own inline style
const cmp1 = () => div('Not recommended').setStyle({ color: 'red', fontWeight: 'bold' });
// GOOD: Use a class or .styled() for shared styles
const cmp2 = () => div('Recommended').addClass('my-shared-style');
Define .my-shared-style
in a global style block or with .styled()
.
See also: Styling Guide, styled, setStyle
This Wiki is a work in progress, and your help is greatly appreciated!
If you have some free time and are interested in contributing to the wiki or the project in general, please don't hesitate to reach out. All contributions are welcome!