Phase 2: Replace Vuero Base Components with shadcn-vue
Depends on: Phase 1 complete
Result: All 68 Vuero base components deleted and replaced with shadcn-vue equivalents. Every component import resolves.
Goal
Delete all 68 custom Vuero base components. Install shadcn-vue component library. Rebuild the ~10 components that have no shadcn equivalent. Update every template reference across the codebase.
Tasks
1. Add shadcn-vue components
- [ ] Install all needed components via CLI
npx shadcn-vue@latest add \
button card input select checkbox radio-group \
dialog dropdown-menu tabs table avatar badge \
progress textarea label switch separator tooltip \
alert accordion collapsible skeleton breadcrumb \
popover sheet scroll-area toggle command sonner form
These install into src/components/ui/.
2. Delete all Vuero base components
- [ ] Delete
src/components/base/— all 68 original components
3. Create custom replacements for components without shadcn equivalents
- [ ]
src/components/base/VPlaceholderPage.vue— empty-state with illustration + message + action button (Tailwind) - [ ]
src/components/base/VPlaceholderSection.vue— simpler section empty state (Tailwind) - [ ]
src/components/base/VDarkmodeSwitch.vue— sun/moon toggle using shadcnButton variant="ghost"+ Iconify icons - [ ]
src/components/base/VIcon.vue— keep as thin wrapper for<iconify-icon>(framework-agnostic) - [ ]
src/components/base/VIconButton.vue— shadcnButton variant="ghost" size="icon" - [ ]
src/components/base/VLoader.vue— spinner using Tailwindanimate-spin - [ ]
src/components/base/VRangeRating.vue— custom star rating, restyle with Tailwind - [ ]
src/components/base/VFlexTable.vue— thin wrapper around shadcnTable(app uses@tanstack/vue-table) - [ ]
src/components/base/VFlexPagination.vue— pagination using shadcnButtoncomponents
4. Add custom variants to shadcn components
- [ ] Add
success,warning,infovariants tosrc/components/ui/button/Button.vue - [ ] Add
success,warning,infovariants tosrc/components/ui/badge/Badge.vue
shadcn only ships: default, destructive, outline, secondary, ghost, link. The app uses success/warning/info colors extensively.
5. Update all component references across the codebase
This is the bulk of the work — every .vue file using Vuero components needs template updates (~120+ files).
Direct replacements (similar API):
| Find | Replace with | Notes |
|---|---|---|
<VButton color="primary"> | <Button> | Default variant = primary |
<VButton color="danger"> | <Button variant="destructive"> | |
<VButton color="success"> | <Button variant="success"> | Custom variant |
<VButton color="warning"> | <Button variant="warning"> | Custom variant |
<VButton color="info"> | <Button variant="info"> | Custom variant |
<VButton outlined> | <Button variant="outline"> | |
<VButton loading> | <Button disabled> + spinner icon | |
<VInput v-model="x" /> | <Input v-model="x" /> | Near drop-in |
<VTextarea v-model="x" /> | <Textarea v-model="x" /> | Near drop-in |
<VLabel> | <Label> | Drop-in |
<VProgress :value="n" /> | <Progress :value="n" /> | Drop-in |
<VTag color="X"> | <Badge variant="X"> | Map color → variant |
<VMessage color="X"> | <Alert variant="X"> | Map color → variant |
- [ ] Replace all
VButton→Button - [ ] Replace all
VInput→Input - [ ] Replace all
VTextarea→Textarea - [ ] Replace all
VLabel→Label - [ ] Replace all
VProgress→Progress - [ ] Replace all
VTag→Badge - [ ] Replace all
VMessage→Alert
Structural replacements (different API):
| Find | Replace with | Notes |
|---|---|---|
<VCard radius="smooth"> | <Card class="rounded-lg"><CardContent> | Wrap content in CardContent |
<VCardAdvanced> | <Card> + <CardHeader> + <CardContent> + <CardFooter> | Restructure named slots |
<VModal :open @close> | <Dialog v-model:open> + <DialogContent> + <DialogHeader> | Radix-based |
<VDropdown> | <DropdownMenu> + Trigger + Content + Item | Radix-based |
<VTabs :selected="i"> | <Tabs v-model="val"> + TabsList + TabsTrigger + TabsContent | String values, not index |
<VSelect> | <Select> + SelectTrigger + SelectContent + SelectItem | Radix-based |
<VCheckbox v-model> | <Checkbox :checked @update:checked> | Radix, no native v-model |
<VRadio> | <RadioGroup> + <RadioGroupItem> | Group-based |
<VAvatar :picture :initials> | <Avatar> + <AvatarImage> + <AvatarFallback> | Composition API |
<VAccordion> | <Accordion> + AccordionItem + AccordionTrigger + AccordionContent | Radix |
<VCollapse> | <Collapsible> + CollapsibleTrigger + CollapsibleContent | Radix |
<VBreadcrumb> | <Breadcrumb> + BreadcrumbList + BreadcrumbItem + BreadcrumbLink | Composition |
<VSwitchBlock> | <Switch> | Similar |
- [ ] Replace all
VCard/VCardAdvanced - [ ] Replace all
VModal/VResponsiveModal→Dialog - [ ] Replace all
VDropdown→DropdownMenu - [ ] Replace all
VTabs - [ ] Replace all
VSelect - [ ] Replace all
VCheckbox - [ ] Replace all
VRadio - [ ] Replace all
VAvatar - [ ] Replace all
VAccordion - [ ] Replace all
VCollapse - [ ] Replace all
VBreadcrumb - [ ] Replace all
VSwitchBlock→Switch
Utility components (replace with Tailwind classes):
| Find | Replace with |
|---|---|
<VFlex> / <VFlexItem> | <div class="flex"> / <div> |
<VGrid> / <VGridItem> | <div class="grid grid-cols-*"> / <div> |
<VBlock> | <div class="flex items-center gap-3"> |
<VIconBox> / <VIconWrap> | <div class="flex items-center justify-center rounded-lg ..."> |
<VTextEllipsis> | <span class="truncate"> |
<VLink> | <RouterLink> or <a> with Tailwind classes |
<VButtons> | <div class="flex gap-2"> |
<VPlaceload*> | <Skeleton class="h-4 w-full" /> |
<VSnack> | Use Sonner toast or keep Notyf |
- [ ] Replace all
VFlex/VFlexItem→ Tailwind flex divs - [ ] Replace all
VGrid/VGridItem→ Tailwind grid divs - [ ] Replace all
VBlock→ flex div - [ ] Replace all
VIconBox/VIconWrap→ Tailwind divs - [ ] Replace all
VTextEllipsis→<span class="truncate"> - [ ] Replace all
VLink→<RouterLink>/<a> - [ ] Replace all
VButtons→<div class="flex gap-2"> - [ ] Replace all
VPlaceload*→<Skeleton>
6. Update form validation integration
- [ ] Replace all
VField+VControlpatterns with shadcnFormField+FormItem
<!-- OLD -->
<VField id="email" v-slot="{ field }">
<VLabel>Email</VLabel>
<VControl icon="lucide:mail">
<VInput type="email" v-bind="field" />
</VControl>
</VField>
<!-- NEW -->
<FormField v-slot="{ componentField }" name="email">
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input type="email" v-bind="componentField" />
</FormControl>
<FormMessage />
</FormItem>
</FormField>
Key form files to update:
- [ ]
src/components/forms/campaigns/NewCampaignForm.vue - [ ]
src/components/forms/clients/NewClientForm.vue - [ ]
src/pages/auth/index.vue(login) - [ ]
src/pages/auth/signup.vue - [ ]
src/pages/auth/profile.vue - [ ]
src/pages/app/settings.vue - [ ]
src/pages/app/client/[id]/settings.vue
7. Update auto-import component resolution
- [ ] Verify
vite.config.tsauto-importComponentsplugin resolves shadcn-vue components insrc/components/ui/correctly - [ ] The nested directory structure (e.g.,
ui/button/Button.vue) may need explicit resolver config
Files Created
| File | Purpose |
|---|---|
src/components/ui/* | ~25 shadcn-vue component directories |
src/components/base/VPlaceholderPage.vue | Custom empty state |
src/components/base/VPlaceholderSection.vue | Custom section empty state |
src/components/base/VDarkmodeSwitch.vue | Custom dark mode toggle |
src/components/base/VIcon.vue | Iconify wrapper (kept) |
src/components/base/VIconButton.vue | Icon button |
src/components/base/VLoader.vue | Loading spinner |
src/components/base/VRangeRating.vue | Star rating |
src/components/base/VFlexTable.vue | Table wrapper |
src/components/base/VFlexPagination.vue | Pagination |
Files Deleted
| File | Reason |
|---|---|
src/components/base/* (68 files) | Original Vuero components replaced |
Files Modified
| File | Change |
|---|---|
~120+ .vue files | Template component references updated |
src/components/ui/button/Button.vue | Add success/warning/info variants |
src/components/ui/badge/Badge.vue | Add success/warning/info variants |
vite.config.ts | Auto-import resolver for shadcn |
Checklist
- [ ] All shadcn-vue components installed
- [ ] All 68 original Vuero base components deleted
- [ ] 9 custom replacement components created
- [ ] Custom variants (success, warning, info) added to Button and Badge
- [ ] All
VButtonreferences replaced - [ ] All
VCard/VCardAdvancedreferences replaced - [ ] All
VInput/VTextareareferences replaced - [ ] All
VModalreferences replaced → Dialog - [ ] All
VDropdownreferences replaced → DropdownMenu - [ ] All
VTabsreferences replaced - [ ] All
VSelectreferences replaced - [ ] All
VCheckbox/VRadioreferences replaced - [ ] All
VAvatarreferences replaced - [ ] All
VTagreferences replaced → Badge - [ ] All
VField+VControlpatterns replaced → FormField + FormItem - [ ] All utility components replaced with Tailwind classes
- [ ] Auto-import resolves all shadcn components
- [ ]
pnpm test:tscpasses — no unresolved imports - [ ]
pnpm buildcompiles successfully - [ ] Form validation works with shadcn Form + vee-validate