A collection of professionally designed, every day UI components built on a framework-agnostic technology. πŸ₯Ύ

  • By Shoelace
  • Last update: Jan 8, 2023
  • Comments: 16


A forward-thinking library of web components.

  • Works with all frameworks 🧩
  • Works with CDNs πŸš›
  • Fully customizable with CSS 🎨
  • Includes an official dark theme πŸŒ›
  • Built with accessibility in mind ♿️
  • Open source 😸

Designed in New Hampshire by Cory LaViska.

Documentation: shoelace.style

Source: github.com/shoelace-style/shoelace

Twitter: @shoelace_style

Shoemakers πŸ₯Ύ

Shoemakers, or "Shoelace developers," can use this documentation to learn how to build Shoelace from source. You will need Node >= 14 to build and run the project locally. It is preferred, but not required, to use npm 7.

You don't need to do any of this to use Shoelace! This page is for people who want to contribute to the project, tinker with the source, or create a custom build of Shoelace.

If that's not what you're trying to do, the documentation website is where you want to be.

What are you using to build Shoelace?

Components are built with LitElement, a custom elements base class that provides an intuitive API and reactive data binding. The build is a custom script with bundling powered by esbuild.

Forking the Repo

Start by forking the repo on GitHub, then clone it locally and install dependencies.

git clone https://github.com/YOUR_GITHUB_USERNAME/shoelace
cd shoelace
npm install


Once you've cloned the repo, run the following command.

npm start

This will spin up the Shoelace dev server. After the initial build, a browser will open automatically. There is currently no hot module reloading (HMR), as browser's don't provide a way to reregister custom elements, but most changes to the source will reload the browser automatically.

The documentation is powered by Docsify, which uses raw markdown files to generate pages. As such, no static files are built for the docs.


To generate a production build, run the following command.

npm run build

Creating New Components

To scaffold a new component, run the following command, replacing sl-tag-name with the desired tag name.

npm run create sl-tag-name

This will generate a source file, a stylesheet, and a docs page for you. When you start the dev server, you'll find the new component in the "Components" section of the sidebar.


Shoelace is an open source project and contributions are encouraged! If you're interesting in contributing, please review the contribution guidelines first.


Shoelace is designed in New Hampshire by Cory LaViska. It’s available under the terms of the MIT license.

Designing, developing, and supporting this library requires a lot of time, effort, and skill. I’d like to keep it open source so everyone can use it, but that doesn’t provide me with any income.

Therefore, if you’re using my software to make a profit, I respectfully ask that you help fund its development by becoming a sponsor. There are multiple tiers to choose from with benefits at every level, including prioritized support, bug fixes, feature requests, and advertising.

πŸ‘‡ Your support is very much appreciated! πŸ‘‡

