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.