DEV Community

Cover image for I ported shadcn/ui to modern Ember.js
Ignace Maes
Ignace Maes

Posted on

I ported shadcn/ui to modern Ember.js

About a week ago, I made shadcn-ember public. It is an unofficial, community-led port of shadcn/ui for Ember.js.

If you are not familiar with shadcn/ui, the short version is: you copy component code into your project instead of installing it as a dependency. You own the source. You can change anything. No more fighting with library APIs or overriding styles with !important.

I wanted that for Ember. So I (and Claude) built it.

What is this, exactly?

It is a collection of 47 components: buttons, dialogs, dropdowns, tooltips, toasts, sliders, tabs, sidebars, and more. All built for modern Ember (Glimmer components, .gts files, tracked properties).

The components are styled with Tailwind CSS v4 and use CSS variables for theming. You can customize colors, border radius, and dark mode out of the box.

There is also a CLI that handles the "copy and paste" part for you.

How it works

1. Set up your project

Run the init command. It installs dependencies, sets up the Tailwind config, and adds the cn utility for class merging.

npx shadcn-ember@latest init
Enter fullscreen mode Exit fullscreen mode

You will get a few questions: which style, which base color, whether to use CSS variables. Pick what you like.

2. Add a component

npx shadcn-ember@latest add button
Enter fullscreen mode Exit fullscreen mode

This puts a button.gts file in app/components/ui/. It looks like this:

import { hash } from '@ember/helper';
import Component from '@glimmer/component';
import { cn } from '@/lib/utils';

// ... types and variants

class Button extends Component<ButtonSignature> {
  get classes() {
    return buttonVariants(
      this.args.variant ?? 'default',
      this.args.size ?? 'default',
      this.args.class
    );
  }

  <template>
    <button class={{this.classes}} ...attributes>
      {{yield}}
    </button>
  </template>
}

export { Button, buttonVariants };
Enter fullscreen mode Exit fullscreen mode

It is just a Glimmer component. Nothing special. You can read it, understand it, and change it.

3. Use it

import { Button } from '@/components/ui/button';

<template>
  <Button @variant="outline">Click me</Button>
</template>
Enter fullscreen mode Exit fullscreen mode

That is it.

Other CLI commands

There are a few more commands if you need them:

  • npx shadcn-ember@latest add dialog toast tabs adds multiple components at once
  • npx shadcn-ember@latest view button shows you the component code before you add it
  • npx shadcn-ember@latest build generates registry JSON if you want to host your own component registry

Installation options

The docs cover setup for:

  • Vite (recommended for new projects)
  • Astro
  • Manual (if you want to set things up yourself)

All install guides are at shadcn-ember.com/docs/installation.

Why I made this

Ember has always valued stability and conventions. But when it comes to UI, we have been a bit behind. I wanted to bring the same "open code" approach that has worked so well in other ecosystems.

The original shadcn/ui project has a clear philosophy: you should be able to read, understand, and modify your UI code. That resonated with me, and I think it fits well with how Ember developers like to work.

This is an ongoing project. There are more components to add, edge cases to handle, and docs to write. Contributions are welcome.

Links

Let me know what you think. I am curious to hear how it works in your projects.

Top comments (0)