feat(shadcn): #54 rebuild Bottom nav, remove daisyUI and dead MUI deps#61
Merged
Conversation
Handcrafted shadcn init to preserve the front/* alias and Nx layout. Scaffolding only — no call-site swaps; daisyUI plugin remains active. - apps/web/components.json — shadcn schema 1, style default, rsc true, baseColor neutral, cssVariables, aliases mapped onto front/* (components → front/new-component, ui → front/new-component/ui, utils → front/lib/utils, lib → front/lib, hooks → front/hooks), iconLibrary lucide - apps/web/src/lib/utils.ts — cn helper (clsx + tailwind-merge) - apps/web/src/new-component/ui/ directory created (empty; #49 fills) - apps/web/tailwind.config.js — darkMode ['class'], theme.extend.colors wired to hsl(var(--*)) shadcn tokens, theme.extend.borderRadius, plugins keep `require('daisyui')` and add `tailwindcss-animate` - apps/web/app/globals.css — :root + .dark CSS variables under @layer base - package.json — class-variance-authority, clsx, tailwind-merge, tailwindcss-animate, lucide-react added - nx affected -t lint test build --exclude web-e2e green (4 projects, 10 tasks) - daisyUI classes still render identically (coexistence by design through #54) Refs #48
Five shadcn/ui components written directly into apps/web/src/new-component/ui/ to match the aliases configured in #48. Standard shadcn default-style implementations using cn(), class-variance-authority (button only), and Radix primitives for Avatar and Progress. No call-site swaps — files are unreferenced until #50–#54 consume them. - button.tsx — variants (default/destructive/outline/secondary/ghost/ link), sizes (default/sm/lg/icon), asChild via @radix-ui/react-slot - card.tsx — Card + CardHeader/Title/Description/Content/Footer - skeleton.tsx — animated muted placeholder - avatar.tsx — Radix Avatar/Image/Fallback ("use client") - progress.tsx — Radix Progress with translate-based indicator ("use client") - package.json — @radix-ui/react-slot, @radix-ui/react-avatar, @radix-ui/react-progress added - nx affected -t lint test build --exclude web-e2e green Refs #49
…50) Header: - Drops daisyUI navbar/bg-neutral/text-neutral-content/btn-ghost and rebuilds as a plain Tailwind flex row using shadcn Button variant="ghost" for the title link - bg-neutral-900 / text-neutral-100 token pair preserves the dark contrast originally supplied by daisyUI's neutral theme tokens Sidebar: - Deleted. The component was pulled only via the new-component/ barrel export and rendered nowhere (no consumers after the catch-all bridge and SiteRouter were removed in #35). - new-component/index.ts drops `export * from './sidebar'`. - nx affected -t lint test build --exclude web-e2e green - daisyUI plugin still present; coexists with shadcn through #54 Refs #50
Count.tsx: - daisyUI `avatar` + nested `div.skeleton` → shadcn Avatar/AvatarImage and Skeleton. Loading state is now an explicit Skeleton branch instead of a class toggle, so there's no more empty .avatar box while loading. - The two text rows (name, totalCount) likewise use Skeleton during isLoading. - "use client" added (was missing; Count uses hooks). Contents.tsx: - `<button className="btn btn-link btn-primary">` → shadcn <Button variant="link">. router.push wiring unchanged. - nx affected -t lint test build --exclude web-e2e green - daisyUI plugin still present Refs #51
AnimalCard.tsx: - daisyUI `card bg-base-100 shadow-xl` + `card-body` → shadcn Card + CardContent - `"use client"` added (was missing; useLike is a Zustand hook) - Inner `<table className="table table-sm">` rewritten without daisyUI table classes — plain <table> with Tailwind padding/ font utilities SearchView.tsx: - react-infinite-scroller loader `<progress className="progress"/>` → shadcn <Progress className="h-2" /> Form.tsx: - Submit `<button className="btn btn-sm">` → shadcn <Button size="sm" type="submit"> - nx affected -t lint test build --exclude web-e2e green - daisyUI plugin still present Refs #52
…#53) Scope-adjusted from "Radix Select + rhf Controller" to Tailwind-styled native select while preserving the rhf `register` flow. Reason: Radix Select rejects empty-string SelectItem values, and every init* row (initSido, initSigungu, initShelter, initKind, Upkinds[0]) uses `''` as the "모두" sentinel. Switching to Radix would have required patching every init entry + translating back on submit — a medium-risk refactor that delivers no user-visible benefit beyond the styling change itself. Select.tsx: - `select select-bordered select-xs` → plain <select> with shadcn token classes (border-input, bg-background, ring-ring) - cn() helper adopted - Label wrapper: daisyUI `form-control` / `label-text` → plain flex-col + text-muted-foreground All callers (SidoSelect, SigunguSelect, ShelterSelect, UpkindSelect, KindSelect) are unchanged — they still pass `register` + children <option> elements. - nx affected -t lint test build --exclude web-e2e green - daisyUI plugin still present (removed in #54) Refs #53
Closes out the #8 chain. Bottom.tsx: - daisyUI `btm-nav btm-nav-xs` + nested `<button><a>` rebuilt as a plain Tailwind fixed bottom nav: `fixed inset-x-0 bottom-0 h-12 flex border-t border-border bg-background`. Each item is a real <button type="button"> (no anchor-in-button nesting) with aria-label per item, active state swaps text-primary vs text-muted-foreground. - React-icons kept; layout fires router.push as before. Tailwind config: - `plugins: [require('tailwindcss-animate'), require('daisyui')]` → `plugins: [require('tailwindcss-animate')]`. CSS variables still drive all color tokens (set up in #48). Dependency purge: - daisyui - @mui/joy, @mui/icons-material, @mui/x-date-pickers — all zero imports in apps/web/src (grep-verified) - @emotion/react, @emotion/styled — bundled only because MUI pulled them; framer-motion has its own emotion vendoring so dropping these is safe Final audits: - nx affected -t lint test build --exclude web-e2e green - rg "bg-neutral(?![-\\w])|text-neutral-content|bg-base-\\d| text-base-content|btm-nav|navbar|btn-ghost|btn-link|btn-primary| btn-neutral|card-body|card-title|select-bordered|menu-|daisyui" apps/web → zero matches outside .next/ - package.json contains no daisyui/@mui/@emotion entries Refs #54
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Reviewer's GuideMigrates the web app’s UI away from daisyUI/MUI to a shadcn-style Tailwind + Radix component stack, rebuilding the bottom navigation and key search/home components while wiring Tailwind to design tokens and purging legacy dependencies. Sequence diagram for navigation via rebuilt Bottom navsequenceDiagram
actor User
participant Bottom as Bottom_nav
participant Router as Next_router
participant Page as Next_page
User->>Bottom: tap_button(path)
Bottom->>Router: push(path)
Router-->>Page: render_new_route
Page-->>User: updated_screen
Class diagram for new shadcn-style UI primitives and utilitiesclassDiagram
direction LR
class Utils {
+cn(inputs ClassValue[]) string
}
class Button {
+buttonVariants
+asChild boolean
+variant
+size
}
class Card {
}
class CardHeader {
}
class CardTitle {
}
class CardDescription {
}
class CardContent {
}
class CardFooter {
}
class Avatar {
}
class AvatarImage {
}
class AvatarFallback {
}
class Progress {
+value number
}
class Skeleton {
}
Utils <.. Button : uses cn
Utils <.. Card : uses cn
Utils <.. CardHeader : uses cn
Utils <.. CardTitle : uses cn
Utils <.. CardDescription : uses cn
Utils <.. CardContent : uses cn
Utils <.. CardFooter : uses cn
Utils <.. Avatar : uses cn
Utils <.. AvatarImage : uses cn
Utils <.. AvatarFallback : uses cn
Utils <.. Progress : uses cn
Utils <.. Skeleton : uses cn
Button ..> Progress : shares_tailwind_tokens
Button ..> Card : shares_tailwind_tokens
Button ..> Avatar : shares_tailwind_tokens
Button ..> Skeleton : shares_tailwind_tokens
Class diagram for updated page-level components using new UI primitivesclassDiagram
direction LR
class Bottom {
-pathname string
-router
-barItem
}
class Header {
}
class CountList {
-items Sido[]
-query
}
class AnimalCard {
-item AnimalInfo
-like boolean
-toggleLike()
}
class Select {
-labelName string
-children ReactNode
-register UseFormRegister
-name string
}
class SearchView {
-animalInfoRequest AnimalInfoRequestType
-fetchNextPage()
}
class Button {
}
class Card {
}
class CardContent {
}
class Avatar {
}
class AvatarImage {
}
class Progress {
}
class Skeleton {
}
Bottom ..> Button : uses_variant_and_cn
Header ..> Button : uses_ghost_variant
CountList ..> Avatar : renders_logo
CountList ..> AvatarImage : renders_logo_image
CountList ..> Skeleton : loading_placeholders
AnimalCard ..> Card : wraps_content
AnimalCard ..> CardContent : body_layout
Select ..> Button : not_used
Select ..> Skeleton : not_used
SearchView ..> Progress : loader_indicator
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
View your CI Pipeline Execution ↗ for commit d8116be
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In the new
CardTitleandCardDescriptioncomponents, the forwarded ref/prop types (HTMLHeadingElement/HTMLParagraphElement) don't match the actual rendered element (div), which can cause typing and ref issues; either change the element tohX/ptags or align the generic types withHTMLDivElement. - Several lists still use
uuidv4()for React keys (Bottomnav items,CountList), which regenerates keys on every render; consider using a stable property from the data (e.g.,pathororgCd) as the key to avoid unnecessary remounting. - The new Radix
Progress-based loader inSearchViewis always rendered withvalueundefined (falling back to 0), so the indicator remains fully translated offscreen; if you intend an indeterminate loader, consider adding a CSS animation or passing a mid-range value to make the progress bar visibly active.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the new `CardTitle` and `CardDescription` components, the forwarded ref/prop types (`HTMLHeadingElement` / `HTMLParagraphElement`) don't match the actual rendered element (`div`), which can cause typing and ref issues; either change the element to `hX`/`p` tags or align the generic types with `HTMLDivElement`.
- Several lists still use `uuidv4()` for React keys (`Bottom` nav items, `CountList`), which regenerates keys on every render; consider using a stable property from the data (e.g., `path` or `orgCd`) as the key to avoid unnecessary remounting.
- The new Radix `Progress`-based loader in `SearchView` is always rendered with `value` undefined (falling back to 0), so the indicator remains fully translated offscreen; if you intend an indeterminate loader, consider adding a CSS animation or passing a mid-range value to make the progress bar visibly active.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
This was referenced Apr 13, 2026
This was referenced Apr 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #60. Closes the #8 chain.
Bottom.tsx rebuilt
btm-nav btm-nav-xs+ nested<button><a>→ plain Tailwind fixed bottom nav:fixed inset-x-0 bottom-0 h-12 flex border-t border-border bg-background<button type="button">witharia-label(no more anchor-in-button nesting); active state swapstext-primaryvstext-muted-foregroundrouter.pushTailwind
plugins: [require('tailwindcss-animate'), require('daisyui')]→plugins: [require('tailwindcss-animate')]Dependency purge
daisyui@mui/joy,@mui/icons-material,@mui/x-date-pickers— all zero imports inapps/web/src(grep verified)@emotion/react,@emotion/styled— pulled only by MUI; framer-motion has its own emotion vendoring so dropping these is safeCloses #54. Parent #8 closes on merge.
Test plan
npx nx affected -t lint test build --exclude web-e2egreenrg "bg-neutral(?![-\w])|text-neutral-content|bg-base-\d|text-base-content|btm-nav|navbar|btn-ghost|btn-link|btn-primary|btn-neutral|card-body|card-title|select-bordered|menu-|daisyui" apps/web→ zero matches (outside.next/)grep -nE "daisyui|@mui/|@emotion/" package.json→ zero🤖 Generated with Claude Code
Summary by Sourcery
Refactor the web app UI away from DaisyUI/MUI to a Shadcn/Radix-based Tailwind setup, rebuilding navigation and shared components on the new design system.
New Features:
Bug Fixes:
Enhancements:
cnutility for composing Tailwind class names and simplify styling across components.Build:
tailwindcss-animate, and wire theme tokens to CSS variables.Chores: