hayleigh-dot-dev/elm-lustre-ui/1.0.0

elm-lustre-ui

A collection of unstyled, primitive Web Components built with Lustre.

Example

toggle : String -> String -> Html message
toggle label symbol =
    Lustre.Ui.Tooltip.view [ Lustre.Ui.Tooltip.delay 300 ]
        (Lustre.Ui.Tooltip.popover
            [ Lustre.Ui.Tooltip.side Lustre.Ui.Tooltip.Top
            , Lustre.Ui.Tooltip.offset 10
            ]
            [ Html.text label ]
        )
        (Lustre.Ui.Tooltip.trigger []
            [ Lustre.Ui.Toggle.view
                [ Lustre.Ui.Toggle.default_pressed defaultPressed ]
                [ Html.span [] [ Html.text symbol ] ]
            ]
        )

Philosophy

Most other frontend ecosystems have one or more "headless" component libraries that focus on providing unstyled, accessible primitives that design systems and applications can be built on top of.

Here are some of the high-level goals I have for lustre/ui and these bindings:

  • A focus on accessibility and usability, meaning correct ARIA attributes (where appropriate) and considered keyboard interactions.

  • No ports or additional JavaScript interop. This library should feel like an extension of the platform, using typical attributes and events for communication, and no exotic hacks or backdoors for working around Elm's design.

  • "Low level" HTML-like API that feels like existing HTML elements. This should allow more-opinionated libraries or application code to build their own abstractions on top of these primitives.

  • Provide a faster-moving release cycle while the underlying lustre/ui package is in active development. Hopefully this means getting some good feedback and iteration on the API 💕.

Installation

In order to use this package you'll also need to grab the JavaScript that registers the Web Components and make sure it runs before your Elm app starts. You can find both a regular and minified bundle in the assets/ directory of this package on GitHub.

Once copied into your project, it's important to make sure the JavaScript is run before your Elm app starts. The module will automatically register the Web Components when it's important, so it is enough to just import the script in your main JavaScript entry point.

Here's what it looks like in our elm-book app:

import "../../assets/ui.js";
import "./storybook.css";
import { Elm } from "./Main.elm";

Elm.Main.init({ node: document.body });

If you'd prefer to build the JavaScript bundle yourself, you can do so by cloning the Gleam repo and running: gleam run -m lustre/dev build lustre/ui

Note: Lustre's dev tools run on Gleam's Erlang target so you'll need a recent distribution of Erlang installed to do this. It would also be possible to produce this bundle with JavaScript tools like esbuild or rollup, but I'm not able to provide support if you choose to go that route.

Contributing

The best way to contribute is to help find and report errors, or to suggest improvements. I'm not sure I have the bandwidth to support code contributions right now, but if you're curious you can take a peek at the base repo:

https://github.com/lustre-labs/ui/tree/hayleigh/headless-redux-redux

AI disclosure

This package is an automated port of lustre/ui using both traditional code generation and generative AI. The implenentation of the Web Components themselves, all the documentation, and the design of the public API were hand-written without the use of AI.

The documentation and the public API for the port were automatically generated using the codegen program included in this repo. This works by taking the "package interface" produced by Gleam and scaffolding out corresponding Elm modules with the same API and documentation.

The implementation of the public API in this package was largely generated by AI by pointing it at the original Gleam source code and tasking it to translate it into Elm. That means the Elm elements, attributes, and event handlers for each Web Component were generated by AI, but not the functionality itself.

For some folks, any use of generative AI will be a dealbreaker. This disclaimer is for those that want to make sure they are not pulling in a vibe-coded project of questionable quality or ownership.