2.0.2 β€’ Published 2 months ago

class-variant v2.0.2

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

Features

Vanilla, Next, React, Vue, Tailwind CSS, and Master CSS are available:

  • ⚑️ Ultra-lightweight ~1.5KB, powered by Proxy
  • πŸ›‘οΈ Type safety
  • 🌈 Dynamically change styles based on properties
  • πŸ’« Re-expand existing elements, like NextLink
  • 🧩 Compatible with server and client components
  • πŸͺ„ Built-in first-class clsx handling

Why?

😰 Before: Creating a simple styled element using a FunctionalComponent is unpleasant.

function Button(props) {
    return (
        <button {...props} className={"inline-flex font:14" + (props.className ? ' ' + props.className : '')}>
            {props.children}
        </button>
    )
}

πŸ₯³ After: It's in one line and ~80% code less.

import styled from '@master/styled.react' // or .vue

const Button = styled.button`inline-flex font:14`

Apply it as usual:

export default function App() {
    return (
        <Button className="uppercase">submit</Button>
    )
}

It will be rendered as:

<button class="inline-flex font:14 uppercase">submit</button>

Getting Started

Install the package depending on your framework:

Vanilla

npm install class-variant
import cv from 'class-variant'

const btn = cv(...params)
const btn = cv`...` // or

btn(props) // -> string

React

npm install @master/styled.react
import styled from '@master/styled.react'

const Button = styled.button(...params)
const Button = styled.button`...` // or

<Button {...props}>

Vue

npm install @master/styled.vue
import styled from '@master/styled.vue'

const Button = styled.button(...params)
const Button = styled.button`...` // or

<Button {...props}>

Basic usage

Create a styled element

Declared in two ways: function or template literal, and parameters inherit all features of clsx.

const Element = styled.div`flex text:center`
const Element = styled.div('flex text:center') // or

return (
    <Element className="uppercase">Hello World</Element>
)
<div class="flex text:center uppercase">Hello World</div>

Apply based on predefined variants

Predefine the class variant corresponding to the property.

const Button = styled.button('flex', {
    $size: {
        sm: 'font:12 size:8x',
        md: 'font:14 size:12x'
    },
    disabled: 'opacity:.5',
    ...
})

return (
    <Button $size="sm" disabled />
)
<button class="flex font:12 size:8x opacity:.5" disabled></button>

⚠️ Custom properties that are not element-owned properties must be prefixed with $prop, otherwise they will be reflected on the final element and an error may be thrown.

You can set default properties for elements.

Button.defaultProps = {
    $size: 'md'
}

return (
    <Button />
)
<button class="font:14 size:12x"></button>

Apply based on function properties

Dynamically apply class names based on function properties.

const Element = styled.div('fg:white',
    ({ $color }) => $color && `bg:${$color}`
)

return (
    <Element $color="blue" />
)
<div class="inline-flex text:center fg:white bg:blue"></div>

Apply based on matching properties

Applies the target class name matching all specified property keys and their values.

const Button = styled.button('inline-flex',
    ['uppercase', { $intent: 'primary', $size: 'md' }]
)

return (
    <Button $intent="primary">Not matched</button>
    <Button $size="md">Not matched</button>
    <Button $intent="primary" $size="md">Matched</button>
)
<button class="inline-flex">Not matched</button>
<button class="inline-flex">Not matched</button>
<button class="inline-flex uppercase">Matched</button>

Extended

Extend a styled element

Extend an existing styled element and add additional classes or conditions.

const A = styled.p('a')
const B = styled.p(A)`b`

return (
    <A>A</A>
    <B>B</B>
)
<p class="a">A</p>
<p class="a b">B</p>

Change an element's tag name

Changing the original tag name of an element, such as <button> to <a>. Left empty '' even if there are no additional classes.

const Button = styled.button('inline-flex')
const Link = styled.a(Button)``

return (
    <Button>button</Button>
    <Link href="#example">link</Link>
)
<button class="inline-flex">button</button>
<a class="inline-flex" href="#example">link</a>

Extend multiple styled elements

Extend multiple style elements at once.

const A = styled.p`a`
const B = styled.p`b`
const C = styled.p`c`
const D = styled(A)(B)(C)`d`

return (
    <A>A</A>
    <B>B</B>
    <C>C</C>
    <D>D</D>
)
<p class="a">A</p>
<p class="b">B</p>
<p class="c">C</p>
<p class="a b c d">D</p>

Typings

declare type Props = {
    $size: 'sm' | 'md'
}

const Button = styled.button<Props>('flex', {
    $size: {
        sm: 'font:12 size:8x',
        md: 'font:14 size:12x'
    },
    disabled: 'opacity:.5'
})

Overview class-variant APIs

