A reusable React client component that renders contextual empty state UI for vendors, posts, search results, and generic scenarios, with smart CTA logic that adapts based on the current route.
## Key Components
### `EmptyStateProps` Interface
| Prop | Type | Default | Description |
|---|---|---|---|
| `type` | `'vendors' \| 'posts' \| 'search' \| 'generic'` | — | Determines default icon, title, and description |
| `title` | `string` | type-based default | Override the default heading |
| `description` | `string` | type-based default | Override the default body text |
| `showBackButton` | `boolean` | `false` | Renders an optional secondary back button |
| `onGoBack` | `() => void` | — | Callback for the back button |
| `backButtonText` | `string` | `"Go Back"` | Label for the back button |
| `showCTA` | `boolean` | `true` | Toggles the primary CTA button |
| `ctaText` | `string` | smart default | Custom CTA label |
| `onCtaClick` | `() => void` | smart default | Custom CTA handler |
| `ctaVariant` | `'primary' \| 'secondary'` | `'primary'` | CTA button style variant |
### `EmptyState` Component
- **`getDefaultContent()`** — Returns icon, title, and description based on `type`
- **`getSmartCTA()`** — Derives CTA label and action from `type` and `window.location.pathname`; custom `ctaText`/`onCtaClick` always take precedence. Falls back to route-aware defaults (e.g. resets URL search params on vendor/blog/search pages, navigates to `/vendors` or `/blog` elsewhere)
## Usage Example
```typescript
// Basic usage — type-driven defaults
// Search results with filter reset
// Custom CTA and back button
router.push('/vendors')}
ctaVariant="secondary"
showBackButton
onGoBack={() => router.back()}
backButtonText="Return"
/>
```
## Source
[`empty-state.tsx`](https://github.com/flamingo-stack/openframe-oss-lib/blob/main/openframe-frontend-core/src/components/empty-state.tsx)
## `ctaHref` (added with the meeting-scheduler work)
Link-CTA mode: renders the CTA as a navigation `Button href` (plain or `mailto:`). Wins over `onCtaClick` and SHORT-CIRCUITS the smart-CTA path-sniffing (which reads `window.location.pathname` — SSR/client divergence). Existing callers without `ctaHref` keep the smart defaults unchanged.
## Smart-CTA reset behavior (promoted from the hub clone at convergence)
Filter resets are SURGICAL — each branch deletes only the params its surface owns (`search`/`page` [+`category`/`tags` for posts, +`category`/`subcategory` for vendors]) and navigates with `replace` + `scroll: false`. The posts branch also matches `/case-studies`. The hub-local `components/ui/empty-state.tsx` near-clone was deleted; this component is the ONE EmptyState.