Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tailwind with Linaria #19

Open
ramblehead opened this issue Aug 24, 2023 · 3 comments
Open

Tailwind with Linaria #19

ramblehead opened this issue Aug 24, 2023 · 3 comments

Comments

@ramblehead
Copy link

ramblehead commented Aug 24, 2023

I am using using Subj. for a few mounts now. Tailwind provides theme and utility classes while Linaria is used to define components and compose Tailwind design tokens and classes.

In nextjs next-with-linaria does a great job bringing hot reloads to Linaria components!

Recently I started looking into nextjs app directory for server-side components and discovered that my "Tailwind with Linaria" settings no longer works when changing from pages router to app.

I have setup couple of repositories to demonstrate the case:
https://github.com/ramblehead/nextjs-tw-linaria
https://github.com/ramblehead/nextjs-app-tw-linaria

When running yarn dev, nextjs-tw-linaria works as expected:

  1. Remove backgroundImage from tailwind.config.ts config.
  2. Change body.background in src/styles/globals.css.
  3. Change background-color in src/components/view/linaria-button.ts.

All above changes are reflected via hot reload as expected.

When running yarn dev, nextjs-app-tw-linaria hot reload only works with Linaria components:

  1. Change background-color in src/components/view/linaria-button.ts

Changes to globals.cssand Tailwind are no longer hot-reloaded.

Some initial investigations

I have narrowed down the cache conflict to the following line in next-with-linaria:

Commenting-out above setData() call resolves the issue with Tailwind and global.css hot reloading. However, Linaria components are no longer cached causing full reload on every change.

It looks like adding any linaria-produced css module to backendOrStorage._data prevents any further cache updates for all other css modules...

At this point I am running out of my understanding of Webpack "virtual file system" to debug it any further...

@usulpro
Copy link

usulpro commented Sep 13, 2023

@ramblehead Hey Victor! Your idea to use two frameworks looks awesome to me. We utilize both but didn't try to combine them in one project. I wonder wouldn't you share some details about your setup and what benefits it can give to a project?

@ramblehead
Copy link
Author

ramblehead commented Sep 27, 2023

@usulpro Hi Oleg! That is a good question. The following post from airbnb was my original source of inspiration:
https://medium.com/airbnb-engineering/airbnbs-trip-to-linaria-dc169230bd12

Previously, we used Tailwind CSS with Styled Components. Tailwind theme in those settings was generated from a theme object similarly to zendeskgarden:
https://github.com/zendeskgarden/tailwindcss

Theme object solution is not bad, but for small projects such as landing or personal pages it might be an overkill as it requires one to maintain a full tailwind plugin just to generate design tokens from the theme object.

At some point I tried using just Tailwind for everything - similar to currently trending shadcn/ui. In my perception, using tailwind for styling components is a bad idea because for any fairly complex component the className string becomes long and unreadable, forcing developers to use additional abstractions such as twMerge and clsx.

Then, I tried tailwind with CSS modules and PostCSS. That was a nearly tolerable solution. However, after using Styled Components, CSS modules feels unnecessary complex and still requires clsx alike.

Then I came across airbnb post mentioned above and decided to try linaria. As I am using next.js and currently switching to app dir, I started using next-with-linaria. Linaria, like CSS modules, can use PostCSS making tailwind theme/tokens available to linaria components, eliminating the need of a separate theme object. For example:

export const buttonCssStr = `
  all: unset;
  -webkit-tap-highlight-color: transparent;
  border-radius: theme(space.5);
  cursor: pointer;
  height: theme(space.10);
  padding-left: theme(space.3);
  padding-right: theme(space.3);
  display: inline-flex;
  align-items: center;
  justify-content: center;

  transition: border-color 0.25s ease-in-out, box-shadow 0.1s ease-in-out,
    background-color 0.25s ease-in-out, color 0.25s ease-in-out,
    z-index 0.25s ease-in-out;

  @apply shadow;

  color: theme(colors.foreground.DEFAULT);
  background-color: theme(colors.background.DEFAULT);

  .dark & {
    @apply shadow-neutral-600;
    color: theme(colors.foreground.invert);
    background-color: theme(colors.background.invert);
  }

  &.hover {
    background-color: theme(colors.neutral.200);
  }

  .dark &.hover {
    background-color: theme(colors.neutral.700);
  }

  &.active {
    background-color: theme(colors.neutral.300);
  }

  .dark &.active {
    background-color: theme(colors.neutral.600);
  }

  &.focusFromKey {
    box-shadow: 0 0 0 2px theme(colors.neutral.500);
    background-color: theme(colors.neutral.200);
  }

  .dark &.focusFromKey {
    box-shadow: 0 0 0 2px theme(colors.neutral.500);
    background-color: theme(colors.neutral.700);
  }
`;

export const StyledButton = styled(Interactive.Button)`
  ${buttonCssStr}
`;

Tailwind utility classes are then used to style everything else - typography, layout, responsive folding etc. In this approach tailwind and linaria blend naturally and allow developer to chose the appropriate CSS syntax depending on the use case.

The whole setup is still experimental. At the moment I only use it for my personal site. The site code is not published as open source yet, but I can add you to collaborators if interested.

@ramblehead
Copy link
Author

ramblehead commented Nov 14, 2023

Subj. is still an issue in 0.6.0

My webpack-virtual-modules monkey patch seems to work with version 0.6.0. Here is the patched version:
https://github.com/ramblehead/next-with-linaria/tree/%40rh/0.6.0

I tested the patched version with [email protected], @linaria/[email protected], @linaria/[email protected], @linaria/[email protected] and [email protected]
So far all seems to be operational...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants