I have a button that changes the theme color on navBar and it's working. When I click the button, the background color changes faster then the text colors. The "Home", "Cadastros", "Dash", "Notas" changes first than the icons and whatever is rendered in Outlet inside the MainLayout Demonstration
Relevant codes
index.css
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
@apply transition-all duration-300;
}
.lightTheme {
--background: 250, 250, 250;
--text: 0, 0, 0;
--title: 0, 0, 0;
--navBarShadow: 2, 6, 23, 0.1;
}
.darkTheme {
--background: 15, 23, 42;
--text: 250, 250, 250;
--title: 250, 250, 250;
--navBarShadow: 2, 6, 23, 0.2;
}
NavBar.jsx
import { Moon, Sun, User } from "lucide-react";
function NavBar({theme, onChangeThemeClick}) {
const themeIcon = theme === 'lightTheme' ? <Sun /> : <Moon />;
return (
<nav className={` ${theme} w-full h-15 absolute z-10 top-0 bg-background text-title p-4 shadow-navBarShadow shadow-lg `}>
<ul className="flex space-x-10 bg justify-end ">
<li ><a href="#" >Home</a></li>
<li><a href="#">Cadastros</a></li>
<li><a href="#">Dash</a></li>
<li><a href="#">Notas</a></li>
<li onClick={() => onChangeThemeClick()}><a href="#">
{themeIcon}
</a></li>
<li ><a href="#">
<User />
</a></li>
</ul>
</nav>
);
}
export default NavBar;
MainContainer.jsx
function MainContainer({theme, children}){
return(
<div className={`${theme} pt-20 z-0 w-full h-screen bg-background`}>
{children}
</div>
)
}
export default MainContainer;
RegistrationsTable.jsx
function RegistrationsTable() {
return(
<div className="w-1/2 h-max bg-background text-text border-text">
<table>
<tbody>
<tr>
<td>
<p>adad</p>
</td>
</tr>
</tbody>
</table>
</div>
)
}
export default RegistrationsTable;
RegistrationsPage.jsx
import RegistrationsTable from "../components/RegistrationsTable.jsx";
function RegistrationsPage() {
return (
<>
<RegistrationsTable />
</>
);
}
export default RegistrationsPage;
MainLayout.jsx
import { useState } from 'react'
import NavBar from '../components/NavBar.jsx'
import { Outlet } from 'react-router-dom'
import MainContainer from "../components/MainContainer.jsx";
function MainLayout() {
const [theme, setTheme] = useState('lightTheme')
function onChangeThemeClick() {
if (theme === 'lightTheme'){
setTheme('darkTheme')
} else if (theme === 'darkTheme'){
setTheme('lightTheme')
}
}
return (
<>
<NavBar theme={theme} onChangeThemeClick={onChangeThemeClick} />
<MainContainer theme={theme}>
<Outlet />
</MainContainer>
</>
)
}
export default MainLayout
tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: ["./index.html", "./src/**/*.{html,js,jsx,ts,tsx}"],
theme: {
extend: {
colors: {
//Theme colors
background: "rgba(var(--background))",
text: "rgba(var(--text))",
title: "rgba(var(--title))",
navBarShadow: "rgba(var(--navBarShadow))",
},
},
},
plugins: [],
};
I tried to apply the transition duration to dark and light theme but doesn't work. Like this:
@tailwind base;
@tailwind components;
@tailwind utilities;
.lightTheme {
--background: 250, 250, 250;
--text: 0, 0, 0;
--title: 0, 0, 0;
--navBarShadow: 2, 6, 23, 0.1;
@apply transition-all duration-300;
}
.darkTheme {
--background: 15, 23, 42;
--text: 250, 250, 250;
--title: 250, 250, 250;
--navBarShadow: 2, 6, 23, 0.2;
@apply transition-all duration-300;
}
Tried to pass theme variable trough the Outlet to use it in ClassName, but doesn't work too
Elements that don't have an explicit color
set have inherit
as their effective value. This means that the element resolves its value from its parent:
<div style="color: blue">
I am blue.
<p>I am blue also because I inherit from parent.</p>
</div>
In Chromium-based browsers (and as per your screencast, Opera is based on Chromium), when a parent's color
value is switched, it seems like child elements with inherit
value get the new value after transitions happen, and then switch their own resolved value, playing their own transition, thus causing the cascading delay.
Thus, you could consider only applying the color
transition to element(s) that don't have inherit
as a value for color
. So:
*
rule to only transition color properties that are not color
:
* {
transition: theme(transitionDuration.DEFAULT) theme(transitionTimingFunction.DEFAULT);
transition-property: var(--transition-properties);
--transition-properties: background-color, border-color;
}
color
for the top-level only:
.lightTheme, .darkTheme {
transition-property: color, var(--transition-properties);
}
color
for elements that have their color
property explicitly set:
<div className="… text-text … transition-color">
tailwind.config = {
theme: {
extend: {
colors: {
//Theme colors
background: "rgba(var(--background))",
text: "rgba(var(--text))",
title: "rgba(var(--title))",
navBarShadow: "rgba(var(--navBarShadow))",
},
},
},
};
<script src="https://cdn.tailwindcss.com/3.4.15"></script>
<style type="text/tailwindcss">
* {
transition: theme(transitionDuration.DEFAULT) theme(transitionTimingFunction.DEFAULT);
transition-property: var(--transition-properties);
--transition-properties: background-color, border-color;
}
.lightTheme {
--background: 250, 250, 250;
--text: 0, 0, 0;
--title: 0, 0, 0;
--navBarShadow: 2, 6, 23, 0.1;
}
.darkTheme {
--background: 15, 23, 42;
--text: 250, 250, 250;
--title: 250, 250, 250;
--navBarShadow: 2, 6, 23, 0.2;
}
.lightTheme, .darkTheme {
transition-property: color, var(--transition-properties);
}
</style>
<div id="app"></div>
<script src="https://unpkg.com/@babel/[email protected]"></script>
<script type="text/babel" data-type="module">
import React from "https://esm.sh/[email protected]";
import client from "https://esm.sh/[email protected]/client";
import { Moon, Sun, User } from "https://esm.sh/[email protected]";
import { BrowserRouter, Routes, Route, Outlet } from "https://esm.sh/[email protected]";
function NavBar({ theme, onChangeThemeClick }) {
const themeIcon = theme === "lightTheme" ? <Sun /> : <Moon />;
return (
<nav
className={` ${theme} w-full h-15 absolute z-10 top-0 bg-background text-title p-4 shadow-navBarShadow shadow-lg `}
>
<ul className="flex space-x-10 bg justify-end ">
<li>
<a href="#">Home</a>
</li>
<li>
<a href="#">Cadastros</a>
</li>
<li>
<a href="#">Dash</a>
</li>
<li>
<a href="#">Notas</a>
</li>
<li onClick={() => onChangeThemeClick()}>
<a href="#">{themeIcon}</a>
</li>
<li>
<a href="#">
<User />
</a>
</li>
</ul>
</nav>
);
}
function MainContainer({ theme, children }) {
return (
<div className={`${theme} pt-20 z-0 w-full h-screen bg-background`}>
{children}
</div>
);
}
function RegistrationsTable() {
return (
<div className="w-1/2 h-max bg-background text-text border-text transition-color">
<table>
<tbody>
<tr>
<td>
<p>adad</p>
</td>
</tr>
</tbody>
</table>
</div>
);
}
function RegistrationsPage() {
return (
<>
<RegistrationsTable />
</>
);
}
const { useState } = React;
function MainLayout() {
const [theme, setTheme] = useState("lightTheme");
function onChangeThemeClick() {
if (theme === "lightTheme") {
setTheme("darkTheme");
} else if (theme === "darkTheme") {
setTheme("lightTheme");
}
}
return (
<>
<NavBar theme={theme} onChangeThemeClick={onChangeThemeClick} />
<MainContainer theme={theme}>
<Outlet />
</MainContainer>
</>
);
}
client.createRoot(document.getElementById('app')).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<MainLayout />}>
<Route path="js" element={<RegistrationsPage />} />
</Route>
</Routes>
</BrowserRouter>
);
</script>