Skip to content

Commit c32f489

Browse files
committed
feat(ui): add Button component
1 parent 306e8d1 commit c32f489

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

apps/www/components/Button.tsx

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2024, Brion Mario
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import {Slot, SlotProps} from '@radix-ui/react-slot';
26+
import {cva, type VariantProps} from 'class-variance-authority';
27+
import {ButtonHTMLAttributes, ForwardedRef, forwardRef, ForwardRefExoticComponent, RefAttributes} from 'react';
28+
import {ClassProp} from 'class-variance-authority/types';
29+
import {cn} from '@/lib/utils';
30+
31+
/**
32+
* `buttonVariants` defines the styles for different button variants and sizes using class-variance-authority.
33+
*/
34+
export const buttonVariants: (props?: (Record<string, unknown> & ClassProp) | undefined) => string = cva(
35+
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0',
36+
{
37+
variants: {
38+
variant: {
39+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
40+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
41+
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
42+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
43+
ghost: 'hover:bg-accent hover:text-accent-foreground',
44+
link: 'text-primary underline-offset-4 hover:underline',
45+
},
46+
size: {
47+
default: 'h-10 px-4 py-2',
48+
sm: 'h-9 rounded-md px-3',
49+
lg: 'h-11 rounded-md px-8',
50+
icon: 'h-10 w-10',
51+
},
52+
},
53+
defaultVariants: {
54+
variant: 'default',
55+
size: 'default',
56+
},
57+
},
58+
);
59+
60+
/**
61+
* Props for the `Button` component.
62+
*/
63+
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
64+
/** If true, the button will render as a child component. */
65+
asChild?: boolean;
66+
}
67+
68+
/**
69+
* `Button` is a React component that renders a button with various styles and sizes.
70+
*
71+
* @example
72+
* ```tsx
73+
* <Button variant="destructive" size="lg">Delete</Button>
74+
* ```
75+
*
76+
* @param props - Props for the component.
77+
* @returns Button as a React component.
78+
*/
79+
const Button: ForwardRefExoticComponent<ButtonProps & RefAttributes<HTMLButtonElement>> = forwardRef<
80+
HTMLButtonElement,
81+
ButtonProps
82+
>(({className, variant, size, asChild = false, ...props}: ButtonProps, ref: ForwardedRef<HTMLButtonElement>) => {
83+
const Comp: ForwardRefExoticComponent<SlotProps & RefAttributes<HTMLElement>> | 'button' = asChild ? Slot : 'button';
84+
return <Comp className={cn(buttonVariants({variant, size, className}))} ref={ref} {...props} />;
85+
});
86+
87+
Button.displayName = 'Button';
88+
89+
export default Button;

0 commit comments

Comments
 (0)