-
Notifications
You must be signed in to change notification settings - Fork 4
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
Compatibility with CRA #9
Comments
@peguerosdc Thank you for your feedback , I will adapter to CRA at the later. |
@hiyangguo thank you very much! looking forward to it :) |
Hi! I have come up with a very hacky way to get this to work. I created a gist example if anyone is interested, but you can check the full implementation in my own project. Again, this is very (very) hacky so if someone comes up with a cleaner implementation, it would be awesome! As I state in my gist example, as I am messing around with the original CRA's webpack config, the first run of the application results in a blank page (but it works as expected after reloading the page) and there is a limit to the amount of themes you can add before the compiler runs out of memory (I don't know why). Also (this is not in my gist example as this is more to my particular use case, but you can check it in my repository) I couldn't find a way to achieve the theme switching with custom colors (i.e. orange + dark mode, orange + light mode) and to use rsute's less variables in my own less files at the same time (i.e. to use function themeContent(themeName) {
const isDark = themeName.startsWith("dark")
return (
`
@import '~rsuite/lib/styles/themes/${isDark ? "dark" : "default"}/index.less';
.my_component:hover {
background-color: @nav-item-default-hover-bg;
}
`
)
} and here it is the config I use: multipleThemesCompile({
themesConfig: themes,
lessContent: (themeName, config) => themeContent(themeName),
styleLoaders: [
{ loader: 'css-loader' },
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true
}
}
}
],
cwd: path.resolve('./')
}) This is very very hacky too, but I couldn't find another way as using both |
I also used a rather "hacky" workaround. I bypassed this plugin entirely to achieve runtime theme switching. I used "react-boilerplate", but I got the exact same problem. First thing is, you have to check if you use the latest webpack style-loader version: rules: [
{
test: /\.less$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader',
options: {
attributes: { id: 'theme' },
},
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
//... Then, create a directory "themes", if you didn't already and create a .less file for each theme and an optional global file: Put all non-rsuite and global variables inside @base-color: #0000ff;
.bg { background-image: @bg-image }
.fg { background-image: @fg-image }
@import '../../node_modules/rsuite/lib/styles/constants.less';
@import '../../node_modules/rsuite/lib/styles/variables.less';
@import '../../node_modules/rsuite/lib/styles/mixins/utilities.less';
@import '../../node_modules/rsuite/lib/styles/themes/default/index.less';
@import './global.less';
@text-color: #ff0000;
@bg-image: url("../images/assets/bg-light-02.png");
@fg-image: url("../images/assets/bg-light-01.png"); @import '../../node_modules/rsuite/lib/styles/constants.less';
@import '../../node_modules/rsuite/lib/styles/variables.less';
@import '../../node_modules/rsuite/lib/styles/mixins/utilities.less';
@import '../../node_modules/rsuite/lib/styles/themes/dark/index.less';
@import './global.less';
@text-color: #00ff00;
@bg-image: url("../images/assets/bg-dark-02.png");
@fg-image: url("../images/assets/bg-dark-01.png"); (I used red and green text to easily see the the style change. Use whatever text color or variables you like) Enough less for now. Now jump into your import '../../themes/dark.less';
import '../../themes/light.less'; just to remove the const themes = {};
themes.dark = document.getElementById('theme');
themes.dark.parentElement.removeChild(themes.dark);
themes.light = document.getElementById('theme');
themes.light.parentElement.removeChild(themes.light); We stored both our removed elements, so we are able to append them later. Then create a const switchTheme = theme => {
try {
const rem = document.getElementById('theme');
rem.parentElement.removeChild(rem);
// eslint-disable-next-line no-empty
} catch (e) {}
document.head.appendChild(themes[theme]);
}; Try-catch block just in case something goes wrong. This function removes the existing |
@Phrosh your approach worked like a charm in my CRA app. Struggling to make it work for a NextJS app though... 🤔 |
Easy way to switch themes dynamicallyFound a very easy way to switch themes dynamically, without messing with Webpack. TL;DR:
Works beautifully in CRA and NextJS projects. Example// themes.less
@import '~rsuite/lib/styles/constants.less';
@import '~rsuite/lib/styles/variables.less';
@import '~rsuite/lib/styles/mixins/utilities.less';
.theme-dark {
@import '~rsuite/lib/styles/themes/dark/index.less';
@import './your-custom-variables.less';
}
.theme-light {
@import '~rsuite/lib/styles/themes/default/index.less';
@import './your-custom-variables.less';
} // index.js
import './themes.less'
let currentTheme = ''
const setTheme = (theme) => {
// skip it during SSR
if (typeof document === 'undefined') {
return
}
if (currentTheme) {
document.body.classList.remove(`theme-${currentTheme}`)
}
document.body.classList.add(`theme-${theme}`)
currentTheme = theme
}
// ... some place later - change your theme dynamically:
setTheme('dark')
// or...
setTheme('light') The only disadvantage of this method compared to webpack-multiple-themes-compile is bundle size - which would include both themes in the resulting CSS bundle. But the simplicity of it! @hiyangguo Would you consider adding this method to examples and the docs? IMO it's a very simple method compared to tweaking Webpack set-up, and for many people it could mean the difference between using RSuite or not using it due to complex multi-theme set-up. I've spent a few hours of my life trying to make it work until I discovered this solution 🙈 |
Update: unfortunately, the approach above breaks in a few places, e.g. for Dropdown: // from Dropdown/styles/common.less
& &-menu {
position: absolute;
// dropdown-menu zindex value is greater than dropdown-toggle
z-index: @zindex-dropdown + 1;
display: none; // none by default, but block on "open" of the menu
float: left;
box-shadow: @dropdown-shadow;
} This leads to the following CSS produced: .theme-dark .rs-dropdown .theme-dark .rs-dropdown-menu {
position: absolute;
z-index: 6;
display: none;
float: left;
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.2), 0 4px 4px 3px rgba(0, 0, 0, 0.24);
} Where it should be: .theme-dark .rs-dropdown .rs-dropdown-menu {
position: absolute;
z-index: 6;
display: none;
float: left;
box-shadow: 0 0 10px 1px rgba(0, 0, 0, 0.2), 0 4px 4px 3px rgba(0, 0, 0, 0.24);
} And so the dropdown menu isn't styled correctly. Trying to figure out a workaround... |
Hi!
This issue is already kind of open in rsuite#947, but I thought I should open the issue here (where I think it belongs) with some more details.
I am trying to use
webpack-multiple-themes-compile
with CRA throughreact-app-rewired
. My packages' versions are:And I am trying to override CRA's configuration with the following
config-overrides.js
(which is a based on this repository's README):But even though the compilation is successful, the application doesn't start as I only see a blank page. I think it is because the entry points of the default config and the ones generated by
multipleThemesCompile
are not being merged correctly as their definitions don't look compatible. This is how they look:So the resulting merged object apparently just takes the entry from the latter (I am not writing the other attributes here as they seem to be merged correctly, but as I am no webpack expert, I am not 100% sure) which would explain why my application doesn't load but the css files do seem to load.
I have tried some things like merging manually, merging the entry points with Derek-Hu/react-app-rewire-multiple-entry, but each of them throws different errors.
Is there a workaround for this or am I doing something wrong?
My final goal is to achieve runtime theme switching (like in Rsuite's website) with custom light and dark themes (i.e. light mode with
base_color : green
and dark mode withbase_color : red
).Thanks!
The text was updated successfully, but these errors were encountered: