Tiny styled() for Tailwind + React (works with intrinsic elements and custom components)
npm install @hamcker/styled-tailwindTiny, zero-CSS-in-JS styled() for React — write Tailwind classes with a familiar styled-components / emotion API.





What it is: A tiny utility that returns React components from tagged templates of Tailwind classes, just like styled-components/@emotion/styled — but without runtime styles, no style tags, and no Babel plugins. It only concatenates class names.
What it’s not: A CSS-in-JS engine. There’s no style injection or compiler; Tailwind does the styling, you get a clean component API.
—
- Minimal: tiny surface area, no config, no runtime CSS
- Familiar: styled.div...` and styled(Component)... APIsclassName
- Composable: merge incoming + computed classesas
- Typed: full TypeScript inference for intrinsic tags and custom components
- Polymorphic: change the underlying tag via
- React-compatible: works from React 16.8+ (hooks + forwardRef)
- Peer deps: react (>= 16.8), tailwindcss (>= 3)
`with bun
bun add @hamcker/styled-tailwind
Quick Start
`tsx
import { styled } from "@hamcker/styled-tailwind";// 1) Intrinsic element
const MyDiv = styled.div
bg-blue;
// hello -> hello// 2) Props-driven classes
const Box = styled.div<{ primary?: boolean }>
;// 3) Custom component
type FancyProps = { title: string; className?: string; children?: React.ReactNode };
function Fancy({ title, className, children }: FancyProps) {
return (
{title}
{children}
);
}
const StyledFancy = styled(Fancy)
border p-2 shadow;// 4) Polymorphic via
as
const Linky = styled.divunderline;
// link -> link
`$3
- JavaScript requires either a function call or a tagged template; syntax like
styled.divbg-blue is not valid JS.
- This utility mirrors styled-components/@emotion/styled with backticks: styled.divbg-blue.API
-
styled.tag\...\: for any HTML tag, e.g. styled.div, styled.button.
- styled(Component)\...\: wrap your own component.
- Interpolations: plain strings/numbers, falsy (null | undefined | false), or (props) => string | number | falsy.
- className merge: incoming className is concatenated with computed classes.
- Polymorphic: optional as prop to swap the underlying element.
- Ref forwarding: components are React.forwardRef-aware.$3
-
cx(...parts): safe class concatenation.
- compileClasses(strings, exprs, props): turns a tagged template + interpolations into a final class string.TypeScript
- Inference for intrinsic tags and custom components.
- Add prop types:
styled.div<{ primary?: boolean }>.
- as prop is typed as React.ElementType for flexibility.Testing
- Run tests:
bun test
- Tests use Bun’s built-in bun:test and assert on returned React elements.Performance & SSR
- No style sheet manipulation — class strings are computed and attached once.
- SSR works out of the box; output is plain React elements with
className.Comparison
- Like
styled-components or @emotion/styled, but outputs Tailwind classes and doesn’t inject CSS.
- No Babel/runtime styling; bring your own Tailwind setup for styles.Build
-
bun run build outputs ESM (dist/index.js), CJS (dist/index.cjs), and types (dist/index.d.ts`).MIT © Hamcker