Skip to content

feat(web): install and configure shadcn/ui#40

Merged
GRACENOBLE merged 3 commits into
mainfrom
35-feat-shadcn-ui
Jun 23, 2026
Merged

feat(web): install and configure shadcn/ui#40
GRACENOBLE merged 3 commits into
mainfrom
35-feat-shadcn-ui

Conversation

@GRACENOBLE

@GRACENOBLE GRACENOBLE commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • Ran shadcn init with the Nova preset (Lucide icons + Geist fonts — matches our existing font setup) on Tailwind v4
  • components.json committed at repo root with cssVariables: true and correct @/components/ui alias
  • globals.css updated with full design token set exposed as CSS variables; dark mode via .dark class toggle (@custom-variant dark (&:is(.dark *)))
  • Installed primitives: button, input, label, card, dialog, dropdown-menu, avatar, badge, separator, skeleton, sonner (toast is deprecated upstream — sonner is its replacement)
  • Added lib/utils.ts (cn helper) and components/common/container.tsx
  • Button Vitest tests confirm import path, disabled state, and variant attribute

Notes

  • The shadcn CLI rewrote app/page.tsx to a blank stub; the old scaffold tests in page.test.tsx were updated to a smoke test
  • next-themes intentionally omitted — per issue notes, it lands with the auth issue

Test plan

  • pnpm test — 41/41 passing
  • pnpm lint — 0 errors
  • pnpm build — passes cleanly
  • All primitives importable from @/components/ui/<name>
  • Dark mode tokens present in .dark block of globals.css

Closes #35

Summary by CodeRabbit

  • New Features

    • Introduced comprehensive UI component library including Avatars, Badges, Buttons, Cards, Dialogs, Dropdowns, Inputs, Labels, Separators, Skeletons, and Toast notifications.
    • Added dark mode and theme switching support.
  • Style

    • Redesigned design system with enhanced color tokens and typography.
  • Tests

    • Updated component and page tests with simplified assertions.
  • Chores

    • Refreshed homepage.
    • Added UI framework configuration.

- Run shadcn init with Nova preset (Lucide icons, Geist fonts, Tailwind v4)
- Add components.json with radix-nova style and CSS variable theming
- Update globals.css with full design token set (light + dark via .dark class)
- Install primitives: button, input, label, card, dialog, dropdown-menu,
  sonner (replaces deprecated toast), avatar, badge, separator, skeleton
- Add lib/utils.ts (cn helper) and components/common/container.tsx
- Add Vitest render tests for Button (label, disabled, variant attribute)
- Update page.test.tsx smoke test to match new minimal page stub

Closes #35
@github-actions github-actions Bot added area: web Next.js web app type: chore Cleanup or maintenance tasks labels Jun 23, 2026
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@GRACENOBLE, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 54 minutes and 9 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2831e4fa-e174-48c1-8d1f-e63435a18224

📥 Commits

Reviewing files that changed from the base of the PR and between f370c45 and f8b1a2a.

📒 Files selected for processing (9)
  • web/app/globals.css
  • web/components/common/container.tsx
  • web/components/common/h1.tsx
  • web/components/common/h2.tsx
  • web/components/common/h3.tsx
  • web/components/common/loader.tsx
  • web/components/ui/dialog.tsx
  • web/components/ui/sonner.tsx
  • web/lib/utils.test.ts
📝 Walkthrough

Walkthrough

Bootstraps shadcn/ui in the web project: adds components.json, rewrites globals.css with oklch design tokens and dark-mode class toggle, introduces a cn utility, adds eleven UI primitive components (Button, Badge, Input, Label, Card, Dialog, DropdownMenu, Avatar, Separator, Skeleton, Sonner), a Container layout helper, a minimal home page, and Button render tests.

Changes

shadcn/ui Installation and Component Library

Layer / File(s) Summary
Dependencies, cn utility, shadcn config, and CSS design tokens
web/package.json, web/lib/utils.ts, web/components.json, web/app/globals.css
Adds UI/utility packages, introduces the cn class-merging function, commits components.json with shadcn generation settings, and rewrites globals.css with oklch-based design tokens, a .dark class override, and Tailwind @layer base global styles.
Button, Badge, Input, Label, Separator, Skeleton primitives
web/components/ui/button.tsx, web/components/ui/badge.tsx, web/components/ui/input.tsx, web/components/ui/label.tsx, web/components/ui/separator.tsx, web/components/ui/skeleton.tsx
Six thin UI primitive components wrapping HTML elements or Radix primitives with CVA/cn-based styling, data-slot/data-variant attributes, and asChild support where applicable.
Avatar, Card, Dialog, DropdownMenu, and Sonner/Toaster
web/components/ui/avatar.tsx, web/components/ui/card.tsx, web/components/ui/dialog.tsx, web/components/ui/dropdown-menu.tsx, web/components/ui/sonner.tsx
Five richer component modules: Avatar with size/group/badge variants; Card with seven sub-components; Dialog with optional close buttons; DropdownMenu with full item/checkbox/radio/sub-menu support; and a themed Sonner Toaster that reads next-themes.
Container helper and simplified home page
web/components/common/container.tsx, web/app/page.tsx
Adds a centered mx-auto max-w-7xl Container layout component and replaces the structured home page with a minimal empty <div />.
Button render tests and simplified page smoke test
web/__tests__/button.test.tsx, web/__tests__/page.test.tsx
Adds three RTL tests for Button (label text, disabled state, data-variant attribute) and collapses the Home page test to a single crash-guard assertion.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • GRACENOBLE/fullstack-template#13: Both PRs modify web/__tests__/page.test.tsx; the earlier PR added specific UI text assertions for the Home page which this PR removes in favour of a simpler crash-guard test.

Suggested labels

area: web

🐰 A hop, a skip, a shadcn delight,
New tokens in oklch, dark mode just right!
Buttons and badges and dialogs galore,
A skeleton dances on every blank shore.
The rabbit has built you a UI to keep —
Now cn your classes and skip off to sleep! 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(web): install and configure shadcn/ui' directly and clearly summarizes the main change—installation and configuration of shadcn/ui as described in the PR objectives.
Linked Issues check ✅ Passed All work items from issue #35 are completed: components.json is created, all primitives (except toast, replaced with sonner) are installed and importable, CSS variables are configured with dark-mode support, and Vitest tests validate the import path.
Out of Scope Changes check ✅ Passed All changes directly support shadcn/ui installation and configuration. Package additions (class-variance-authority, clsx, lucide-react, radix-ui, etc.) are required for component functionality; CSS refactoring enables theming; test updates validate imports; and page.tsx rewrite aligns with shadcn CLI behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 35-feat-shadcn-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/components/ui/label.tsx (1)

1-25: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add a render test for this new Client Component.

Label is introduced as a Client Component, but this PR only adds Button/page tests; a @testing-library/react render test for Label is required by repo policy.

