Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Hi, I'm Atomico js and I bring you the React syntax for webcomponents, I think you and I get along very well 😊.
First let's say that Atomico is light since it has a size close to 3kB vs React + ReactDOM that have a size close to 60kB, now if your project is already written in React I can integrate Atomico progressively since a component created can be instantiated as a component for React thanks to @atomico/react, example:
import { Button } from "@formas/button/react";
function App(){
return <>
<h1>React App!</h1>
<Button onClick={()=>console.log("Click!")}>
Submit
</Button>
</>
}Magical 🪄, isn't it?... well now let's speed up your Atomico learning path:
Atomico, like React, allows a declaration of components using only functions, example:
import { useState } from "
import { c, useProp }
From the example we will highlight the following differences:
In Atomico you only use one import.
useProp is like useState, but with the difference that useProp references the state from the webcomponent property defined in counter.props.
const props allows us to create the properties of our webcomponent, these are like React's propTypes, but with a big difference they are associated with the instance and can be read and modified by referencing the node, example document.querySelector("my-counter").count = 10;
ReactDom.render needs a reference to mount the component, in Atomico you only need to create the my-counter tag to create a new instance of the component.
The <host/> tag is similar to <> </> for React, but <host/> represents the webcomponent instance and every component created with Atomico must return the host tag
This is only readability, but in Atomico by convention we do not use capital letters when naming our component, these are only used when creating the customElement as in line 16, since Counter is instantiable.
Now I want to invite you to learn how to declare a style using Atomico.
It is common to see the use of libraries such as Emotion or styled-components to encapsulate styles in React, but these add an additional cost, be it for performance or bundle, in Atomico there is no such cost.
It is normal for React to create components that you then instantiate within other components, for example:
with Atomico there are certain differences:
The constructor in Atomic is the product of the c function and is the one you will use to register your webcomponent, example:
According to the previous example, you can instantiate MyComponent as a JSX Component, example:
This instance type allows autocompletion at the JSX level and type validation at the Typescript level.
This will be useful for reusing templates, but always remember stateless.
Retrieves the nodes assigned to a slot.
With Atomico you can do this and more
const Button = styled.a`
/* This renders the buttons above... Edit me! */
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
/* The GitHub button is a primary button
* edit this to target it specifically! */
${props => props.primary && css`
background: white;
color: black;
`}
`
render(
<div>
<Button
href="https://github.com/styled-components/styled-components"
target="_blank"
rel="noopener"
primary
>
GitHub
</Button>
<Button as={Link} href="/docs">
Documentation
</Button>
</div>
)import { c, css } from "atomico";
const props = { primary: { type: Boolean, relfect: true } };
const styles = css`
:host {
display: inline-block;
border-radius: 3px;
padding: 0.5rem 0;
margin: 0.5rem 1rem;
width: 11rem;
background: transparent;
color: white;
border: 2px solid white;
}
:host([primary]) {
background: white;
color: black;
}
`;
export const Button = c(
() => (
<host shadowDom>
<slot />
</host>
),
{ props, styles }
);
customElements.define("my-button", Button);
function Child({children}){
return <span>children</span>
}
function Main(){
return <>
<Child>text 1...</Child>
<Child>text 2...</Child>
</>
}import { c } from "atomico";
export const MyComponent = c(() => <host>...</host>); // Constructor
customElements.define("my-component", MyComponent);import { c } from "atomico";
import { MyComponent } from "./my-component";
export const MyApp = c(() => (
<host>
<MyComponent />
</host>
));
customElements.define("my-app", MyApp);function MyIcon({ size }) {
return (
<svg height={size} width={size}>
<circle r="45" cx="50" cy="50" fill="red" />
</svg>
);
}
const MyComponent = c(() => (
<host>
Small <MyIcon size={"1rem"} />
Large <MyIcon size={"2rem"} />
</host>
));Retrieve a node higher than the current webcomponent.
import { useParent, useParentPath } from "@atomico/hooks/use-parent";const selector = "form";
const parent = useParent(selector);Where:
selector: String, Selector to be used by Element.matches when searching for the parent.
parent: Element, ascending search result according to selector.
Where:
parents: parent nodes of the webcomponent
composed: bypasses shadow DOM in parent capture.
import { useSlot } from "@atomico/hooks/use-slot";const optionalFilter = (element)=> element instanceof MyCustomElement;
const childNodes = useSlot(ref, optionalFilter);Where:
ref: Reference of the slot to observe.
childNodes: List of nodes assigned to the observed slot.
optionalFilter: allows to filter nodes assign to childNodes
Observe the size change of a reference.
import {
useResizeObserver,
useResizeObserverState,
} from "@atomico/hooks/use-resize-observer";useResizeObserver(
ref,
(rect) => void
);Where:
ref: Ref, reference to observe the resizing.
rect: Object, the return of DOMRectReadOnly.toJSON(), documentation of
width
height
x
y
Where:
ref: Ref, reference to observe the resizing.
rect: Object, the return of DOMRectReadOnly.toJSON(), documentation of
useProxySlot allows you to observe the nodes assigned to a slot and reassign them to another slot dynamically, example:
Input: Suppose we have a component that observe the slot[name="slide"] node
<my-component>
<img slot="slide" src="slide-1"/>
<img slot="slide" src="slide-1"/>
<img slot="slide" src="slide-1"/>
</my-component>output: thanks to useProxySlot you will be able to modify the assignment of the list nodes without losing the nodes in the process as normally happens with useSlot, example:
<my-component>
<img slot="slide-1" src="slide-1"/>
<img slot="slide-2" src="slide-1"/>
<img slot="slide-3" src="slide-1"/>
</my-component>import { useRef } from "atomico";
import { useProxySlot } from "@atomico/hooks/use-slot";
function component() {
const ref = useRef();
const children = useProxySlot(ref);
return (
<host shadowDom>
<slot name="slide" ref={ref} />
{children.map((child, index) => (
<slot name={(child.slot = "slide-" + index)} />
))}
</host>
);
}Atomico makes it easy to build components with less code, better readability, and better reusability.
We invite you to discover part of the development experience you will get with Atomico:
Quick components to write since with Atomico you will require fewer lines of code to declare your webcomponents which will help you to be more productive
Fast in performance, since Atomico sends less code to the client, making your interface load quickly
This is thanks to a functional orientation inherited from React hooks plus some internal optimization from Atomic that ease the process of shaking the tree at compile time, achieving in this way sending the client a highly optimized JS that only has what you really use
This is thanks to Atomico's reliance on React hooks syntax plus the ability to completely eliminate the need for this when using webcomponents.
Atomic offers additional coverage for native behavior for React and Vue, allowing your component to be more embed-friendly, example React:
This guide will know the essentials to start developing webcomponents with Atomico
Thanks for being here and getting started with Atomico. Let's talk a little about what Atomico offers today:
Development agility, Atomico's functional approach simplifies code at all stages of development.
Lightweight inside and out, Atomico allows you to create a component with less code and with a low dependency impact. Approximately 3kb.
Really fast, Atomico has a in the browser and an agile development experience. Let's understand what a webcomponent created with Atomico looks like:
Let's analyze the code in parts ...
What have we imported?
c: Function that transforms the functional component into a standard customElement.
css: Function that allows creating the CSSStyleSheet (CSS) for our component as long as it declares the shadowDom.
Our function receives all the props (Properties and Attributes) declared in props, the component function declares all the logic and template of the webcomponent. An important rule within Atomico is "📌 every component created with Atomico must always return the tag".
Atomico detects the prop (Properties and Attributes) of the component thanks to the association of the props object, this through the use of index and value allows you to define:
index: Name of the property and attribute.
value: type of the prop.
From the example we can infer that Atomico will create in our webcomponent a property and attribute called message and this can only receive values of the String type.
Atomico detects the static styles of your component thanks to the association of the styles property:
styles accepts individual or list CSSStyleSheet (CSS) values, the return from the css function is a standard CSSStyleSheet, so it can be shared outside of Atomico.
To create our standard customElement we will have to deliver our functional component to the c function of the Atomico module, the c function will generate as a return a customElement that can be defined or extended.
working on this documentation...
working on this documentation...

