I think that in this example there can be many problems, and why it does not comply with the "one class per element" rule. One reason for applying the rule of one class to an element is that we can easily change the appearance of the state of an element without affecting the element. (In principle, the promise of CSS itself is finally realized.) If you have several classes on an element, it is difficult to control the appearance without changing the element. This is especially true if you use classes (rather than semantic).
A class such as "button-primary-left-bold" has a semantic meaning ("button-primary"), but it also has a layout value ("left") and a text value ("bold"). The Button component probably does not have a business controlling its own layout. Remember that you can also create React components! So you can have something more:
<Left><Button type="primary">Click Me!</Button></Left>
The CSS module for the Button component can now worry about button types. And the Button component can be used anywhere, with any layout, and not just with a floating point.
Even better, the float can be added to a more semantic component. Perhaps something like:
<ButtonBar> <Button>Cancel</Button> <Button type="primary">Save</Button> </ButtonBar>
ButtonBar can have its own CSS module that executes the layout. And later you can change this bright floating layout for a chic flexbox layout. :-)
Your bold modifier example, of course, does not have a place inside the Button component. It is better to think about why something is bold, and then create a component or semantic property for it. Otherwise, if the design requires changing these bold buttons to italic green buttons, you will need to change the group of elements.
If you do this (sharing visual / layout classes for semantic components and splitting CSS components and modules), you will have less "exponential increase." If you end up in a situation where you really need to combine several semantic properties, there is still some value in having these states outlined. A good example would be "primary-disabled". This is better than "primary disconnected" for several reasons. First, itβs easy to browse in the CSS module and see the specified explicit state. Secondly, there are no ambiguous applications and relationships of these classes. Is "primary disconnected" really used by these classes? This can be found out only if someone uses documents. The disabled class can override something in the primary class, which means there are implicit order dependencies. It's easy for complete editing to break things down in the future, because the relationships between these classes are not obvious. As it often happens, choosing something implicit to save some keystrokes can lead to subtle errors. Taking into account that the keystroke bit blocks things and makes it obvious what will work and what will not.
Another small point that will save you a few keystrokes: there really is no reason for the "button-" prefix. That's what CSS modules are for. Do this instead:
.normal color: $button-default background-color: transparent font-family: $font-family font-size: $default-font-size font-weight: $font-regular line-height: $default-button-height margin: 0 $pad 0 0 outline: none padding: 0 $pad*2 .primary composes: normal color: $background-interaction background-color: $button-default
The file name itself is the prefix "button".