Published on

Building UI Components at Etiqa: Lessons from Storybook, CSS-in-TS, and Why We Didn’t Use Tailwind

Authors
  • avatar
    Name
    Haikal Tahar
    Twitter

Introduction

Spent a year at Etiqa building UI components in React. Used Storybook as our playground and chose CSS-in-TS over Tailwind. Here's what worked, what sucked, and what we learned from open-source giants like shadcn/ui, Radix UI, and Mantine.

Table of Contents

Tech Stack

  • React + Storybook for all UI work
  • CSS-in-TS using styled-components / vanilla-extract (depends on context)
  • No Tailwind and here’s why ↓

Why CSS-in-TS Instead of Tailwind?

Reasons We Chose It

  • Props + styles in the same file = better co-location
  • Dynamic styling (based on props/state) was easier
  • Theme-aware design tokens integrated well (colors, spacing, breakpoints)
  • Better control over specificity vs utility classes

What Inspired Us

  • Looked at how shadcn/ui, Radix, and Mantine structured components
  • Noticed most of them abstracted styling logic cleanly
  • Wanted similar control + flexibility
  • Didn’t want to fight Tailwind on edge cases

Example

// button.tsx
export const Button = styled.button(({ variant, theme }) => ({
  backgroundColor: variant === 'primary' ? theme.colors.blue : theme.colors.gray,
  padding: theme.spacing.md,
  borderRadius: theme.radius.sm,
}))

vs

// tailwind version
<button className="rounded bg-blue-500 px-4 py-2" />

Pain Points

High Maintenance Cost

  • Every style change = component rebuild + Storybook test + app re-check
  • Theming logic sometimes too abstract
  • Onboarding new devs took longer without Tailwind familiarity
  • Too much friction: changes required writing changesets, going through strict PR reviews, and fixing linter/style/test issues just to tweak a button
  • Some devs ended up building their own components instead of reusing Etiqa UI, easier than dealing with the overhead

Design-Token Drift

  • Needed good sync between design tokens and component logic
  • If design team changed a spacing or color token, had to update in multiple places

Scaling Problems

  • Every new component added more surface area to maintain
  • Needed strict PR reviews to avoid styling hacks creeping in

Takeaways

What We’d Do Again

  • Co-located styles and logic helped long term
  • Storybook was essential to help catch bugs early
  • CSS-in-TS gave us full control over themes + props

What We’d Reconsider

  • Tailwind + shadcn might be a better middle ground now
  • Less setup, better DX, more community support
  • CSS-in-TS shines when you need deep control but that comes with a price

Conclusion

  • Building a component library looks simple on the surface.
  • But once you go past buttons and modals, it gets complex fast theming, tokens, docs, consistency, accessibility, etc.
  • Our CSS-in-TS setup worked for us at Etiqa, but wouldn't recommend it blindly. Evaluate your needs, your team, and your appetite for long-term maintenance.