shadcn_guide
2
总安装量
2
周安装量
#74617
全站排名
安装命令
npx skills add https://github.com/mamma1234/example-app --skill shadcn_guide
Agent 安装分布
opencode
2
gemini-cli
2
antigravity
2
codex
2
kimi-cli
2
Skill 文档
Shadcn/ui (Vue) ê°ì´ë â moove íë¡ì í¸
â ï¸ ì¤ì: Vue íë¡ì í¸ ì ì©
ì´ íë¡ì í¸ë Vue 3 기ë°ì ëë¤. Shadcn/uiì Vue ë²ì ì ì¬ì©í©ëë¤.
| êµ¬ë¶ | â React (ì¬ì© ê¸ì§) | â Vue (ì´ íë¡ì í¸) |
|---|---|---|
| ìì´ì½ | lucide-react |
lucide-vue-next |
| ì ëë©ì´ì | framer-motion |
@vueuse/motion ëë Tailwind transitions |
| Primitives | @radix-ui/react-* |
radix-vue |
| Shadcn import | @/components/ui (React) |
@/components/ui (Vue) |
ì»´í¬ëí¸ ì¤ì¹
# Shadcn Vue ì»´í¬ëí¸ ì¶ê°
npx shadcn-vue@latest add button
npx shadcn-vue@latest add dialog
npx shadcn-vue@latest add table
npx shadcn-vue@latest add form
npx shadcn-vue@latest add select
npx shadcn-vue@latest add input
npx shadcn-vue@latest add badge
npx shadcn-vue@latest add card
ì¤ì¹ë ì»´í¬ëí¸ë components/ui/ ëë í 리ì ìì¹í©ëë¤.
ì ì»´í¬ëí¸ ì¬ì© ì , 먼ì components/ui/ì ì´ë¯¸ ìëì§ íì¸íì¸ì.
Import ê²½ë¡
<script setup lang="ts">
// â
ì¬ë°ë¥¸ import ê²½ë¡
import { Button } from '@/components/ui/button'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import { Input } from '@/components/ui/input'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
</script>
cn() ì í¸ë¦¬í°
í´ëì¤ ë³í©ì íì cn()ì ì¬ì©í©ëë¤. ì¡°ê±´ë¶ í´ëì¤ë ì¸ë¶ í´ëì¤ ì£¼ì
ì íìì
ëë¤.
<script setup lang="ts">
import { cn } from '@/lib/utils'
const props = defineProps<{
variant?: 'default' | 'destructive' | 'outline' | 'ghost'
size?: 'sm' | 'md' | 'lg'
class?: string
}>()
</script>
<template>
<button
:class="cn(
'inline-flex items-center justify-center rounded-md font-medium transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring',
'disabled:opacity-50 disabled:cursor-not-allowed',
{
'bg-primary text-primary-foreground hover:bg-primary/90': props.variant === 'default',
'bg-destructive text-destructive-foreground hover:bg-destructive/90': props.variant === 'destructive',
'border border-input bg-background hover:bg-accent': props.variant === 'outline',
'hover:bg-accent hover:text-accent-foreground': props.variant === 'ghost',
'h-8 px-3 text-sm': props.size === 'sm',
'h-10 px-4': props.size === 'md',
'h-12 px-6 text-lg': props.size === 'lg',
},
props.class
)"
>
<slot />
</button>
</template>
ìì´ì½ â lucide-vue-next
<script setup lang="ts">
// â
Vue íë¡ì í¸ììë lucide-vue-next ì¬ì©
import { Search, Plus, Trash2, Edit, ChevronRight, Loader2 } from 'lucide-vue-next'
// â ì ë ì¬ì© ê¸ì§ (React ì ì©)
// import { Search } from 'lucide-react'
</script>
<template>
<div class="flex items-center gap-2">
<Search class="h-4 w-4 text-muted-foreground" />
<span>ê²ì</span>
</div>
<!-- ë¡ë© ì¤í¼ë -->
<Loader2 class="h-4 w-4 animate-spin" />
</template>
ì ëë©ì´ì
ê°ë¨í ì í í¨ê³¼ë Tailwind utilities를 ì¬ì©í©ëë¤. ë³µì¡í ì ëë©ì´ì
ì´ íìí ê²½ì° @vueuse/motionì ì¬ì©í©ëë¤.
<template>
<!-- â
ê°ë¨í ì í â Tailwind transitions -->
<button class="transition-all duration-150 hover:scale-105 active:scale-95">
í´ë¦
</button>
<!-- â
íì´ë ì¸/ìì â Vue Transition ì»´í¬ëí¸ -->
<Transition
enter-active-class="transition-opacity duration-200"
enter-from-class="opacity-0"
enter-to-class="opacity-100"
leave-active-class="transition-opacity duration-150"
leave-from-class="opacity-100"
leave-to-class="opacity-0"
>
<div v-if="isVisible">ì½í
ì¸ </div>
</Transition>
</template>
Shadcn ì»´í¬ëí¸ ì»¤ì¤í°ë§ì´ì§
ì»´í¬ëí¸ë¥¼ ìì í ëë components/ui/ ë´ íì¼ì ì§ì í¸ì§í©ëë¤.
ë¨, ê¸°ë° Primitive(radix-vue)ë ë³´ì¡´íê³ ì¤íì¼ê³¼ propsë§ ìµìíì¼ë¡ ë³ê²½í©ëë¤.
<!-- components/ui/badge.vue 커ì¤í°ë§ì´ì§ ìì -->
<script setup lang="ts">
import { cn } from '@/lib/utils'
interface Props {
variant?: 'default' | 'secondary' | 'destructive' | 'outline' | 'success' | 'warning'
class?: string
}
const props = withDefaults(defineProps<Props>(), {
variant: 'default',
})
</script>
<template>
<div
:class="cn(
'inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold',
{
'border-transparent bg-primary text-primary-foreground': props.variant === 'default',
'border-transparent bg-secondary text-secondary-foreground': props.variant === 'secondary',
'border-transparent bg-destructive text-destructive-foreground': props.variant === 'destructive',
'border-transparent bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200': props.variant === 'success',
'border-transparent bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200': props.variant === 'warning',
},
props.class
)"
>
<slot />
</div>
</template>
ì주 ì°ë í¨í´
ë¤ì´ì¼ë¡ê·¸
<script setup lang="ts">
import { ref } from 'vue'
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
const isOpen = ref(false)
</script>
<template>
<Button @click="isOpen = true">ì´ê¸°</Button>
<Dialog v-model:open="isOpen">
<DialogContent class="sm:max-w-md">
<DialogHeader>
<DialogTitle>ì 목</DialogTitle>
</DialogHeader>
<div>ë´ì©</div>
<DialogFooter>
<Button variant="outline" @click="isOpen = false">ì·¨ì</Button>
<Button @click="handleConfirm">íì¸</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</template>
ë°ì´í° í ì´ë¸
<script setup lang="ts">
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
import { Badge } from '@/components/ui/badge'
import type { User } from '@/types'
defineProps<{ users: User[] }>()
</script>
<template>
<Table>
<TableHeader>
<TableRow>
<TableHead>ì´ë¦</TableHead>
<TableHead>ì´ë©ì¼</TableHead>
<TableHead>ìí</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow v-for="user in users" :key="user.id">
<TableCell>{{ user.name }}</TableCell>
<TableCell>{{ user.email }}</TableCell>
<TableCell>
<Badge :variant="user.is_active ? 'success' : 'secondary'">
{{ user.is_active ? 'íì±' : 'ë¹íì±' }}
</Badge>
</TableCell>
</TableRow>
</TableBody>
</Table>
</template>
ì²´í¬ë¦¬ì¤í¸
- ì»´í¬ëí¸ ì¬ì© ì
components/ui/ì ì´ë¯¸ ìëì§ íì¸ - ìì¼ë©´
npx shadcn-vue@latest add <ì»´í¬ëí¸ëª >ì¼ë¡ ì¤ì¹ - í´ëì¤ ë³í©ì
cn()ì í¸ë¦¬í° ì¬ì© - ìì´ì½ì
lucide-vue-nextì¬ì© (lucide-reactì ë ê¸ì§) - ì ëë©ì´ì
ì Tailwind transitions ëë Vue
<Transition>ì¬ì© - ì»´í¬ëí¸ ì»¤ì¤í°ë§ì´ì§ ì radix-vue Primitive ë³´ì¡´
-
dark:í´ëì¤ë¡ ë¤í¬ 모ë í¸íì± íë³´