As per coding guidelines: “All Client Components ("use client") must have render tests using @testing-library/react” and “New Client Components in Next.js must have rendering tests with Vitest + @testing-library/react”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/components/ui/label.tsx` around lines 1 - 25, The `Label` component is a
new Client Component (marked with "use client") but lacks a required render test
file. Create a test file for the Label component using Vitest and
`@testing-library/react` that includes render tests verifying the component
renders correctly with its default styling and properly applies custom className
props. Ensure the test follows the repository's testing conventions and covers
basic rendering scenarios for the Label component.

Source: Coding guidelines

web/components/ui/separator.tsx (1)

1-29: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add a render test for this new Client Component.

Separator is added as a Client Component without a corresponding RTL render test in this PR.

As per coding guidelines: “All Client Components ("use client") must have render tests using @testing-library/react” and “New Client Components in Next.js must have rendering tests with Vitest + @testing-library/react”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web/components/ui/separator.tsx` around lines 1 - 29, Create a render test
file for the Separator component using Vitest and `@testing-library/react`. The
test should verify that the Separator component renders correctly as a Client
Component. Add test cases to check that the component renders with default props
(horizontal orientation and decorative=true), and test various prop combinations
such as different orientations (vertical) and decorative attribute variations.
Ensure the test file follows the project's testing conventions and is properly
integrated into the test suite.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@web/components/common/container.tsx`:
- Around line 3-4: Make the className property optional in the Container
component's props definition. In the Container function signature, change the
className property from a required string (className: string) to an optional
string (className?: string). This allows the cn() utility to handle cases where
className is undefined, enabling the component to be used without providing a
className prop every time.

In `@web/components/ui/dialog.tsx`:
- Around line 72-76: Add explicit type="button" attribute to the Button
component used as a dialog close action to prevent it from defaulting to submit
behavior inside forms. This applies to the close button around line 72-76 and
also to the close button around line 118. Ensure both close control buttons in
the dialog component have type="button" explicitly set to avoid unintended form
submissions.

In `@web/components/ui/sonner.tsx`:
- Around line 31-38: Remove the inline style prop containing the Sonner CSS
variables (--normal-bg, --normal-text, --normal-border, --border-radius) from
the component and move these custom property definitions to a CSS class (such as
.toaster or .cn-toast) in the project's CSS files. Replace the style prop with a
className attribute that references the CSS class containing these variable
definitions to maintain Tailwind v4 compliance and keep the component
className-driven.

In `@web/lib/utils.ts`:
- Around line 4-6: Create a Vitest unit test file for the cn utility function
that exports from web/lib/utils.ts. Write test cases that verify the cn function
correctly combines and merges CSS class values by confirming it properly passes
inputs to clsx and applies the twMerge transformation. Ensure the tests cover
various scenarios including multiple class inputs, conflicting Tailwind classes,
and edge cases to guarantee the function behaves as expected per project
guidelines requiring all lib/ functions to have unit test coverage.

---

Outside diff comments:
In `@web/components/ui/label.tsx`:
- Around line 1-25: The `Label` component is a new Client Component (marked with
"use client") but lacks a required render test file. Create a test file for the
Label component using Vitest and `@testing-library/react` that includes render
tests verifying the component renders correctly with its default styling and
properly applies custom className props. Ensure the test follows the
repository's testing conventions and covers basic rendering scenarios for the
Label component.

In `@web/components/ui/separator.tsx`:
- Around line 1-29: Create a render test file for the Separator component using
Vitest and `@testing-library/react`. The test should verify that the Separator
component renders correctly as a Client Component. Add test cases to check that
the component renders with default props (horizontal orientation and
decorative=true), and test various prop combinations such as different
orientations (vertical) and decorative attribute variations. Ensure the test
file follows the project's testing conventions and is properly integrated into
the test suite.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6e6ef0cf-84d7-4869-b847-579bcdb4cd11

📥 Commits

Reviewing files that changed from the base of the PR and between 47c348f and f370c45.

⛔ Files ignored due to path filters (1)
  • web/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • web/__tests__/button.test.tsx
  • web/__tests__/page.test.tsx
  • web/app/globals.css
  • web/app/page.tsx
  • web/components.json
  • web/components/common/container.tsx
  • web/components/ui/avatar.tsx
  • web/components/ui/badge.tsx
  • web/components/ui/button.tsx
  • web/components/ui/card.tsx
  • web/components/ui/dialog.tsx
  • web/components/ui/dropdown-menu.tsx
  • web/components/ui/input.tsx
  • web/components/ui/label.tsx
  • web/components/ui/separator.tsx
  • web/components/ui/skeleton.tsx
  • web/components/ui/sonner.tsx
  • web/lib/utils.ts
  • web/package.json

Comment thread web/components/common/container.tsx Outdated
Comment thread web/components/ui/dialog.tsx
Comment thread web/components/ui/sonner.tsx Outdated
Comment thread web/lib/utils.ts
GRACENOBLE and others added 2 commits June 23, 2026 17:36
- container.tsx, h2.tsx: make className optional (cn handles undefined safely)
- dialog.tsx: add type="button" to close buttons to prevent form submission
- sonner.tsx: remove inline style prop; move CSS vars to .toaster in globals.css
- lib/utils.test.ts: add Vitest unit tests for cn (merge, falsy, conflict, conditional)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@GRACENOBLE GRACENOBLE merged commit b471f47 into main Jun 23, 2026
3 checks passed
@GRACENOBLE GRACENOBLE deleted the 35-feat-shadcn-ui branch June 23, 2026 14:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: web Next.js web app type: chore Cleanup or maintenance tasks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(web): install and configure shadcn/ui

1 participant