Feature Card Block ๐ŸŽฏ

August 9, 2025 ยท View on GitHub

Showcase features, products, or services with beautiful card layouts. Fully configurable with content projection for unlimited customization and flexible layouts that adapt to your content needs.

Features

  • ๐ŸŽจ Multiple Variants - Default, minimal, glass, gradient, outlined, and filled styles
  • ๐Ÿ“ฑ Responsive Design - Mobile-first approach with flexible grid layouts
  • ๐Ÿ”ง Content Projection - Unlimited customization through slot-based architecture
  • โšก Interactive States - Hover effects, click handling, and focus management
  • ๐ŸŽฏ Flexible Sizing - From compact cards to large feature showcases
  • โ™ฟ Accessibility - ARIA compliant with keyboard navigation support
  • ๐ŸŽญ Theme Aware - Automatic dark mode support with Tailwind CSS
  • ๐Ÿš€ Performance - Optimized rendering with Angular signals

Installation

Add the Feature Card Block component:

npx ngsui-cli add block feature-card

Usage

Create feature cards with custom content using slot-based architecture:

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FeatureCardBlock } from '@lib/blocks/feature-card';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [CommonModule, FeatureCardBlock],
  template: `
    <!-- Basic Feature Card -->
    <FeatureCardBlock variant="default" size="default" spacing="default">
      <div slot="icon" class="w-12 h-12 bg-blue-500 rounded-lg flex items-center justify-center mb-4">
        <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
        </svg>
      </div>
      <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Lightning Fast</h3>
      <p slot="description" class="text-gray-600 dark:text-gray-300">Optimized performance with modern Angular features and lazy loading.</p>
      <button slot="cta" class="mt-4 text-blue-600 hover:text-blue-700 font-medium">Learn More โ†’</button>
    </FeatureCardBlock>
  `
})
export class ExampleComponent {}

Examples

Default Style Cards

@Component({
  imports: [CommonModule, FeatureCardBlock],
  template: `
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      <FeatureCardBlock variant="default" size="default" spacing="default">
        <div slot="icon" class="w-12 h-12 bg-blue-500 rounded-lg flex items-center justify-center mb-4">
          <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
          </svg>
        </div>
        <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Lightning Fast</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300">Optimized performance with modern Angular features and lazy loading.</p>
        <button slot="cta" class="mt-4 text-blue-600 hover:text-blue-700 font-medium">Learn More โ†’</button>
      </FeatureCardBlock>

      <FeatureCardBlock variant="default" size="default" spacing="default">
        <div slot="icon" class="w-12 h-12 bg-green-500 rounded-lg flex items-center justify-center mb-4">
          <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
          </svg>
        </div>
        <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Type Safe</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300">Built with TypeScript for better developer experience and fewer runtime errors.</p>
        <button slot="cta" class="mt-4 text-green-600 hover:text-green-700 font-medium">Explore โ†’</button>
      </FeatureCardBlock>

      <FeatureCardBlock variant="default" size="default" spacing="default">
        <div slot="icon" class="w-12 h-12 bg-purple-500 rounded-lg flex items-center justify-center mb-4">
          <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zM21 5a2 2 0 00-2-2h-4a2 2 0 00-2 2v12a4 4 0 004 4h4a2 2 0 002-2V5z"></path>
          </svg>
        </div>
        <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Customizable</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300">Unlimited customization with content projection and Tailwind CSS classes.</p>
        <button slot="cta" class="mt-4 text-purple-600 hover:text-purple-700 font-medium">Customize โ†’</button>
      </FeatureCardBlock>
    </div>
  `
})

Gradient Style with Enhanced Content

