# AppCard

## Overview

Enhanced card component built on top of the base Card component. Provides a simplified prop-based API with built-in header, body, and footer sections, 10 visual variants (including semantic states), size control, loading skeleton state, and sub-components for advanced composition.

---

## Props

### AppCardProps

| Prop               | Type                                                                                                   | Default     | Description                                                         |
| ------------------ | ------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------- |
| `title`            | `string \| React.ReactNode`                                                                            | `undefined` | Card title displayed in the header.                                 |
| `description`      | `string \| React.ReactNode`                                                                            | `undefined` | Card description displayed below the title.                         |
| `header`           | `React.ReactNode`                                                                                      | `undefined` | Custom header content; overrides `title` and `description`.         |
| `body`             | `React.ReactNode`                                                                                      | `undefined` | Main content rendered inside CardContent.                           |
| `children`         | `React.ReactNode`                                                                                      | `undefined` | Fallback body content when `body` is not provided.                  |
| `actions`          | `React.ReactNode`                                                                                      | `undefined` | Right-aligned action elements inside the header.                    |
| `footer`           | `React.ReactNode`                                                                                      | `undefined` | Footer content (typically action buttons).                          |
| `variant`          | `AppCardVariant`                                                                                       | `"default"` | Visual variant of the card (see table below).                       |
| `size`             | `"sm" \| "default" \| "lg" \| "none"`                                                                 | `undefined` | Controls internal padding via the base Card component.              |
| `isLoading`        | `boolean`                                                                                              | `false`     | When true, renders skeleton placeholders instead of content.        |
| `showHeaderBorder` | `boolean`                                                                                              | `false`     | Displays a border between the header and body sections.             |
| `showFooterBorder` | `boolean`                                                                                              | `false`     | Displays a border between the body and footer sections.             |
| `className`        | `string`                                                                                               | `undefined` | Additional classes for the card container.                          |
| `headerClassName`  | `string`                                                                                               | `undefined` | Additional classes for the header section.                          |
| `bodyClassName`    | `string`                                                                                               | `undefined` | Additional classes for the body section.                            |
| `footerClassName`  | `string`                                                                                               | `undefined` | Additional classes for the footer section.                          |

### Variant Reference

| Variant       | Description                                                                     |
| ------------- | ------------------------------------------------------------------------------- |
| `default`     | Standard card with background, border, and subtle shadow.                       |
| `elevated`    | Stronger shadow for layered or floating layouts.                                |
| `outlined`    | Transparent background with visible border; no shadow.                          |
| `ghost`       | No border, no shadow — blends seamlessly into the background.                   |
| `flat`        | Muted background, no border or shadow; ideal for nested card contexts.          |
| `interactive` | Default styling with hover shadow and border accent; pointer cursor for clicks. |
| `success`     | Green-tinted semantic card for positive states and confirmations.               |
| `warning`     | Amber-tinted semantic card for cautionary messages and alerts.                  |
| `destructive` | Red-tinted semantic card for errors, danger states, or critical notices.        |
| `info`        | Primary-tinted semantic card for informational context and updates.             |

### Size Reference

| Size      | Description                                          |
| --------- | ---------------------------------------------------- |
| `sm`      | Reduced padding — compact cards and nested contexts. |
| `default` | Standard padding (base Card default).                |
| `lg`      | Spacious padding for prominent content areas.        |
| `none`    | No default padding — apply custom padding manually.  |

---

## Exports

- **AppCard**: Main card component.
- **AppCardHeader**: Sub-component for composing custom headers.
- **AppCardBody**: Sub-component for composing custom body sections.
- **AppCardFooter**: Sub-component for composing custom footer sections.
- **AppCardProps**: TypeScript interface for AppCard props.
- **AppCardHeaderProps**: TypeScript interface for AppCardHeader props.
- **AppCardVariant**: Union type of all 10 variant values.
- **AppCardSize**: Union type of all size values (`"sm" | "default" | "lg" | "none"`).

---

## Behavior

- **`body` vs `children`**: `body` takes precedence. When `body` is omitted, `children` is rendered inside `CardContent`. This allows both prop-based and JSX-composition patterns.
- **`isLoading`**: When true, all section content is replaced with a skeleton showing a title placeholder, description placeholder, and three text-line placeholders. The skeleton respects the `size` and `variant` of the card.
- **`size` passthrough**: The `size` prop is forwarded to the underlying `Card` component, controlling padding and gap via the base `paddingMap`.
- **Conditional sections**: Header, body, and footer sections are only rendered if their corresponding props have content. An empty card renders just the card container.
- **Header border**: Setting `showHeaderBorder` adds `border-b` to the `CardHeader`. When absent, the body section removes its top padding to maintain visual continuity.
- **Footer border**: Setting `showFooterBorder` adds `border-b` to the body `CardContent`. When absent, the footer section removes its top padding.
- **`interactive` variant**: Adds `cursor-pointer` and hover-triggered shadow/border transitions. The card is a `div`, so attach `onClick` directly to the `AppCard` element.
- **Focus management**: The card container uses `focusRingWithin` from `designTokens`, so focusable elements inside the card display the system focus ring.

---

## Examples

### Basic

```tsx
import { AppCard, Button } from "laif-ds";

export function BasicCard() {
  return (
    <AppCard
      title="Card Title"
      description="Optional description providing additional context."
      body={<p>Main content of the card.</p>}
      footer={<Button>Primary Action</Button>}
      className="w-[380px]"
    />
  );
}
```

