# Loader

Loader [#loader]

The **Loader** is a small family of busy visuals shown while a local model warms up or streams its first token. Pick a `variant` (dots / pulse / typing / spinner), or use `Shimmer` to render skeleton-text lines for content that is expected but not yet arrived.

Preview [#preview]

```tsx
'use client';

/**
 * @file loader-demo.tsx
 * @description Docs preview for `Loader`. Shows every variant plus the `Shimmer`
 * skeleton-text placeholder.
 */
import { Loader, Shimmer } from '@/components/loader';

export default function LoaderDemo() {
  return (
    <div className="flex w-full max-w-md flex-col gap-5">
      <div className="flex flex-wrap items-center gap-6">
        <Loader variant="dots" label="dots" />
        <Loader variant="pulse" label="pulse" />
        <Loader variant="typing" label="typing" />
        <Loader variant="spinner" label="spinner" />
      </div>
      <div className="rounded-lg border border-border p-3">
        <Shimmer lines={3} />
      </div>
    </div>
  );
}
```

Installation [#installation]

```bash
npx shadcn@latest add @localmode/ui/conversation/loader
```

Dependencies [#dependencies]

* *None* — pure presentational component
* `clsx` + `tailwind-merge` — via the shared `cn()` util (installed automatically as a registry dependency)

Files installed [#files-installed]

* `loader.tsx` — `Loader` + `Shimmer`
* `lib/utils.ts` — the `cn()` helper (if not already present)

Props [#props]

**Loader**

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `variant` | `"spinner" \| "typing" \| "pulse" \| "dots"` | `"dots"` | Which animated indicator to show. |
| `label` | `string` | — | Optional label rendered after the indicator (e.g. "Thinking…"). |

Examples [#examples]

Typing indicator while pending [#typing-indicator-while-pending]

```tsx
import { Loader } from '@/components/loader';

{isStreaming && lastMessage.content === '' && <Loader variant="typing" label="Thinking…" />}
```

Shimmer skeleton [#shimmer-skeleton]

```tsx
import { Shimmer } from '@/components/loader';

<Shimmer lines={4} />
```

Customization [#customization]

The dot animation uses an inline `@keyframes` block so the component is self-contained. Swap the `bg-current`/`bg-muted` tokens or the variant set to match your design system.

These primitives are presentational and hook-driven: they render props and emit callbacks, holding only local view state. The orchestration state lives in your app. Every surface uses shadcn/ui CSS-variable utilities, so it inherits your theme — restyle the copied file freely.