import cv from 'class-variant'

const btn = cv(
    'inline-flex rounded',
    {
        intent: {
            primary: 'bg:blue fg:white bg:blue-60:hover',
            secondary: 'bg:white fg:slate-30 bg:slate-90:hover',
        },
        size: {
            sm: 'text:14 p:5|15',
            md: 'text:16 p:10|25'
        }
    },
    ['uppercase', { intent: 'primary', size: 'md' }],
    ({ indent, size }) => indent && size && 'font:semibold'
)

btn.default = {
    intent: 'primary',
    size: 'sm'
}

btn()
// inline-flex rounded bg:blue fg:white bg:blue-55:hover text:14 p:5|8 font:semibold

btn({ indent: 'secondary', size: 'sm' })
// inline-flex rounded bg:white fg:slate-30 bg:slate-90:hover text:14 p:5|8 font:semibold

btn({ indent: 'primary', size: 'md' })
// inline-flex rounded bg:blue fg:white bg:blue-55:hover text:16 p:10|25 uppercase font:semibold

Community

The Master community can be found here:

Our γ€Š Code of Conduct 》 applies to all Master community channels.

Contributing

Please see our CONTRIBUTING for workflow.

Inspiration

Some of our core concepts and designs are inspired by these giants.

  • Template Literal - The use of template literals as syntactic sugar for reusing components is inspired by Styled Components.
2.0.2

2 months ago

2.0.1

2 months ago

2.0.0

2 months ago

2.0.0-rc.21

2 months ago

2.0.0-rc.20

2 months ago

2.0.0-rc.19

2 months ago

2.0.0-rc.17

3 months ago

2.0.0-rc.16

3 months ago

2.0.0-rc.15

3 months ago

2.0.0-rc.14

3 months ago

2.0.0-rc.13

3 months ago

2.0.0-rc.12

3 months ago

2.0.0-rc.11

3 months ago

2.0.0-rc.10

3 months ago

2.0.0-rc.9

3 months ago

2.0.0-rc.8

4 months ago

2.0.0-rc.7

4 months ago

2.0.0-rc.3

4 months ago

2.0.0-rc.4

4 months ago

2.0.0-rc.5

4 months ago

2.0.0-rc.6

4 months ago

2.0.0-rc.2

4 months ago

2.0.0-rc.1

4 months ago

2.0.0-beta.215

4 months ago

2.0.0-beta.214

5 months ago

2.0.0-beta.213

5 months ago

2.0.0-beta.212

5 months ago

2.0.0-beta.211

5 months ago

2.0.0-beta.210

5 months ago

2.0.0-beta.209

5 months ago

2.0.0-beta.208

5 months ago

2.0.0-beta.207

5 months ago

2.0.0-beta.206

5 months ago

2.0.0-beta.205

5 months ago

2.0.0-beta.204

6 months ago

2.0.0-beta.203

6 months ago

2.0.0-beta.202

6 months ago

2.0.0-beta.201

6 months ago

2.0.0-beta.200

6 months ago

2.0.0-beta.199

6 months ago

2.0.0-beta.198

6 months ago

2.0.0-beta.197

6 months ago

2.0.0-beta.196

6 months ago

2.0.0-beta.195

6 months ago

2.0.0-beta.194

6 months ago

2.0.0-beta.193

6 months ago

2.0.0-beta.192

6 months ago

2.0.0-beta.191

6 months ago

2.0.0-beta.190

6 months ago

2.0.0-beta.189

6 months ago

2.0.0-beta.188

6 months ago

2.0.0-beta.187

6 months ago

2.0.0-beta.186

7 months ago

2.0.0-beta.185

7 months ago

2.0.0-beta.184

7 months ago

2.0.0-beta.183

7 months ago

2.0.0-beta.182

7 months ago

2.0.0-beta.181

7 months ago

2.0.0-beta.180

7 months ago

2.0.0-beta.179

7 months ago

2.0.0-beta.178

7 months ago

2.0.0-beta.177

7 months ago

2.0.0-beta.176

7 months ago

2.0.0-beta.175

7 months ago

2.0.0-beta.174

8 months ago

2.0.0-beta.173

8 months ago

2.0.0-beta.172

8 months ago

2.0.0-beta.171

8 months ago

2.0.0-beta.170

8 months ago

2.0.0-beta.169

9 months ago

2.0.0-beta.168

9 months ago

2.0.0-beta.167

9 months ago

2.0.0-beta.166

10 months ago

2.0.0-beta.165

10 months ago

2.0.0-beta.164

10 months ago

2.0.0-beta.163

10 months ago

2.0.0-beta.162

10 months ago

2.0.0-beta.161

10 months ago

2.0.0-beta.160

10 months ago