GolemUI v2.0.0: Introducing GolemUI Components
GolemUI v2.0.0 is out, and it brings a new library: GolemUI Components, the gui-* elements behind every GolemUI form, now usable on their own.
Introducing GolemUI Components
Section titled “Introducing GolemUI Components”Freedom to choose has been a goal of GolemUI from the start. You pick the framework your forms render in: React, Angular, Vue, Lit or none. You pick the i18n library, the Markdown parser and the upload service, and GolemUI talks to them through small interfaces. The elements themselves were the exception. In 1.x the text fields, date pickers and lists lived inside the form engine, and only custom widgets used them directly.
In 2.0 they are a library of their own, with their own documentation, and your forms keep rendering with them as before.
That also gives the rest of your app the look and feel of your forms. The contact form you write by hand, the search box in the header, the tabs that move between sections: they can use the same elements as the dynamic forms GolemUI renders, with one theme for all of them.
Install the package and its one peer dependency, Lit:
npm install @golemui/gui-components litEach element has its own entry point, so you load only the ones you use:
import '@golemui/gui-components/index.css';import '@golemui/gui-components/textinput';import '@golemui/gui-components/date-picker';Then use the tags anywhere HTML goes:
<gui-textinput label="Full name" name="name" required></gui-textinput><gui-date-picker label="Check-in" name="checkIn" required></gui-date-picker>React gets a typed component for every element, with an onGui* prop for each event:
import { GuiTextinput } from '@golemui/gui-components/react';
<GuiTextinput label="Email" onGuiChange={(event) => save(event.detail.value)}/>;Angular, Vue and Lit use the tags directly, and Vue gets typings for every element. There are 33 inputs, from text fields to date-time range pickers, dropdowns with search and file uploads, plus a button, tabs, an accordion, an alert and Markdown text.
The documentation lives at golemui.com/components. Every example there is a live demo, with its code in React, Angular, Vue, Lit and plain JavaScript.
GolemUI Components features
Section titled “GolemUI Components features”Native form controls
Section titled “Native form controls”Every element that holds a value is a form control, like <input> or <select>. Give it a name inside a <form> and it submits its value, blocks the submit while it is invalid, and restores its value when the form resets. No JavaScript of your own:
<form action="/bookings" method="post"> <gui-textinput label="Full name" name="name" required></gui-textinput> <gui-date-picker label="Check-in" name="checkIn" required></gui-date-picker> <gui-tags label="Guests" name="guests"></gui-tags> <button type="submit">Book</button></form>FormData reads the values like those of any other field: a list submits one entry per item, and a date range submits as JSON. A date outside its bounds, a date typed halfway, or a file that is still uploading blocks the submit, as an empty required field does. The Native forms guide has the details.
Server rendering in your framework
Section titled “Server rendering in your framework”@golemui/gui-components/ssr renders the content of the elements on the server, so labels, controls and values arrive in the HTML, styled before any JavaScript runs. The browser takes over the markup it already has.
Installation has the setup for React, Next.js, Angular, Analog, Vue, Nuxt, Lit and Astro. In Nuxt, it is one module:
export default defineNuxtConfig({ modules: ['@golemui/gui-components/nuxt'], css: ['@golemui/gui-components/index.css'],});Dropdowns that search
Section titled “Dropdowns that search”gui-dropdown and gui-multi-dropdown are new. The user types to filter the options, and search-fields says which keys of an object the filter reads. To search on your server instead, add remote-filter: the dropdown fires gui-filter with what the user typed, and you set the matching items.
<gui-dropdown label="Currency" label-field="name" value-field="code" search-fields='["name", "code"]'></gui-dropdown>To change what an option shows, give the dropdown a renderItem function. It returns a template, written with the html tag it receives, so no framework needs to import Lit, and every value in it renders as text:
dropdown.renderItem = (item, { html }) => html`<b>${item.template.symbol}</b> ${item.template.name}`;An option can also render a component of your framework, a React or Angular component for example. The Item renderers guide shows how in each framework, with live demos.
gui-list and gui-multi-list work the other way around: you render the options, with your framework’s markup. The list tells you which items to render through the gui-visible-items-change event, with each item’s id and state. It reports only the items in view and a few on each side, so a list of 10,000 items renders about 15 options.
Accessible, safe and translatable
Section titled “Accessible, safe and translatable”- Accessibility. A field takes its accessible name from its label, and development builds warn about a field without one. Lists, tabs, pickers and dropdowns work with the keyboard. Our tests run axe on every element in the light and the dark theme, and measure the outline of every field against the page, so field outlines keep 3:1 and text keeps 4.5:1. See Accessibility.
- A strict Content Security Policy. Rendered in the browser, the elements run under a strict policy, Trusted Types included. See Strict CSP.
- Markdown you decide to trust.
gui-markdownandgui-markdown-textinsert your parser’s HTML as is, so the parser now returnsSanitizedHtml, a type only a cast creates. The cast sits where you sanitize the HTML, or where you trust its source. - Translations.
configureMessages()translates the strings the elements produce: validation messages, accessible names and announcements. See i18n.
Styling that gives way to yours
Section titled “Styling that gives way to yours”Every GolemUI rule now lives in a golemui.* cascade layer, so CSS of your own wins without matching the specificity of ours:
gui-button button { border-radius: 0;}The --gui-* tokens theme everything, data-theme="dark" or "auto" switches to dark mode, and the optional Clay theme is one more stylesheet. The Styling pages cover each one.
How this affects GolemUI Forms users
Section titled “How this affects GolemUI Forms users”Form definitions are backward compatible. Every 1.x definition, stored JSON included, loads and renders in 2.0, and the props that changed keep working as deprecated aliases. GolemUI Forms render the same elements, so the accessibility and styling work above reaches your forms without a change to them.
The one change to the definitions is the layout. Grid and Flex become one Grid layout, and Flex is deprecated. In a row, the grid lines up the labels, controls and errors of the fields side by side, so an error message never pushes the controls next to it.
gui.layouts.horizontalGrid([firstName, lastName]);gui.layouts.grid([street, city, zip, country], { columns: 'auto' });gui.layouts.horizontalGrid([cancel, save], { justify: 'end' });columns makes a grid that wraps, with 1 to 12 columns or as many as fit. gap takes steps from none to xl instead of pixels, and justify: 'end' puts the buttons on the right. Every grid stacks its children when the form is narrower than 480px. The Grid page has every prop.
Flex layouts still render, as a grid, so you can move a form to the new props the next time you edit it. One layout looks different: a grid without direction now stacks its children, and direction: 'row' keeps the row. From 1.x to 2.0 shows each change with the definition before and after.
Other changes
Section titled “Other changes”- Date-time fields have a time label.
timeLabelnames the time part of the date-time calendar and picker. - Tabs use the keyboard. The arrow keys, Home and End select a tab, in every framework.
- Accordion sections are native
<details>. - A read-only select stays focusable, with
aria-readonly, instead of being disabled. - The MCP server and the agent skill know the grid layout and the markdown parser contract.
Upgrading
Section titled “Upgrading”A few changes need your attention when you upgrade:
- Upgrade every
@golemui/*package to 2.0.0 at once. - Import
@golemui/gui-shared/forms.cssafter@golemui/gui-components/index.css. - Check your global CSS resets: a plain
button { … }rule now wins over GolemUI’s styles. - A
gridwithoutdirectionnow stacks its children. Adddirection: 'row'to keep a row. - If your custom widgets listen to
gui-*elements, their events now start withgui-. - In TypeScript, your markdown parser returns
SanitizedHtml.
From 1.x to 2.0 walks through each change for GolemUI Forms, with the code before and after. GolemUI Components’ guide to 2.0 does the same for code that uses the elements directly. The full list of changes is in the changelog.