placebo.mk/TAILWIND_SHADCN_SETUP.md
2026-01-10 19:41:04 +01:00

6.5 KiB

Tailwind 4 + Shadcn/ui Setup Complete

What's Been Configured

1. Tailwind CSS 4 (CSS-First Approach)

  • Using @import directive (no PostCSS required)
  • Clean CSS variables for theming
  • Dark mode support built-in
  • Responsive utilities

2. Shadcn/ui Components

  • Card: Display article content
    • CardHeader
    • CardTitle
    • CardDescription
    • CardContent
    • CardFooter
  • Button: Interactive elements (available but not used yet)

3. Utilities

  • cn() function for merging Tailwind classes
  • Uses clsx for conditional classes
  • Uses tailwind-merge for Tailwind-specific merging

4. TypeScript Configuration

  • Path aliases configured: @/./src/
  • shadcn/ui aliases: @/components, @/utils

How to Use

Using Existing Components

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

export function MyComponent() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Title</CardTitle>
        <CardDescription>Description</CardDescription>
      </CardHeader>
      <CardContent>
        <p>Content goes here</p>
      </CardContent>
      <CardFooter>
        <span>Footer content</span>
      </CardFooter>
    </Card>
  )
}

Using Tailwind Classes

export function MyComponent() {
  return (
    <div className="p-4 bg-background text-foreground">
      <h1 className="text-2xl font-bold">Title</h1>
      <p className="text-muted-foreground">Description</p>
    </div>
  )
}

Using the cn() Utility

import { cn } from '@/lib/utils'

export function MyComponent({ className, isActive }: Props) {
  return (
    <div className={cn(
      "base-class p-4",
      isActive && "active-class",
      className
    )}>
      Content
    </div>
  )
}

Adding More Shadcn/ui Components

Using the CLI

cd frontend
npx shadcn@latest add [component-name]
npx shadcn@latest add badge      # For article tags
npx shadcn@latest add input      # For search
npx shadcn@latest add dialog     # For article details modal
npx shadcn@latest add tabs       # For organizing content
npx shadcn@latest add separator  # For visual separation
npx shadcn@latest add skeleton   # For loading states
npx shadcn@latest add pagination # For article list navigation

Manual Installation

If CLI doesn't work, you can manually create components:

  1. Visit ui.shadcn.com
  2. Find the component you want
  3. Copy the code
  4. Create file: frontend/src/components/ui/[component].tsx
  5. Import and use

Customization

Theme Colors

Edit src/index.css:

:root {
  --background: 0 0% 100%;     /* Background color */
  --foreground: 222.2 84% 4.9%;   /* Text color */
  --primary: 222.2 47.4% 11.2%;    /* Primary color */
  --card: 0 0% 100%;               /* Card background */
  /* ... more variables */
}

Adding Custom Colors to Tailwind

Edit tailwind.config.js:

theme: {
  extend: {
    colors: {
      brand: {
        50: '#f0f9ff',
        100: '#e0e7ff',
        500: '#3b82f6',
        // ... more shades
      }
    }
  }
}

Current Implementation

App.tsx

The main app displays:

  • Header with "Placebo.mk" title
  • Subtitle "Sarcastic news from Macedonia"
  • Responsive grid of article cards (1/2/3 columns)
  • Each card shows:
    • Featured image (if available)
    • Title (truncated to 2 lines)
    • Excerpt (truncated to 3 lines)
    • Content preview (truncated to 4 lines)
    • Creation date
    • View count
  • Loading and error states
  • Empty state when no articles

Dark Mode

To enable dark mode, add a toggle:

import { useEffect } from 'react'

export function ThemeToggle() {
  useEffect(() => {
    const isDark = localStorage.getItem('theme') === 'dark'
    document.documentElement.classList.toggle('dark', isDark)
  }, [])

  const toggleTheme = () => {
    const isDark = document.documentElement.classList.toggle('dark')
    localStorage.setItem('theme', isDark ? 'dark' : 'light')
  }

  return (
    <button onClick={toggleTheme}>
      Toggle Theme
    </button>
  )
}

Troubleshooting

Tailwind Classes Not Applying

  1. Check that @tailwind directives are in src/index.css
  2. Restart dev server: npm run dev
  3. Hard refresh browser: Ctrl+Shift+R
  4. Check browser DevTools → Elements → Computed Styles

Component Not Found

  1. Check file exists: frontend/src/components/ui/[component].tsx
  2. Check export name matches: export const ComponentName = ...
  3. Check import path: @/components/ui/component
  4. Restart TypeScript server (VSCode: Cmd+Shift+P → "TypeScript: Restart TS Server")

TypeScript Errors

  1. Check tsconfig.json has @/ paths configured
  2. Restart TypeScript server
  3. Run: npm run type-check
  4. Check components.json aliases

Performance Tips

  1. Image Optimization: Add loading="lazy" to article images
  2. Code Splitting: Use lazy() for large components
  3. Query Caching: TanStack Query caches automatically
  4. Bundle Analysis: Run npm run build and check bundle size

File Structure

frontend/
├── src/
│   ├── components/
│   │   └── ui/              # shadcn/ui components
│   │       ├── button.tsx
│   │       └── card.tsx
│   ├── lib/
│   │   ├── api.ts            # API functions
│   │   ├── query-client.ts    # TanStack Query
│   │   └── utils.ts         # cn() utility
│   ├── App.tsx               # Main application
│   ├── index.css              # Tailwind + CSS variables
│   └── main.tsx
├── components.json            # shadcn config
├── tailwind.config.js         # Tailwind configuration
└── package.json

Next Steps

  1. Add article detail page: Click on card to view full article
  2. Add search input: Filter articles by title/content
  3. Add category filter: Filter by article category
  4. Add tag badges: Display article tags
  5. Add pagination: Navigate through large article lists
  6. Add dark mode toggle: Switch between light/dark themes
  7. Add article detail modal: View article without leaving page

Resources