Last active
June 11, 2021 19:32
-
-
Save smashercosmo/1b39a0c70268e74294300bcbd3878f88 to your computer and use it in GitHub Desktop.
Base 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
.root { | |
--pl: initial; | |
--pr: initial; | |
--pt: initial; | |
--pb: initial; | |
--ml: initial; | |
--mr: initial; | |
--mt: initial; | |
--mb: initial; | |
--w: initial; | |
--h: initial; | |
--max-w: initial; | |
--min-w: initial; | |
--max-h: initial; | |
--min-h: initial; | |
--d: initial; | |
padding: var(--pt, 0) var(--pr, 0) var(--pb, 0) var(--pl, 0); | |
margin: var(--mt, 0) var(--mr, 0) var(--mb, 0) var(--ml, 0); | |
width: var(--w); | |
height: var(--h); | |
min-width: var(--min-w); | |
min-height: var(--min-h); | |
max-width: var(--max-w); | |
max-height: var(--max-h); | |
display: var(--d); | |
} | |
div.box { | |
display: var(--d, block); | |
} | |
div.grid { | |
display: var(--d, grid); | |
} | |
div.flex { | |
display: var(--d, flex); | |
} |
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 from 'react' | |
import clsx from 'clsx' | |
import { getPadding } from './getPadding' | |
import { getMargin } from './getMargin' | |
import { getDimensions } from './getDimensions' | |
import './Base.css' | |
type Padding = string | number | |
type Margin = string | number | |
type Dimensions = string | number | |
type Display = | |
| 'flex' | |
| 'grid' | |
| 'inline' | |
| 'block' | |
| 'inline-block' | |
| 'none' | |
type BaseProps = { | |
p?: Padding | |
px?: Padding | |
py?: Padding | |
pl?: Padding | |
pr?: Padding | |
pt?: Padding | |
pb?: Padding | |
m?: Margin | |
mx?: Margin | |
my?: Margin | |
ml?: Margin | |
mr?: Margin | |
mt?: Margin | |
mb?: Margin | |
width?: Dimensions | |
height?: Dimensions | |
minHeight?: Dimensions | |
minWidth?: Dimensions | |
maxHeight?: Dimensions | |
maxWidth?: Dimensions | |
display?: Display | |
__dangerousClassName?: string | |
__dangerousStyle?: React.CSSProperties | |
} | |
function useProps<P>({ | |
props, | |
componentClassName, | |
}: { | |
props: BaseProps & P | |
componentClassName?: string | |
}) { | |
const { | |
p, | |
px, | |
py, | |
pl, | |
pr, | |
pt, | |
pb, | |
m, | |
mx, | |
my, | |
ml, | |
mr, | |
mt, | |
mb, | |
width, | |
height, | |
minWidth, | |
minHeight, | |
maxWidth, | |
maxHeight, | |
display, | |
__dangerousStyle, | |
__dangerousClassName, | |
...rest | |
} = props | |
const className = clsx('root', componentClassName, __dangerousClassName) | |
const style = { | |
...getPadding({ p, px, py, pl, pr, pt, pb }), | |
...getMargin({ m, mx, my, ml, mr, mt, mb }), | |
...getDimensions({ | |
width, | |
height, | |
maxWidth, | |
maxHeight, | |
minWidth, | |
minHeight, | |
}), | |
...(display !== undefined && { ['--d']: display }), | |
...__dangerousStyle, | |
} | |
return { | |
style, | |
className, | |
props: rest, | |
} | |
} | |
type HtmlPropsWithoutClassNameAndStyle< | |
T extends keyof JSX.IntrinsicElements | HTMLElement, | |
> = Omit< | |
T extends keyof JSX.IntrinsicElements | |
? JSX.IntrinsicElements[T] | |
: React.DetailedHTMLProps<React.HTMLAttributes<T>, T>, | |
'className' | 'style' | |
> | |
const [Box, Grid, Flex] = ( | |
[ | |
{ displayName: 'Box', tag: 'div', className: 'box' }, | |
{ displayName: 'Grid', tag: 'div', className: 'grid' }, | |
{ displayName: 'Flex', tag: 'div', className: 'flex' }, | |
] as const | |
).map(function createBoxElements({ | |
displayName, | |
tag: Tag, | |
className: componentClassName, | |
}) { | |
function Component( | |
props: BaseProps & HtmlPropsWithoutClassNameAndStyle<'div'>, | |
) { | |
const { children } = props | |
const { | |
style, | |
className, | |
props: rest, | |
} = useProps<HtmlPropsWithoutClassNameAndStyle<'div'>>({ | |
props, | |
componentClassName, | |
}) | |
return ( | |
<Tag className={className} style={style} {...rest}> | |
{children} | |
</Tag> | |
) | |
} | |
Component.displayName = displayName | |
return Component | |
}) | |
export { Box } | |
export { Grid } | |
export { Flex } |
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 { getProperty } from './getProperty' | |
import type { Dimensions } from './Base' | |
function getDimensions(props: { | |
width?: Dimensions | |
height?: Dimensions | |
minWidth?: Dimensions | |
maxWidth?: Dimensions | |
minHeight?: Dimensions | |
maxHeight?: Dimensions | |
}) { | |
const { width, height, minWidth, minHeight, maxWidth, maxHeight } = props | |
const names = { | |
width: 'w', | |
height: 'h', | |
minWidth: 'min-w', | |
minHeight: 'min-h', | |
maxWidth: 'max-w', | |
maxHeight: 'max-h', | |
} | |
return { | |
...getProperty({ name: names.width, value: width }), | |
...getProperty({ name: names.height, value: height }), | |
...getProperty({ name: names.minWidth, value: minWidth }), | |
...getProperty({ name: names.minHeight, value: minHeight }), | |
...getProperty({ name: names.maxWidth, value: maxWidth }), | |
...getProperty({ name: names.maxHeight, value: maxHeight }), | |
} | |
} | |
export { getDimensions } |
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 { getProperty } from './getProperty' | |
import type { Margin } from './Base' | |
function getMargin(props: { | |
m?: Margin | |
mx?: Margin | |
my?: Margin | |
ml?: Margin | |
mr?: Margin | |
mt?: Margin | |
mb?: Margin | |
}) { | |
const { m, mx, my, ml: _ml, mr: _mr, mt: _mt, mb: _mb } = props | |
const names = { | |
ml: 'ml', | |
mr: 'mr', | |
mt: 'mt', | |
mb: 'mb', | |
} | |
const values = { | |
ml: _ml ?? mx ?? m, | |
mr: _mr ?? mx ?? m, | |
mt: _mt ?? my ?? m, | |
mb: _mb ?? my ?? m, | |
} | |
const ml = getProperty({ | |
name: names.ml, | |
value: values.ml, | |
}) | |
const mr = getProperty({ | |
name: names.mr, | |
value: values.mr, | |
}) | |
const mt = getProperty({ | |
name: names.mt, | |
value: values.mt, | |
}) | |
const mb = getProperty({ | |
name: names.mb, | |
value: values.mb, | |
}) | |
return { | |
...ml, | |
...mr, | |
...mt, | |
...mb, | |
} | |
} | |
export { getMargin } |
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 { getProperty } from './getProperty' | |
import type { Padding } from './Base' | |
function getPadding(props: { | |
p?: Padding | |
px?: Padding | |
py?: Padding | |
pl?: Padding | |
pr?: Padding | |
pt?: Padding | |
pb?: Padding | |
}) { | |
const { p, px, py, pl: _pl, pr: _pr, pt: _pt, pb: _pb } = props | |
const names = { | |
pl: 'pl', | |
pr: 'pr', | |
pt: 'pt', | |
pb: 'pb', | |
} | |
const values = { | |
pl: _pl ?? px ?? p, | |
pr: _pr ?? px ?? p, | |
pt: _pt ?? py ?? p, | |
pb: _pb ?? py ?? p, | |
} | |
const pl = getProperty({ | |
name: names.pl, | |
value: values.pl, | |
}) | |
const pr = getProperty({ | |
name: names.pr, | |
value: values.pr, | |
}) | |
const pt = getProperty({ | |
name: names.pt, | |
value: values.pt, | |
}) | |
const pb = getProperty({ | |
name: names.pb, | |
value: values.pb, | |
}) | |
return { | |
...pl, | |
...pr, | |
...pt, | |
...pb, | |
} | |
} | |
export { getPadding } |
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
export function getProperty({ | |
name, | |
value: v, | |
}: { | |
name: string | |
value?: number | string | |
}) { | |
if (v === null || v === undefined) return undefined | |
const value = typeof v === 'number' ? `${v}px` : v | |
return { | |
[`--${name}`]: value, | |
} | |
} |
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 from 'react' | |
import { Box, Flex } from '../Base/Base' | |
export function SomeComponent(props: TilesProps) { | |
const { children, gap, width, mode } = props | |
return ( | |
<Box display="inline-block" width={300} p={20} m={20}> | |
<Flex px={10}> | |
<Box>Hello</Box> | |
<Box>World</Box> | |
</Flex> | |
</Box> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment