atoms-element v5.0.0

#js

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);