Completely unstyled and fully accessible UI components for Phoenix Framework.

Sprout UI provides a collection of common UI components, which are completely unstyled and are built following the WAI-ARIA guide, to help you easily build your own design systems and rich web applications with Phoenix and LiveView.

Renderless function components

Sprout UI component does not render any visible HTML tags. It only controls user interactions and related UI states with an underlying custom element. It is your responsibility to decide how to render the component, and all you need to do is just passing attributes to the tags you're rendering. You can see the flexibility of renderless component from the example code.

<Overlay.dialog :let={api}>
  <button class="button" {api.trigger_attrs}>Open</button>

  <div {api.container_attrs}>
    <div class="backdrop" {api.backdrop_attrs}></div>
    <div class="dialog" {api.panel_attrs}>
      <h2 {api.title_attrs}>Dialog</h2>
      <p {api.description_attrs}>...</p>
      <button class="button" {api.close_button}>&times;</button>
    </div>
  </div>
</Overlay.dialog>
WAI-ARIA compliant components

Sprout UI follows the WAI-ARIA guide to create accessible web experiences. It fully supports assistive technology like screen readers and keyboard navigations. Try using Up Down Home End to navigate through the accordion items and using Enter or Space to expand/collapse the accordion item.

Styling components made easy

Since you're in control of rendering all the HTML tags, you can choose whatever styling methods you like. Every component is composed of different parts rendered with a data-part attribute so that you can style each part using CSS atribute selector. And when a component can have multiple UI states, these states are presented in a data-state attribute. Sprout UI also comes with a tailwindcss plugin that makes it easier for styling different UI states.

<Input.switch :let={api}>
  <button
    class="ui-checked:bg-emerald-500 ui-unchecked:bg-gray-200"
    {api.track_attrs}
  >
    <span
      class="ui-unchecked:translate-x-[3px] ui-checked:translate-x-[33px]"
      {api.thumb_attrs}
    >
    </span>
  </button>
</Input.switch>