+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Part 167 of 355

๐ŸŽจ Styled Components: CSS-in-JS with Types

Master styled components: css-in-js with types in TypeScript with practical examples, best practices, and real-world applications ๐Ÿš€

๐Ÿš€Intermediate
25 min read

Prerequisites

  • Basic understanding of JavaScript ๐Ÿ“
  • TypeScript installation โšก
  • VS Code or preferred IDE ๐Ÿ’ป
  • React basics ๐ŸŽ›๏ธ

What you'll learn

  • Understand styled-components fundamentals ๐ŸŽฏ
  • Apply type-safe styling in real projects ๐Ÿ—๏ธ
  • Debug common CSS-in-JS issues ๐Ÿ›
  • Write type-safe styled components โœจ

๐ŸŽฏ Introduction

Welcome to the colorful world of styled-components! ๐ŸŽจ In this guide, weโ€™ll explore how to combine the power of CSS-in-JS with TypeScriptโ€™s type safety to create beautiful, maintainable components.

Styled-components lets you write CSS directly in your JavaScript/TypeScript, making styling feel like a natural part of your component logic. Whether youโ€™re building stunning user interfaces ๐ŸŒˆ, theming systems ๐ŸŽญ, or responsive layouts ๐Ÿ“ฑ, styled-components with TypeScript will revolutionize how you approach styling!

By the end of this tutorial, youโ€™ll feel confident creating type-safe styled components that are both beautiful and bulletproof! Letโ€™s paint some code! ๐Ÿ–Œ๏ธ

๐Ÿ“š Understanding Styled Components

๐Ÿค” What are Styled Components?

Styled-components is like having a magical paintbrush ๐Ÿ–Œ๏ธ that lets you paint styles directly onto your React components. Think of it as writing CSS, but with superpowers - you get JavaScriptโ€™s dynamic capabilities and TypeScriptโ€™s type safety all in one!

In TypeScript terms, styled-components creates React components with styles attached using template literals. This means you can:

  • โœจ Write CSS that feels like JavaScript
  • ๐Ÿš€ Use props to create dynamic styles
  • ๐Ÿ›ก๏ธ Get TypeScriptโ€™s type safety for your styles
  • ๐ŸŽจ Create reusable styled components

๐Ÿ’ก Why Use Styled Components with TypeScript?

Hereโ€™s why developers love this combination:

  1. Type Safety ๐Ÿ”’: TypeScript catches styling errors at compile-time
  2. Dynamic Styling ๐ŸŽจ: Use props to change styles programmatically
  3. Component Scoping ๐Ÿ“ฆ: No more CSS class name conflicts
  4. Theme Support ๐ŸŽญ: Built-in theming with type safety
  5. No CSS Files ๐Ÿ“: Keep styles and components together

Real-world example: Imagine building a button component ๐ŸŽ›๏ธ. With styled-components + TypeScript, you can create a button that changes color based on props, with full type safety!

๐Ÿ”ง Basic Syntax and Usage

๐Ÿ“ฆ Installation

First, letโ€™s get styled-components set up:

# ๐Ÿ“ฆ Install styled-components and TypeScript types
npm install styled-components
npm install --save-dev @types/styled-components

# ๐ŸŽจ For pnpm users:
pnpm add styled-components
pnpm add -D @types/styled-components

๐Ÿ“ Simple Example

Letโ€™s start with a friendly example:

// ๐Ÿ‘‹ Hello, Styled Components!
import styled from 'styled-components';

// ๐ŸŽจ Creating a simple styled component
const WelcomeTitle = styled.h1`
  color: #6366f1; /* ๐Ÿ’œ Beautiful purple */
  font-size: 2rem;
  text-align: center;
  margin: 1rem 0;
  
  /* โœจ Add a subtle animation */
  animation: fadeIn 0.5s ease-in;
  
  @keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
  }
`;

// ๐ŸŽฏ Using our styled component
function App() {
  return (
    <WelcomeTitle>
      Welcome to Styled Components! ๐ŸŽ‰
    </WelcomeTitle>
  );
}

๐Ÿ’ก Explanation: Notice how we use template literals (backticks) to write CSS directly in TypeScript! The styled.h1 creates a new component that renders as an h1 with our styles.

๐ŸŽฏ Props-Based Styling

Hereโ€™s where the magic happens - dynamic styling with props:

