npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@obinexusltd/obix-jsx-components

v0.1.2

Published

JSX factory functions for all 30 OBIX components — wraps obix-component-runtime

Readme

@obinexusltd/obix-jsx-components

JSX Factory Functions for 30 OBIX UI Components

NPM Version License: MIT TypeScript


Overview

@obinexusltd/obix-jsx-components provides 30 production-ready JSX component factories that compile to pure OBIX data objects. No virtual DOM. No framework dependencies. Just plain HTML/CSS/JS.

Core Philosophy

JSX is syntax sugar. Components are data objects.

// JSX Input (React specification-compliant)
<obix-button label="Save" variant="primary" />

// ↓ (TypeScript compiler)

// Function Call (intermediate)
h(obixButton, { label: "Save", variant: "primary" })

// ↓ (@obinexusltd/obix-jsx-adapter)

// Data Object (OBIX runtime)
{
  name: 'Button',
  state: { label: 'Save', variant: 'primary', ... },
  actions: { setLabel, setDisabled, ... },
  render: (state) => '<button>Save</button>',
  aria: { ... }
}

Features

30 Components Organized by Category

| Category | Components | |----------|-----------| | Primitives | button, card, image, video, link | | Forms | input, checkbox, radio-group, select, textarea, form, date-picker, file-upload | | Navigation | navigation, breadcrumb, pagination, tabs, stepper | | Overlays | modal, dropdown, tooltip | | Feedback | alert, toast, progress, loading | | Controls | slider, switch | | Data | table, accordion | | Search | search, autocomplete |

Benefits

Framework-Agnostic — Works in vanilla JS, React, Vue, SSR, HTMX, Svelte
Type-Safe — Full TypeScript support with JSX compilation
Accessibility First — WCAG 2.1 AA compliant by default
Immutable State — Pure functions for predictable rendering
Server-Renderable — No DOM needed, just .render(state) → HTML string
Non-Monolithic — Paradigm-agnostic, works with Functional/OOP/Reactive adapters
Zero Dependencies — Only depends on obix-component-runtime and obix-jsx-adapter
Tested — Unit + render + integration tests for every component


Installation

npm install @obinexusltd/obix-jsx-components
npm install @obinexusltd/obix-jsx-adapter  # Required peer
npm install @obinexusltd/obix-component-runtime  # Required peer

TypeScript Configuration

{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "h",
    "jsxFragmentFactory": "Fragment",
    "target": "ES2020",
    "module": "ESNext",
    "strict": true
  }
}

Quick Start

1. Vanilla JavaScript (No Build Step)

<!DOCTYPE html>
<html>
<head>
  <title>OBIX JSX Demo</title>
</head>
<body>
  <div id="app"></div>
  <script type="module">
    import { h } from '@obinexusltd/obix-jsx-adapter';
    import { obixButton } from '@obinexusltd/obix-jsx-components';

    const button = h(obixButton, { label: 'Click Me', variant: 'primary' });
    document.getElementById('app').innerHTML = button.render(button.state);
  </script>
</body>
</html>

2. TypeScript with JSX Syntax

/** @jsx h */
/** @jsxFrag Fragment */

import { h, Fragment } from '@obinexusltd/obix-jsx-adapter';
import { obixForm, obixInput, obixButton } from '@obinexusltd/obix-jsx-components';

function LoginForm() {
  return (
    <obix-form label="Login">
      <obix-input 
        name="email" 
        type="email" 
        label="Email" 
        required 
      />
      <obix-input 
        name="password" 
        type="password" 
        label="Password" 
        required 
      />
      <obix-button label="Sign In" variant="primary" />
    </obix-form>
  );
}

const form = LoginForm();
document.getElementById('app').innerHTML = form.render(form.state);

3. Server-Side Rendering

import express from 'express';
import { h } from '@obinexusltd/obix-jsx-adapter';
import { obixCard, obixButton } from '@obinexusltd/obix-jsx-components';

const app = express();

app.get('/', (req, res) => {
  const card = h(obixCard, { title: 'Dashboard' });
  const button = h(obixButton, { label: 'Get Started', variant: 'primary' });

  const html = `
    <!DOCTYPE html>
    <html>
      <body>
        ${card.render(card.state)}
        ${button.render(button.state)}
      </body>
    </html>
  `;

  res.send(html);
});

app.listen(3000);

Component API

Button

import { obixButton } from '@obinexusltd/obix-jsx-components';

const button = h(obixButton, {
  label: 'Save',                          // string
  variant: 'primary',                     // 'default' | 'primary' | 'secondary' | 'danger'
  size: 'md',                             // 'sm' | 'md' | 'lg'
  disabled: false,                        // boolean
  loading: false,                         // boolean
  type: 'button',                         // 'button' | 'submit' | 'reset'
  ariaLabel: 'Save changes',              // string
  icon: 'save',                           // string
  className: 'custom-class'               // string
});

Input

import { obixInput } from '@obinexusltd/obix-jsx-components';

const input = h(obixInput, {
  name: 'email',                          // string
  type: 'email',                          // 'text' | 'email' | 'password' | 'number' | ...
  label: 'Email Address',                 // string
  placeholder: '[email protected]',         // string
  value: '',                              // string
  required: true,                         // boolean
  disabled: false,                        // boolean
  minLength: 0,                           // number
  maxLength: 255,                         // number
  error: null,                            // string | null
  hint: 'We\'ll never share.',            // string
  validation: 'blur',                     // 'blur' | 'change' | 'submit'
  ariaLabel: 'Email',                     // string
  ariaDescribedBy: 'email-help'           // string
});