Whether you're building Shoelace or building something with Shoelace β€” have fun creating! πŸ₯Ύ




  • 1

    RFC: i18n

    It's time to start thinking about i18n. This discussion will be scoped to localization, whereas #191 will focus on RTL support.

    There is a need for common labels in components that need to be localized. An example is in dialog/drawer/tab/tag, which all feature a built-in close button. Currently, the buttons don't have a label so screen readers don't announce them properly.

    Important: I don't expect there to be many terms, nor do I want users to rely on Shoelace to power their app's localization. At this point in the library's development, a simple solution is preferred over a robust one.

    Updated to reflect new requirements and information.

  • 2

    feat: add new tree-view component

    This PR adds a Tree and TreeItem components that allow user to display a hierarchical list of items, expanding and collapsing the nodes that have nested items.

    The sl-tree component implements the API to interact with the whole tree, like the selection and the keyboard navigation. It has just a default slot that can contain sl-tree-item components, that represent the nodes of the tree.

    Each sl-tree-item can in turn contain other sl-tree-item, allowing to the user to define nested trees. A tree item with nested nodes, can be expanded and collapsed.

    Closes #539

    Code example

          Parent Node
          <sl-tree-item>Child Node</sl-tree-item>


    Screenshot from 2022-07-23 10-10-58

  • 3

    Handler violations when using SL with SvelteKit

    Describe the bug

    I'm running into handler violations where event handlers took too much time to return (for instance focusinof modals and drawers taking seconds to process).

    To Reproduce I made repro repo available here https://github.com/brgrz/sl-bugs

    Steps to reproduce the behavior:

    1. Clone the repo
    2. Run npm i
    3. Run npm run dev, it will run the SvelteKit app at http://localhost:3000
    4. Open Chrome + devtools, in Devtools->Console tab->select All issues (or Verbose)
    5. Open the app, click the Open drawer button
    6. Inside the drawer try clicking around on the whitespace, try clicking into the input and then onto the whitespace and so forth
    7. You should be seeing instances of [Violation] 'focusin' handler took 6519ms in the Console (while this happens, the app will freeze preventing you to click on anything else)

    Expected behavior No freezes, no violations/timeouts

    Desktop (please complete the following information):

    • OS: Windows 10
    • Browser Chrome, Edge, both latest BUT was unable to reproduce this in Firefox
  • 4

    2.0: Back to the basics (again)

    TL;DR – now that browser support has improved for custom props and CSS grid, Shoelace 2.0 will go back to its roots and once again be highly customizable without the need for any sort of build process.

    As Shoelace evolved, it became clear that we weren't quite ready for certain CSS features in production. I feel I was a bit too premature with pushing Custom Properties and CSS Grid Layout when Shoelace was released back in July, but I think we're ready to move these features to the mainstream.

    Edge 16 was released on October 16, and with it brings full support for Custom Properties and CSS Grid Layout. This doesn't include IE11, but I'm OK with that at this point.

    Here's what I'd like to do moving forward:

    • [ ] Remove all cssnext-specific features so you don't have to build Shoelace to use it.
    • [ ] Rework the build process so the dist contains custom properties. This will make Shoelace easier to use and, once again, customizable via CDN.
    • [ ] Split variables into their own component files again, making Shoelace much more modular and extensible. For example, you'll be able to include a single third party .css file that inherits your theme/component styles automatically, even from a CDN!
    • [ ] Address #12 by requiring component classes (e.g. <button class="btn">) for default components. My updated thoughts on this: styling is easier, implementing is easier, and the "namespace" has some benefits.

    This is a bit of a backpedal, but I think it's finally time. Of course, this will introduce a breaking change in terms of browser support, so the new version will be 2.0.


  • 5

    Create React App doesn't work out of the box with Shoelace

    UPDATE: The original issue mentioned below has been resolved, but a new issue was uncovered regarding Create React App + Shoelace. See below for more details.

    Jump to the latest issue πŸ‘‡

    View original issue

    Describe the bug

    After updating to 2.0.0-beta.86, getting import error (probably due to recent package.json exports field changes, using vite 3.2.5).

    Importing like this:

    import { SlButton } from "@shoelace-style/shoelace/dist/react";

    Produces this error:

    Internal server error: Missing "./dist/react" export in "@shoelace-style/shoelace" package

    This can be fixed by changing the import to this:

    import { SlButton } from "@shoelace-style/shoelace/dist/react/index.js";

    Possible solutions

    1. Update documentation to use the '@shoelace-style/shoelace/dist/react/index.js' import
    2. Might be able to maintain current behaviour by modifying the package.json exports field to add this:
        "./dist/react": "./dist/react/index.js",
    1. Could output a ./dist/react.js file, add that to the exports and import using @shoelace-style/shoelace/dist/react.js
  • 6

    Style tag injected into document head

    Describe the bug

    Importing a shoelace component inserts a <style> tag into the document <head>.

    If shoelace components are being used in a shadow root, then this style won't have any effect.

    Would it be possible to include these styles in the default stylesheet instead?

    (I see it used to be in https://unpkg.com/browse/@shoelace-style/[email protected]/dist/themes/base.css, but now it's a separate and automatically inserted into the <head> from https://unpkg.com/browse/@shoelace-style/[email protected]/dist/styles/component.styles.js).

    This isn't strictly causing a problem because the class names are unique enough, but I did find it a little odd and seemingly unnecessary, and it violates the principle of encapsulation.

    To Reproduce

    import '@shoelace-style/shoelace/dist/components/dialog/dialog.js';

    Observe new style tag in head:

      .sl-scroll-lock {
        overflow: hidden !important;
      .sl-toast-stack {
        position: fixed;
        top: 0;
        right: 0;
        z-index: var(--sl-z-index-toast);
        width: 28rem;
        max-width: 100%;
        max-height: 100%;
        overflow: auto;
      .sl-toast-stack sl-alert {
        --box-shadow: var(--sl-shadow-large);
        margin: var(--sl-spacing-medium);
  • 7

    sl-datepicker component

    Added the sl-datepicker component to shoelace library. ~~This pull request don't include the component doc~~. Fixed timezone issue with date https://github.com/shoelace-style/shoelace/issues/467#issuecomment-870958811

    Other relevant commits:

    1. package.json added node engine constraint to support optional chaining operator (node >= 14)
    2. type safe emitter
  • 8

    RTL Support via Logical CSS Properties

    Is your feature request related to a problem? Please describe. Internationalization and the adaptation of UTF-8 became a necessity for Multilanguage apps. a support for RTL in shoelace in its early stage in development will be great added advantage for developers.

    Describe the solution you'd like is it possible to put it under consideration while the project still in its alpha. As RTL support is lacked from many frameworks including Bootstrap.

    Describe alternatives you've considered using custom css on top of shoelace. please consider this site https://rtlcss.com/playground/

  • 9

    Tree shake big bundle size

    I'm trying the amazing Shoelace for the first time today.

    I'm working on a project with Rollup.

    Everything works and is amazing.

    One thing I don't like though.

    Just adding the following lines of code to my project increases it by 232 KB (from 747 KB to 979 KB) javascript side only.

    import { SlButton } from '@shoelace-style/shoelace'
    customElements.define('sl-button', SlButton)


    If I use this instead it increases by 383 KB (from 747 KB to 1130 KB).

    import { defineCustomElements } from '@shoelace-style/shoelace'


    As you can see from the images we have @stencil/core/internal/client/index.js of ~ 16 KB. Is it really needed?

    Is it really necessary to have those 232 KB all together? Can we tree-shaking?

  • 10

    Chrome freezes when dropping down select

    Describe the bug

    Under certain conditions, if the dropdown of an SlSelect is dropped down, Chrome will freeze in an infinite loop.

    To Reproduce

    Steps to reproduce the behavior:

    1. Go to https://codepen.io/oliversalzburg/pen/VwQdYgO?editors=1100
    2. Drop down the lists one after another until one makes the browser freeze

    If this doesn't happen, go into Responsive Design mode and reduce the viewport size as shown below.



    Browser / OS

    • OS: Windows
    • Browser: Chrome
    • Browser: 102.0.5005.63

    Additional information

    This doesn't seem to happen in Firefox. From what I could tell, this seems to be an infinite loop in https://github.com/floating-ui/floating-ui

  • 11

    sl-details open="true" fails in beta.28+

    Describe the bug Loading a sl-details with it's body open on init worked prior to beta.28. See this video: shoe-height

    Frombeta.28 on it's initialized with only a portion of the body content visible. On subsequent open/close class it's fine: shoe-height-broken

    Expected behavior Inits with body content fully visible with open="true".

    Desktop (please complete the following information):

    • OS: Web
    • Browser Chrome
    • Version 88
  • 12

    `` triggers click/tap events

    Describe the bug

    <sl-menu-item disabled> is ignored. Tested in versions .88β†’.61 (likely goes further past).

    To Reproduce

    Steps to reproduce the behavior:

    1. Go to https://sl.rt.ht/1113/?io
    2. Click/tap on Option 2 in the output panel
      • ❌ <sl-menu-item disabled> is ignored!
    3. Click/tap on Button or SlButton
      • βœ”οΈ <β‹― disabled> prevents event.


    See above.



    Browser / OS

    • OS: all
    • Browser: all
    • Browser version: all

    Additional information

    Discovered while adding support for <sl-menu-item inert> in https://github.com/shoelace-style/shoelace/issues/1107#issuecomment-1374806787

  • 13

    Export `assets/icons/*` from package

    What issue are you having?

    A bit of an obscure use case, but: I like to import some of the icons directly as raw SVG to use them directly in the code without depending on external files.

    // I can import the raw SVG as a string using vite like this:
    import iconBold from "@shoelace-style/shoelace/dist/assets/icons/type-bold.svg?raw"

    However, dist/assets/icons/* ist not part of the exports field in package.json, so vite rejects importing it. For Vite, this is intended behaviour and they won't change it.

    Describe the solution you'd like

    I'd like to simply adjust Shoelace's package.json to export the icons.

    Describe alternatives you've considered

    Right now, I am manually changing Shoelace's package.json, which is not great on many levels.

  • 14

    Document remaining design tokens

    Many 2.0 design tokens have been documented already, but there are a lot that haven't. I propose adding a new page in the docs for miscellaneous tokens with name and descriptions, including tips on how to style common things such as button/input heights.

  • 15

    Improve Tests

    Before 2.0 stable lands, more tests are needed. Any help here will be appreciated, as I'm currently doing this solo.

    • [ ] Audit existing tests to identify which components need more tests, which tests need to be improved, and which ones are good to go
    • [ ] Improve consistency of existing tests
      • A lot of contributors have pitched in to help with testing. Unfortunately, this introduced multiple ways to do the same thing. It would be nice to refactor them to improve consistency and maybe even document the preferred way to test various things in docs/resources/contributing.md

    I don't care about the number of tests or even coverage β€” I care about sensibility and making sure the important things are covered.

    If you plan on assisting with this, please post below so we can coordinate. Thanks!

  • 16

    Tests are currently failing on Windows

    To repro, run the following on a Windows machine not using WSL:

    npm install @shoelace-style/shoelace
    cd shoelace
    npm i
    npm run build
    npm run test

    This was reported by a user and also fails on my Windows machine. Apologies, but I don't have the error handy to paste here.