// ๐ŸŽจ Type-safe props interface
interface ButtonProps {
  variant: 'primary' | 'secondary' | 'danger';
  size: 'small' | 'medium' | 'large';
  disabled?: boolean;
}

// ๐ŸŽ›๏ธ Dynamic styled button
const StyledButton = styled.button<ButtonProps>`
  /* ๐ŸŽจ Base styles */
  padding: ${props => {
    switch (props.size) {
      case 'small': return '0.5rem 1rem';
      case 'large': return '1rem 2rem';
      default: return '0.75rem 1.5rem';
    }
  }};
  
  border: none;
  border-radius: 0.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
  
  /* ๐ŸŒˆ Color variants */
  background-color: ${props => {
    switch (props.variant) {
      case 'primary': return '#3b82f6';
      case 'danger': return '#ef4444';
      default: return '#6b7280';
    }
  }};
  
  color: white;
  
  /* ๐Ÿšซ Disabled state */
  opacity: ${props => props.disabled ? 0.5 : 1};
  cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
  
  /* โœจ Hover effects */
  &:hover {
    transform: ${props => props.disabled ? 'none' : 'translateY(-2px)'};
    box-shadow: ${props => 
      props.disabled ? 'none' : '0 4px 12px rgba(0, 0, 0, 0.15)'
    };
  }
`;

// ๐ŸŽฎ Using our dynamic button
function ButtonDemo() {
  return (
    <div>
      <StyledButton variant="primary" size="medium">
        Primary Button ๐Ÿš€
      </StyledButton>
      
      <StyledButton variant="danger" size="small" disabled>
        Disabled Button ๐Ÿšซ
      </StyledButton>
    </div>
  );
}

๐Ÿ’ก Practical Examples

๐Ÿ›’ Example 1: E-commerce Product Card

Letโ€™s build something real - a product card for an online store:

// ๐Ÿ›๏ธ Product data interface
interface Product {
  id: string;
  name: string;
  price: number;
  image: string;
  rating: number;
  inStock: boolean;
}

// ๐ŸŽจ Styled card components
const ProductCard = styled.div`
  background: white;
  border-radius: 1rem;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  
  &:hover {
    transform: translateY(-4px); /* โœจ Lift on hover */
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
  }
`;

const ProductImage = styled.img`
  width: 100%;
  height: 200px;
  object-fit: cover;
`;

const ProductInfo = styled.div`
  padding: 1rem;
`;

const ProductName = styled.h3`
  font-size: 1.125rem;
  font-weight: 600;
  margin: 0 0 0.5rem 0;
  color: #1f2937;
`;

interface PriceTagProps {
  inStock: boolean;
}

const PriceTag = styled.div<PriceTagProps>`
  font-size: 1.25rem;
  font-weight: bold;
  color: ${props => props.inStock ? '#059669' : '#6b7280'};
  margin: 0.5rem 0;
  
  &::before {
    content: '${props => props.inStock ? '๐Ÿ’ฐ' : '๐Ÿšซ'}';
    margin-right: 0.5rem;
  }
`;

const StarRating = styled.div`
  display: flex;
  align-items: center;
  gap: 0.25rem;
  margin-top: 0.5rem;
`;

// ๐ŸŽ›๏ธ The complete product card component
interface ProductCardComponentProps {
  product: Product;
}

const ProductCardComponent: React.FC<ProductCardComponentProps> = ({ product }) => {
  // ๐ŸŒŸ Generate star rating
  const stars = Array.from({ length: 5 }, (_, i) => 
    i < Math.floor(product.rating) ? 'โญ' : 'โ˜†'
  ).join('');

  return (
    <ProductCard>
      <ProductImage src={product.image} alt={product.name} />
      <ProductInfo>
        <ProductName>{product.name}</ProductName>
        <PriceTag inStock={product.inStock}>
          ${product.price.toFixed(2)}
        </PriceTag>
        <StarRating>
          <span>{stars}</span>
          <span>({product.rating}/5)</span>
        </StarRating>
      </ProductInfo>
    </ProductCard>
  );
};

๐ŸŽฏ Try it yourself: Add a โ€œAdd to Cartโ€ button that changes color based on stock status!

๐ŸŽฎ Example 2: Gaming Dashboard Theme

Letโ€™s create a cool gaming-themed component with themes:

