jay-cm
v0.1.8
Published
Jay is a fast, lightweight Web Component framework with Shadow DOM support, reactive props, design tokens, and zero-compiler overhead.
Maintainers
Readme
The Jay Framework
Jay is a lightweight and reactive framework built with TypeScript, devloped with an aim to make writing frontend code feel better with just enough abstraction.
It brings the speed and flexibility of web components together with a modern developer experience, providing tools to craft interfaces at scale without endless dependencies.
We want to redefine the way people write code for the web, yes that's a bold statement but give it a go and see for yourself!
Why Use Jay?
- Auto-Reactive Properties – Just update props; Jay re-renders your component.
- Scoped Utility-First CSS – Tailwind-style utility classes with design tokens and media query support.
- Simple Lifecycle Hooks –
onRender,onUpdate,onMount,onDestroy,onPropChange - Fast Build-Time Compiler – Built-in CSS compiler for a native JS feel.
- No Boilerplate – A component can be written in just two lines, every line is declarative.
- Built-in Events & HTTP – Easy pub/sub events and data fetching.
- Automatic HTML Element Definition – Elements are built from the classname:
Button-><comp-button>
Installation
npm install --save-dev jay-comp webpack webpack-cliOr clone directly:
git clone https://github.com/Taghunter98/jay-comps.git
cd jay-comps
npm install
npx tscWebpack Setup
Make sure type is set to "module" in your package.json.
Then create a webpack.config.cjs file:
const path = require("path");
module.exports = {
entry: "./index.js",
mode: "development", // or "production"
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist"),
},
};In index.js, import your components:
import "./components/test.js";Build with:
npx webpackExample Component
import { Define, Component, html, cls, host } from "jay-comp";
@Define
class HelloWorld extends Component {
message = "Hello, Jay!";
clicked = false;
html = html`
<div class="card">
<h1 class="heading">${this.message}</h1>
<button class="btn">
${this.clicked ? "Clicked!" : "Click Me"}
</button>
</div>
`;
css = [
host("w_auto"),
cls("card", "p_16 flex_col g_12 bg_white shadow_sm rounded_md"),
cls("heading", "heading font_bold"),
cls("btn:hover", "bg_red"),
cls("btn", "p_12 rounded_sm text_white bg_black"),
];
callback = () => {
this.query(".btn").addEventListener("click", () => {
this.clicked = true;
});
};
}Core Concepts
HTML
Use tagged template syntax for better syntax highlighting and cleaner code:
html = html`<div>Hello ${this.name}</div>`;CSS
Use the cls() helper to build scoped, composable, utility-first CSS with full support for:
- Media queries (e.g.
sm_p_16) - Pseudo classes (
hover_bg_red) - Design tokens (
bg_primary,text_grey,shadow_md, etc.)
Or define styles inline with objects:
css = [
{
class: "custom",
padding: 12,
borderRadius: 4,
backgroundVar: "white",
},
];Reactive Props
Mutable props auto-trigger re-renders:
name = "Jay"; // reactive
isOpen = false; // reactiveImmutable values can also be declared if preferred for performance.
Design Tokens & Utilities
Jay ships with a built-in design system powered by utility class parsing:
cls("card", "p_16 bg_white rounded_sm shadow_md text_grey");Example Utility Keys:
| Utility | Output |
| -------------- | --------------------------------------------- |
| p_16 | padding: 16px |
| bg_white | background: var(--white) |
| sm_p_12 | @media (max-width: 640px) { padding: 12px } |
| hover_bg_red | :hover { background: var(--red) } |
| text_grey | color: var(--black60) |
See the Wiki for the full list of utility classes and design tokens.
Lifecycle Hooks
| Hook | When it runs |
| -------------- | -------------------------------------------------- |
| onMount | Once after the component is attached to the DOM |
| onRender | Once after first render and DOM injection |
| onUpdate | After every render update (including the first) |
| onDestroy | On component removal (disconnect from DOM) |
| onPropChange | When a reactive property is changed (receives key) |
Events & HTTP
Use built-in methods for communication:
this.publish("modal-open"); // Event pub/sub
this.subscribe("login", () => (this.loggedIn = true));
request<{ id: number; username: string }>("/api/user"); // GET/POST JSON
formSubmit<{ status: boolean }>("/api/login", formData); // Submit forms easilyDocumentation
Visit the Jay Wiki for advanced usage:
- Lifecycle
- Pseudo-classes & media queries
- Token-based design system
- CSS compilation
- Reactive architecture
- Shadow DOM management
Roadmap Ideas
- [ ] Devtools Integration
- [ ] VS Code IntelliSense plugin
- [ ] Live CSS hot reload
- [ ] Improved SSR support
- [ ] Built-in animation library
Contributing
PRs are welcome! Please:
- Fork the repo
- Create a feature branch
- Add tests or docs where relevant
- Open a pull request
Licensed under the Apache 2.0 License.
