Info¶
The idea of presets builds upon local variables to offer localized default configurations. This helps mitigate micro-class creep, which happens when classes become too small and generalized. You tend to see micro-class creep in the majority of UI libraries, for example, when a handful of classes are used to construct a single element such as a button. This makes sense in an HTML multi-class design pattern, but this pattern, in my eyes, is an anti-pattern for ctr
. My rule of thumb is, when possible, always strive for a single source of truth architecture and presets help to achieve this goal.
Syntax¶
Description: preset
is defined as predefined local variable configurations.
ctrSetClass('<class>', {
$$: {
<property>: <value:default>
preset: {
<preset:one>: {
<property>: <value:preset:one>
}
<preset:two>: {
<property>: <value:preset:two>
}
}
}
<...>: '$<property>$'
})
// default
ctr('<#selector>', {
extend: <class>
})
// preset one
ctr('<#selector-one>', {
extend: {
<class>: {
preset: <preset:one>
}
}
})
// preset two
ctr('<#selector-two>', {
extend: {
<class>: {
preset: <preset:two>
}
}
})
ctr:::setClass:<class>:
$$:
<property>: <value:default>
preset:
<preset:one>:
<property>: <value:preset:one>
<preset:two>:
<property>: <value:preset:two>
<...>: $<property>$
# default
<#selector>:
extend: <class>
# preset one
<#selector-one>:
extend:
<class>:
preset: <preset:one>
# preset two
<#selector-two>:
extend:
<class>:
preset: <preset:two>
<#selector> {
<...>: <value:default>;
}
<#selector-one> {
<...>: <value:preset:one>;
}
<#selector-two> {
<...>: <value:preset:two>;
}
Notes
- Object lookup is performed through lodash’s
_.get
Function using dot notation:$<path>.<to>.<var>$
Basic¶
Description: A String value for the preset
property applies the defined preset to the specified default local variables.
ctrSetClass('Box', {
$$: {
size: 200px
preset: {
small: {
size: 100px
}
large: {
size: 300px
}
}
}
width: '$size$'
height: '$size$'
})
ctr('.test', {
width: 200px
components: {
'.small-box': {
extend-Box: {
preset: 'small'
}
}
'.large-box': {
extend-Box: {
preset: 'large'
}
}
}
})
ctr:::setClass:Box:
$$:
size: 200px
preset:
small:
size: 100px
large:
size: 300px
width: $size$
height: $size$
.test:
width: 200px
components:
.small-box:
extend-Box:
preset: small
.large-box:
extend-Box:
preset: large
.test {
width: 200px;
}
.test > .small-box {
width: 100px;
height: 100px;
}
.test > .large-box {
width: 300px;
height: 300px;
}
ctrSetClass('Box', {
$$: {
size: 200px
preset: {
small: {
size: 100px
}
large: {
size: 300px
}
}
}
width: '$size$'
height: '$size$'
})
ctr('.test', {
width: 200px
components: {
'.small-box': {
extend-Box: {
preset: 'small'
}
}
'.large-box': {
extend-Box: {
preset: 'large'
}
}
}
})
.test {
width: 200px;
}
.test > .small-box {
width: 100px;
height: 100px;
}
.test > .large-box {
width: 300px;
height: 300px;
}
ctr:::setClass:Box:
$$:
size: 200px
preset:
small:
size: 100px
large:
size: 300px
width: $size$
height: $size$
.test:
width: 200px
components:
.small-box:
extend-Box:
preset: small
.large-box:
extend-Box:
preset: large
Notes
- The same results could be achieved through three diffrent classes, but I think you will agree this is a much more elegant solution
Multiple¶
Description: A List value for the preset
property applies the preset List in the order it is received.
ctrSetClass('Box', {
$$: {
size: 200px
background: red
preset: {
size: {
small: {
size: 100px
}
large: {
size: 300px
}
}
color: {
primary: {
background: blue
}
secondary: {
background: black
}
}
}
}
width: '$size$'
height: '$size$'
background: '$background$'
})
ctr('.test', {
width: 200px
components: {
'.small-box': {
extend-Box: {
preset: 'size.small' 'color.secondary'
}
}
'.large-box': {
extend-Box: {
// secondary will not overwrite primary
preset: 'size.large' 'color.primary' 'color.secondary'
}
}
}
})
ctr:::setClass:Box:
$$:
size: 200px
background: red
preset:
size:
small:
size: 100px
large:
size: 300px
color:
primary:
background: blue
secondary:
background: black
width: $size$
height: $size$
background: $background$
.test:
width: 200px
components:
.small-box:
extend-Box:
preset: [size.small, color.secondary]
.large-box:
extend-Box:
# secondary will not overwrite primary
preset: [size.large, color.primary, color.secondary]
.test {
width: 200px;
}
.test > .small-box {
width: 100px;
height: 100px;
background: #000;
}
.test > .large-box {
width: 300px;
height: 300px;
background: #00f;
}
ctrSetClass('Box', {
$$: {
size: 200px
background: red
preset: {
size: {
small: {
size: 100px
}
large: {
size: 300px
}
}
color: {
primary: {
background: blue
}
secondary: {
background: black
}
}
}
}
width: '$size$'
height: '$size$'
background: '$background$'
})
ctr('.test', {
width: 200px
components: {
'.small-box': {
extend-Box: {
preset: 'size.small' 'color.secondary'
}
}
'.large-box': {
extend-Box: {
// secondary will not overwrite primary
preset: 'size.large' 'color.primary' 'color.secondary'
}
}
}
})
.test {
width: 200px;
}
.test > .small-box {
width: 100px;
height: 100px;
background: #000;
}
.test > .large-box {
width: 300px;
height: 300px;
background: #00f;
}
ctr:::setClass:Box:
$$:
size: 200px
background: red
preset:
size:
small:
size: 100px
large:
size: 300px
color:
primary:
background: blue
secondary:
background: black
width: $size$
height: $size$
background: $background$
.test:
width: 200px
components:
.small-box:
extend-Box:
preset: [size.small, color.secondary]
.large-box:
extend-Box:
# secondary will not overwrite primary
preset: [size.large, color.primary, color.secondary]
Notes
- Lowest index supersedes in conflicts