- Introduction / motivation / context
- Talk about TailwindCSS
- Talk about TailwindUI
- Talk about making an ember app/addon to provide some TWUI components
I (jacobq) care about good UI/UX but am admittedly not great at making them from scratch.
Plus, I'm often in situations where I don't have the luxury of a designer to help me (without resorting to begging).
In the past I've leaned on things like
Bootstrap,
MaterializeCSS, or
ember-paper
.
These aren't bad tools. They can certainly save time and lead to UIs that aren't awful.
However, they all suffer from the problem that they are difficult to customize beyond some predefined level
(e.g. color palettes, themes, etc.).
This can be a problem if you need to match branding guidelines, need something the kit doesn't provide, or simply don't like the way something looks.
This is a major part of the motivation for TailwindCSS, yet in trying not to "do too much" TailwindCSS puts much of the burden of design
back on its users, which makes it less attractive for solving the problem I originally mentioned.
Aims to be "A utility-first CSS framework for rapidly building custom designs." "With Tailwind, you style elements by applying pre-existing classes directly in your HTML [rather than writing CSS]" https://tailwindcss.com/docs/utility-first
When I first saw that I thought, "Wait, wait, won't this lead to lots of duplication?"
I didn't see it as any different than simply applying style="..."
attributes to elements.
I also didn't like the idea of yet another thing to learn/remember (e.g. mx-auto py-2
for margin-x: auto;
& padding-y: 2
).
Additionally, ember-cli
's ember serve
command supports automatically reloaded style changes without refreshing the page,
so an argument about "flipping back and forth between HTML and CSS" probably wouldn't inflence me much.
However, there are a number of reasons why Tailwind's approach has stopped bothering me now:
- Nowadays we aren't manually putting together lots of HTML documents. We are writing templates. This is usually even true for static, non-JS pages as they are typically created by static-site generators. Hence it should be feasible to confine any duplication that occurs to the rendered output, not in the source code. https://tailwindcss.com/docs/extracting-components
- In my experience, it's not uncommon to write CSS rules that apply to only one element. So is CSS adding much value in that case vs. inline styling? Not really.
- It's more than just writing CSS as class names on HTML elements. It offers a lot of additional features, such as theming and plugins.
How do I use Tailwind with Ember?
This is actually confusing, because one might be inclined to suspect that ember install ember-cli-tailwind
would be the recommended approach.
Unforunately, ember-cli-tailwind
(video) was deprecated about a year ago.
Does that mean you have to wire it up from scratch? Thankfully not, but you will need to get familiar with PostCSS.
PostCSS is a "tool for transforming CSS with JavaScript" (https://postcss.org/), and Tailwind uses it.
Another relief is that you can ember install ember-cli-postcss
and there're also plenty of examples,
e.g. https://github.com/chrism/emberjs-tailwind-purgecss
Bills itself as:
Beautiful UI components, crafted by the creators of Tailwind CSS. Fully responsive HTML components, designed and developed by Adam Wathan and Steve Schoger.
Basically, it's an organized collection of examples/solutions for various UI tasks written in HTML using TailwindCSS.
If you want to learn more you then checkout the website, watch their videos, etc.
https://vimeo.com/393580241/82c6d7c5f6
The most direct way to get started is to create a new ember application, install ember-cli-postcss,
and simply start copying and pasting markup from TWUI into components as you make them with ember generate component ...
.
In fact, that is what I did when I started using TWUI for the first time (out of laziness & a need to slap together a demo quickly).
This isn't ideal though, for a couple reasons:
-
We would like to minimize the amount of "wheel reinventing" and "boilerplate code" we need to write. Many components have interactivity, described in the HTML comments but not implemented. It is very likely that every time we copy/paste from TWUI we'll need to write some JS to make the thing work right.
-
If you have custom branding, style guides, etc. then it's likely you'll also have more than one application, and you'll definitely want to be able to share common components amongst them. Unless care is taken, this direct approach will lead to duplice code, an enemy of robust, maintainable software.
The conventional solution to this is to make an ember addon. Indeed, I believe this is probably the best path for this also though I haven't attempted it yet (need to think a little more about how to best deal with PostCSS setup and tailwind config first). I'm also planning to watch and learn from how the developers at Tailwind Labs go about making React and Vue components. Perhaps eventually I and others from the Ember.js community can help get a similar solution in place for TWUI and Ember.
For now, let's pretend you're trying to start a small business and want to make a single, smallish app quickly, but you hope to grow someday so don't want to paint yourself into a corner. It is relatively easy to move Ember.js components from one application or addon to another, and this provides us with some justification for not splitting everything out from the get-go.
Side-note: I'd be curious to hear people's opinions about monorepos in the chat.
- In favor
- Opposed
- Mixed/Neutral/Other
so for better or for worse we can feel OK provides some justification for the decision allows us to feel OK about having the (or at least gives )
Note: In case it's not obvious, you can use npm
instead of yarn
, if you want.
I (jacobq) am using yarn
out of personal preference.
ember new ember-tailwindui-demo --yarn --no-welcome
cd ember-tailwindui-demo
ember install ember-cli-postcss
yarn add postcss-import tailwindcss @tailwindcss/ui @tailwindcss/typography typeface-inter
- We need to configure the
postcssOptions
and bring in the "Inter" font, which we do by editing theember-cli-build.js
file. This part gets a little tricky when building an addon instead. - Configure our project to run TailwindCSS processing.
Create
config/tailwind.config.js
(if you prefer, you can locate this somewhere else likeapp/tailwind/config.js
) and add the TailwindCSS postcss plugin to our list inpostcssOptions
inember-cli-build.js
. - Take an example "UI Shell" and make refactor it as ember components.
We won't worry about making the logic/interactivity work yet, just get markup in appropriate places
ember g component nav/main
ember g component-class nav/main
ember g component nav/mobile
ember g component-class nav/mobile
ember g component nav/menu
ember g component-class nav/menu
ember g component nav/header
- Create a controller and service so we can store content there instead of in the components.
The point is to extract parts of ember components that doesn't match their responsibilities.
We want them to be reusable / general purpose.
e.g. some other app might be getting this content via
fetch
orember-data
We'll also add basic debug logging support.ember g controller application
ember g service local-data
yarn add debug
- Refactor nav components to take data from outside instead of hard coding.
ember g route feature
ember g route table
ember g route settings
ember g route sign-out