A utility library for 🧁vanilla-extract.
Install the package:
$ npm i vanilla-icecream
#or
$ yarn add vanilla-icecream
#or
$ pnpm i vanilla-icecream
This package is dedicated to use with
react
andvanilla-extract
. But in the future can be adapted to use with others framework.
Configure vanilla-extract and sprinkles
and have your atoms ready:
// sprinkles.css.ts
import { createSprinkles, defineProperties} from '@vanilla-extract/sprinkles';
const space = {
none: 0,
small: 4,
medium: 8,
large: 16,
};
const colors = {
primary: 'blue',
// ...
};
const responsiveProperties = defineProperties({
conditions: {
mobile: {},
tablet: { '@media': 'screen and (min-width: 768px)' },
desktop: { '@media': 'screen and (min-width: 1024px)' },
},
properties: {
padding: space,
backgroundColor: colors,
// ...
},
// ...
});
export const sprinkles = createSprinkles(responsiveProperties);
Check
sprinkles
docs for more context into how to create these atoms.
This function allow you to create a component and adding all your sprinkles
props.
This function is dedicated to use only with
react
for now. Downside of this function is that this will add a tiny runtime because have to iterate over given props of your component. I recommend use rainbow-sprinkles that give you the same and more with zero runtime.
Step 1: Create a .ts
file and use createComponentWithSprinkles(sprinkles)
function to generate your magic function, let's call that function createComponent
in the utils folder of our project for this example.
// utils/createComponentWithSprinkles.ts
import { createComponentWithSprinkles } from 'vanilla-icecream';
import { sprinkles } from '../sprinkles.css';
const createComponent = createComponentWithSprinkles(sprinkles);
Step 2: Create a .tsx
file for your component, example Box.tsx
and call createComponent
function that you create previously. This function need a required parameter called type
, that allow you to define the type of the component that you are creating. This allows you to create all type of HTML component like div
, button
, input
, img
, ...etc, and give your component the native props of that type of component.
// box.tsx
import { createComponent } from 'utils/createComponent';
const Box = createComponent('div');
An example is html
button
vsdiv
, htmlbutton
element have it a native prop calledtype
and htmldiv
does not have it. So you will get the correct types for your component.
Step 2.1: You can pass a second optional parameter to this createComponent
function for give your component default styles. This parameter give you 3 - 4 ways of you apply default styles to your component.
- You can use the
defaultClassName
property to assign default values to the htmlclassName
property.
// center.tsx
import { createComponent } from 'utils/createComponent';
import { componentStyle } from 'component.css';
const Center = createComponent('div', {
defaultClassName: 'd-flex center-items',
//or
defaultClassName: componentStyle,
});
- You can use the
defaultSprinkles
property to assign default sprinkles values.
// center.tsx
import { createComponent } from 'utils/createComponent';
const Center = createComponent('div', {
defaultSprinkles: {
display: 'flex',
flexPlaceItems: 'center',
background: { lightMode: 'primary.100', darkMode: 'primary.400' }
},
});
- You can use the
variantFn
property to assign default variants to your component. You have to pass the result of therecipe
function ofvanilla-extract
.
// center.css.ts
import { recipe } from '@vanilla-extract/recipes';
export const componentVariants = recipe({
....
});
// center.tsx
import { createComponent } from 'utils/createComponent';
import { componentVariants } from './center.css'
const Center = createComponent('div', {
variantFn: componentVariants
});
You can also mix them, but is not recomended.
Step 2.2: The return component has 2 additional props in addition to the properties of your sprinkles and the default html properties of the component. One is variant
and the other is as
.
variant
give you the ability to select the variant of the component.as
give you the ability to change the type of the component.
//Example of as and variant props
<Heading as={'h1'} variant={{ style: 'bigText', color: 'redText' }}>
Build with Vanilla Kit
</Heading>
<Box
display={'flex'}
justifyContent={{ mobile: 'center', desktop: 'space-between' }}
alignItems={'center'}
padding={'sm'}
background={{ lightMode: 'error.200', darkMode: 'error.100' }}
color={'error.200'}
>
Example
</Box>
This function allow you to extend the form of represent your colors when your defining your vars.
Default of vanilla-extract
//colors.css.ts
import { createColors } from 'vanilla-icecream';
export const colors = {
white: '#FFF',
black: '#000',
"primary.100":"#11F1BB",
"primary.200":"#10E0AE",
};
//theme.css.ts
import { createGlobalTheme } from '@vanilla-extract/css';
import { colors } from './colors.css';
export const vars = createGlobalTheme(':root', {
colors: colors,
//...
});
With createColors
function
//colors.css.ts
import { createColors } from 'vanilla-icecream';
export const colors = createColors({
white: '#FFF',
black: '#000',
primary: {
100: '#11F1BB',
200: '#10E0AE',
//...
},
error: {
100: '#F11122',
200: '#E01020',
//...
},
neutral: {
100: '#E0E0E0',
200: '#A0A0A0',
//...
}
});
//theme.css.ts
import { createGlobalTheme } from '@vanilla-extract/css';
import { colors } from './colors.css';
export const vars = createGlobalTheme(':root', {
colors: colors,
//...
});
Also, the result is a
Color
type, so only accept this color types: RGB | RGBA | HEX | HSV
createComponentWithAtoms: (sprinkles: SprinklesFn) =>
(type: JSX.IntrinsicElements, defaultStyles?: {
defaultClassName?: string,
defaultSprinkles?: Parameters<typeof sprinkles>[0],
variantFn?: RecipeVariants
})
=> ReactElement
createColors: (colorRecord: Record<string, string | Record<number, Color>>) =>
Record<string, Color>
type Color = RGB | RGBA | HEX | HSV;
Thanks to the team of vanilla-extract
for creating so amazing libraries.