Skip to content

Add Card component using shadcn/ui primitives with custom ProductCard extension#37

Draft
Copilot wants to merge 5 commits into
mainfrom
copilot/add-card-component
Draft

Add Card component using shadcn/ui primitives with custom ProductCard extension#37
Copilot wants to merge 5 commits into
mainfrom
copilot/add-card-component

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Nov 26, 2025

Implements a Card component system using shadcn/ui base primitives, extended with a custom ProductCard wrapper for specific requirements including title, description, optional CTA (button/link), and optional image with configurable positioning.

Implementation

shadcn/ui Base Components (card-primitives.tsx)

  • Card - Root container with border, shadow, rounded corners
  • CardHeader - Header section with spacing
  • CardTitle - Heading element (h3) with typography
  • CardDescription - Description text with muted color
  • CardContent - Content area with padding
  • CardFooter - Footer section for actions

Custom ProductCard (card.tsx)

  • Built on top of shadcn primitives for consistency
  • Dynamic heading level (h2-h4) for semantic HTML via titleHeadingLevel prop
  • Optional CTA supporting both onClick handlers and href (internal/external)
  • Optional image with imagePosition variant: top, bottom, or none
  • Uses class-variance-authority for variant management
  • Border radius adapts to image position (top: rounded-t-lg, bottom: rounded-b-lg)

URL Handling
External link detection checks http://, https://, and protocol-relative // URLs, automatically adding target="_blank" and rel="noopener noreferrer".

Testing & Documentation

  • 23 unit tests with 100% coverage including accessibility validation
  • 13 Storybook stories demonstrating all configurations

Usage

Using shadcn primitives directly

import { 
  Card, 
  CardHeader, 
  CardTitle, 
  CardDescription, 
  CardContent, 
  CardFooter 
} from "@/components/ui/card";

<Card>
  <CardHeader>
    <CardTitle>Custom Card</CardTitle>
    <CardDescription>Build any layout</CardDescription>
  </CardHeader>
  <CardContent>
    Your custom content here
  </CardContent>
  <CardFooter>
    <Button>Action</Button>
  </CardFooter>
</Card>

Using ProductCard wrapper

import { ProductCard } from "@/components/ui/card";

<ProductCard 
  title="Feature Card"
  titleHeadingLevel="h3"
  description="Description text"
  image={{ src: "/image.jpg", alt: "Feature" }}
  imagePosition="top"
  cta={{ text: "Learn more", href: "/about" }}
/>

Benefits

Flexibility - Use shadcn primitives for custom layouts or ProductCard for quick implementation
Consistency - Base components follow shadcn/ui design system and patterns
Extensibility - Easy to create new variants by composing primitives
Type Safety - Full TypeScript support with proper type exports
Accessibility - Semantic HTML and WCAG compliant

Screenshots

Refactored Card Component with shadcn/ui primitives

Original prompt

This section details on the original issue you should resolve

<issue_title>New</issue_title>
<issue_description>add a card component to the codebase.

title, description, optional cta, optional image maybe a titleHeadlingLevel prop with h2 - h4,

image top, image bottom options.

and whatever else you think that might be nice. dont go overboard</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@github-actions
Copy link
Copy Markdown

Coverage after merging copilot/add-card-component into main will be

35.48%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
src/app
   favicon.ico100%100%100%100%
   layout.tsx0%100%0%0%15, 5
   page.tsx0%100%0%0%5
src/components/numbered-list
   index.ts100%100%100%100%
   numbered-list.tsx100%100%100%100%
src/components/ui/button
   button.tsx100%100%100%100%
   index.ts100%100%100%100%
src/lib
   fonts.ts0%0%100%0%10, 15, 20–21, 24, 24, 24–25, 28–29, 31, 36, 42
   utils.ts100%100%100%100%
src/lib/test-utils
   accessibility.ts25%100%25%25%125–126, 37–38, 72–73

@github-actions
Copy link
Copy Markdown

🚀 Lighthouse Performance Results

URL Performance Accessibility Best Practices SEO Report
http://localhost:3000/ 100 100 100 100 📊 Details

Download the lighthouse-results artifact from the workflow run to view detailed HTML reports.

Copilot AI and others added 2 commits November 26, 2025 12:21
- Create Card component with TypeScript in src/components/ui/card/
- Support title with configurable heading level (h2-h4)
- Support description text
- Optional CTA button or link (internal/external)
- Optional image with top/bottom positioning
- Use class-variance-authority for variants
- Use Tailwind CSS for styling with hover effects
- Add comprehensive unit tests (22 tests, 100% coverage)
- Add extensive Storybook stories for documentation
- Add barrel export via index.ts
- Full accessibility support with a11y tests

Co-authored-by: DanStuartDept <87612831+DanStuartDept@users.noreply.github.com>
- Fix image border radius to respect imagePosition (top vs bottom)
- Improve external URL detection to include http://, https://, and //
- Fix imagePosition default logic to prevent inconsistent behavior
- Add test for protocol-relative URLs
- Maintain 100% test coverage (23 tests passing)

Co-authored-by: DanStuartDept <87612831+DanStuartDept@users.noreply.github.com>
Copilot AI changed the title [WIP] Add card component to the codebase Add Card component with configurable heading, CTA, and image positioning Nov 26, 2025
Copilot AI requested a review from DanStuartDept November 26, 2025 12:28
@DanStuartDept
Copy link
Copy Markdown
Owner

@copilot actually can we reuse shadcn elements and then use those ui components and extend with my custom requirements

- Add card-primitives.tsx with shadcn base components
- Refactor card.tsx to build ProductCard on top of primitives
- Export shadcn primitives and custom ProductCard
- ProductCard extends shadcn with image positioning, CTA, heading levels
- Update tests and stories to use ProductCard
- All 47 tests passing with 100% coverage on card.tsx

Co-authored-by: DanStuartDept <87612831+DanStuartDept@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Nov 26, 2025

@copilot actually can we reuse shadcn elements and then use those ui components and extend with my custom requirements

Done! I've refactored the Card component to use shadcn/ui primitives as the foundation (commit 1999a26).

What changed:

  • Added card-primitives.tsx with shadcn base components (Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter)
  • Refactored to export both the shadcn primitives AND a custom ProductCard wrapper
  • ProductCard builds on top of shadcn primitives, extending them with your requirements (image positioning, CTA buttons/links, configurable heading levels)

You can now use either:

  1. Shadcn primitives directly for complete flexibility:
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "@/components/ui/card";

<Card>
  <CardHeader>
    <CardTitle>Custom Layout</CardTitle>
    <CardDescription>Build anything</CardDescription>
  </CardHeader>
  <CardContent>Your content</CardContent>
  <CardFooter><Button>Action</Button></CardFooter>
</Card>
  1. ProductCard wrapper for your specific use case:
import { ProductCard } from "@/components/ui/card";

<ProductCard 
  title="Feature"
  titleHeadingLevel="h3"
  description="Description"
  image={{ src: "/img.jpg", alt: "Feature" }}
  imagePosition="top"
  cta={{ text: "Learn more", href: "/about" }}
/>

All 47 tests passing, 100% coverage maintained.

Updated Card Component

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • storybook.js.org
    • Triggering command: /usr/local/bin/node node /home/REDACTED/work/example-next-product/example-next-product/node_modules/.bin/../storybook/dist/bin/dispatcher.js dev -p 6006 (dns block)
  • ui.shadcn.com
    • Triggering command: /usr/local/bin/node node /home/REDACTED/.npm/_npx/d66c5096c7023bfb/node_modules/.bin/shadcn add card --yes (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Co-authored-by: DanStuartDept <87612831+DanStuartDept@users.noreply.github.com>
Copilot AI changed the title Add Card component with configurable heading, CTA, and image positioning Add Card component using shadcn/ui primitives with custom ProductCard extension Nov 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New

2 participants