Components and UI kits
v0.0.1
A component is a reusable piece of markup that your pages draw by name, such as an alert, a card or a pricing table. A UI kit is a bundle of components with the JS hooks and the stylesheet they need, installed together. This page explains what a component is, who can draw it, how the CMS draws it, and how a kit brings a whole set of them to a site. To install a kit, follow Install or upgrade a UI kit.
What a component is
A component is a record in the database. It holds a template and a description of the values it takes. The visual editor lists the components of your site on the Components tab, and a page draws one with a component tag that names it and the site it comes from:
<.component component_name="chelekom-alert" site="Global" />The CMS compiles each component into a module, as it does for a page. See How a page reaches visitors. Because a component is a record, you can edit it in the builder, keep its history and restore an earlier copy.
The parts of a component
| Field | What it holds |
|---|---|
| Name and Description | A name of 3 to 100 characters, unique within a site, and an optional description of up to 500. |
| Template and Format | The markup, written as HEEx, EEx or Markdown. The default is HEEx. |
| Type | A category label of up to 50 characters, such as general, forms, navigations, overlays, feedback or media. |
| Attributes | The values the component takes. Each has a name and a type: string, integer, float, boolean, atom, list, map, any, global or struct. |
| Slots | The areas where a page puts its own content inside the component. |
| Helper Functions | Small functions that the template calls. |
| Live component | Off, the component is a function component: it draws what it is given and holds nothing. On, it keeps its own state between renders and answers its own events, as a Phoenix LiveComponent. |
| Precompile | On, the CMS builds the module at boot. Off, the first render that uses it builds it. It has no effect on the CSS. |
dependencies | The components and JS files this component needs, such as chelekom-icon. |
required | Whether the CMS cannot run without this component. The installer does not let you deselect it. |
| Site | The site the component belongs to. Empty means global. |
Global and site components
A component with no site is global. Every site can draw it, and the tag names it with site="Global". A component that has a site belongs to that site, and only that site can draw it. In the palette, a G badge marks a global component and a T badge marks one that only this site has.
A page draws the global components and the components of its own site, and nothing else. A tag that names a component of another site is refused before anything is built, and the page draws nothing in its place. A plugin can answer the runtime:render:component_unavailable event to draw markup of its own.
When a master installs from the Studio, This site adds the component to the site in the editor and All sites shares it with every site. A site admin installs to their own site.
How a component is drawn
- The module. The CMS builds it at boot when Precompile is on, and otherwise on the first render that needs it. A page or layout builds the components it reaches, several at once, before it draws them.
- The styles. The stylesheet of a site covers the components that the site reaches. A component that is not precompiled still renders styled the first time it appears.
- The canvas. The editor draws a component in its cold state, with no process behind it, so a live component does not answer clicks there. The editor says so beside the selection.
- Stored content. A post body or a documentation note can name a component with a marker that an author writes. If that component raises while it draws, the rest of the page still draws, and a small box that reads This component could not be drawn takes its place. The error is logged under an id, and only dashboard admins see the id. A live component is not caught this way.
UI kits
A UI kit is a mishka.ui_kit.bundle.v3 JSON file. Each entry under components is one component record, each entry under js_hooks is one JS hook and each entry under stylesheets is one stylesheet. The file is the install plan.
Kits come from three places:
- The official kits. Chelekom ships a styled and a headless package. The installer fetches the newest release by default, and you can choose a pre-release or the master branch.
- A file on the server. A bundle in the
priv/cms_ui_kits/folder is offered by the installer. - An extension. Mishka Blog and Mishka Document ship their components as a bundle, which installs when you set the extension up on a site.
What an install does
- It fires the
runtime:ui_kit:before_installevent. - It checks each component against the kit contract. A component with no name or template, or with a field of the wrong shape, is skipped and named in the log. The rest of the kit installs.
- It writes every component, JS hook and stylesheet in one transaction, so an install that fails leaves nothing half written. A component that is archived on the site is skipped.
- It rebuilds the runtime once, after the whole kit has committed, and fires the
runtime:ui_kit:after_installevent.
A kit installs for every site or for one. A narrowed install, with chosen components and chosen variants or colors, renders without the values it leaves out. Components are named after their kit, as in chelekom-alert, so two kits installed side by side never replace each other's components. Removing a kit deletes the components with its prefix, and its JS hooks and stylesheets.
Updating a kit
The installer stamps each component with the version of the kit that wrote it and a fingerprint of what it wrote. An update, offered for the kits that extensions ship, compares those with the bundle. It updates a component that still equals what the kit installed. It writes a component someone edited only when an admin asks for it by name, and the copy it held stays in the history of the component.
Example: one global component and one of your own
You install Chelekom for every site. Your site, coffee-shop, also gets a component of its own named coffee-shop-promo. A page of that site draws both:
<.component component_name="chelekom-alert" site="Global" />
<.component component_name="coffee-shop-promo" site="coffee-shop" />The first tag draws on every site that has the kit. The second draws on coffee-shop only. A page of another site that names coffee-shop-promo draws nothing in its place. Attributes that a component requires go on the tag as well.