Home Cover

Homepage hero of the Panda websites (the original cover): the cover photo (phone cover on phones) or the plan's looping background video, the hero video play button, the owner portrait on phones and the centered…

Headless hookClient component@pandaidx/widgets 1.14.1

Anatomy

Every piece of Home Cover as it nests in code. A root holds the data and state; its parts and hooks only work inside it.

<PandaProvider>Mounted once in app/layout.tsx
<HomeCover />complete widget

Homepage hero of the Panda websites (the original cover): the cover photo (phone cover on phones) or the plan's looping background video,…

</PandaProvider>

Installation

  1. 1
    npm install <tarball or @pandaidx/widgets>
    Terminal
    npm install https://github.com/pandaidx/panda-widgets/releases/download/v1.14.1/pandaidx-widgets-1.14.1.tgz
  2. 2
    import "@pandaidx/widgets/styles.css" in app/layout.tsx
  3. 3
    Wrap the site in <PandaProvider publicKey apiUrl preset theme> (app/layout.tsx)
  4. 4
    In each page (Server Component) call the widget's server loader, then render the widget with its data
  5. 5
    Allow the images: next.config images.remotePatterns [{ protocol: "https", hostname: "**" }] (listing and blog photos come from several CDNs)

Usage

HomeCover
// app/page.tsx: the Panda homepage hero (cover + centered search)
import { HomeCover } from "@pandaidx/widgets/client"
import { fetchHomeCover } from "@pandaidx/widgets/server"
export default async function Home() {
const cover = await fetchHomeCover({ publicKey: process.env.NEXT_PUBLIC_PANDA_PUBLIC_KEY!, apiUrl: process.env.NEXT_PUBLIC_PANDA_API_URL })
return <HomeCover data={cover} />
}

Examples

A hero in the site's own markup with the cover, video and search

HomeCover
// components/hero.tsx
"use client"
import Image from "next/image"
import { HomeSearch, VideoModal, useHomeCover, type HomeCoverData } from "@pandaidx/widgets/client"
export const Hero = ({ data }: { data: HomeCoverData | null }) => {
const cover = useHomeCover({ data })
return (
<section className="relative isolate flex h-122.5 items-end justify-center overflow-hidden pb-10 sm:h-screen lg:pb-25">
{cover.cover ? <Image src={cover.cover} alt="" fill priority sizes="100vw" className="-z-10 object-cover" /> : null}
<div className="flex w-full flex-col items-center gap-10">
{cover.videoUrl ? <VideoModal url={cover.videoUrl}><button type="button">Play</button></VideoModal> : null}
{cover.showSearchBar ? <HomeSearch /> : null}
</div>
</section>
)
}

API reference

HomeCover

Homepage hero of the Panda websites (the original cover): the cover photo (phone cover on phones) or the plan's looping background video, the hero video play button, the owner portrait on phones and the centered HomeSearch (websites pill design: For Sale / For Rent / Sold tabs over the pill autocomplete). Every default matches websites.

Import from @pandaidx/widgets/client · renders inside PandaProvider

PropTypeDefaultDescription
data*object—Cover photos, videos, search switch and owner portrait (null renders nothing).
viewport"mobile" | "desktop""desktop"Device class of the request (user agent): mobile shows coverMobile, like websites.
showSearchboolean—Shows the search bar (default data.showSearchBar).
searchobject—HomeSearch params of the hero search (default the websites pill design): variant, tabs, initialMarket, placeholder, background, color, spacing, tone, size, buttonStyle, buttonLabel, buttonIcon, buttonTone, buttonBackground, buttonColor, searchPath, classNames, and its layout and look width, align, tabsPlacement, tabsAlign, shape, surface, border, tabStyle, tabsAttached, and the results dropdown look suggestions (images, imageShape, size, weight, itemShape, highlight, panelShape, shadow). Example (square bar, tabs left-aligned on top of it): search={{ shape: "square", align: "start", tabsAlign: "start", tabsAttached: true }}.
searchLayoutobject—{ position, offset } where the hero search sits: position bottom (websites) | center | top; offset its distance from that edge, a CSS length ("120px") or one per min-width breakpoint ({ base: "112px", sm: "144px", md: "208px", lg: "160px" }; a missing breakpoint keeps the smaller one; default the websites 10 spacing units, 25 from lg; ignored for center). With search.width / align / tabsPlacement this replaces any CSS on the widget markup: move or resize the hero search with these params only.
showPlayButtonbooleantrueShows the play button of the hero video (data.coverVideo).
showAvatarbooleantrueShows the owner portrait on phones when there is no phone cover nor video.
classNamesobject—Tailwind classes for root (cover box), media (photo/video layer), body (the wrapper that positions the play button and the search: its vertical padding IS the search offset, e.g. body: "pb-28 md:pb-52") and content (play button + search column). They win over the widget classes at every breakpoint, no ! needed; prefer searchLayout for the search position.
preset"default" | "template1"—Preset for this widget only (defaults to the provider preset).
variant"default" | "template1"—Deprecated alias of preset.
themeobject—Token overrides for this widget only, merged over the provider theme (same shape as PandaProvider.theme).

Hooks

useHomeCover()inside PandaProvider

useHomeCover({ data }) → { cover, coverMobile (show it below sm, the desktop cover from sm up), backgroundVideo (looping MP4 for a <video autoPlay muted loop playsInline>), videoUrl (the hero YouTube video as a watch?v= URL for <VideoModal url>), avatar, ownerName, showSearchBar (the agent wants <HomeSearch /> or useHomeSearch over the hero), hasTopBar, empty } — data comes from fetchHomeCover (null → empty cover). Paint the photo with next/image (fill, priority, sizes="100vw"). HomeCover stays the ready-made hero. Client component only.

Server data

Loaders run in a Server Component and come from @pandaidx/widgets/server. Typed data is for a page you design yourself, rendered inside the root.

fetchHomeCover()widget loader

GET /v1/site → the hero fields (homepage.cover/coverMobile/backgroundVideo/coverVideo, the plan's video flag, coverSearch.showSearchBar, owner portrait, top bar). toHomeCoverData(site) maps a site you already loaded. Returns HomeCoverData | null → data