javivelasco / react-css-themr

Easy theming and composition for CSS Modules.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Document namespaced theme feature

javivelasco opened this issue · comments

Now it's possible to namespace a theme by using a themeNamespace property for the component. This avoids collisions between modules of different components using the same classname. It's a feature that it's working and it's published but not documented. We need to write a section detailing the API which is very simple!

I think it would also be nice to update the rest of the docs including new features: nested themes, theme spreads etc.

Do you plan to support namespaces in default/from context theme?

@artem-popov The problem with namespaces is that themr relies on the fact that classname string starts with namespace and checks it with startsWith. But actual classname construction is controlled by css-loader and it may prepend something to the classname with some different configuration.
Therefore I would suggest using nested themes - if your parent component contains some theme for its child component like here:

//parent.css
.container {
 ...
}

.child__container {
}
.child__content {
}

then instead of using themeNamespace as child__ you should move child's styles to a separate module:

//parent.css
.container {
}

//parent-child.css
.container {
}
.content {
}

Then when rendering you should pass child's theme object instead of namespace string.
Instead of

import { themr } from 'react-css-themr';
import * as css from './parent.css';
const Parent = ({theme}) => (
  <div className={theme.container}>
    <Child theme={theme} themeNamespace="child__"/>
  </div>
);
const ThemedParent = themr(Symbol(), css)(Parent);

you should use

import { themr, themeable } from 'react-css-themr';
import * as css from './parent.css';
import * as childCss from './parent-child.css';
const Parent = ({theme}) => (
  <div className={theme.container}>
    <Child theme={theme.Child}/>
  </div>
);
const theme = themeable(css, {
  Child: childCss
});
const ThemedParent = themr(Symbol(), theme)(Parent);

Please correct me if I'm wrong because I don't fully understand the purpose of theme namespaces.

UPDATE: nested themes are supported on every level of theme merging: context, props and default configuration.

Sorry for late answer.
Let me explain my case.

I''m very often use HOC's and each of the HOC's add some feature to component and possible has it's own styles.

Styles are already in different files, and in my HOC I'm adding default theme.

I'm adding namespace with sass:

.namespace {
   &someClass { ... }
}

So, I have all themes merged all together:

  • base one in context
  • passed theme from prop
  • default theme added by HOC
  • default theme of the component

In result I want to put component default theme and HOC's theme in different namespaces to not intersect names and do not worry about of this.

I don't see any problem with HOC's: you can still split HOC's styles and its child styles into different files and combine them into one theme object using themeable and nesting.
You gain all the profits you've enumerated and you don't need to mess with string values.

Please provide more concrete example if I don't get you right. But still I think namespaces in actual theme values instead of theme keys aren't a good solution because the values are details controlled by lower level of abstraction - webpack-loader. Even more, default configuration of latest version uses plain hashes in runtime instead of readable classnames.

UPDATE:
I checked the code once again and I'm wrong with values. Namespaces are applied to theme keys.
To sum up - I think that plans about supporting merging of namespaced themes on all levels should be considered by @javivelasco because I don't actually use them.

PS. You could still open a PR :)

@artem-popov
What's more many devs use react and themr with typescript and namespaces break possibility to check the type of theme received in props because actual keys differ from defined in props interface. So I think it's another point for nested themes.

I'll think about that :)