Open-source project
garronej/tss-react avatar
garronej/tss-react

tss-react: a type-safe CSS-in-JS layer over Emotion, shaped like JSS

✨ Dynamic CSS-in-TS solution, based on Emotion

727 stars39 forksTypeScriptMIT

At a glance

What is it?
tss-react gives React and MUI applications a JSS-style makeStyles API with TypeScript inference on style objects, layered on top of the Emotion runtime. The trade-off is explicit: dynamic styles mean no React Server Component support.
Who is it for?
tss-react fits teams that already run MUI, want plain CSS syntax with checked property names, and are staying on the classic Next.js router rather than moving to server components. It is the wrong pick for App Router projects that need React Server Components today, or for teams that want to remove CSS-in-JS from the runtime entirely.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 164 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why another CSS-in-JS layer exists when Emotion already ships one

The project's own framing is that tss-react can be thought of as @emotion/jss. The JSS API is a type-safe equivalent of it, powered by Emotion, in the same way @emotion/styled is the styled-components API powered by Emotion. The gap it fills is narrow and real. It targets teams whose MUI v4 code writes `makeStyles` with nested selectors, dynamic values and a `The project's own framing is that tss-react can be thought of as @emotion/jss. The JSS API is a type-safe equivalent of it, powered by Emotion, in the same way @emotion/styled is the styled-components API powered by Emotion. The gap it fills is narrow and real. prefix convention, for whom moving to a different styling API would mean rewriting every style object.

The target audience is therefore a specific migration path: React and MUI applications that want to leave the v4 generation of MUI and `react-jss` behind without rewriting their styling layer, while keeping TypeScript inference over style properties. The project states that using TypeScript in the application is optional, but recommended. The emphasis on plain CSS is deliberate: no custom styling syntax to learn and no shorthand, only standard CSS rules inside a typed object.

It also targets a second audience, library authors. A library that styles its components with tss-react does not need to add tss-react to its peerDependencies, which removes a common source of consumer version conflicts. Whether that matters to you depends on whether you publish a component library at all.

The makeStyles hook reads props and state at render time

The mechanism is dynamic style generation. Styles are produced from the props and internal states of a component, so a style object can branch on values that arrive at render time rather than being fixed when the module loads. This is the feature that separates tss-react from a static CSS file, and it is also the reason the project cannot support React Server Components.

The authoring model is the JSS one: a `makeStyles` hook returns a class name or a props object that the component spreads onto its elements. The nested selector syntax gets a type-safe equivalent of the JSS `$` convention, so a child selector is written in the familiar form but checked against the shape of the style object rather than passed through as raw text.

The project makes a point of where those styles live. The stated preference is that your JSX stays readable, with styles isolated from the component structure instead of interleaved with markup. It also acknowledges the opposite case, saying that sometimes it is easier to inline styles directly within components, and offers that as well. So the layout question is a choice you make per component rather than a fixed constraint of the library.

One more detail worth knowing before you start: the API shape is the JSS shape, so if your team already knows styled-components, the muscle memory transfers to the rule objects, not to the hook.

The Emotion cache stays open, and specificity can be overridden deliberately

Underneath the JSS-style surface sits @emotion/react, and the project lets you freely customize the underlying Emotion cache. That matters for server rendering setups where the cache key, insertion point or container has to be coordinated with the framework, and it is the reason the library can sit inside Next.js in both the App and Page Router.

The second mechanism is precedence control. The project presents this as eliminating CSS priority conflicts, and the mechanism is that with tss-react you can determine the precedence of multiple classes applied to a component and arbitrarily increase the specificity of some rules. When a third-party class lands on the same element and wins the cascade, you can push your own rule above it deliberately instead of resorting to an awkward selector or an inline style.

Bundle impact is stated in the same breath: the library builds on @emotion/react and is said to have very little impact on bundle size alongside MUI, at around 5kB minzipped. For a page already shipping MUI, that is a small addition, though it is still a runtime CSS-in-JS cost on every page that uses it.

For the older the v4 generation of MUI crowd there is also an improved `withStyles` API, described as a way to help migration away from the v4 generation of MUI, which covers the HOC path as well as the hook path.

Dynamic styles rule out React Server Components

This is the project's clearest limitation and it is stated without hedging. Because styles are generated from props and internal state, the library cannot support Server Components in Next.js. The project says it remains hopeful for future support of RSC, contingent on a suitable solution being provided by Vercel and React, and points at the Next.js styling documentation for the current state of that discussion.

If you need RSC support today, the project names two zero runtime alternatives: Panda CSS and Vanilla Extract. The difference in approach is the important part. Both compile styles away ahead of time, so no style-generating runtime ships to the browser and nothing depends on render-time state. The cost the project identifies is expression: complex styles are significantly harder in that paradigm, and the JSS model of deriving a rule from a prop has no direct equivalent once you are writing a static stylesheet ahead of time.

That is the whole trade: give up the ability to compute styles per render, get a runtime-free pipeline and server component compatibility. For a dashboard where a dozen components read the same theme token, runtime generation may be worth it. For a marketing site built in the App Router, it usually is not.

Cloning the repository and running the demo apps

The project publishes to npm under the name tss-react and links its package page from the header, and it points new users at its documentation site through the Get started link. The README itself shows the workflow for working with the source rather than the consumer install, so the commands below are the ones to run if you intend to read the code or try the demo applications.

Cloning, installing dependencies and building puts the compiled output in the dist folder, and the two tsc invocations watch both the CommonJS and the ES module builds:

bash
git clone https://github.com/garronej/tss-react
cd tss-react
yarn
yarn build
npx tsc -w & npx tsc --module es2015 --outDir dist/esm -w

The build script in package.json runs the compiler twice with a second configuration for the ES module output, then runs a ts-node script named shim_jsx_element.ts. After the watchers are running, a second terminal launches one of three demo targets:

bash
yarn start_spa  # For testing in in a Create React App setup
yarn start_ssr  # For testing in a Next.js setup
yarn start_appdir  #  Next.js 13 setup in App directory mode

The three targets correspond to the three rendering contexts the library claims to support, so the app directory mode is the one that shows the server component limitation in practice. The repo also ships a Playground on StackBlitz, linked from the header, which is the fastest way to see the JSX and style object side by side without installing anything.

One package, separate entry points for MUI, Next.js and DSFR

The package.json exports map is the most concrete thing to check before adopting the library, because the integration you need is chosen by import path rather than by configuration. The base entry exposes the main build and the ES module build:

json
    "main": "dist/index.js",
    "types": "dist/index.d.ts",
    "module": "dist/esm/index.js",
    "exports": {
        ".": {
            "module": "./dist/esm/index.js",
            "default": "./dist/index.js"
        },

Beyond the root there are separate paths for the MUI integration, for the Next.js Page Router, for the Next.js App Router, for the French DSFR design system, for a combined css and cx helper, for a generic Next.js entry, for a legacy nextJs path, and for two compatibility layers named compat and mui-compat. Each of them ships an ES module build alongside the default CommonJS one, so bundler resolution follows the same module and default pattern.

The practical consequence is that the import specifier is part of the design. If a codebase mixes MUI components, a DSFR theme and a Next.js app, it will pull in several of these paths rather than one, and the resulting chunking is worth checking against the bundle sizes the project claims.

Licence, release cadence and the last push date

The licence is MIT, so the code can be used, modified and redistributed in commercial and closed source products, subject to the licence text. That is a factual reading of the identifier, not legal advice, and projects embedding the library in a product should review the licence file themselves.

On maintenance, the repository is not archived, and the last push was on 2026-05-12, which is the same date as release v4.9.21. The two releases before it were v4.9.20 on 2025-12-05 and v4.9.19 on 2025-07-19, so the release line is on a 4.9.x version and the project publishes patch releases rather than frequent majors.

The README also claims the library is maintained for the foreseeable future and that issues are dealt with within good delays, attributing that to a long-standing arrangement with the MUI maintainers. The observable fact behind that claim is the release history above, with a release roughly every four to five months across 2025 and a final one in May 2026. A team that needs daily responsiveness should judge that gap themselves.

The project describes TypeScript as the implementation language and the repository contains tsconfig.json, tsconfig-esm.json and a src directory, which matches the claim that the package ships type definitions alongside the runtime.

Editorial conclusion

tss-react fits teams that already run MUI, want plain CSS syntax with checked property names, and are staying on the classic Next.js router rather than moving to server components. It is the wrong pick for App Router projects that need React Server Components today, or for teams that want to remove CSS-in-JS from the runtime entirely. Before adopting, verify the entry point your setup needs, since the package splits MUI, Next.js pages and app directory, and DSFR integrations into separate export paths, and confirm the small bundle cost the project states, around 5kB minzipped next to MUI, is acceptable on the pages you care about.

Frequently asked questions

What is tss-react and how is it different from styled-components?

tss-react is a CSS-in-JS API for React and MUI built on @emotion/react, and it is described as a type-safe equivalent of the JSS API. Unlike styled-components, you write plain CSS rules inside a style object and call a makeStyles hook rather than wrapping elements in tagged template components.

Does tss-react support React Server Components in Next.js?

No. The project states that dynamic style generation based on props and internal states prevents support for Server Components in Next.js, and that it remains hopeful for future support depending on a solution from Vercel and React. For RSC support today it points to zero runtime options such as Panda CSS or Vanilla Extract.

How do I use tss-react with MUI and Next.js?

The package exposes separate import paths for each integration, including tss-react/mui, tss-react/next/pagesDir and tss-react/next/appDir, so you import the entry point matching your framework and router. The underlying Emotion cache can also be customized.

Official sources

  1. garronej/tss-react on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/garronej-tss-react.svg)](https://hysenlabs.com/projects/garronej-tss-react)

Was this useful?