Form

import { obixForm } from '@obinexusltd/obix-jsx-components';

const form = h(obixForm, {
  label: 'Contact Us',                    // string
  legend: 'Send us a message',            // string
  noValidate: false,                      // boolean
  errorSummary: true,                     // boolean
  ariaLabel: 'Contact form'               // string
});

// Add children via h()
const emailInput = h(obixInput, { label: 'Email', type: 'email' });
const messageInput = h(obixInput, { label: 'Message' });
const submitBtn = h(obixButton, { label: 'Send' });

const completeForm = h(obixForm, { label: 'Contact' }, emailInput, messageInput, submitBtn);

Alert

import { obixAlert } from '@obinexusltd/obix-jsx-components';

const alert = h(obixAlert, {
  message: 'Operation successful!',       // string
  type: 'success',                        // 'info' | 'success' | 'warning' | 'error'
  title: 'Success',                       // string
  dismissible: true,                      // boolean
  ariaLive: 'polite'                      // 'polite' | 'assertive'
});

All 30 Components

Full API reference available in COMPONENT_API.md


Paradigm Usage

Functional (Immutable)

import { toJSXFunctional } from '@obinexusltd/obix-jsx-integration';

const button = h(obixButton, { label: 'Count: 0' });
const functional = toJSXFunctional(button);

let count = 0;

function increment() {
  count++;
  const newState = functional.dispatch('setLabel', `Count: ${count}`);
  const html = button.render(newState);
  document.getElementById('app').innerHTML = html;
}

OOP (Mutable)

import { toJSXOOP } from '@obinexusltd/obix-jsx-integration';

const button = h(obixButton, { label: 'Count: 0' });
const oop = toJSXOOP(button);

let count = 0;

function increment() {
  count++;
  oop.instance.label = `Count: ${count}`;
  const html = button.render(oop.instance);
  document.getElementById('app').innerHTML = html;
}

Reactive (Observer)

import { toJSXReactive } from '@obinexusltd/obix-jsx-integration';

const button = h(obixButton, { label: 'Count: 0' });
const reactive = toJSXReactive(button);

let count = 0;

reactive.subscribe((newState) => {
  const html = button.render(newState);
  document.getElementById('app').innerHTML = html;
});

function increment() {
  count++;
  reactive.dispatch('setLabel', `Count: ${count}`);
}

Testing

Run Tests

npm test                # Run all tests
npm run test:watch      # Watch mode
npm run test:coverage   # Coverage report

Test Structure

Each component has three test layers:

  1. Unit Test — Factory creates correct object shape
  2. Render Test.render(state) produces valid HTML
  3. Integration Test — Works with h() factory and paradigms

Example:

describe('obixButton', () => {
  it('creates component with correct shape', () => {
    const button = obixButton({ label: 'Save' });
    expect(button).toHaveProperty('state');
    expect(button).toHaveProperty('actions');
    expect(button).toHaveProperty('render');
  });

  it('renders HTML string from state', () => {
    const button = obixButton({ label: 'Save' });
    const html = button.render(button.state);
    expect(html).toContain('Save');
  });

  it('works with h() factory', () => {
    const button = h(obixButton, { label: 'Save' });
    expect(button.render(button.state)).toContain('Save');
  });
});

Examples

Vanilla JS + HTML/CSS

See: examples/vanilla-js/

Server-Side Rendering

See: examples/server-side/

Functional Paradigm

See: examples/functional-paradigm/


CSS Classes & Styles

All components use consistent BEM naming convention:

.obix-[component]
.obix-[component]__[element]
.obix-[component]--[modifier]

Examples:

  • .obix-button
  • .obix-button--primary
  • .obix-button--disabled
  • .obix-input-group
  • .obix-input__label
  • .obix-input--error
  • .obix-form__legend

Styles are not included in this package. Import from @obinexusltd/obix-component-runtime:

import '@obinexusltd/obix-component-runtime/styles';

Accessibility

All components follow WCAG 2.1 AA standards:

ARIA Attributes — Roles, labels, descriptions, live regions
Keyboard Navigation — Fully operable without mouse
Touch Targets — Minimum 48×48 pixels
Contrast — 4.5:1 minimum for text
Focus Indicators — Always visible
Semantic HTML — Proper fieldsets, legends, labels

Example:

const input = h(obixInput, {
  label: 'Email Address',              // Associated label
  required: true,                      // aria-required
  ariaDescribedBy: 'email-help',       // aria-describedby
  error: 'Invalid email',              // aria-invalid
  hint: 'We\'ll never share'           // Accessible hint
});

Browser Support

| Browser | Version | |---------|---------| | Chrome | 90+ | | Firefox | 88+ | | Safari | 14+ | | Edge | 90+ | | Node.js (SSR) | 18+ |


Publishing

This package is published to NPM:

npm install @obinexusltd/obix-jsx-components

Version History

  • 0.1.0 (2026-06-03) — Initial release with 30 components, full test suite, examples

Contributing

Contributions welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new components
  4. Ensure all tests pass
  5. Submit a pull request

Support


License

MIT © 2026 Nnamdi Okpalan / OBINexus Computing


Related Packages


Built with ❤️ for accessibility-first UI development