A foundation of primitive building blocks for rapid component design and development
Explore the docs »
Bug Report
·
Feature Request
Table of Contents
There are many design systems packages available; however, I didn't find one that really suited all my needs or requirements so I've been building out my own. I wanted a small, simple yet extensible layer that work in conjunction with most css in js libraries that supported Typescript out of the box.
- Hooks directly into your existing theme
- Works with most css in js libraries, but built primarily to work along side styled-components
- Responsive out of the box, each primitive and foundation can output different styles based on configured breakpoints
- Existing foundations are set up to be unambiguous between the styles they produce
- Rapidly create your own set of foundations or hook easily hook into the ones already provided
Of course, no one package will serve all projects since your needs may be different. I'll be enhancing and adding to this package as requirements arise. You may also suggest changes by forking this repo and creating a pull request or opening an issue.
Styled Foundations is a collection of utility functions that allow you to extend your React components in a easy and predictable manner, allowing you to use your already configured theme to control your styles without needing to refactor large parts of your codebase.
Styled Foundations is to be used in conjunction with your css in js package of choice, if this is a new project you will need to install and configure one so Styled Foundations can be used.
To use Styled Foundations you'll need to install a css in js package such as styled-components, if you already have one installed you can skip that step and install just install styled-foundations.
yarn add styled-components
yarn add styled-foundations
Most css in js packages will provide you with some sort of ThemeProvider so you can access your projects theme when constructing your components. Styled Foundations will work out of the box with minimal additional configuration with your existing theme.
To make use of responsive foundations your theme will need to have a breakpoints property configured, this is how and where Styled Foundations looks when creating media queries when outputting css. You have two flavours to choose from, either an array of breakpoints or an object with named breakpoints, both have their pros and cons.
Breakpoint Array
// theme declaration that will be consumed by your css in js library
const theme = {
breakpoints: ['48em', '64em', '76em', '88em'],
}
// prop usage when calling upon your components (these reflect the order declared in your theme)
;<Block margin={['0.25rem', '0.5rem', '0.75rem', '1rem']} />
Breakpoint Object
A key advantage of using an object over an array is that when providing the props for your components you can easily skip over the breakpoint by not including it. You can also use the array syntax in the props as long as you have each desired value in order.
// theme declaration that will be consumed by your css in js library
const theme = {
breakpoints: {
sm: '48em',
md: '64em',
lg: '76em',
xl: '88em',
}
}
// prop usage when calling upon your components (_ is the default size)
<Block margin={{ _: '0', sm: '0.25rem', md: '0.5rem', lg: '0.75rem', xl: '1rem' }} />
// or skipping some breakpoints
<Block margin={{ _: '0', sm: '0.25rem', xl: '1rem' }} />
A foundation is the building block of Styled Foundations and is how you can easily construct reusable modifiers throughout your components. If there is a foundation that is not already provided by our existing set of foundations, you can create your own by using the foundation utility.
import type { Theme } from 'types'
import styled from 'styled-components'
import { foundation } from 'styled-foundations'
const color = foundation<Theme>({
prop: ['color', 'colour'],
properties: {
color: {
theme: 'colors',
fallback: '#00DC82',
},
},
})
const ColoredParagraph = styled.p`
${color}
`
export default ColoredParagraph
The color foundation created here will allow you to provide either a color or colour prop to specify what text color the paragraph tag will be. It will look in your theme too and pickup and values under the colors property. If no color property is set on the ColoredParagraph component it will fallback and use #00DC82 as a default value.
prop
either a string or an array of the names of the props to be used on the componentproperties
a object of css properties to be used in the returned stylesproperties.theme
a string with the key or path to an object of key value pairs in your themeproperties.fallback
a string of the value which should be used if a value isn't found or provided
If your foundation does not need to use your theme, or have any fallbacks you can easily omit that by using a shorthand declaration of the foundation utility.
const paddingY = foundation({
prop: 'py',
properties: {
paddingTop: true,
paddingBottom: true,
},
})
If you're finding you are needing to group multiple foundations into a single object so you can easily import it to be used in your components, you can do so with the following syntax. Each option here can then be accessed via your components.
const padding = foundation([
{
prop: 'px',
properties: {
paddingLeft: true,
paddingRight: true,
},
},
{
prop: 'py',
properties: {
paddingTop: true,
paddingBottom: true,
},
},
])
There currently are a few already prebuilt foundations you can use, I do plan to extend upon these! Here are a few you can directly import into your projects. The props are all optional and support both longhand names and shorthand names.
name | props | theme | type |
---|---|---|---|
color | color, colour, bg, backgoundColor | colors | ColorProps |
display | display | DisplayProps | |
flex | flex, flexBasis, flexDirection, flexFlow, flexGrow, flexShrink, flexWrap, alignContent, alignItems, alignSelf, gridGap, justifyContent | FlexProps | |
layout | height, minHeight, maxHeight, width, minWidth, maxWidth, overflow, overflowX, overflowY, size | space | LayoutProps |
margin | margin, m, mt, marginTop, mr, marginRight, mb, marginBottom, ml, marginLeft | space | MarginProps |
padding | padding, p, pt, paddingTop, pr, paddingRight, pb, paddingBottom, pl, paddingLeft | space | PaddingProps |
position | position | PositionProps | |
text align | textAlign | TextAlignProps |
import type { MarginProps, PaddingProps } from 'styled-foundations'
import { margin, padding } from 'styled-foundations'
type BlockProps = MarginProps & PaddingProps
const Block = styled.div<BlockProps>`
${margin}
${padding}
`
// example component usage
<Block my="10px" px="5px" />
You can use variants to apply different styles based on props, this can be useful when you're wanting to support multiple looks of a single reusable component. You can use this inline inside the component itself, or use a reference like in the example below.
type Shape = 'square' | 'round' | 'pill'
const shape = variant<Shape>({
prop: 'shape',
variants: {
square: {
borderRadius: '0px',
},
round: {
borderRadius: '10px',
},
pill: {
borderRadius: '100px',
},
},
})
const Button = styled.button`
${shape}
`
// example component usage
<Button shape="round" />
The conditional foundation is used to colocate all your toggleable props in a single area, where they are no longer sporadically defined across a complex component with all the odd formatting they induce. You simply define either the success styles (if the condition passes where it is true), or any failure styles that could otherwise occur.
type ButtonProps = {
wide?: boolean
disabled?: boolean
}
const conditionals = conditional({
success: {
wide: {
width: '100%',
},
disabled: {
opacity: 0.6,
},
},
failure: {
disabled: {
opacity: 1
}
}
})
const Button = styled.button<ButtonProps>`
${conditionals}
`
// example component usage
<Button wide disabled />
- add responsive foundation to hook into breakpoints to remove the need to write media queries.
- add more prebuilt foundations
- improve documentation
- add unit tests
See the open issues for a full list of proposed features (and known issues).
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/amazing-feature
) - Commit your Changes (
git commit -m 'feat: add some amazing feature'
) - Push to the Branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Distributed under the MIT License. See LICENSE
for more information.
This project was inspired by styled-systems, an existing package that seems to be abandoned. I've created this package to better support my needs and any community needs, where I plan to continually add them here as required.