| .claude | ||
| .github/workflows | ||
| .husky | ||
| .vscode | ||
| assets | ||
| demo | ||
| docs | ||
| scripts | ||
| src | ||
| test | ||
| vendors/htm | ||
| .gitignore | ||
| .npmignore | ||
| .nvmrc | ||
| .prettierignore | ||
| AGENTS.md | ||
| eslint.config.mjs | ||
| LICENSE | ||
| netlify.toml | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| prettier.config.mjs | ||
| README.md | ||
| size-change-log.md | ||
| tsconfig.json | ||
| vitest.config.mjs | ||
| vitest.e2e.config.mjs | ||
Web Component Base
Note
Correctness fixes shipped (v5.0.0) — We now have better compliance with the custom elements specs, better property type handling and clearer distinction between attributes and property within
onChanges()hook (breaking change). See the change log for more details. Next up: faster templates!
🤷♂️ zero-dependency, 🤏 tiny JS base class for creating reactive custom elements easily ✨
This is the base class used for web components in Ayo's projects, primarily cozy-games, mcfly, his personal site, his blog, and others.
Read more about it on the docs or view a demo on CodePen.
When you extend the WebComponent class for your component, you only have to define the template and properties. Any change in any property value will automatically cause just the component UI to render.
The result is a reactive UI on property changes.
TypeScript: typed props
this.props is untyped ({ [name: string]: any }) by default. Pass the shape of your defaults as a type argument to get compile-time types on declared props:
const props = { variant: 'primary', disabled: false }
class CozyButton extends WebComponent<typeof props> {
static props = props
get template() {
this.props.variant // string
this.props.disabled // boolean
this.props.disabled = 'yes' // ❌ compile error
return html`<button class=${this.props.variant}></button>`
}
}
The runtime is unchanged — this is types-only, and omitting the type argument keeps the previous behavior. See the prop access guide for details.
Want to get in touch?
There are many ways to get in touch:
- Open a GitHub issue or discussion
- Submit a ticket via SourceHut todo
- Email me: hi@ayo.run
Inspirations and thanks
- htm - I use it for the
htmlfunction for tagged templates, and take a lot of inspiration in building the rendering implementation. It is highly likely that I will go for what Preact is doing... but we'll see. - fast - When I found that Microsoft has their own base class I thought it was super cool!
- lit -
lit-htmlcontinues to amaze me and I worked to makewcbgeneric so I (and others) can continue to use it
Size change log
See size-change-log.md for a running record of how each correctness/feature change affects the WebComponent base class bundle size, with the reason and benefit of each.
Just keep building.
A project by Ayo
