@@ -54,13 +54,12 @@ fits your version of Tailwind CSS.
54544 . Pass ` className ` to the recipe, and drop the ` cn ` call around it. The
5555 recipe adds ` className ` last, and merges it with its join.
5656
57- Here is a ` button.tsx ` before the change. The exact classes depend on
58- your version of shadcn/ui:
57+ Here is a ` button.tsx ` built on [ Base UI ] ( https://base-ui.com ) before the
58+ change. The exact classes depend on your version of shadcn/ui:
5959
6060``` tsx
6161// src/components/ui/button.tsx
62- import * as React from " react" ;
63- import { Slot } from " @radix-ui/react-slot" ;
62+ import { Button as ButtonPrimitive } from " @base-ui/react/button" ;
6463import { cva , type VariantProps } from " class-variance-authority" ;
6564
6665import { cn } from " @/lib/utils" ;
@@ -95,18 +94,12 @@ const buttonVariants = cva(
9594
9695function Button({
9796 className ,
98- variant ,
99- size ,
100- asChild = false ,
97+ variant = " default" ,
98+ size = " default" ,
10199 ... props
102- }: React .ComponentProps <" button" > &
103- VariantProps <typeof buttonVariants > & {
104- asChild? : boolean ;
105- }) {
106- const Comp = asChild ? Slot : " button" ;
107-
100+ }: ButtonPrimitive .Props & VariantProps <typeof buttonVariants >) {
108101 return (
109- <Comp
102+ <ButtonPrimitive
110103 data-slot = " button"
111104 className = { cn (buttonVariants ({ variant , size , className }))}
112105 { ... props }
@@ -121,9 +114,8 @@ And after:
121114
122115``` tsx
123116// src/components/ui/button.tsx
124- import * as React from " react" ;
117+ import { Button as ButtonPrimitive } from " @base-ui/ react/button " ;
125118import type { VariantsOf } from " @lynstack/class-recipe" ;
126- import { Slot } from " @radix-ui/react-slot" ;
127119import { cva } from " @/lib/utils" ;
128120
129121const buttonVariants = cva ({
@@ -153,20 +145,21 @@ const buttonVariants = cva({
153145
154146function Button({
155147 className ,
156- variant ,
157- size ,
158- asChild = false ,
148+ variant = " default" ,
149+ size = " default" ,
159150 ... props
160- }: React .ComponentProps <" button" > &
161- VariantsOf <typeof buttonVariants > & {
162- asChild? : boolean ;
163- }) {
164- const Comp = asChild ? Slot : " button" ;
165-
151+ }: ButtonPrimitive .Props & VariantsOf <typeof buttonVariants >) {
166152 return (
167- <Comp
153+ <ButtonPrimitive
168154 data-slot = " button"
169- className = { buttonVariants ({ variant , size , className })}
155+ className = { (state ) =>
156+ buttonVariants ({
157+ variant ,
158+ size ,
159+ className:
160+ typeof className === " function" ? className (state ) : className ,
161+ })
162+ }
170163 { ... props }
171164 />
172165 );
@@ -175,12 +168,22 @@ function Button({
175168export { Button , buttonVariants };
176169```
177170
178- The component keeps its API: ` variant ` , ` size ` , ` asChild ` with ` Slot `
179- from ` @radix-ui/react-slot ` , and the ` buttonVariants ` export, which other
180- components and links call, such as
181- ` <a className={buttonVariants({ variant: "ghost" })}> ` . Newer versions of
182- shadcn/ui import ` Slot ` from ` radix-ui ` instead; keep the import that your
183- component has.
171+ A Base UI component takes a ` className ` that is either a string or a
172+ function of its state, such as
173+ ` className={(state) => (state.disabled ? "opacity-25" : "")} ` . A recipe
174+ takes a string, so the component passes Base UI a function, which calls
175+ the recipe with the ` className ` of that state. class-variance-authority
176+ ignores a function, so the classes it returned were lost; the recipe adds
177+ them.
178+
179+ The component keeps its API: ` variant ` , ` size ` , the ` render ` prop of
180+ Base UI, such as ` <Button nativeButton={false} render={<a href="/" />}> ` ,
181+ and the ` buttonVariants ` export, which other components and links call,
182+ such as ` <a className={buttonVariants({ variant: "ghost" })}> ` .
183+
184+ A component built on Radix takes ` asChild ` and renders ` Slot ` instead,
185+ and its ` className ` is a string: pass it to the recipe directly, as in
186+ ` className={buttonVariants({ variant, size, className })} ` .
184187
185188Every variant of the button has a default, so its props stay optional. In
186189a component whose variant has no default, ` VariantsOf ` makes that variant
0 commit comments