-
Notifications
You must be signed in to change notification settings - Fork 8
/
classed.ts
41 lines (36 loc) · 1.1 KB
/
classed.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import React from 'react'
import cn from 'classnames'
// all the cuteness of tw.span`text-green-500 uppercase` with zero magic
const make =
<T extends keyof JSX.IntrinsicElements>(tag: T) =>
// only one argument here means string interpolations are not allowed
(strings: TemplateStringsArray) =>
({ className, children, ...rest }: JSX.IntrinsicElements[T]) =>
React.createElement(
tag,
{ className: cn(strings[0], className), ...rest },
children
)
// JSX.IntrinsicElements[T] ensures same props as the real DOM element. For example,
// classed.span doesn't allow a type attr but classed.input does.
export const classed = {
button: make('button'),
div: make('div'),
h1: make('h1'),
h2: make('h2'),
h3: make('h3'),
h4: make('h4'),
hr: make('hr'),
header: make('header'),
input: make('input'),
label: make('label'),
li: make('li'),
main: make('main'),
ol: make('ol'),
p: make('p'),
span: make('span'),
td: make('td'),
th: make('th'),
tr: make('tr'),
} as const
// result: classed.button`text-green-500 uppercase` returns a component with those classes