Stencil Elm Output Target for typesafe web components

Introducing stencil-elm-output-target, a plug-in for Stencil, a TypeScript-based toolchain for building web components:

React in TypeScript is nice. Elm is very nice. If you’re like us, you have a lot of both, and you need to build a sustainable component library for your design system. Web components to the rescue!

The problems with web components in React are well documented, but are also well solved by Stencil’s React Output Target, which auto-generates a React component with TypeScript types for each of your web components, that manages the interop between React’s events system and DOM events.

Web components in Elm have problems too:

  • They provide no type-safe API out of the box
  • Invoking methods on DOM nodes requires ports, which have friction (by design, as this buys you compiler guarantees)
  • Component properties must be serializable as JSON (e.g. no functions)

This package seeks to solve as many of these problems as possible, by generating an Elm module for each of your Stencil components, that defines a type-safe API to use it in your Elm programs.

So instead of using a stencil-button element like this:

view : Html Msg
view =
    Html.node "stencil-button"
        [ Html.Attributes.attribute "variant" "primary"
        , Html.Events.on "buttonClick" (Json.Decode.succeed ButtonClick)
        ]
        [ Html.text "Click me" ]

you can import Components.StencilButton and have the compiler guarantee that you’re passing all the right attributes:

import Components.StencilButton as StencilButton

view : Html Msg
view =
    StencilButton.view
        { variant = Just StencilButton.Primary
        , onClick = Just ButtonClick
        }
        [ Html.text "Click me" ]

The StencilButton module here is automatically generated by Stencil when you build your component library.

Nice, right?

We’re looking forward to using this to enable our UI components to own just a little bit of their own view state when we want them to, and to being able to use them in both our Elm and React codebases (and who knows what else in the future!).

For a more detailed list of the supported component API features, and a description of the caveats of this initial version, check out the README.

19 Likes

So good man – thank you!

I have been creating a few “vanilla web components” these last few days to use in an Elm app. I will definitely try Stencil + this package to see how much it improves my dev experience.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.