// ๐ŸŽญ Theme interface for type safety
interface Theme {
  colors: {
    primary: string;
    secondary: string;
    accent: string;
    background: string;
    text: string;
  };
  fonts: {
    heading: string;
    body: string;
  };
}

// ๐ŸŽฎ Gaming themes
const gamingTheme: Theme = {
  colors: {
    primary: '#ff6b6b',    // ๐Ÿ”ด Red
    secondary: '#4ecdc4',   // ๐ŸŸข Teal
    accent: '#ffe66d',      // ๐ŸŸก Yellow
    background: '#1a1a2e',  // ๐ŸŒ™ Dark blue
    text: '#ffffff'         // โšช White
  },
  fonts: {
    heading: 'Orbitron, monospace',
    body: 'Roboto, sans-serif'
  }
};

// ๐ŸŽจ Themed gaming card
interface GamingCardProps {
  theme: Theme;
  glowing?: boolean;
}

const GamingCard = styled.div<GamingCardProps>`
  background: ${props => props.theme.colors.background};
  color: ${props => props.theme.colors.text};
  padding: 2rem;
  border-radius: 1rem;
  border: 2px solid ${props => props.theme.colors.primary};
  position: relative;
  font-family: ${props => props.theme.fonts.body};
  
  /* ๐ŸŒŸ Glowing effect */
  ${props => props.glowing && `
    box-shadow: 
      0 0 20px ${props.theme.colors.primary}40,
      0 0 40px ${props.theme.colors.primary}20,
      0 0 60px ${props.theme.colors.primary}10;
    animation: pulse 2s infinite;
  `}
  
  @keyframes pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.02); }
  }
`;

const GamingTitle = styled.h2<{ theme: Theme }>`
  font-family: ${props => props.theme.fonts.heading};
  color: ${props => props.theme.colors.accent};
  font-size: 1.5rem;
  margin: 0 0 1rem 0;
  text-transform: uppercase;
  letter-spacing: 2px;
`;

const ScoreDisplay = styled.div<{ theme: Theme }>`
  background: linear-gradient(
    45deg, 
    ${props => props.theme.colors.primary}, 
    ${props => props.theme.colors.secondary}
  );
  padding: 1rem;
  border-radius: 0.5rem;
  text-align: center;
  font-weight: bold;
  font-size: 1.25rem;
`;

// ๐ŸŽฏ Gaming dashboard component
interface GamingDashboardProps {
  playerName: string;
  score: number;
  level: number;
  achievements: string[];
}

const GamingDashboard: React.FC<GamingDashboardProps> = ({
  playerName, score, level, achievements
}) => {
  return (
    <GamingCard theme={gamingTheme} glowing={level > 10}>
      <GamingTitle theme={gamingTheme}>
        ๐ŸŽฎ Player: {playerName}
      </GamingTitle>
      
      <ScoreDisplay theme={gamingTheme}>
        ๐Ÿ’ฏ Score: {score.toLocaleString()}
      </ScoreDisplay>
      
      <div style={{ marginTop: '1rem' }}>
        <strong>๐Ÿ† Level {level}</strong>
        <div style={{ marginTop: '0.5rem' }}>
          <strong>๐ŸŒŸ Achievements:</strong>
          <div>{achievements.join(' ')}</div>
        </div>
      </div>
    </GamingCard>
  );
};

๐Ÿš€ Advanced Concepts

๐Ÿง™โ€โ™‚๏ธ Advanced Topic 1: TypeScript Theme Provider

When youโ€™re ready to level up, try this advanced theming pattern:

// ๐ŸŽญ Advanced theme with nested types
interface AdvancedTheme {
  breakpoints: {
    mobile: string;
    tablet: string;
    desktop: string;
  };
  spacing: {
    xs: string;
    sm: string;
    md: string;
    lg: string;
    xl: string;
  };
  colors: {
    primary: {
      50: string;
      500: string;
      900: string;
    };
    semantic: {
      success: string;
      warning: string;
      error: string;
    };
  };
}

// ๐ŸŽจ Theme object with full type safety
const advancedTheme: AdvancedTheme = {
  breakpoints: {
    mobile: '768px',
    tablet: '1024px',
    desktop: '1200px'
  },
  spacing: {
    xs: '0.25rem',
    sm: '0.5rem',
    md: '1rem',
    lg: '2rem',
    xl: '4rem'
  },
  colors: {
    primary: {
      50: '#eff6ff',
      500: '#3b82f6',
      900: '#1e3a8a'
    },
    semantic: {
      success: '#10b981',
      warning: '#f59e0b',
      error: '#ef4444'
    }
  }
};

