Recipes
In this section, we'll look at how to make the most of the EffCSS features.
Composition of makers
The StyleSheet maker function does not have to be pure - you can collect styles by combining calls to other functions, including other makers.
Example
import { TStyleSheetMaker } from 'effcss';
import { type TFirstMaker, firstMaker } from 'firstMakerLib';
import { type TSecondMaker, secondMaker } from 'secondMakerLib';
export type TCompositeMaker = TFirstMaker & TSecondMaker;
export const compositeMaker: TStyleSheetMaker = (utils) => {
return {
...firstMaker(utils),
...secondMaker(utils)
};
};Maker factory
Sometimes you need to configure styles inside the StyleSheet maker function without using theme variables. In this case, you can describe the StyleSheet maker creator function, which will create a maker based on the passed parameters.
Example
import { TStyleSheetMaker } from 'effcss';
export type TMakerCreator = (params: {
sizes: {
s: number;
m: number;
l: number;
};
max: number;
min: number;
}) => TStyleSheetMaker;
export const DEF_PARAMS = {
sizes: {
s: 2.5,
m: 5,
l: 7.5
},
min: 0,
max: 10
};
export const createMaker: TMakerCreator = (params = DEF_PARAMS) => (utils) => {
const {
sizes,
max,
min
} = params;
return {
// css
};
};When using such a feature, you will need to create an instance of the maker and use it to create a stylesheet.
Example
import { type TConfiguredMaker, createMaker } from './maker';
export type TConfiguredMaker;
export const maker = createMaker({
sizes: {
s: 1,
m: 4,
l: 10
},
min: 0,
max: 12
});Changing makers
Sometimes your styles need to be calculated anew, but the selectors themselves must remain the same. For example, you provide the user with the opportunity to adjust the sizes and colors of your component interactively. Although EffCSS assumes only a single call to the StyleSheet maker function for each stylesheet, you can achieve recomputation using the remake method. This method even allows you to use different makers if you have a link to the original.
Example
import { TStyleSheetMaker } from 'effcss';
const original: TStyleSheetMaker = () => ({
// css
});
const substitute: TStyleSheetMaker = () => ({
// css
});
const [originalBEM] = consumer.use(original); // use original
const substituteBEM = consumer.remake(substitute, original); // now substitute creates the original selectors
console.log(originalBEM('block.elem.mod').toString() === substituteBEM('block.elem.mod').toString()); // true - identical selectorsWARNING
If you are changing the maker for the stylesheet, make sure that your code contains only references to the new maker. All accesses to the original version will result in the creation of a new style sheet with its own unique key.
Multiple values for CSS property
Some CSS properties have different browser support, so you may need to specify several options. To do this, use arrays with the desired order of values.
Example
import { TStyleSheetMaker } from 'effcss';
const maker: TStyleSheetMaker = () => {
return {
'.cls': {
textDecoration: ['underline', 'underline dotted'] // .cls{text-decoration:underline;text-decoration:underline dotted;}
}
};
};Using prepared CSS styles (^4.5.0)
Sometimes you already have a string with ready-made CSS. You can return it from the maker to avoid unnecessary conversions and transformations.
Example
import { TStyleSheetMaker } from 'effcss';
const css = '.cls{text-decoration:underline;}';
const maker: TStyleSheetMaker = () => {
return css;
};Atomic CSS
Often your styles are simpler with the help of atomic rules. In this case, the table type can be described using the generic TMonoElement:
Example
import type { TMonoElement, TStyleSheetMaker } from 'effcss';
export type TMaker = TMonoElement<{
w: 's' | 'm' | 'l';
h: 's' | 'm' | 'l';
bg: 'primary' | 'secondary';
}>;Note that the stylesheet format allows you to use atomic rules along with BEM rules - you can explicitly specify them in the default element of the default block.:
Example
import type { TStyleSheetMaker } from 'effcss';
export type TMaker = {
'': {
'': {
w: 's' | 'm' | 'l';
h: 's' | 'm' | 'l';
bg: 'primary' | 'secondary';
};
};
block: {
elem: {
mod: 'val1' | 'val2';
};
};
};