### Semantic Variants

```tsx
import { AppCard } from "laif-ds";

export function SemanticCards() {
  return (
    <div className="grid grid-cols-2 gap-4">
      <AppCard
        title="Operation Successful"
        description="All services are running normally."
        body={<p>Deployment completed in 2m 34s.</p>}
        variant="success"
        className="w-[300px]"
      />
      <AppCard
        title="Warning"
        description="Storage usage is high."
        body={<p>Disk at 80% capacity. Consider cleanup.</p>}
        variant="warning"
        className="w-[300px]"
      />
      <AppCard
        title="Error Detected"
        description="Service is not responding."
        body={<p>Payment gateway returned a 503 error.</p>}
        variant="destructive"
        className="w-[300px]"
      />
      <AppCard
        title="Update Available"
        description="Version 2.4.0 is ready to install."
        body={<p>Includes security patches and new features.</p>}
        variant="info"
        className="w-[300px]"
      />
    </div>
  );
}
```

### Interactive Card with onClick

```tsx
import { useState } from "react";
import { AppCard } from "laif-ds";

export function ClickableCard() {
  const [count, setCount] = useState(0);

  return (
    <AppCard
      title="Clickable Card"
      description="Click anywhere on the card"
      body={<p className="text-sm">Clicked {count} times.</p>}
      variant="interactive"
      onClick={() => setCount((c) => c + 1)}
      className="w-[320px]"
    />
  );
}
```

### Loading State

```tsx
import { useState } from "react";
import { AppCard, Button } from "laif-ds";

export function LoadingCard() {
  const [loading, setLoading] = useState(true);

  return (
    <div className="flex flex-col gap-4">
      <Button onClick={() => setLoading((v) => !v)}>Toggle Loading</Button>
      <AppCard
        title="Remote Data Card"
        description="Loaded from external source"
        body={<p>This is the real content.</p>}
        footer={<Button>Action</Button>}
        isLoading={loading}
        className="w-[380px]"
      />
    </div>
  );
}
```

### Nested Flat Cards

```tsx
import { AppCard } from "laif-ds";

export function NestedCards() {
  return (
    <AppCard
      title="Parent Card"
      description="Contains nested flat sub-cards"
      body={
        <div className="flex flex-col gap-3">
          <AppCard
            title="Nested Item A"
            body={<p className="text-sm">Flat cards have no border or shadow.</p>}
            variant="flat"
            size="sm"
          />
          <AppCard
            title="Nested Item B"
            body={<p className="text-sm">Good for secondary content regions.</p>}
            variant="flat"
            size="sm"
          />
        </div>
      }
      className="w-[420px]"
    />
  );
}
```

### Size Variants

```tsx
import { AppCard } from "laif-ds";

export function SizeVariants() {
  return (
    <div className="flex flex-col gap-6 w-[400px]">
      <AppCard
        size="sm"
        title="Size: Small"
        description="Reduced padding for compact layouts"
        body={<p>This card uses size="sm".</p>}
      />
      <AppCard
        size="default"
        title="Size: Default"
        description="Standard padding"
        body={<p>This card uses size="default".</p>}
      />
      <AppCard
        size="lg"
        title="Size: Large"
        description="Spacious padding for prominent content"
        body={<p>This card uses size="lg".</p>}
      />
    </div>
  );
}
```

### Children as Fallback Body

```tsx
import { AppCard } from "laif-ds";

export function ChildrenCard() {
  return (
    <AppCard title="Card with Children" className="w-[380px]">
      <p>This content is passed as children and rendered inside CardContent.</p>
    </AppCard>
  );
}
```

### Advanced Composition with Sub-components

```tsx
import {
  AppCard,
  AppCardHeader,
  AppCardBody,
  AppCardFooter,
  Button,
  Badge,
} from "laif-ds";

export function ComposedCard() {
  return (
    <AppCard className="w-[380px]">
      <AppCardHeader
        title="Advanced Composition"
        description="Using sub-components directly"
        actions={<Badge>New</Badge>}
      />
      <AppCardBody>
        <p>Full control over each section independently.</p>
      </AppCardBody>
      <AppCardFooter>
        <Button className="w-full">Confirm</Button>
      </AppCardFooter>
    </AppCard>
  );
}
```

---

## Notes

- **`body` vs `children` precedence**: If both are provided, `body` wins. Use `body` for the prop-based API and `children` when composing JSX naturally.
- **`interactive` variant and accessibility**: The `interactive` variant only adds visual affordances (hover states, pointer cursor). For keyboard accessibility on a clickable card, consider wrapping with an `<a>` or `<button>` using `asChild` on a child component, or ensure the card content includes a focusable element.
- **Sub-components**: `AppCardHeader`, `AppCardBody`, and `AppCardFooter` wrap the base `CardHeader`, `CardContent`, and `CardFooter` respectively. Use them when the prop API of `AppCard` is insufficient for your layout needs.
- **vs Card**: Use `AppCard` for most card use cases — it handles conditional rendering and spacing automatically. Use the base `Card` and its sub-components directly when you need maximum layout control with no abstraction overhead.
- **Semantic variants and theming**: The semantic variant colors (`success`, `warning`, `destructive`, `info`) use CSS variable tokens that respond to light/dark mode automatically.
