payloadcms / payload

Payload is the open-source, fullstack Next.js framework, giving you instant backend superpowers. Get a full TypeScript backend and admin panel instantly. Use Payload as a headless CMS or for building powerful applications.
https://payloadcms.com
MIT License
25.54k stars 1.62k forks source link

How to use tailwind reset styles with Payload without breaking admin styling #8878

Closed thgh closed 1 day ago

thgh commented 2 weeks ago

Describe the Bug

I was loading custom css (@tailwind) using a simple import. The latest update from version 110 -> 117 changed the order that styles are loaded which unstyles the payload Button component.

Link to the code that reproduces this issue

todo

Reproduction Steps

  1. Setup tailwindcss
  2. Add import "./custom.css" with the @tailwind base directive
  3. Open admin panel
  4. Notice buttons without style

Which area(s) are affected? (Select all that apply)

area: ui

Environment Info

Binaries: Node: 22.5.1 npm: 10.8.2 Yarn: 1.22.22 pnpm: N/A Relevant Packages: payload: 3.0.0-beta.117 next: 15.0.1 @payloadcms/db-mongodb: 3.0.0-beta.117 @payloadcms/email-nodemailer: 3.0.0-beta.117 @payloadcms/graphql: 3.0.0-beta.117 @payloadcms/next/utilities: 3.0.0-beta.117 @payloadcms/plugin-cloud: 3.0.0-beta.117 @payloadcms/richtext-lexical: 3.0.0-beta.117 @payloadcms/translations: 3.0.0-beta.117 @payloadcms/ui/shared: 3.0.0-beta.117 react: 19.0.0-rc-65a56d0e-20241020 react-dom: 19.0.0-rc-65a56d0e-20241020

thgh commented 2 weeks ago

Oh, it's kind of documented, solved it using:

@layer payload-default {
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
}

/* My custom styles */
thgh commented 2 weeks ago

It's not working 100% as hoped. Some payload styles are defined in the payload-default layer, e.g. h1, h2, h3 which means the group field title is affected by loading tailwind.

So the challenge is: how to define styles with lower priority than the payload-default layer? How about adding one more layer: payload-before?

paulpopus commented 2 weeks ago

That could break a lot of styling regardless and I don't want to introduce another layer unless we have to.

To double check this, have you tried disabling preflight? You can remove the base inclusion from the payload styles altogether or disable it globally in your tailwind config: https://tailwindcss.com/docs/preflight#disabling-preflight

This removes the actual resets affecting our styles.

Stefan94V commented 1 week ago

I have a similar issue is that I had several custom dashboard components made with ShadCN & Tailwind which also breaks the whole admin ui now.

Disabling preflights works for the admin part, but it breaks all my custom dashboard components, and frontend unfortunately

paulpopus commented 1 week ago

Disabling preflights works for the admin part, but it breaks all my custom dashboard components, and frontend unfortunately

You can leave preflight enabled and then just dont import the @tailwind base; import in your css file for payload. These styles are always going to interfere with Payload because those are style resets applied to elements themselves, what you want is just the components and utilities

thgh commented 1 week ago

I want to share components over projects, and also between admin and pages using other layouts. Not having the reset and default html font-size means I have to worry more about things breaking.

Would you consider refactoring payload styles to depend on BEM and not on the reset? I think it's 95% there.

paulpopus commented 1 day ago

Would you consider refactoring payload styles to depend on BEM and not on the reset? I think it's 95% there.

That is not going to happen in time for v3 unfortunately. I have some ideas for improving everything here for v4...

Did some testing and unfortunately it's basically always going to be the case that something will break when injecting new resets.

There is a way to scope the resets with tailwind from this discord thread https://discord.com/channels/967097582721572934/1304542354111205426/1305633796711776256

Using tailwindcss-scoped-preflight plugin for tailwind and the following configuration

import { scopedPreflightStyles, isolateInsideOfContainer } from 'tailwindcss-scoped-preflight';
...
plugins: [
    scopedPreflightStyles({
      isolationStrategy: isolateInsideOfContainer(['.useTw']),
    }),
  ],

You can then add the .useTw class as need per component. In your frontend you'll need to add this globally. This a compromise until we can make Payload work seamlessly with frameworks like tailwind or uno.

I'll update the title of this issue as well so people can land on this solution

github-actions[bot] commented 5 hours ago

This issue has been automatically locked. Please open a new issue if this issue persists with any additional detail.