@Component({
  imports: [CommonModule, FeatureCardBlock],
  template: `
    <div class="grid grid-cols-1 md:grid-cols-2 gap-8">
      <FeatureCardBlock variant="gradient" size="lg" spacing="relaxed">
        <div slot="badge" class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-orange-100 text-orange-800 mb-4">
          Popular
        </div>
        <div slot="icon" class="w-16 h-16 bg-gradient-to-br from-orange-400 to-pink-500 rounded-2xl flex items-center justify-center mb-6">
          <svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path>
          </svg>
        </div>
        <h3 slot="title" class="text-2xl font-bold text-gray-900 dark:text-white mb-3">Premium Features</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-lg leading-relaxed">
          Access advanced components, premium themes, and priority support for your projects.
        </p>
        <div slot="stats" class="flex items-center gap-6 mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
          <div class="text-center">
            <div class="text-2xl font-bold text-gray-900 dark:text-white">50+</div>
            <div class="text-sm text-gray-500">Components</div>
          </div>
          <div class="text-center">
            <div class="text-2xl font-bold text-gray-900 dark:text-white">10+</div>
            <div class="text-sm text-gray-500">Themes</div>
          </div>
          <div class="text-center">
            <div class="text-2xl font-bold text-gray-900 dark:text-white">24/7</div>
            <div class="text-sm text-gray-500">Support</div>
          </div>
        </div>
      </FeatureCardBlock>

      <FeatureCardBlock variant="gradient" size="lg" spacing="relaxed">
        <div slot="icon" class="w-16 h-16 bg-gradient-to-br from-blue-400 to-indigo-500 rounded-2xl flex items-center justify-center mb-6">
          <svg class="w-8 h-8 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"></path>
          </svg>
        </div>
        <h3 slot="title" class="text-2xl font-bold text-gray-900 dark:text-white mb-3">Smart Analytics</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-lg leading-relaxed">
          Get insights into your application performance with built-in analytics and monitoring.
        </p>
        <div slot="actions" class="flex gap-3 mt-6">
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
            Get Started
          </button>
          <button class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
            Learn More
          </button>
        </div>
      </FeatureCardBlock>
    </div>
  `
})

Glass Effect Style

@Component({
  imports: [CommonModule, FeatureCardBlock],
  template: `
    <div class="relative p-8 bg-gradient-to-br from-purple-500 via-pink-500 to-red-500 rounded-2xl">
      <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
        <FeatureCardBlock variant="glass" size="default" spacing="default">
          <div slot="icon" class="w-10 h-10 bg-white/20 rounded-lg flex items-center justify-center mb-4">
            <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"></path>
            </svg>
          </div>
          <h3 slot="title" class="text-lg font-semibold text-white mb-2">Secure</h3>
          <p slot="description" class="text-white/80">Enterprise-grade security with encryption and authentication.</p>
        </FeatureCardBlock>

        <FeatureCardBlock variant="glass" size="default" spacing="default">
          <div slot="icon" class="w-10 h-10 bg-white/20 rounded-lg flex items-center justify-center mb-4">
            <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 10V3L4 14h7v7l9-11h-7z"></path>
            </svg>
          </div>
          <h3 slot="title" class="text-lg font-semibold text-white mb-2">Fast</h3>
          <p slot="description" class="text-white/80">Optimized for performance with lazy loading and caching.</p>
        </FeatureCardBlock>

        <FeatureCardBlock variant="glass" size="default" spacing="default">
          <div slot="icon" class="w-10 h-10 bg-white/20 rounded-lg flex items-center justify-center mb-4">
            <svg class="w-5 h-5 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"></path>
            </svg>
          </div>
          <h3 slot="title" class="text-lg font-semibold text-white mb-2">Loved</h3>
          <p slot="description" class="text-white/80">Trusted by thousands of developers worldwide.</p>
        </FeatureCardBlock>
      </div>
    </div>
  `
})

Minimal Style with Icon Component

import { Icon } from '@lib/components/icon';

@Component({
  imports: [CommonModule, FeatureCardBlock, Icon],
  template: `
    <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
      <FeatureCardBlock variant="minimal" size="default" spacing="compact">
        <div slot="icon" class="w-8 h-8 bg-red-500 rounded-lg flex items-center justify-center mb-3">
          <Icon icon="fas fa-bolt" size="sm" variant="default" class="text-white" ariaLabel="Performance icon" />
        </div>
        <h3 slot="title" class="text-lg font-semibold text-gray-900 dark:text-white mb-1">Performance</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-sm">Optimized for speed</p>
      </FeatureCardBlock>

      <FeatureCardBlock variant="minimal" size="default" spacing="compact">
        <div slot="icon" class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center mb-3">
          <Icon icon="fas fa-shield-alt" size="sm" variant="default" class="text-white" ariaLabel="Security icon" />
        </div>
        <h3 slot="title" class="text-lg font-semibold text-gray-900 dark:text-white mb-1">Security</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-sm">Enterprise-grade protection</p>
      </FeatureCardBlock>

      <FeatureCardBlock variant="minimal" size="default" spacing="compact">
        <div slot="icon" class="w-8 h-8 bg-green-500 rounded-lg flex items-center justify-center mb-3">
          <Icon icon="fas fa-expand-arrows-alt" size="sm" variant="default" class="text-white" ariaLabel="Scalability icon" />
        </div>
        <h3 slot="title" class="text-lg font-semibold text-gray-900 dark:text-white mb-1">Scalability</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-sm">Grows with your needs</p>
      </FeatureCardBlock>

      <FeatureCardBlock variant="minimal" size="default" spacing="compact">
        <div slot="icon" class="w-8 h-8 bg-purple-500 rounded-lg flex items-center justify-center mb-3">
          <Icon icon="fas fa-headset" size="sm" variant="default" class="text-white" ariaLabel="Support icon" />
        </div>
        <h3 slot="title" class="text-lg font-semibold text-gray-900 dark:text-white mb-1">Support</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 text-sm">24/7 expert assistance</p>
      </FeatureCardBlock>
    </div>
  `
})

Interactive Cards with Events

@Component({
  imports: [CommonModule, FeatureCardBlock],
  template: `
    <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
      <FeatureCardBlock 
        variant="outlined" 
        size="lg" 
        [interactive]="true"
        (cardClick)="onCardClick('premium')"
        (cardHover)="onCardHover('premium')"
      >
        <div slot="badge" class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-blue-100 text-blue-800 mb-4">
          Recommended
        </div>
        <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Premium Plan</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 mb-4">
          Everything you need to build professional applications with advanced features.
        </p>
        <div slot="actions" class="flex items-center justify-between">
          <span class="text-2xl font-bold text-gray-900 dark:text-white">\$29/mo</span>
          <button class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
            Choose Plan
          </button>
        </div>
      </FeatureCardBlock>

      <FeatureCardBlock 
        variant="filled" 
        size="lg" 
        [highlighted]="true"
        [interactive]="true"
        (cardClick)="onCardClick('enterprise')"
      >
        <h3 slot="title" class="text-xl font-semibold text-gray-900 dark:text-white mb-2">Enterprise</h3>
        <p slot="description" class="text-gray-600 dark:text-gray-300 mb-4">
          Custom solutions for large teams with dedicated support and advanced security.
        </p>
        <div slot="actions" class="flex items-center justify-between">
          <span class="text-lg text-gray-600 dark:text-gray-400">Custom pricing</span>
          <button class="px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 transition-colors">
            Contact Sales
          </button>
        </div>
      </FeatureCardBlock>
    </div>
  `
})
export class InteractiveCardsComponent {
  onCardClick(plan: string) {
    console.log('Card clicked:', plan);
  }

  onCardHover(plan: string) {
    console.log('Card hovered:', plan);
  }
}

API Reference

Props

PropTypeDefaultDescription
variant'default' | 'minimal' | 'glass' | 'gradient' | 'outlined' | 'filled' | 'custom''default'Card visual style variant
size'sm' | 'default' | 'lg' | 'xl' | 'custom''default'Card padding and size
spacing'compact' | 'default' | 'relaxed' | 'custom''default'Internal content spacing
highlightedbooleanfalseAdds highlight ring to card
disabledbooleanfalseDisables interactions and adds opacity
interactivebooleantrueEnables hover effects and cursor pointer
classstring''Additional CSS classes for the card
contentClassstring''Additional CSS classes for content area

Events

EventTypeDescription
cardClickEventEmitter<MouseEvent>Emitted when card is clicked
cardHoverEventEmitter<MouseEvent>Emitted when card is hovered
cardFocusEventEmitter<FocusEvent>Emitted when card receives focus

Content Slots

SlotDescriptionUsage
slot="icon"Icon or media areaIcons, images, or custom graphics
slot="media"Alternative media slotImages, videos, or complex media
slot="image"Image-specific slotProduct images, avatars, etc.
slot="badge"Badge or label areaStatus badges, labels, or tags
slot="title"Main headingCard title or name
slot="description"Description textCard description or details
slot="stats"Statistics areaNumbers, metrics, or data points
slot="metrics"Alternative metrics slotPerformance indicators, ratings
slot="actions"Action buttons areaCTAs, buttons, or links
slot="cta"Call-to-action slotPrimary action buttons
slot="footer"Footer contentAdditional information or links
slot="overlay"Overlay contentDecorative overlays or badges
slot="decorative"Decorative elementsBackground patterns, gradients

Variant Styles

VariantDescriptionUse Case
defaultStandard card with shadow and borderGeneral purpose feature cards
minimalClean design without borders/shadowsSimple content presentation
glassGlassmorphism effect with backdrop blurModern, overlay-style cards
gradientSubtle gradient backgroundPremium or highlighted content
outlinedProminent border stylingInteractive or selectable cards
filledColored background with subtle stylingGrouped or categorized content
customNo default stylingComplete customization control

Styling

Custom Styling

@Component({
  template: `
    <FeatureCardBlock 
      variant="custom"
      class="bg-gradient-to-r from-cyan-500 to-blue-500 text-white rounded-2xl shadow-2xl"
      contentClass="space-y-6"
    >
      <div slot="icon" class="w-12 h-12 bg-white/20 rounded-full flex items-center justify-center">
        <Icon icon="fas fa-rocket" size="lg" class="text-white" />
      </div>
      <h3 slot="title" class="text-2xl font-bold">Custom Styled Card</h3>
      <p slot="description" class="text-white/90">
        Complete control over styling with custom variant.
      </p>
    </FeatureCardBlock>
  `
})

Responsive Design

@Component({
  template: `
    <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 md:gap-6">
      <FeatureCardBlock 
        variant="default" 
        size="default"
        class="lg:col-span-2"
      >
        <!-- Featured card spanning 2 columns on large screens -->
      </FeatureCardBlock>
      
      <FeatureCardBlock variant="minimal" size="sm" class="sm:size-default">
        <!-- Adaptive sizing based on screen size -->
      </FeatureCardBlock>
    </div>
  `
})

Dark Mode Support

@Component({
  template: `
    <FeatureCardBlock 
      variant="default"
      class="bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700"
    >
      <h3 slot="title" class="text-gray-900 dark:text-white">Dark Mode Ready</h3>
      <p slot="description" class="text-gray-600 dark:text-gray-300">
        Automatic dark mode support with Tailwind CSS classes.
      </p>
    </FeatureCardBlock>
  `
})

Best Practices

Content Organization

  • Use clear, descriptive titles that communicate the main benefit
  • Keep descriptions concise but informative (1-2 sentences)
  • Place primary actions prominently with clear CTAs
  • Use icons that are immediately recognizable and relevant

Layout Guidelines

  • Maintain consistent card heights within the same row
  • Use appropriate grid layouts for different screen sizes
  • Ensure adequate spacing between cards for readability
  • Consider card aspect ratios for visual balance

Accessibility

  • Provide meaningful alt text for icons and images
  • Use semantic HTML within content slots
  • Ensure sufficient color contrast for text content
  • Test keyboard navigation and screen reader compatibility

Performance

  • Optimize images and icons for web delivery
  • Use lazy loading for cards below the fold
  • Consider virtualization for large lists of cards
  • Minimize complex animations that impact performance

Interactive Design

  • Use hover effects to indicate interactivity
  • Provide clear visual feedback for user actions
  • Implement loading states for async operations
  • Consider mobile touch interactions and gestures

Content Strategy

  • Focus on benefits rather than features in descriptions
  • Use action-oriented language for CTAs
  • Group related cards logically with consistent styling
  • Test different layouts and content variations for effectiveness

Examples in Production

Feature Showcase

Perfect for highlighting product features, service offerings, or key benefits on landing pages.

Pricing Plans

Ideal for presenting different subscription tiers or service packages with clear comparisons.

Team Members

Great for showcasing team members with photos, roles, and brief descriptions.

Portfolio Items

Excellent for displaying work samples, case studies, or project highlights.

Service Offerings

Suitable for presenting different services with icons, descriptions, and booking links.

Product Cards

Perfect for e-commerce product listings with images, descriptions, and purchase options.