// ๐Ÿ—๏ธ Responsive styled component
const ResponsiveContainer = styled.div<{ theme: AdvancedTheme }>`
  padding: ${props => props.theme.spacing.md};
  
  /* ๐Ÿ“ฑ Mobile first */
  @media (max-width: ${props => props.theme.breakpoints.mobile}) {
    padding: ${props => props.theme.spacing.sm};
  }
  
  /* ๐Ÿ’ป Desktop */
  @media (min-width: ${props => props.theme.breakpoints.desktop}) {
    padding: ${props => props.theme.spacing.xl};
  }
`;

๐Ÿ—๏ธ Advanced Topic 2: Styled Component Extensions

For the brave developers:

// ๐Ÿ”ง Base button component
const BaseButton = styled.button`
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 0.5rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s ease;
`;

// โœจ Extend base button with variations
const PrimaryButton = styled(BaseButton)`
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
  }
`;

const GhostButton = styled(BaseButton)`
  background: transparent;
  color: #667eea;
  border: 2px solid #667eea;
  
  &:hover {
    background: #667eea;
    color: white;
  }
`;

// ๐ŸŽฏ Component that can be styled differently
const StyledLink = styled(BaseButton).attrs({ as: 'a' })`
  text-decoration: none;
  display: inline-block;
`;

โš ๏ธ Common Pitfalls and Solutions

๐Ÿ˜ฑ Pitfall 1: Missing TypeScript Props

// โŒ Wrong way - no TypeScript interface!
const BadButton = styled.button`
  background: ${props => props.primary ? 'blue' : 'gray'};
  // ๐Ÿ’ฅ TypeScript error: Property 'primary' does not exist!
`;

// โœ… Correct way - define the interface!
interface ButtonProps {
  primary?: boolean;
}

const GoodButton = styled.button<ButtonProps>`
  background: ${props => props.primary ? 'blue' : 'gray'};
  // โœจ TypeScript is happy!
`;

๐Ÿคฏ Pitfall 2: Theme Type Errors

// โŒ Dangerous - no theme types!
const UnsafeComponent = styled.div`
  color: ${props => props.theme.colors.primary};
  // ๐Ÿ’ฅ Runtime error if theme structure changes!
`;

// โœ… Safe - with proper theme typing!
interface ThemeProps {
  theme: {
    colors: {
      primary: string;
    };
  };
}

const SafeComponent = styled.div<ThemeProps>`
  color: ${props => props.theme.colors.primary};
  // โœ… TypeScript catches theme structure issues!
`;

๐Ÿ› ๏ธ Best Practices

  1. ๐ŸŽฏ Define Prop Interfaces: Always create TypeScript interfaces for your styled component props
  2. ๐Ÿ“ Use Theme Provider: Centralize your design tokens in a typed theme
  3. ๐Ÿ›ก๏ธ Avoid Inline Styles: Keep all styling in styled-components for consistency
  4. ๐ŸŽจ Use CSS Custom Properties: For dynamic values that change frequently
  5. โœจ Keep Components Focused: One responsibility per styled component
  6. ๐Ÿ“ฆ Export Styled Components: Make them reusable across your app

๐Ÿงช Hands-On Exercise

๐ŸŽฏ Challenge: Build a Social Media Card System

Create a type-safe social media card component:

๐Ÿ“‹ Requirements:

  • โœ… User profile with avatar, name, and verification badge
  • ๐Ÿท๏ธ Post content with text, images, and engagement metrics
  • ๐Ÿ‘ค Different card themes (light, dark, colorful)
  • ๐Ÿ“… Responsive design for mobile and desktop
  • ๐ŸŽจ Props for customizing colors, sizes, and layouts

๐Ÿš€ Bonus Points:

  • Add hover animations
  • Include a โ€œverifiedโ€ user badge
  • Create different card variants (compact, detailed)
  • Add loading states with skeleton styles

๐ŸŽฏ Starter Code:

interface User {
  id: string;
  name: string;
  username: string;
  avatar: string;
  verified: boolean;
}

interface SocialPost {
  id: string;
  user: User;
  content: string;
  imageUrl?: string;
  likes: number;
  comments: number;
  shares: number;
  timestamp: Date;
}

// ๐ŸŽจ Your styled components go here!
// Create: SocialCard, UserInfo, PostContent, EngagementBar

๐Ÿ’ก Solution

๐Ÿ” Click to see solution
// ๐ŸŽฏ Our complete social media card system!
import styled, { keyframes } from 'styled-components';
import React from 'react';

interface User {
  id: string;
  name: string;
  username: string;
  avatar: string;
  verified: boolean;
}

interface SocialPost {
  id: string;
  user: User;
  content: string;
  imageUrl?: string;
  likes: number;
  comments: number;
  shares: number;
  timestamp: Date;
}

// ๐ŸŽจ Theme types
interface SocialTheme {
  name: 'light' | 'dark' | 'colorful';
  colors: {
    background: string;
    text: string;
    border: string;
    accent: string;
    verified: string;
  };
}

const themes: Record<SocialTheme['name'], SocialTheme> = {
  light: {
    name: 'light',
    colors: {
      background: '#ffffff',
      text: '#1f2937',
      border: '#e5e7eb',
      accent: '#3b82f6',
      verified: '#10b981'
    }
  },
  dark: {
    name: 'dark',
    colors: {
      background: '#1f2937',
      text: '#f9fafb',
      border: '#374151',
      accent: '#60a5fa',
      verified: '#34d399'
    }
  },
  colorful: {
    name: 'colorful',
    colors: {
      background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
      text: '#ffffff',
      border: 'rgba(255, 255, 255, 0.2)',
      accent: '#fbbf24',
      verified: '#10b981'
    }
  }
};

// โœจ Animations
const fadeIn = keyframes`
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
`;

const pulse = keyframes`
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.05); }
`;

// ๐ŸŽจ Styled components
interface SocialCardProps {
  theme: SocialTheme;
}

const SocialCard = styled.div<SocialCardProps>`
  background: ${props => props.theme.colors.background};
  border: 1px solid ${props => props.theme.colors.border};
  border-radius: 1rem;
  padding: 1.5rem;
  max-width: 400px;
  animation: ${fadeIn} 0.3s ease-out;
  transition: all 0.2s ease;
  
  &:hover {
    transform: translateY(-2px);
    box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
  }
  
  /* ๐Ÿ“ฑ Responsive */
  @media (max-width: 768px) {
    padding: 1rem;
    margin: 0.5rem;
  }
`;

const UserInfo = styled.div`
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
`;

const Avatar = styled.img`
  width: 50px;
  height: 50px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid ${props => (props as any).theme.colors.accent};
`;

const UserDetails = styled.div`
  flex: 1;
`;

const UserName = styled.div<SocialCardProps>`
  font-weight: 600;
  color: ${props => props.theme.colors.text};
  display: flex;
  align-items: center;
  gap: 0.5rem;
`;

const Username = styled.div<SocialCardProps>`
  color: ${props => props.theme.colors.text};
  opacity: 0.7;
  font-size: 0.9rem;
`;

const VerifiedBadge = styled.span<SocialCardProps>`
  color: ${props => props.theme.colors.verified};
  animation: ${pulse} 2s infinite;
`;

const PostContent = styled.div<SocialCardProps>`
  color: ${props => props.theme.colors.text};
  line-height: 1.5;
  margin-bottom: 1rem;
`;

const PostImage = styled.img`
  width: 100%;
  border-radius: 0.5rem;
  margin: 1rem 0;
`;

const EngagementBar = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 1rem;
  border-top: 1px solid ${props => (props as any).theme.colors.border};
`;

const EngagementButton = styled.button<SocialCardProps>`
  background: none;
  border: none;
  color: ${props => props.theme.colors.text};
  opacity: 0.7;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 0.25rem;
  font-size: 0.9rem;
  padding: 0.5rem;
  border-radius: 0.25rem;
  transition: all 0.2s ease;
  
  &:hover {
    opacity: 1;
    background: ${props => props.theme.colors.accent}20;
    transform: scale(1.05);
  }
`;

const Timestamp = styled.div<SocialCardProps>`
  color: ${props => props.theme.colors.text};
  opacity: 0.5;
  font-size: 0.8rem;
`;

// ๐ŸŽฏ Main component
interface SocialMediaCardProps {
  post: SocialPost;
  themeName?: SocialTheme['name'];
}

const SocialMediaCard: React.FC<SocialMediaCardProps> = ({ 
  post, 
  themeName = 'light' 
}) => {
  const theme = themes[themeName];
  
  const formatNumber = (num: number) => {
    if (num >= 1000) {
      return `${(num / 1000).toFixed(1)}k`;
    }
    return num.toString();
  };
  
  const formatTime = (date: Date) => {
    const now = new Date();
    const diff = now.getTime() - date.getTime();
    const hours = Math.floor(diff / (1000 * 60 * 60));
    
    if (hours < 1) return 'now';
    if (hours < 24) return `${hours}h`;
    return `${Math.floor(hours / 24)}d`;
  };

  return (
    <SocialCard theme={theme}>
      <UserInfo>
        <Avatar src={post.user.avatar} alt={post.user.name} theme={theme} />
        <UserDetails>
          <UserName theme={theme}>
            {post.user.name}
            {post.user.verified && (
              <VerifiedBadge theme={theme}>โœ…</VerifiedBadge>
            )}
          </UserName>
          <Username theme={theme}>@{post.user.username}</Username>
        </UserDetails>
        <Timestamp theme={theme}>
          {formatTime(post.timestamp)}
        </Timestamp>
      </UserInfo>
      
      <PostContent theme={theme}>
        {post.content}
      </PostContent>
      
      {post.imageUrl && (
        <PostImage src={post.imageUrl} alt="Post content" />
      )}
      
      <EngagementBar theme={theme}>
        <EngagementButton theme={theme}>
          โค๏ธ {formatNumber(post.likes)}
        </EngagementButton>
        <EngagementButton theme={theme}>
          ๐Ÿ’ฌ {formatNumber(post.comments)}
        </EngagementButton>
        <EngagementButton theme={theme}>
          ๐Ÿ”„ {formatNumber(post.shares)}
        </EngagementButton>
      </EngagementBar>
    </SocialCard>
  );
};

// ๐ŸŽฎ Example usage
const examplePost: SocialPost = {
  id: '1',
  user: {
    id: '1',
    name: 'Sarah Developer',
    username: 'sarahcodes',
    avatar: 'https://images.unsplash.com/photo-1494790108755-2616b25c8c5c?w=100',
    verified: true
  },
  content: 'Just shipped a new feature using styled-components with TypeScript! The type safety is incredible ๐Ÿš€โœจ #typescript #react',
  likes: 1234,
  comments: 89,
  shares: 56,
  timestamp: new Date(Date.now() - 2 * 60 * 60 * 1000) // 2 hours ago
};

// ๐ŸŽจ Demo component
const SocialMediaDemo = () => {
  return (
    <div style={{ display: 'flex', gap: '1rem', flexWrap: 'wrap' }}>
      <SocialMediaCard post={examplePost} themeName="light" />
      <SocialMediaCard post={examplePost} themeName="dark" />
      <SocialMediaCard post={examplePost} themeName="colorful" />
    </div>
  );
};

export default SocialMediaDemo;

๐ŸŽ“ Key Takeaways

Youโ€™ve learned so much! Hereโ€™s what you can now do:

  • โœ… Create styled components with full TypeScript support ๐Ÿ’ช
  • โœ… Use props for dynamic styling thatโ€™s type-safe ๐Ÿ›ก๏ธ
  • โœ… Build themeable component systems in real projects ๐ŸŽฏ
  • โœ… Debug styling issues like a pro ๐Ÿ›
  • โœ… Combine CSS-in-JS with TypeScript to build awesome UIs! ๐Ÿš€

Remember: Styled-components isnโ€™t just about writing CSS in JS - itโ€™s about creating a more maintainable, type-safe way to handle styling in your React applications! ๐Ÿค

๐Ÿค Next Steps

Congratulations! ๐ŸŽ‰ Youโ€™ve mastered styled-components with TypeScript!

Hereโ€™s what to do next:

  1. ๐Ÿ’ป Practice with the social media card exercise above
  2. ๐Ÿ—๏ธ Build a complete design system using styled-components
  3. ๐Ÿ“š Move on to our next tutorial: Emotion: Alternative CSS-in-JS Library
  4. ๐ŸŒŸ Create your own component library with styled-components!

Remember: Every great UI was built one component at a time. Keep styling, keep learning, and most importantly, have fun creating beautiful interfaces! ๐Ÿš€


Happy styling! ๐ŸŽจ๐Ÿš€โœจ