TunkShif

TunkShif

Sprout UI provides a collection of common UI components. All of these components are completely unstyled, and they are built following the WAI-ARIA guide to be accessible.


Currently, it is not ready for a stable release yet, but I just can’t wait to share the progress I’ve made and get some feedback. Check out the links below for more information.

Website (including documentation and component demos) | Github Repo


Design goals for Sprout UI:

renderless function component

If you’ve never heard about this concept, it’s highly recommended to check out this informative blog post by @LostKobrakai . Also check out libraries like Downshift JS and Zag JS in front-end world.

A renderless function component does not render any visible HTML tags, but just provides necessary context information for rendering. And it is the user’s responsibility to decide what component structure should be rendered like.

For example, a simple dialog component is used like this:

<.dialog :let={api}>
  <button {api.trigger_attrs}>Open modal</button>

  <div {api.container_attrs}>
    <div {api.backdrop_attrs}></div>
    <div {api.panel_attrs}>
      <h2 {api.title_attrs}>Dialog</h2>
      <p {api.description_attrs}>...</p>
    </div>
  </div>
</dialog>

The component itself won’t render any HTML structures for your dialog, but just takes care of all the needed attributes for user interactions and accessibility.

no unnecessary round-trip to server for user interactions

Under the hood, Sprout UI components are using custom elements for handling user interactions like clicking or keyboard events. You won’t need to communicate to the server-side just for opening a modal or toggling an element.

And it can be used with LiveView or just plain server-side rendered templates withour LiveView.

styling and transition made easy

Generally, a Sprout UI component is composed of multiple component parts. For example, the dialog example above may eventually rendered like some HTML structures like this:

<sp-dialog data-state="open">
  <button data-part="trigger">Open modal</button>

  <div data-part="container">
    <div data-part="backdrop"></div>
    <div data-part="panel" aria-attributes>
      <h2 data-part="title">Dialog</h2>
      <p data-part="description">...</p>
    </div>
  </div>
<sp-dialog>

sp-dialog is a custom element for handling dialog opening/closing interactions and managing focus. Each component part is rendered with a data-part attribute. And for components with multiple UI states, like dialog can be open or closed, the state is presented in a data-state attribute as well. You can use CSS attribute selector to style a component part or a specific state.

[data-part="backdrop"] {
  background-color: #000;
  opacity: 0.6;
}

:where([data-state="open"]) [data-part="backdrop"] {
  /* ... */
}

Also, Sprout UI comes with a Tailwind CSS plugin that makes it easier for styling different UI states using variants. So you can just do things like ui-open:opacity-100 ui-closed:opacity-0.

And Sprout UI provides a transition utility to help you add transitions when a component part entering or leaving in a declarative way. Here is an example of how you can add transitions for a dialog backdrop:

  <div
    data-transition
    data-enter="transition duration-300 ease-in-out"
    data-enter-from="opacity-0"
    data-enter-to="opacity-100"
    data-leave="transition duration-300 ease-in-out"
    data-leave-from="opacity-100"
    data-leave-to="opacity-0"
    {api.backdrop_attrs}
  >
  </div>

Currently I’m still having lots of work to do: writing tests and docs, fixing some existing issues with these components, implementing more common component patterns.

So feel free to try it out yourself and share your ideas!

Showing Posts 1 to 1

teamon

teamon

I took great inspiration from Sprout when deciding on how to build headless, thank you @TunkShif :purple_heart:

— All posts loaded —

Where Next? Top

Trending in Announcing Top

woylie
Flop is an Elixir library that applies filtering, ordering and pagination parameters to your Ecto queries. offset-based pagination with...
New
MRdotB
I needed to reuse React components from my Chrome extension in my Phoenix/LiveView backend. I noticed that for Svelte/Vue, there are live...
New
woylie
I released Doggo, a collection of unstyled Phoenix components. https://github.com/woylie/doggo Features Unstyled Phoenix components....
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
anuaralfetahe
Hello Published a new library - ProcessHub! ProcessHub is a library designed to manage process distribution within the Elixir cluster. ...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
sergio
It’s not that it’s vocabulary is too advanced. It’s something worse. I get lost trying to follow even a paragraph written by Claude. It’...
New
AstonJ
This showed up on my feed.. anyone heard of it? Just hype? Ox Alpha is a reasoning model designed for coding, sustained ag...
New
bartblast
Hey folks, I just published a post about Hologram’s funding and where the project goes next - the short version: Curiosum as Main Spons...
New
sorenone
Today we’re releasing Oban for Python. Not an Oban client in Python. Not a pythonx wrapper embedded in Elixir. Nope, it’s a fully operati...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews