Skip to content

Instantly share code, notes, and snippets.

@bbg
Created June 15, 2022 10:05
Show Gist options
  • Save bbg/730e3dfdfd65f5fd11abecaa28963d36 to your computer and use it in GitHub Desktop.
Save bbg/730e3dfdfd65f5fd11abecaa28963d36 to your computer and use it in GitHub Desktop.
const Box = twx('div')`
bg-red
p-2 lg:p-4
rounded-sm lg:rounded-lg
${props => props?.size === 'small' && 'text-sm'}
`
// it's allow especialization
const ErrorBox = twx(Box)`
border-red
`
// and you can continue using className prop to add extra class names
const App = () => (
<Box className="m-4">
Magic!
</Box>
)
import * as React from 'react'
type Props = { [key: string]: any }
type ComponentOrTag = string | React.ComponentType<Props>
type PropsHandler = (props?: Props) => string
type Fragment = string | PropsHandler
type Utility = TemplateStringsArray | string[]
const byProps = (fragment: Fragment = '', props?: Props) =>
(typeof fragment === 'function' ? fragment(props) : fragment) || ''
export const tw = (str: Utility, ...args: Fragment[]) =>
(props?: Props) =>
str.reduce(
(memo, current, index) =>
`${memo}${current}${byProps(args[index], props)}`
.trim()
.replace(/\s{2,}/g, ' '),
''
)
export const twx = (componentName: ComponentOrTag) =>
(strs: Utility, ...args: [Fragment]) => ({ className = '', as: useAs = componentName, children, ...props }: Props) => {
const Component = typeof useAs === 'string' ? `${useAs}` : useAs
const names = tw(strs, ...args)(props)
return (
<Component {...props} className={`${names} ${className}`}>
{children}
</Component>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment