Composi

Make Component-Based Interfaces

Star

Modular

Create simple components and combine them into more complex ones. The virtual DOM takes care of efficiently updating the HTML when a component's props change.

@composi/core is small, barely 2KB. It has three main functions: h, render and run. And three lifecycle events: onmount, onupdate and onunmount.

Declarative

Define your component markup with JSX, or Hyperscript.

Everything is just JavaScript. You can use JavaScript inside your render functions.

No need for special markup syntax or directives.

Reusable

Functional components and runtime programs encapsulate their behavior and properties, so you can reuse them even in other applications.

Render default HTML on the server and bring everything to life at load time with Composi.


@composi/core

The core provides support for functional components just like React, using JSX. There is a render function for injecting content into the DOM: render(<Component />, document.body). You use it the same way you use the ReactDOM.render function. Unlike React, function components come with support for three lifecycle hooks. These are implemented as props so you can track any element as it mounts, updates and unmounts. No need for camel case events or special attributes like React does. Use normal HTML attributes. You can use JSX for components, but you don't have to use odd attribute names. React requires className, onClick, etc. With @composi/core you use normal HTML attributes: class, onclick, etc. If you want to use innerHTML, it is just a normal HTML attribute that accepts a string. We do expect you to be aware of the security implications of using it.

@composi/core runtime

Core also provides state management for functional components through its runtime. Inspired by the Elm architecture, the runtime is based on the pattern of SVU-State, View and Update. State can be any valid JavaScript type. View is a function that returns a representation of the state. Update is like a simplified version of Redux, but without all the boilerplate. The runtime also provides a way to deal with effects. Runtime programs support composition as well, with communication between parent and child through effects.

In just 2KB, @composi/core with the runtime provides the same functionality as React functional components, but with Redux-like state management. @composi/core does not need shouldComponentUpdate, etc. It checks props and automatically bails if they have not changed.

Type Safe JavaScript

Composi comes fully typed using JSDoc comments. When you use create-composi-app to make a new project, it comes set up to provide you with automatic type checking. It does this by running the TypeScript language service in the background to parse the JavaScript files and understand the types based on its JSDoc comment. If you already know how to write comments with JSDoc, you add type coveage for the code you write.


A Simple Functional Component

Use render to inject markup into the DOM. This takes a functional component to convert to HTML and a container to inject in.

See the Pen @composi/core - Hello World by Robert Biggs (@rbiggs) on CodePen.

Updating a Component

You can update a functional component by rendering it with a new value for its props.

In this example we're updating the component every second until 100. We use the lifecycle method onmount to start the tick method.

See the Pen @composi/core - timer by Robert Biggs (@rbiggs) on CodePen.

A Todo List

Here we put together a todo list with core and runtime for state management, along with tagged unions for simpler update actions and messaging. List items and their children inherit state through props passed down from their parent. Child components communicate with their parent through messages.

Inline events handle user interactions. All todos are saved to localStorage. On reloads, the saved items are used.

Animations are implemented using onmount and onunmount lifecycle events.

See the Pen @composi/core - runtime Todo List by Robert Biggs (@rbiggs) on CodePen.

A Calculator

Here is a simple calculator implemented with @composi/core and @composi/datastore. The parent component manages events for all the subcomponents. This component has many custom methods for handling all the Math computations, etc.

See the Pen @composi/core Mac Calculator by Robert Biggs (@rbiggs) on CodePen.

An Image Browser with Popup

This uses @composi/core with the runtime and a tagged union for state management. It grabs images from Flickr. You can click on an image to get a closer look. Clicking again will close it.

When you click on the "10 More" button, its sends a message to the program update function, which fetches 10 more images and returns the new state to re-render the view.

See the Pen @composi/core Image Browser with runtime & tagged unions by Robert Biggs (@rbiggs) on CodePen.

SVG Animation

Here we're using D3 to animate a Pythagoras tree using Composi's virtual DOM to update the SVG in real time. Move the cursor over the panel. As you do so, upto 2,000 rectanges will be created, animated and destroyed in real time based on the cursor position. This shows how efficient Composi's virtual DOM is.

You can use many third-party libraries and frameworks with Composi, such a Redux, Mobx, RxJS, Lodash, Bootstrap, Material Design Lite, etc.

See the Pen @composi/core Pythagoras Dancing Tree by Robert Biggs (@rbiggs) on CodePen.

Dynamic Counters

This is a functional component that generates keyed counters. It uses the runtime along with a tagged union for state management. This is similar to how the todo app is implemented above. Each counter occupies a keyed list item. This makes it more efficient for deleting random counters from the list.

Each counter has the events and functionality it needs to act like an independent component. In reality they are just part of a larger, all-encomposing component.

We're also using the Fragment tag to generate a group of sibling elements--the buttons that constitute the counter.

See the Pen @composi/core --Counters with Runtime by Robert Biggs (@rbiggs) on CodePen.