Support Tailwind CSS 4
Tailwind CSS 4 has been released, and it is hoped that it will support Tailwind CSS 4.
Which means at the moment, the installation docs aren't working, because the docs say:
npm init solid@latest
Which template would you like to use? with-tailwindcss
which means that the solid template will install tailwind 4.0.5 ( https://github.com/solidjs/templates/blob/main/js-tailwindcss/package.json#L14 )
solid-ui is does not work after updated the solidstart to 1.1 , even if I changed the dependencies version of tailwind to 3.4.17
Hello all, while waiting for Tailwind V4 support, here is my functional setup for Solid-UI:
// app.config.ts (solid-start) or adapt it for vite.config.ts
import { defineConfig } from "@solidjs/start/config";
import tailwindcss from "@tailwindcss/vite";
import tsconfigPaths from "vite-tsconfig-paths";
export default defineConfig({
ssr: false, // This project is an SPA, so I use SSR false, but feel free to use SSR if you had to ;)
vite: {
plugins: [
tsconfigPaths(),
tailwindcss(),
],
},
});
/* src/app.css or put it where you have your main .css file */
@import "tailwindcss";
@plugin 'tailwindcss-animate';
@plugin '@kobalte/tailwindcss';
@custom-variant dark (.dark &,[data-kb-theme="dark"] &);
@layer base {
:root {
--color-background: hsl(0 0% 100%);
--color-foreground: hsl(240 10% 3.9%);
--color-muted: hsl(240 4.8% 95.9%);
--color-muted-foreground: hsl(240 3.8% 46.1%);
--color-popover: hsl(0 0% 100%);
--color-popover-foreground: hsl(240 10% 3.9%);
--color-border: hsl(240 5.9% 90%);
--color-input: hsl(240 5.9% 90%);
--color-card: hsl(0 0% 100%);
--color-card-foreground: hsl(240 10% 3.9%);
--color-primary: hsl(240 5.9% 10%);
--color-primary-foreground: hsl(0 0% 98%);
--color-secondary: hsl(240 4.8% 95.9%);
--color-secondary-foreground: hsl(240 5.9% 10%);
--color-accent: hsl(240 4.8% 95.9%);
--color-accent-foreground: hsl(240 5.9% 10%);
--color-destructive: hsl(0 84.2% 60.2%);
--color-destructive-foreground: hsl(0 0% 98%);
--color-info: hsl(204 94% 94%);
--color-info-foreground: hsl(199 89% 48%);
--color-success: hsl(149 80% 90%);
--color-success-foreground: hsl(160 84% 39%);
--color-warning: hsl(48 96% 89%);
--color-warning-foreground: hsl(25 95% 53%);
--color-error: hsl(0 93% 94%);
--color-error-foreground: hsl(0 84% 60%);
--color-ring: hsl(240 5.9% 10%);
}
.dark,
[data-kb-theme="dark"] {
--color-background: hsl(240 10% 3.9%);
--color-foreground: hsl(0 0% 98%);
--color-muted: hsl(240 3.7% 15.9%);
--color-muted-foreground: hsl(240 5% 64.9%);
--color-accent: hsl(240 3.7% 15.9%);
--color-accent-foreground: hsl(0 0% 98%);
--color-popover: hsl(240 10% 3.9%);
--color-popover-foreground: hsl(0 0% 98%);
--color-border: hsl(240 3.7% 15.9%);
--color-input: hsl(240 3.7% 15.9%);
--color-card: hsl(240 10% 3.9%);
--color-card-foreground: hsl(0 0% 98%);
--color-primary: hsl(0 0% 98%);
--color-primary-foreground: hsl(240 5.9% 10%);
--color-secondary: hsl(240 3.7% 15.9%);
--color-secondary-foreground: hsl(0 0% 98%);
--color-destructive: hsl(0 62.8% 30.6%);
--color-destructive-foreground: hsl(0 0% 98%);
--color-info: hsl(226.2 57% 21%);
--color-info-foreground: hsl(199 89% 48%);
--color-success: hsl(165.7 91.3% 9%);
--color-success-foreground: hsl(160 84% 39%);
--color-warning: hsl(26 83.3% 14.1%);
--color-warning-foreground: hsl(25 95% 53%);
--color-error: hsl(0 74.7% 15.5%);
--color-error-foreground: hsl(0 84% 60%);
--color-ring: hsl(240 4.9% 83.9%);
}
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
font-feature-settings: "rlig" 1, "calt" 1;
}
@media (max-width: 640px) {
.container {
@apply px-4;
}
}
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-thumb {
border-radius: 9999px;
border: 4px solid transparent;
background-clip: content-box;
@apply bg-accent;
}
::-webkit-scrollbar-corner {
display: none;
}
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@theme {
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-error: var(--error);
--color-error-foreground: var(--error-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--radius: 0.5rem;
--radius-xl: calc(var(--radius) + 4px);
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--kb-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--kb-accordion-content-height);
}
to {
height: 0;
}
}
@keyframes content-show {
from {
opacity: 0;
transform: scale(0.96);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes content-hide {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.96);
}
}
@keyframes caret-blink {
0%,
70%,
100% {
opacity: 1;
}
20%,
50% {
opacity: 0;
}
}
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;
--animate-content-show: content-show 0.2s ease-out;
--animate-content-hide: content-hide 0.2s ease-out;
--animate-caret-blink: caret-blink 1.25s ease-out infinite;
}
@utility container {
margin-inline: auto;
padding-inline: 2rem;
@media (width >= --theme(--breakpoint-sm)) {
max-width: none;
}
@media (width >= 1400px) {
max-width: 1400px;
}
}
@utility step {
counter-increment: step;
&:before {
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
@apply ml-[-50px] mt-[-4px];
content: counter(step);
}
}
I hope for those who are blocked will be happy to work with this wonderful lib & Tailwind 4 :)
Thanks @carere, following these steps more-or-less worked for me, though I did need to install kobalte/tailwindcss with npm install -D @kobalte/tailwindcss --legacy-peer-deps as I did not have it in the project already.
thanks!
thanks for all the feedback :) for now v4 support is not planned since I only have limited time due to our newborn and I want so solve all the issues first :)
but once solid 2 beta hits I have to redo all the components anyway and that's when I want to add v4 support
but if someone has some time at hand and wants to provide a PR for the cli feel free to do it! <3 this would help so much especially most of the stuff can be ported from shadcn :)
@stefan-karger I can help you on this one, do you have an exhaustive list to add support for tailwind V4 to the CLI ?
this one, do you have an exhaustive list to add support for
Unfortunatelly I don't have a CONTRIBUTION.md or a list of what needs to be done or how it should be done, since in the past it was always more or less just try stuff out and see if it works.
I usually looked at all the cli tools out there (shadcn, shadcn-solid, shadcn-svelte) and ported everything that made sense but I think for now shadcn is the only one with v4 support, so that would be the only source we can look at.
What I definitely would like to have is some kind of automated getTailwindVersion() like in shadcn that decides how the tailwind/css files should be initialized.
And I would love to see stuff like olkch colors. :)
So I'd see feel free to open a PR and just start with it. :)
/edit
This tanstack router demo by devagrawal09 uses both v4 and SolidUI: https://github.com/devagrawal09/tanstack-router-strello/blob/master/src/styles.css
The tailwind config I shared is already working with v4 and SolidUi, since it is what I use on my own project :) So i'll use this as a base and open a PR :)
The tailwind config I shared is already working with v4 and SolidUi, since it is what I use on my own project :) So i'll use this as a base and open a PR :)
could you still have a look at the guide that shadcn provides? the setup you have works fine but he proposes a few changes that look like it makes the css file more readable :)
https://ui.shadcn.com/docs/tailwind-v4#2-update-your-css-variables
shadcn slightly changed the colors: https://github.com/shadcn-ui/ui/blob/8d5d62f9d996204f515e2001856ca8aab48fca1a/apps/www/public/r/colors/zinc.json#L100-L167
PR: https://github.com/shadcn-ui/ui/pull/6903/
/edit: there is also now a tailwind v4 compatible alternative for tailwind animate https://ui.shadcn.com/docs/tailwind-v4#march-19-2025---deprecate-tailwindcss-animate https://github.com/Wombosvideo/tw-animate-css
@stefan-karger Hello :)
I plan on copying the entire CLI from ShadCn and replace the existing one in Soilid-UI. Is that ok with you ?? That way we will have every feature from ShadCN since it's the most advanced CLI actually amongs all projects (yours, shadcn-solid, shadcn-ui, etc)
@stefan-karger Hello :)
I plan on copying the entire CLI from ShadCn and replace the existing one in Soilid-UI. Is that ok with you ?? That way we will have every feature from ShadCN since it's the most advanced CLI actually amongs all projects (yours, shadcn-solid, shadcn-ui, etc)
that would be what I would do next so feel free to start a pr :)
@stefan-karger Ok after a good investigation, it seems that we may be able to use shadcn directly.
By using Registry Feature, we simply have to implement a registry for Solid-UI, then we can use ShadCn's CLI to add all the components we need.
That way we don't have to support the CLI (which is already supported / funded by Vercel), we only have to implement some components, and update the registry.
I'll try to setup a working example in order to showcase this feature π
Hello all π
Here is the PR for Tailwind V4 migration (and Shadcn registry).
For the most impatients, you can check the CSS files used in this PR for the SolidUI website, it's updated to Tailwind V4, with OKCHL colors & it is based on Shadcn version.
@import "tailwindcss";
@import "tw-animate-css";
@plugin "@kobalte/tailwindcss";
@custom-variant dark (&:where(.dark, .dark *, [data-kb-theme=dark], [data-kb-theme=dark] *));
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--secondary: oklch(0.97 0 0);
--secondary-foreground: oklch(0.205 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: oklch(0.97 0 0);
--accent-foreground: oklch(0.205 0 0);
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.577 0.245 27.325);
--info: oklch(0.95 0.024 236.81);
--info-foreground: oklch(0.68 0.148143 238.1044);
--success: oklch(0.95 0.0506 162.83);
--success-foreground: oklch(0.69 0.1481 162.37);
--warning: oklch(0.96 0.0569 95.61);
--warning-foreground: oklch(0.71 0.186 48.13);
--error: oklch(0.93 0.0314 17.73);
--error-foreground: oklch(0.64 0.2082 25.38);
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--ring: oklch(0.708 0 0);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: oklch(0.205 0 0);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.97 0 0);
--sidebar-accent-foreground: oklch(0.205 0 0);
--sidebar-border: oklch(0.922 0 0);
--sidebar-ring: oklch(0.708 0 0);
}
.dark,
[data-kb-theme="dark"] {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--card: oklch(0.145 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.145 0 0);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
--primary-foreground: oklch(0.205 0 0);
--secondary: oklch(0.269 0 0);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.269 0 0);
--muted-foreground: oklch(0.708 0 0);
--accent: oklch(0.269 0 0);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.396 0.141 25.723);
--destructive-foreground: oklch(0.637 0.237 25.331);
--info: oklch(0.28 0.0875 267.91);
--info-foreground: oklch(0.68 0.148143 238.1044);
--success: oklch(0.26 0.0487 172.54);
--success-foreground: oklch(0.69 0.1481 162.37);
--warning: oklch(0.29 0.0638 53.82);
--warning-foreground: oklch(0.71 0.186 48.13);
--error: oklch(0.26 0.0886 26.05);
--error-foreground: oklch(0.64 0.2082 25.38);
--border: oklch(0.269 0 0);
--input: oklch(0.269 0 0);
--ring: oklch(0.439 0 0);
--sidebar: oklch(0.205 0 0);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.488 0.243 264.376);
--sidebar-primary-foreground: oklch(0.985 0 0);
--sidebar-accent: oklch(0.269 0 0);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(0.269 0 0);
--sidebar-ring: oklch(0.439 0 0);
}
@theme {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-info: var(--info);
--color-info-foreground: var(--info-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-error: var(--error);
--color-error-foreground: var(--error-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--radius: 0.5rem;
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--kb-accordion-content-height);
}
}
@keyframes accordion-up {
from {
height: var(--kb-accordion-content-height);
}
to {
height: 0;
}
}
@keyframes content-show {
from {
opacity: 0;
transform: scale(0.96);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes content-hide {
from {
opacity: 1;
transform: scale(1);
}
to {
opacity: 0;
transform: scale(0.96);
}
}
}
@utility container {
@apply px-8;
@media (width >=--theme(--breakpoint-sm)) {
@apply max-w-none;
}
@media (max-width: 640px) {
@apply px-4;
}
}
@utility step {
counter-increment: step;
&:before {
@apply absolute w-9 h-9 bg-muted rounded-full font-mono font-medium text-center text-base inline-flex items-center justify-center -indent-px border-4 border-background;
@apply ml-[-50px] mt-[-4px];
content: counter(step);
}
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
/**
* Scrollbar
*/
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-thumb {
border-radius: 9999px;
border: 4px solid transparent;
background-clip: content-box;
@apply bg-accent;
}
::-webkit-scrollbar-corner {
display: none;
}
}
I left a checklist on the PR, in order for you to follow the progression of the migration π
PS: You should remove what you don't need from this CSS file or simply use the one from Shadcn repository.
@stefan-karger Hello :)
I did a new PR which simply update the current monorepo and add only the "registry" part and update some components to TW v4. I also provided the CSS file to the CLI (I let you update the CLI for TW V4).
PS: It is pretty straightforward, the 3000+ modifications are due to the fact I added the generated registry to the public folder π
New PR for those curious about testing Solid-UI directly with the shadcn CLI π
Thank you very much for working on this, @carere and @stefan-karger! π
By any chance do you plan to have a new solid-ui release supporting tailwind 4 soon-ish? If not, would you recommend using the code at head?
Many thanks!
@stefan-karger I know that you don't have much time (all my friends are in baby time actually also, so I know what's your feelings π), but don't hesitate to let us/me know if you need some help to improve docs and more. The big part for TW4 is already done, we only have to update the docs and the cli to inform users of the changes imo.
PS: I can also take care of the llm.txt, I would also need it π
@carere, It's fascinating all the work you have put into this. I thank you and @stefan-karger for creating such great library π₯
@carere Would you mind giving the steps here while waiting for the docs PR? I do not feel this thread is clear on what to do to use solidui with tailwind 4.
Thank you very much! π
@elboWarrior Hello :)
So in order to setup Solid-UI with TW4, follow those steps:
- Install shadcn by following the instructions of the official website
- (optional) Update your tsconfig aliases to use
~if you want - Update your components.json with the following content:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/index.css",
"baseColor": "slate",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "~/components",
"utils": "~/lib/utils",
"ui": "~/components/ui",
"lib": "~/lib",
"hooks": "~/hooks"
},
"registries": {
"@solid-ui": "https://solid-ui.com/r/{name}.json"
}
}
- Update you main css file with the one I provided earlier in this issue
VoilΓ !!
You can add any components like this npx shadcn@beta add @solid-ui/[COMPONENT_NAME]
It should work ;)
Hello @carere, thanks for sharing. Solid-UI can work after modifying the app.css file you posted a few days ago. Whatβs the difference between just modifying app.css and installing Shadcn instead of Solid-UI directly?
My goal with the modifications was to use Shadcn directly to install SolidUI components. So by using the recent shadcn's registries, we can manipulate Solid-ui components with Shadcn, that way we don't have to maintain a CLI which mirror what the Shadcn CLI does.
@stefan-karger is working on the new docs, he is nearly finished, then we will have a clear roadmap on the evolution of Solid UI.
The goal is to have a CLI for SolidUI which is gonna pass-through with most of the features from the Shadcn CLI, that way you'll don't have to tweak files as I advise on my quick solution π
I tryed the command npx shadcn@beta add @solid-ui/[COMPONENT_NAME].json it only worked when I removed ".json"
For posterity, if someone wants to install all the components:
curl -q https://www.solid-ui.com/registry/index.json | jq -r '.[].name' | xargs -I {} pnpm dlx shadcn@latest add @solid-ui/{}
It seems that adding @kobalte/tailwindcss is no longer required either for tailwind v4 per https://github.com/kobaltedev/kobalte/issues/607 for anyone else who encounters this
@carere Thx bro
My solid-ui worked successfully π
finally managed to finish the base of the new docs design :)
I only need to set up the build-registry script to make the <ComponentPreview /> work and then it's time to port all the v4 versions over to the new docs <3
if you want to have a look at the temp repo: https://github.com/stefan-karger/solidbase-mdx
@carere Thanks for the great work!
Noticed that the --destructive and --destructive-foreground colors in light mode are the same:
--destructive: oklch(0.577 0.245 27.325);
--destructive-foreground: oklch(0.577 0.245 27.325);
I assume it's a live bug because the docs also have this issue: