Pretty Basic (I think) React / Tailwind / Next question

Hi everyone, I have tailwind UI and I'm trying to implement a theming system similar to : https://www.skies.dev/tailwind-themes - I'm sure something I'm missing is basic react functionality but I've not been able to find the right answer and I'm sorry to just brain dump here but I've kind of reached an impasse (and don't have a lot of friends familiar enough with React to help...) - His basic tutorial works great, however I'm trying to expand on that. - The Basics, I'm using React, Next.JS (App Directory), Tailwind UI - - I've defined my theme colors in global.css and their associated variables - - In layout.tsx I declare the themes (as colors) and define color as setColor
export default function RootLayout({

children,
}: {
children: React.ReactNode
}) {
const colors = ['light', 'dark', 'blue', 'highcontrast'];
const [color, setColor] = useState<string>(colors[1])
return (

<html className="h-full bg-white">
<body className="h-full">
<div className={[

color && `theme-${color}`,
]
.filter(Boolean)
.join(' ')}>
{children}
</div>
</body>
</html>
)
}
export default function RootLayout({

children,
}: {
children: React.ReactNode
}) {
const colors = ['light', 'dark', 'blue', 'highcontrast'];
const [color, setColor] = useState<string>(colors[1])
return (

<html className="h-full bg-white">
<body className="h-full">
<div className={[

color && `theme-${color}`,
]
.filter(Boolean)
.join(' ')}>
{children}
</div>
</body>
</html>
)
}
- - page.tsx calls the component <Sidebar /> which is not really just a sidebar but also a navbar (from TailwindUI) - - Inside Sidebar I have the following menu drop down to select the themes
<RadioGroup value={color} onChange={setColor}>
<RadioGroup.Label className="mt-5 block">
Select a color:
</RadioGroup.Label>
<div className="">
{colors.map((c) => {
return (
<div>
<RadioGroup.Option
className=""
value={c}
key={c}
>
{c}
</RadioGroup.Option>
</div>
);
})}
</div>
</RadioGroup>
<RadioGroup value={color} onChange={setColor}>
<RadioGroup.Label className="mt-5 block">
Select a color:
</RadioGroup.Label>
<div className="">
{colors.map((c) => {
return (
<div>
<RadioGroup.Option
className=""
value={c}
key={c}
>
{c}
</RadioGroup.Option>
</div>
);
})}
</div>
</RadioGroup>
- - I tried this with both a links and the RadioGroup (since it was what skies used in his demo) but part of the problem is that color and setColor are not defined, I can redeclare them but I feel like that doesn't work since it's not mutating the original property - - My GOAL here isn't JUST to get this working but to also understand why it's either NOT working or what I'm overlooking, I've been googling this for about a week and been given a couple of suggestions of entirely different ways to handle this but I feel like I'm missing a basic thing here... maybe not... and though I want to get this done, it's not an urgent item but I also want to learn
How to Create Themes with Tailwind CSS and React
Use CSS variables to leverage client-side theming with Tailwind CSS and React.js.
5 Replies
ironnator
ironnator10mo ago
@drewhack Best thing to do to get others to help you would be to post your repo. It's hard reading chunks of code without knowing the full context (i.e. what does your layout.tsx/page.tsx/ and sidebar component look like). For example, if your Sidebar button is calling setColor, then setColor needs to be defined as a prop in the component. So const Sidebar = (prop) => {} and your RadioGroup onChange handler would call prop.setColor. You also have setColor on the Layout, instead of the page.tsx. But there's no easy way to call setColor on the Layout without doing more complicated stuff. So for simplicity, I would do the setColor stuff on page.tsx, get that working, and then maybe look at the Layout stuff later. The tutorial doesn't actually mention using layout / app router, and instead stores the preference on local storage. Maybe try and get that working
DrewHack
DrewHack10mo ago
GitHub
GitHub - drewhack/testnextapp
Contribute to drewhack/testnextapp development by creating an account on GitHub.
DrewHack
DrewHack10mo ago
Yeah I was able to get what he was doing working in the base example but once I started trying to adapt it is where things went awry I’m still thinking with a PHP brain
ironnator
ironnator10mo ago
Okay. So.... if you want "child" components to influence something that is overarching, the best thing to do is to use React Context. Might need to watch a tutorial or two. But basically your layout.tsx would have something like: <ThemeProvider> {children} <ThemeProvider/> Usually most people would create a contexts folder, with a file called ThemeProvider.tsx and in there you would use React.createContext, create a component ThemeContext and export const useTheme = React.useContext(ThemeContext). (I can't really dictate out exactly what that would look like right at this second, but there's tons of tutorials). And then in your component, you would call const { currentColor, setColor } = useTheme() or something that you've created.
DrewHack
DrewHack10mo ago
Awesome thank you! Honestly I was so stuck on this I think. That’s a great jumping off point to be honest