Styling Philosophy

Build / Render Phases

  1. Styles
  2. Variants
  3. States
  4. Groups
  5. Props

Mechanics

Property Passthrough

In addition to system props, both of these functions permit configurations with any valid CSS property that has not been overridden. These properties are typed to their CSSType defaults and will not accept values with the responsive syntax.

When generating the styles the function will ignore the all props that have not been configured directly to the resulting CSSObject.

const List = animus
.variant({
key: 'listVariant',
variants: {
vertical: {
listStyle: 'none', // Valid!
p: 0,
m: 0,
},
emoji: {
listStyleType: '\1F44D', // Valid!
pr: [12, 24],
m: 0,
},
},
})
.asElement('ul');

Output:

.List_vertical {
list-style: none;
padding: 0;
margin: 0;
}
.List_emoji {
list-style-type: '\1F44D';
padding-right: 0.75rem;
margin: 0;
}
@media screen and (min-width: 480px) {
.List_emoji {
padding-right: 1.5rem;
}
}

Conflicting properties

Properties that are handled by a system prop with a shorthand will still be available and may result in unexpected styles (property ordering may differ between conflicts and is not guarnateed to be consistent).

While it is highly encouraged to use system properties in all cases, there may be times where you need specific values that are outside of the contraints of normal system properties. In this event do not specify both properties and pick the only one that you need.

import { css } from '@codecademy/gamut-styles';
// ❌ - Combining both properties
const styles = animus
.styles({
mx: 4,
margin: '128.54px',
})
.build();
// ✅ - Use one or the other
const option1 = animus
.styles({
mx: 4,
})
.build();
const option2 = animus
.styles({
margin: '128.54px',
})
.build();

Selector Syntax

All css and variant functions are typed to accept a single level of selectors.

  1. If the style key matches a defined system prop it will allow the responsive syntax
  2. If it is a valid CSS property it will allow any valid CSSType value for the property.
  3. If it is none of these we assume that it is a valid selector and accept a valid configuration of 1 & 2.

This lets you specify scoped selector syntax for anything not matching a valid CSS prop or system property. This with the addition of the CSS Passthrough will allows us to create complete variants for much more complex css as scale. And create robust sharable utilities.

const Anchor = animus
.variant({
variants: {
ui: {
color: 'navy',
'&:hover': {
textDecoration: 'none',
border: '2px solid currentColor',
borderWidth: { md: '4px' },
},
},
inline: {
color: 'hyper',
transition: 'scale 150ms ease',
'&:hover': {
textDecoration: 'underline',
transform: 'scale(1.2)',
},
},
},
})
.asElement('a');