import { Button } from "@formas/button/react";
function App(){
return <>
<h1>React App!</h1>
<Button onClick={()=>console.log("Click!")}>
Submit
</Button>
</>
}// Imports
import { c, css } from "atomico";
// Creating Our Web Component: Custom Element Definition
export const MyComponent = c(
// Defining Component Render Function
({ message }) => {
return <host shadowDom>{message}</host>;
},
{
// Defining Component Properties(props) and Attributes
props: {
message: String,
},
// Defining Encapsulated Styles for the Component
styles: css`
:host {
font-size: 30px;
}
`,
}
);
// Web Component Registration and Definition
customElements.define("my-component", c(component));import { c, css } from "atomico";// Defining Component Render Function
({ message }) => {
return <host shadowDom>{message}</host>;
}// Defining Component Properties(props) and Attributes
props: {
message: String,
},// Defining Encapsulated Styles for the Component
styles: css`
:host {
font-size: 30px;
}
`,// Web Component Registration and Definition
customElements.define("my-component", c(component));top
right
bottom
left
width
height
x
y
top
right
bottom
left
const rect = useResizeObserverState(ref);const parents = useParentPath(composed?: boolean);The props in Atomico are the way to associate the webcomponent properties and reactive attributes that trigger the logic or interface of the webcomponent.
Props is the Atomico recommended way to declare visible and accessible states at the instance level of your webcomponents, with props you can:
Access state via instance, example: document.querySelector("my-component").myStateProp.
Dispatch events on prop value change, example: document.querySelector("my-component").addEventListener("myPropChange",console.log).
Reflect attributes as prop, example: <my-component my-prop="...."> to document.querySelector("my-component").myProp.
define strict input types for props.
Any function that represents the webcomponent will be able to associate the static object props for the declaration of reactive properties and attributes, for example:
The prop names in Camel Case format will be translated to for use as an attribute to the Kebab Case format, this behavior can be modified through the "attr" property when using a structured declaration.
Structured declarations require the "type" property minimally.
Not all types can use the "reflect" properties.
The declaration of the "value" property can vary depending on the type.
Simple statements allow setting just type validations.
Improve the definition by adding utility declarations, allowing for example to reflect the property's value as attributes, automatically emit events or associate default values. Remember these types of declarations minimally require the use of the type property.
If the "reflect" property is set to true, its value is reflected as an attribute of the webcomponent, this is useful for the declaration of CSS states, example:
It allows dispatching an automatic event before the prop value change, example:
Where:
event.type: String - optional, name of the event to be emitted when the prop is changed
event.bubbles: Boolean - optional, indicates that the event can be listened to by containers.
event.detail: Any - optional, allows to attach a custom detail for the event
The special properties of the event are the well-known Event Init, you can know more details in the .
Atomico allows the definition of default values of the props.
The association of callback as value allows generating unique values for each instance of the webcomponent, this is useful with the Object and Array types since it eliminates the references between instances.
Atomico removes the use of "this" given its functional approach, but adds the hook [useProp] (hooks / useprop.md) which allows to reference a prop for use with a functional syntax, eg:
A micro library inspired by React Hooks, designed and optimized for the creation of webcomponents.
import { c } from "
import { c } from "
Atomico simplifies learning, workflow and maintenance when creating webcomponents and achieves it with:
Scalable and reusable interfaces: with Atomico the code is simpler and you can apply practices that facilitate the reuse of your code.
Open communication: with Atomico you can communicate states by events, properties or methods.
Agnostic: your custom Element will work in any web-compatible library, eg React, Vue, Svelte or Angular.
Performance: Atomico has a comparative performance at Svelte levels, winning the third position in performance according to in a comparison of 55 libraries among which is React, Vue, Stencil and Lit.
Today Atomico is used in the development of design systems for various industries such as Banking, Pledge Systems, Insurance, Clinical, Government and more.
Many teams decide to use Atomico for the development of their design systems thanks to its similarity with React, which greatly facilitates the incorporation of human talent into the development of design systems.
Atomico offers you Storybook 7 Support with superpowers, thanks to @atomico/storybook you can create stories without the need to declare the argTypes or args since @Atomico/storybook creates them for you
@atomico/vite makes it easy for you to build in NPM-friendly ESM format
makes it easy for you to export your code by automatically adding the metadata so that it is optimally consumed as a package, @atomico/exports can even automatically create wrappers for React, Preact and Vue
makes it easy for you to maintain a token system efficiently and sustainably
We thank IBM IX since they have shared their experience in the development of the design system for their client Barmer, you can follow this case through Discord or Github.
Atomico has a really efficient and simple type validation method, the type validation works in the following way:
the given value is transformed to the corresponding type, be it String, Number, Boolean, Array or Object, once transformed it is sent to the cycle as property.
evaluates if the value is of the declared type:
If it corresponds to the type:
It is saved in props.
An event is emitted (if this has been configured in the prop).
It is reflected as an attribute (if this has been configured in the prop).
It is sent to the update queue and subsequent rendering.
It does not correspond to the type: an error is created by console with the following data:
target: Instance of the webcomponent.
value: Input value.