shadcn/ui
shadcn/ui는 Radix UI와 tailwindcss를 기반으로 빌드된 컴포넌트 모음집입니다.
toast와 같은 ui 기능들은 Radix ui 에서 가져와 사용하고
tailwindcss와 내부적으로는 tailwind-merge , clsx, cva를 이용하여
즉시 사용할 수 있는 아톰컴포넌트들을 제공합니다.
tailwindcss 계의 mui 같은 느낌이라고 생각할 수도 있을 것 같네요
다만 nodemodules에서 컴포넌트들이 관리되는 것이 아니라
커스터마이징이 훨씬 간편하다는 장점이 있습니다.
실제로도 shadcn/ui는 종속성으로 관리하는 것이 아닌 복사/ 붙여넣기를 통한 관리를 권장합니다
아톰컴포넌트의 스타일링을 하는 것은 상당히 지루한 일인데에 반하여
일반적으로 사용하는 디자인들은 어느정도 유사성이 있으니
그러한 반복적인 작업들을 효율화 시켜주는 라이브러리라고 생각할 수 있습니다.
이번에는 next.js에서의 사용례를 알아봅니다.
how to use?
npx shadcn-ui@latest init
위 명령어를 입력하면 shadcn-ui를 사용하기 위한 설정에 대한 질문을 받습니다.
Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › › app/globals.css
Do you want to use CSS variables for colors? › no / yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no / yes
적절히 자신의 상황에 맞는 답변들을 골라주면 되겠습니다.
저는 tailwind.config.js 대신 .ts를 사용하고 있어서 그 부분을 고쳐줬습니다.
init을 마치고나면
component.json , tailwind.config.js , utils 등의 파일이 생성되거나 변경됩니다.
npx shadcn-ui@latest add button
원하는 아이템을 추가합니다.
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-slate-950 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 dark:ring-offset-slate-950 dark:focus-visible:ring-slate-300",
{
variants: {
variant: {
default: "bg-slate-900 text-slate-50 hover:bg-slate-900/90 dark:bg-slate-50 dark:text-slate-900 dark:hover:bg-slate-50/90",
destructive:
"bg-red-500 text-slate-50 hover:bg-red-500/90 dark:bg-red-900 dark:text-slate-50 dark:hover:bg-red-900/90",
outline:
"border border-slate-200 bg-white hover:bg-slate-100 hover:text-slate-900 dark:border-slate-800 dark:bg-slate-950 dark:hover:bg-slate-800 dark:hover:text-slate-50",
secondary:
"bg-slate-100 text-slate-900 hover:bg-slate-100/80 dark:bg-slate-800 dark:text-slate-50 dark:hover:bg-slate-800/80",
ghost: "hover:bg-slate-100 hover:text-slate-900 dark:hover:bg-slate-800 dark:hover:text-slate-50",
link: "text-slate-900 underline-offset-4 hover:underline dark:text-slate-50",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }
cva에 익숙한 분들은 직접 작성하던 컴포넌트와 차이를 느끼기 힘든 코드입니다.
다만 귀찮게 작성해줘야했던 forwardRef 처리 , children 처리 등이 모두 완료되어있어
매우 사용성이 좋습니다.
toast 사용해보기
npx shadcn-ui@latest add toast
토스트의 경우에는 사용방법이 조금 다릅니다.
위 명령어를 입력하고나면 toast, toaster , use-toast 세개의 파일이 생성됩니다.
toast - toast 컴포넌트의 디자인을 담당합니다. 컴포넌트입니다.
toaster - 컨테이너의 역할을 수행합니다. 컴포넌트입니다.
use-toast - 커스텀훅으로 실제 로직은 여기에 다 들어있습니다.
우선 toaster 컴포넌트를 앱의 최상단에 렌더링시킵니다.
next.js의 경우에는 최상위의 layout.tsx 파일이 됩니다.
const ToastComponent = ({}:ToastComponentProps) => {
const {toast} = useToast()
return <div>
<button onClick={() => toast({title:'hi', description:'설명입니다.', variant:'default'})} >토스트버튼</button>
</div>
}
기본적인 사용 예시는 다음과 같습니다.
이후 필요한만큼 커스터마이징하면 됩니다.
const TOAST_LIMIT = 2
const TOAST_REMOVE_DELAY = 1000000
use-toast 파일의 두 변수 값을 조정하는 것을 통해 토스트의 갯수와 딜레이를 조절할 수 있습니다.
'css' 카테고리의 다른 글
특정한 영역에서만 스크롤바를 다르게 하고싶다면 (0) | 2023.09.18 |
---|---|
display:none과 visibility:hidden의 차이를 아시나요? (1) | 2023.08.24 |
요즘 핫한 panda css next.js app 라우터에서 시작하기 (0) | 2023.08.02 |
빌드타임 css-in-js 이해하기 pandacss와 vanila extract (0) | 2023.08.02 |
swiper/react를 이용하여 반응형 캐러셀 만들기 (5) | 2023.07.31 |