Last active
April 19, 2023 22:51
-
-
Save kjbrum/a5a0bd2bebcd5e8701ff2ef971d66967 to your computer and use it in GitHub Desktop.
React primitive components using styled-system (with styled-components).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# React Primitives | |
> React primitive components using styled-system. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { forwardRef } from 'react' | |
import styled from 'styled-components' | |
import css, { get } from '@styled-system/css' | |
import { | |
system, | |
compose, | |
space, | |
color, | |
typography, | |
layout, | |
flexbox, | |
grid, | |
background, | |
border, | |
position, | |
shadow, | |
} from 'styled-system' | |
import { getMarginProps, omitMarginProps } from '@utils/helpers' | |
// Next Link | |
// import { default as NextLink } from 'next/link' | |
// Gatsby Link | |
// import { Link as GatsbyLink } from 'gatsby' | |
const base = props => css(props.__css) | |
const sx = props => css(props.sx) | |
const variant = ({ theme, variant, tx = '' }) => | |
css(get(theme, 'variants.' + tx + '.' + variant))(theme) | |
export const Box = styled.div( | |
css({ | |
// boxSizing: 'border-box', | |
// minWidth: 0, | |
// margin: 0, | |
// fontFamily: 'sans', | |
// color: 'gray.900', | |
}), | |
base, | |
variant, | |
sx, | |
props => props.css, | |
system({ | |
textTransform: true, | |
textDecoration: true, | |
transform: true, | |
transition: true, | |
visibility: true, | |
pointerEvent: true, | |
}), | |
compose( | |
space, | |
color, | |
typography, | |
layout, | |
flexbox, | |
grid, | |
background, | |
border, | |
position, | |
shadow | |
) | |
) | |
export const Flex = styled(Box)({ | |
display: 'flex', | |
}) | |
export const Grid = forwardRef((props, ref) => ( | |
<Box | |
ref={ref} | |
tx="grid" | |
__css={css({ | |
display: 'grid', | |
})} | |
{...props} | |
/> | |
)) | |
export const Text = forwardRef((props, ref) => ( | |
<Box ref={ref} as="p" tx="texts" {...props} /> | |
)) | |
export const Heading = forwardRef((props, ref) => ( | |
<Box ref={ref} as="h2" tx="headings" variant="h2" {...props} /> | |
)) | |
export const Link = forwardRef((props, ref) => ( | |
<Box ref={ref} as="a" tx="links" {...props} /> | |
)) | |
// Next | |
// export const Link = forwardRef( | |
// ({ href, as, prefetch, replace, scroll, ...props }, ref) => | |
// href && (href.startsWith('/') || href.startsWith('#')) ? ( | |
// <NextLink | |
// as={as} | |
// href={href} | |
// prefetch={prefetch} | |
// replace={replace} | |
// scroll={scroll} | |
// passHref | |
// > | |
// <Box ref={ref} as="a" tx="links" {...props} /> | |
// </NextLink> | |
// ) : ( | |
// <Box | |
// ref={ref} | |
// as="a" | |
// href={href} | |
// rel="nofollow noopener" | |
// tx="links" | |
// {...props} | |
// /> | |
// ) | |
// ) | |
// Gatsby | |
// export const Link = forwardRef(({ href, to, isExternal, ...props }, ref) => { | |
// const url = to || href | |
// return isExternal || isAbsoluteURL(url) ? ( | |
// <Box | |
// ref={ref} | |
// as="a" | |
// href={url} | |
// rel="nofollow noopener" | |
// tx="links" | |
// {...props} | |
// /> | |
// ) : ( | |
// <Box ref={ref} as={GatsbyLink} to={url} tx="links" {...props} /> | |
// ) | |
// }) | |
export const Divider = forwardRef((props, ref) => ( | |
<Box | |
ref={ref} | |
as="hr" | |
tx="dividers" | |
__css={css({ | |
height: 'px', | |
my: 8, | |
bg: 'gray.300', | |
border: 'none', | |
})} | |
{...props} | |
/> | |
)) | |
export const Button = forwardRef((props, ref) => { | |
const defaultStyles = { | |
cursor: 'pointer', | |
appearance: 'none', | |
display: 'inline-block', | |
textAlign: 'center', | |
lineHeight: 'inherit', | |
textDecoration: 'none', | |
fontSize: 'inherit', | |
} | |
const specialStyles = | |
props.variant !== 'plain' | |
? { | |
px: 6, | |
py: 3, | |
border: 1, | |
borderRadius: 3, | |
} | |
: { | |
'&:hover': { | |
color: 'gray.600', | |
}, | |
} | |
return ( | |
<Box | |
ref={ref} | |
as="button" | |
tx="buttons" | |
variant="primary" | |
__css={css({ | |
...defaultStyles, | |
...specialStyles, | |
})} | |
{...props} | |
/> | |
) | |
}) | |
export const Image = forwardRef((props, ref) => ( | |
<Box ref={ref} as="img" tx="images" alt="" {...props} /> | |
)) | |
export const SVG = ({ width = 16, height = 16, ...props }) => ( | |
<Box | |
as="svg" | |
xmlns="http://www.w3.org/2000/svg" | |
// width={width || null} | |
// height={height || null} | |
viewBox={`0 0 ${parseInt(width, 10)} ${parseInt(height, 10)}`} | |
fill="currentcolor" | |
{...props} | |
/> | |
) | |
export const Code = forwardRef((props, ref) => { | |
const sharedStyles = { | |
m: '0', | |
direction: 'ltr', | |
fontFamily: 'mono', | |
color: 'gray.900', | |
textAlign: 'left', | |
fontSize: 'xs', | |
fontWeight: 'normal', | |
lineHeight: 'normal', | |
textDecoration: 'none', | |
whiteSpace: 'pre', | |
wordSpacing: 'normal', | |
wordBreak: 'normal', | |
wordWrap: 'normal', | |
tabSize: '4', | |
hyphens: 'none', | |
bg: 'gray.100', | |
borderRadius: 3, | |
} | |
return ( | |
<Box | |
as="pre" | |
{...getMarginProps(props)} | |
__css={css({ | |
...sharedStyles, | |
overflow: 'auto', | |
p: 4, | |
border: '1px solid', | |
borderColor: 'gray.200', | |
})} | |
> | |
<Box | |
ref={ref} | |
as="code" | |
tx="code" | |
{...omitMarginProps(props)} | |
__css={css({ | |
...sharedStyles, | |
})} | |
/> | |
</Box> | |
) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createGlobalStyle } from 'styled-components' | |
export const CSSReset = createGlobalStyle` | |
/* CSS Reset (Inspired by TailwindCSS) */ | |
html{ | |
line-height: 1.15; | |
-webkit-text-size-adjust: 100%; | |
} | |
body{ | |
margin: 0; | |
} | |
main{ | |
display: block; | |
} | |
hr{ | |
box-sizing: content-box; | |
height: 0; | |
overflow: visible; | |
} | |
pre{ | |
font-family: monospace,monospace; | |
font-size: 1em; | |
} | |
a{ | |
background-color: transparent; | |
} | |
abbr[title]{ | |
border-bottom: none; | |
text-decoration: underline; | |
-webkit-text-decoration: underline dotted; | |
text-decoration: underline dotted; | |
} | |
b,strong{ | |
font-weight: bold; | |
} | |
code,kbd,samp{ | |
font-family: monospace,monospace; | |
font-size: 1em; | |
} | |
small{ | |
font-size: 80%; | |
} | |
sub,sup{ | |
font-size: 75%; | |
line-height: 0; | |
position: relative; | |
vertical-align: baseline; | |
} | |
sub{ | |
bottom: -0.25em; | |
} | |
sup{ | |
top: -.5em; | |
} | |
img{ | |
border-style: none; | |
} | |
button,input,optgroup,select,textarea{ | |
font-family: inherit; | |
font-size: 100%; | |
line-height: 1.15; | |
margin: 0; | |
} | |
button,input{ | |
overflow: visible; | |
} | |
button,select{ | |
text-transform: none; | |
} | |
[type=button],[type=reset],[type=submit],button{ | |
-webkit-appearance: button; | |
} | |
[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{ | |
border-style: none; | |
padding: 0; | |
} | |
[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{ | |
outline: 1px dotted ButtonText; | |
} | |
fieldset{ | |
padding: 0.35em 0.75em 0.625em; | |
} | |
legend{ | |
box-sizing: border-box; | |
color: inherit; | |
display: table; | |
max-width: 100%; | |
padding: 0; | |
white-space: normal; | |
} | |
progress{ | |
vertical-align: baseline; | |
} | |
textarea{ | |
overflow: auto; | |
} | |
[type=checkbox], | |
[type=radio]{ | |
box-sizing: border-box; | |
padding: 0; | |
} | |
[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{ | |
height: auto; | |
} | |
[type=search]{ | |
-webkit-appearance: textfield; | |
outline-offset: -2px; | |
} | |
[type=search]::-webkit-search-decoration{ | |
-webkit-appearance: none; | |
} | |
::-webkit-file-upload-button{ | |
-webkit-appearance: button; | |
font: inherit; | |
} | |
details{ | |
display: block; | |
} | |
summary{ | |
display: list-item; | |
} | |
template{ | |
display: none; | |
} | |
[hidden]{ | |
display: none; | |
} | |
html{ | |
box-sizing: border-box; | |
font-family: sans-serif; | |
} | |
*,::after,::before{ | |
box-sizing: inherit; | |
} | |
blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{ | |
margin: 0; | |
} | |
button{ | |
background: 0 0; | |
padding: 0; | |
border: 0; | |
} | |
button:focus{ | |
outline: 1px dotted; | |
outline: 5px auto -webkit-focus-ring-color; | |
} | |
fieldset{ | |
margin: 0; | |
padding: 0; | |
} | |
ol,ul{ | |
list-style: none; | |
margin: 0; | |
padding: 0; | |
} | |
html{ | |
font-family: ${props => props.theme.fonts.sans}; | |
line-height: 1.5; | |
} | |
img{ | |
border: 0; | |
} | |
textarea{ | |
resize: vertical; | |
} | |
input:-ms-input-placeholder,textarea:-ms-input-placeholder{ | |
color: ${props => props.theme.colors.neutral[700]}; | |
} | |
input::-ms-input-placeholder,textarea::-ms-input-placeholder{ | |
color: ${props => props.theme.colors.neutral[700]}; | |
} | |
input::placeholder,textarea::placeholder{ | |
color: ${props => props.theme.colors.neutral[700]}; | |
} | |
[role=button],button{ | |
cursor: pointer; | |
} | |
table{ | |
border-collapse: collapse; | |
} | |
h1,h2,h3,h4,h5,h6{ | |
font-size: inherit; | |
font-weight: inherit; | |
} | |
a{ | |
color: inherit; | |
text-decoration: inherit; | |
} | |
button,input,optgroup,select,textarea{ | |
padding: 0; | |
line-height: inherit; | |
color: inherit; | |
} | |
code,kbd,pre,samp{ | |
font-family: ${props => props.theme.fonts.mono} | |
} | |
audio,canvas,embed,iframe,img,object,svg,video{ | |
display: block; | |
vertical-align: middle; | |
} | |
img,video{ | |
max-width: 100%; | |
height: auto; | |
} | |
` | |
export default CSSReset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { forwardRef } from 'react' | |
import { Box, Flex, SVG } from './Base' | |
import { getMarginProps, omitMarginProps } from '@utils/helpers' | |
export const Label = forwardRef((props, ref) => ( | |
<Flex | |
ref={ref} | |
as="label" | |
tx="forms" | |
variant="label" | |
{...props} | |
__css={{ | |
width: '100%', | |
fontWeight: 'bold', | |
cursor: 'pointer', | |
}} | |
/> | |
)) | |
export const Input = forwardRef((props, ref) => ( | |
<Box | |
ref={ref} | |
as="input" | |
type="text" | |
tx="forms" | |
variant="input" | |
{...props} | |
__css={{ | |
display: 'block', | |
width: '100%', | |
p: 2, | |
appearance: 'none', | |
fontSize: 'inherit', | |
lineHeight: 'inherit', | |
border: '1px solid', | |
borderRadius: 3, | |
color: 'inherit', | |
bg: 'transparent', | |
}} | |
/> | |
)) | |
export const Textarea = forwardRef((props, ref) => ( | |
<Box | |
ref={ref} | |
as="textarea" | |
tx="forms" | |
variant="textarea" | |
{...props} | |
__css={{ | |
display: 'block', | |
width: '100%', | |
p: 2, | |
appearance: 'none', | |
fontSize: 'inherit', | |
lineHeight: 'inherit', | |
border: '1px solid', | |
borderRadius: 3, | |
color: 'inherit', | |
bg: 'transparent', | |
}} | |
/> | |
)) | |
const SelectArrow = props => ( | |
<SVG {...props}> | |
<path d="M5.293 6.95L6 7.657 11.657 2 10.243.586 6 4.828 1.757.586.343 2z" /> | |
</SVG> | |
) | |
export const Select = forwardRef((props, ref) => ( | |
<Flex {...getMarginProps(props)}> | |
<Box | |
ref={ref} | |
as="select" | |
tx="forms" | |
variant="select" | |
{...omitMarginProps(props)} | |
__css={{ | |
display: 'block', | |
width: '100%', | |
p: 2, | |
appearance: 'none', | |
fontSize: 'inherit', | |
lineHeight: 'inherit', | |
border: '1px solid', | |
borderRadius: 3, | |
color: 'inherit', | |
bg: 'transparent', | |
}} | |
/> | |
<SelectArrow | |
width="12" | |
height="8" | |
aria-hidden={true} | |
sx={{ | |
position: 'relative', | |
right: 2, | |
ml: '-12px', | |
alignSelf: 'center', | |
pointerEvents: 'none', | |
}} | |
/> | |
</Flex> | |
)) | |
const RadioChecked = props => ( | |
<SVG {...props}> | |
<path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" /> | |
</SVG> | |
) | |
const RadioUnchecked = props => ( | |
<SVG {...props}> | |
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" /> | |
</SVG> | |
) | |
const RadioIcon = props => ( | |
<> | |
<RadioChecked | |
{...props} | |
__css={{ | |
display: 'none', | |
'input:checked ~ &': { | |
display: 'block', | |
}, | |
}} | |
/> | |
<RadioUnchecked | |
{...props} | |
__css={{ | |
display: 'block', | |
'input:checked ~ &': { | |
display: 'none', | |
}, | |
}} | |
/> | |
</> | |
) | |
export const Radio = forwardRef( | |
({ className, sx, variant = 'radio', ...props }, ref) => ( | |
<Box> | |
<Box | |
ref={ref} | |
as="input" | |
type="radio" | |
{...props} | |
sx={{ | |
position: 'absolute', | |
overflow: 'hidden', | |
width: 1, | |
height: 1, | |
opacity: 0, | |
zIndex: -1, | |
}} | |
/> | |
<Box | |
as={RadioIcon} | |
aria-hidden={true} | |
tx="forms" | |
variant={variant} | |
className={className} | |
sx={sx} | |
// {...getSystemProps(props)} | |
__css={{ | |
mr: 2, | |
borderRadius: 'full', | |
color: 'gray', | |
'input:checked ~ &': { | |
color: 'gray.900', | |
}, | |
'input:focus ~ &': { | |
bg: 'gray.400', | |
}, | |
}} | |
/> | |
</Box> | |
) | |
) | |
const CheckboxChecked = props => ( | |
<SVG {...props}> | |
<path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" /> | |
</SVG> | |
) | |
const CheckboxUnchecked = props => ( | |
<SVG {...props}> | |
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z" /> | |
</SVG> | |
) | |
const CheckboxIcon = props => ( | |
<> | |
<CheckboxChecked | |
{...props} | |
__css={{ | |
display: 'none', | |
'input:checked ~ &': { | |
display: 'block', | |
}, | |
}} | |
/> | |
<CheckboxUnchecked | |
{...props} | |
__css={{ | |
display: 'block', | |
'input:checked ~ &': { | |
display: 'none', | |
}, | |
}} | |
/> | |
</> | |
) | |
export const Checkbox = forwardRef( | |
({ className, sx, variant = 'checkbox', ...props }, ref) => ( | |
<Box> | |
<Box | |
ref={ref} | |
as="input" | |
type="checkbox" | |
{...props} | |
sx={{ | |
position: 'absolute', | |
opacity: 0, | |
zIndex: -1, | |
width: 1, | |
height: 1, | |
overflow: 'hidden', | |
}} | |
/> | |
<Box | |
as={CheckboxIcon} | |
aria-hidden={true} | |
tx="forms" | |
variant={variant} | |
className={className} | |
sx={sx} | |
// {...getSystemProps(props)} | |
__css={{ | |
mr: 2, | |
borderRadius: 3, | |
color: 'gray.900', | |
'input:checked ~ &': { | |
color: 'gray.900', | |
}, | |
'input:focus ~ &': { | |
color: 'gray.900', | |
bg: 'gray.400', | |
}, | |
}} | |
/> | |
</Box> | |
) | |
) | |
export const Switch = forwardRef(({ checked, ...props }, ref) => { | |
const switchSize = 6 | |
return ( | |
<Box | |
ref={ref} | |
as="button" | |
type="button" | |
role="switch" | |
tx="forms" | |
variant="switch" | |
aria-checked={checked} | |
{...props} | |
__css={{ | |
appearance: 'none', | |
m: 0, | |
p: 0, | |
width: switchSize * 2, | |
height: switchSize, | |
color: 'gray.600', | |
bg: 'transparent', | |
border: '1px solid', | |
borderColor: 'gray.900', | |
borderRadius: 'full', | |
// '&[aria-checked=true]': { | |
// bg: 'gray.100', | |
// }, | |
':focus': { | |
outline: 'none', | |
boxShadow: '0 0 0 2px', | |
}, | |
}} | |
> | |
<Box | |
aria-hidden={true} | |
style={{ | |
transform: checked | |
? `translateX(${switchSize * 4}px)` | |
: 'translateX(0)', | |
}} | |
sx={{ | |
mt: '-1px', | |
ml: '-1px', | |
width: switchSize, | |
height: switchSize, | |
borderRadius: 'full', | |
border: '1px solid', | |
borderColor: 'gray.900', | |
bg: checked ? 'gray.700' : 'gray.400', | |
transitionProperty: 'transform', | |
transitionTimingFunction: 'ease-out', | |
transitionDuration: '0.1s', | |
}} | |
/> | |
</Box> | |
) | |
}) | |
export const Slider = forwardRef(({ ...props }, ref) => ( | |
<Box | |
ref={ref} | |
as="input" | |
type="range" | |
tx="forms" | |
variant="slider" | |
{...props} | |
__css={{ | |
display: 'block', | |
width: '100%', | |
height: '2px', | |
my: 3, | |
cursor: 'pointer', | |
appearance: 'none', | |
borderRadius: 'full', | |
color: 'gray.500', | |
bg: 'gray.200', | |
':focus': { | |
outline: 'none', | |
color: 'gray.700', | |
}, | |
'&::-webkit-slider-thumb': { | |
appearance: 'none', | |
width: 6, | |
height: 6, | |
bg: 'currentcolor', | |
border: '1px solid', | |
borderColor: 'gray.900', | |
borderRadius: 'full', | |
}, | |
}} | |
/> | |
)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createGlobalStyle } from 'styled-components' | |
export const GlobalStyles = createGlobalStyle` | |
html, | |
body { | |
box-sizing: border-box; | |
overflow-x: hidden; | |
min-width: 320px; | |
max-width: 100%; | |
margin: 0; | |
font-family: ${props => props.theme.fonts.sans}; | |
color: ${props => props.theme.colors.neutral[900]}; | |
} | |
` | |
export default GlobalStyles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Retrieve a key value from an object | |
export function get(object, key) { | |
var keys = key.split('.') | |
for (var i = 0; i < keys.length; i++) { | |
if (!object.hasOwnProperty(keys[i])) { | |
return null | |
} | |
object = object[keys[i]] | |
} | |
return object | |
} | |
// Remove margin values from props | |
const MRE = /^m[trblxy]?$/ | |
export const getProps = test => props => { | |
const next = {} | |
for (const key in props) { | |
if (test(key || '')) next[key] = props[key] | |
} | |
return next | |
} | |
export const getMarginProps = getProps(k => MRE.test(k)) | |
export const omitMarginProps = getProps(k => !MRE.test(k)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { fluidRange } from 'polished' | |
export const theme = { | |
breakpoints: [ | |
'30rem', // xs / 480px | |
'40rem', // sm / 640px | |
'48rem', // md / 768px | |
'64rem', // lg / 1024px | |
'80rem', // xl / 1280px | |
], | |
colors: { | |
transparent: 'transparent', | |
black: '#222222', | |
white: '#ffffff', | |
gray: { | |
100: '#f7fafc', | |
200: '#edf2f7', | |
300: '#e2e8f0', | |
400: '#cbd5e0', | |
500: '#a0aec0', | |
600: '#718096', | |
700: '#4a5568', | |
800: '#2d3748', | |
900: '#1a202c', | |
}, | |
red: { | |
100: '#fff5f5', | |
200: '#fed7d7', | |
300: '#feb2b2', | |
400: '#fc8181', | |
500: '#f56565', | |
600: '#e53e3e', | |
700: '#c53030', | |
800: '#9b2c2c', | |
900: '#742a2a', | |
}, | |
orange: { | |
100: '#fffaf0', | |
200: '#feebc8', | |
300: '#fbd38d', | |
400: '#f6ad55', | |
500: '#ed8936', | |
600: '#dd6b20', | |
700: '#c05621', | |
800: '#9c4221', | |
900: '#7b341e', | |
}, | |
yellow: { | |
100: '#fffff0', | |
200: '#fefcbf', | |
300: '#faf089', | |
400: '#f6e05e', | |
500: '#ecc94b', | |
600: '#d69e2e', | |
700: '#b7791f', | |
800: '#975a16', | |
900: '#744210', | |
}, | |
green: { | |
100: '#f0fff4', | |
200: '#c6f6d5', | |
300: '#9ae6b4', | |
400: '#68d391', | |
500: '#48bb78', | |
600: '#38a169', | |
700: '#2f855a', | |
800: '#276749', | |
900: '#22543d', | |
}, | |
teal: { | |
100: '#e6fffa', | |
200: '#b2f5ea', | |
300: '#81e6d9', | |
400: '#4fd1c5', | |
500: '#38b2ac', | |
600: '#319795', | |
700: '#2c7a7b', | |
800: '#285e61', | |
900: '#234e52', | |
}, | |
blue: { | |
100: '#ebf8ff', | |
200: '#bee3f8', | |
300: '#90cdf4', | |
400: '#63b3ed', | |
500: '#4299e1', | |
600: '#3182ce', | |
700: '#2b6cb0', | |
800: '#2c5282', | |
900: '#2a4365', | |
}, | |
indigo: { | |
100: '#ebf4ff', | |
200: '#c3dafe', | |
300: '#a3bffa', | |
400: '#7f9cf5', | |
500: '#667eea', | |
600: '#5a67d8', | |
700: '#4c51bf', | |
800: '#434190', | |
900: '#3c366b', | |
}, | |
purple: { | |
100: '#faf5ff', | |
200: '#e9d8fd', | |
300: '#d6bcfa', | |
400: '#b794f4', | |
500: '#9f7aea', | |
600: '#805ad5', | |
700: '#6b46c1', | |
800: '#553c9a', | |
900: '#44337a', | |
}, | |
pink: { | |
100: '#fff5f7', | |
200: '#fed7e2', | |
300: '#fbb6ce', | |
400: '#f687b3', | |
500: '#ed64a6', | |
600: '#d53f8c', | |
700: '#b83280', | |
800: '#97266d', | |
900: '#702459', | |
}, | |
}, | |
space: { | |
auto: 'auto', | |
px: '1px', | |
em: '1em', | |
0: '0', | |
1: '0.25rem', | |
2: '0.5rem', | |
3: '0.75rem', | |
4: '1rem', | |
5: '1.25rem', | |
6: '1.5rem', | |
8: '2rem', | |
10: '2.5rem', | |
12: '3rem', | |
16: '4rem', | |
20: '5rem', | |
24: '6rem', | |
32: '8rem', | |
40: '10rem', | |
48: '12rem', | |
56: '14rem', | |
64: '16rem', | |
80: '20rem', | |
96: '24rem', | |
128: '32rem', | |
160: '40rem', | |
192: '48rem', | |
224: '56rem', | |
256: '64rem', | |
screenW: '100vw', | |
screenH: '100vh', | |
full: '100%', | |
}, | |
sizes: { | |
auto: 'auto', | |
px: '1px', | |
em: '1em', | |
0: '0', | |
1: '0.25rem', | |
2: '0.5rem', | |
3: '0.75rem', | |
4: '1rem', | |
5: '1.25rem', | |
6: '1.5rem', | |
8: '2rem', | |
10: '2.5rem', | |
12: '3rem', | |
16: '4rem', | |
20: '5rem', | |
24: '6rem', | |
32: '8rem', | |
40: '10rem', | |
48: '12rem', | |
56: '14rem', | |
64: '16rem', | |
80: '20rem', | |
96: '24rem', | |
128: '32rem', | |
160: '40rem', | |
192: '48rem', | |
224: '56rem', | |
256: '64rem', | |
screenW: '100vw', | |
screenH: '100vh', | |
full: '100%', | |
}, | |
fonts: { | |
sans: | |
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"', | |
serif: 'Georgia, Cambria, "Times New Roman", Times, serif', | |
mono: | |
'Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', | |
}, | |
fontSizes: { | |
xxs: '0.625rem', | |
xs: '0.75rem', | |
sm: '0.875rem', | |
base: '1rem', | |
lg: '1.125rem', | |
xl: '1.25rem', | |
'2xl': '1.5rem', | |
'3xl': '1.875rem', | |
'4xl': '2.25rem', | |
'5xl': '3rem', | |
'6xl': '4rem', | |
}, | |
fontWeights: { | |
hairline: '100', | |
thin: '200', | |
light: '300', | |
normal: '400', | |
medium: '500', | |
semibold: '600', | |
bold: '700', | |
extrabold: '800', | |
black: '900', | |
}, | |
lineHeights: { | |
none: '1', | |
tight: '1.25', | |
snug: '1.375', | |
normal: '1.5', | |
relaxed: '1.625', | |
loose: '2', | |
}, | |
letterSpacings: { | |
tighter: '-0.05em', | |
tight: '-0.025em', | |
normal: '0', | |
wide: '0.025em', | |
wider: '0.05em', | |
widest: '0.1em', | |
}, | |
borders: { | |
none: '0', | |
1: '1px solid', | |
2: '2px solid', | |
4: '4px solid', | |
8: '8px solid', | |
}, | |
borderWidths: { | |
0: '0px', | |
1: '1px', | |
2: '2px', | |
4: '4px', | |
8: '8px', | |
}, | |
radii: { | |
none: '0', | |
3: '3px', | |
5: '5px', | |
8: '8px', | |
16: '16px', | |
100: '100%', | |
full: '9999px', | |
}, | |
shadows: { | |
none: 'none', | |
default: | |
'0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)', | |
md: | |
'0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)', | |
lg: | |
'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)', | |
xl: | |
'0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)', | |
outline: '0 0 0 3px rgba(66, 153, 225, 0.5)', | |
}, | |
zIndices: { | |
auto: 'auto', | |
bottom: '-9999', | |
'0': '0', | |
'10': '10', | |
'20': '20', | |
'30': '30', | |
'40': '40', | |
'50': '50', | |
top: '9999', | |
}, | |
} | |
// Breakpoint aliases | |
theme.breakpoints.xs = theme.breakpoints[0] | |
theme.breakpoints.sm = theme.breakpoints[1] | |
theme.breakpoints.md = theme.breakpoints[2] | |
theme.breakpoints.lg = theme.breakpoints[3] | |
theme.breakpoints.xl = theme.breakpoints[4] | |
// Sizes aliases | |
theme.sizes = { | |
...theme.space, | |
xs: theme.breakpoints.xs, | |
sm: theme.breakpoints.sm, | |
md: theme.breakpoints.md, | |
lg: theme.breakpoints.lg, | |
xl: theme.breakpoints.xl, | |
xxl: theme.breakpoints.xxl, | |
xxxl: theme.breakpoints.xxxl, | |
} | |
const fluidFont = (min, max) => | |
fluidRange( | |
{ | |
prop: 'font-size', | |
fromSize: theme.fontSizes[min], | |
toSize: theme.fontSizes[max], | |
}, | |
theme.breakpoints['xs'], | |
theme.breakpoints['xl'] | |
) | |
theme.variants = { | |
general: {}, | |
flex: {}, | |
grid: {}, | |
texts: {}, | |
headings: { | |
display1: { | |
...fluidFont('2xl', '6xl'), | |
lineHeight: 'none', | |
}, | |
display2: { | |
...fluidFont('2xl', '5xl'), | |
lineHeight: 'none', | |
}, | |
h1: { | |
...fluidFont('xl', '4xl'), | |
lineHeight: 'none', | |
}, | |
h2: { | |
...fluidFont('xl', '3xl'), | |
lineHeight: 'tight', | |
}, | |
h3: { | |
...fluidFont('xl', '2xl'), | |
lineHeight: 'tight', | |
}, | |
h4: { | |
...fluidFont('base', 'xl'), | |
lineHeight: 'tight', | |
}, | |
h5: { | |
fontSize: 'base', | |
}, | |
h6: { | |
fontSize: 'xs', | |
}, | |
}, | |
links: {}, | |
dividers: {}, | |
buttons: { | |
primary: { | |
px: 6, | |
py: 3, | |
color: 'white', | |
bg: 'gray.700', | |
border: 1, | |
borderColor: 'gray.700', | |
borderRadius: 3, | |
':hover': { | |
bg: 'gray.500', | |
borderColor: 'gray.500', | |
}, | |
}, | |
outline: { | |
px: 6, | |
py: 3, | |
color: 'gray.700', | |
bg: 'transparent', | |
border: 1, | |
borderColor: 'gray.700', | |
borderRadius: 3, | |
':hover': { | |
color: 'gray.500', | |
borderColor: 'gray.500', | |
}, | |
}, | |
}, | |
images: {}, | |
forms: { | |
label: {}, | |
error: { | |
fontSize: 'sm', | |
color: 'red', | |
}, | |
input: {}, | |
textarea: {}, | |
select: {}, | |
radio: {}, | |
checkbox: {}, | |
switch: {}, | |
slider: {}, | |
}, | |
} | |
export default theme |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment