atoms-element v5.0.0
git clone https://git.pyrossh.dev/atoms-element
A simple web component library for defining your custom elements. It works on both client and server.
examples/elements/app-counter.js
import { classMap, createElement, css, html } from '../../index.js';
// State lives only in the count attribute — no separate internal copy to
// keep in sync. Counter.attrs below declares count as a Number: that folds
// it into observedAttributes on its own (name is still destructured as a
// plain param since it's only ever displayed, never written), and
// createElement hands count to this function already wrapped as a
// {value} getter/setter box, type-checked against the declared constructor.
// count must be set in markup (no default) — reading count.value throws
// otherwise. count.value += 1 reads the live attribute and writes straight
// back via setAttribute.
//
// <output> is the element HTML actually defines for "the result of a
// calculation" — a live-updating count is exactly that, which is what lets
// the CSS below style it by tag name instead of an accessory class like the
// old .count.
const Counter = ({ name, count }) => {
const increment = () => { count.value += 1; };
const decrement = () => { count.value -= 1; };
return html`
<p>Counter: ${name}</p>
<div class="controls">
<button type="button" aria-label="Decrement" @click=${decrement}>-</button>
<output class=${classMap({ warning: count.value > 10 })}>${count.value}</output>
<button type="button" aria-label="Increment" @click=${increment}>+</button>
</div>
`;
};
Counter.attrs = { count: Number };
Counter.styles = css`
:scope {
display: block;
margin-top: 2.5rem;
color: rgb(55 65 81);
--color-danger: rgb(239 68 68);
--color-button-bg: rgb(209 213 219);
--color-button-bg-hover: rgb(229 231 235);
}
p {
margin: 0 0 0.5rem;
}
.controls {
display: flex;
align-items: center;
}
output {
margin: 0 5rem;
font-size: 1.875rem;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}
output.warning {
color: var(--color-danger);
}
button {
background-color: var(--color-button-bg);
color: inherit;
border-radius: 0.25rem;
padding: 0.5rem 1rem;
font-size: 1.875rem;
}
button:hover {
background-color: var(--color-button-bg-hover);
}
button:focus {
outline: none;
}
`;
export default createElement(import.meta, Counter);