Marketplace Shell React block for Tailwind CSS v4
v1.0.0Added in 1.0.0
A React marketplace layout shell with a what and where search header, a category strip, a footer, bottom tabs on phones and cookie consent.
On desktop the header holds the logo, one joined search box and the actions. Type in the query field (press / to focus it): while it is empty it lists your recent searches (remove one with its x or Delete, or clear them) and the popular ones; while typing it suggests categories (Mobile phones, in Electronics › Phones) and matching listings; arrows and Enter pick one. The location field filters the Romanian cities without diacritics and offers All locations and Near me (your position when the browser allows it, else your own city). Enter or Search submits the query, the place and the category; a category chip in the box scopes the search and its x removes it. Favorites and messages carry counts, the avatar opens the account menu (my account, listings, favorites, messages, settings, the theme and sign out), and Post a listing starts a new listing. The category strip below scrolls sideways with edge fades and marks the active category. Once the page scrolls the header gains a hairline and a soft shadow. Below 768px the header is a compact row: the logo mark, a search field that opens a full height sheet (autofocused input, the location as a row that opens its own sheet, recent searches with remove buttons, popular searches and category tiles; Escape, the handle or Cancel closes it) and the avatar. A bottom tab bar holds Home, Search (opens the sheet), the raised Post action, Messages with its count and Account. The minimal variant keeps only the logo, a back or close button and a trust note. The cookie banner shows until the visitor decides and sits above the tab bar; Cookie settings in the footer reopens its settings. The skip link (Skip to content) is the first stop for keyboard users.
Marketplace Shell is a Pro React block in the React blocks category, written in TypeScript for React 19 and Tailwind CSS v4. It installs as source with npx wingo-ui@latest add marketplace-shell, together with Badge, Bottom Tab Bar, Button, Combobox, Cookie Consent and 15 more and the npm package lucide-react.
Add to a project
Requirements: React 19 and Tailwind CSS v4, in Next.js (App Router or Pages), Vite or React Router. Installation guide · Next.js setup · Vite setup
npx wingo-ui@latest add marketplace-shellMarketplace Shell is part of Pro, with 298 more Pro items: $8 a month or $150 once. 14-day refund before you download any Pro item. See plans
Usage
Import MarketplaceShell from @/components/blocks/marketplace-shell.
// app/(market)/layout.tsx
"use client"
import Link from "next/link"
import { usePathname, useRouter } from "next/navigation"
import type { ReactNode } from "react"
import { MarketplaceShell } from "@/components/blocks/marketplace-shell"
export default function MarketLayout({ children }: { children: ReactNode }) {
const pathname = usePathname()
const router = useRouter()
return (
<MarketplaceShell currentPath={pathname} linkComponent={Link} onNavigate={router.push}>
{children}
</MarketplaceShell>
)
}Props
childrenReactNodeThe page, rendered once inside main.
variantdefault"full""full" | "minimal"minimal: logo, minimalAction and minimalNote only (checkout, the publishing wizard); no search, categories, footer or tabs.
layoutdefault"page""page" | "fill"page: the window scrolls under a sticky header and the footer follows the content. fill: the shell is exactly the viewport, main is a flex column for inboxes, the footer is hidden and the tab bar sits in the flow.
currentPathdefault"/"stringThe active route (next: usePathname()). Selects the tab and the category chip; nested routes match by prefix.
categoriesMarketplaceCategory[]The category tree (MARKETPLACE_SHELL_SAMPLE.categories: the 12 Northwind Market categories with lucide icons, counts and subtrees for Vehicles, Real estate and Electronics). The strip shows the top level; the search suggests any level. Compatible with category-picker's CategoryNode.
user{ name: string; email?: string; avatar?: string; city?: string } | nullThe signed-in buyer (MARKETPLACE_SHELL_SAMPLE.user: Emma Carter, city cluj-napoca). null shows Sign in (loginHref). city is the fallback of Near me.
userMenuItemsUserMenuEntry[]The account menu entries above sign out. Default: My account, My listings, Favorites, Messages, Settings and a separator.
onSignOut() => (void | Promise<unknown>)The sign-out row. Default: a toast "Te-ai deconectat".
favoritesCountdefault4numberThe favorites badge (99+ above 99). 0 hides the badge, the icon stays.
messagesCountdefault2numberUnread messages on the header icon and the Mesaje tab. 0 hides the badges.
favoritesHrefdefault"/favorites"stringWhere the heart points.
messagesHrefdefault"/messages"stringWhere the messages icon and tab point.
searchPlaceholderdefault"Search 1,284,310 listings"stringThe query field's and the phone field's placeholder. Empty uses labels.searchPlaceholder.
defaultQuerydefault""stringThe query the search starts with.
defaultLocationdefault""stringA ro-locations city id the search starts with ("cluj-napoca"); "" is All locations. An unknown id shows as typed.
defaultCategorydefault""stringA category id that scopes the search ("phones"); shown as a removable chip in the box.
onSearch(query: { query: string; location: string; category: string }) => voidRuns on Enter, Search, a suggestion or a recent search. Default: navigates to /cautare?q=…&loc=…&cat=… through the router.
popularSearchesstring[]Suggested while the field is empty (MARKETPLACE_SHELL_SAMPLE.popularSearches: iPhone 14, Bike, 2-bedroom apartment, Sofa, Honda Civic).
recentSearchesstring[]The recent searches the field starts with (city bike, macbook air); each submit adds one, and each can be removed.
locationsLocationOption[]The location combobox's cities. Default: cityOptions() from ro-locations, largest first; All locations and Near me are always on top.
searchShortcutdefault"/"stringFocuses the search on desktop and opens the search sheet on phones. "" binds nothing.
postHrefdefault"/post"stringWhere Post a listing and the tab bar's raised action point.
onPost() => voidReplaces the postHref link with a button (open a dialog, check sign-in first).
minimalActiondefault"back""back" | "close" | "none"The minimal variant's leading button.
minimalNoteReactNodeThe minimal variant's trailing trust note. Default: a lock and Secure payment.
onBack() => voidThe minimal button. Default: history.back() when there is history, else backHref.
backHrefdefault"/"stringWhere the minimal button goes without history.
showCategoriesdefaulttruebooleanThe category strip under the header (768px and up).
footerdefaulttruebooleanThe footer with the link columns, the app badges, the cookie settings and the theme (page layout, full variant).
footerLinks{ title: string; links: { label: string; href: string }[] }[]The footer columns (MARKETPLACE_SHELL_SAMPLE.footerLinks: Northwind Market, Help, Legal, For business).
footerNoteReactNodeExtra content in the footer's bottom row, next to Cookie settings.
appBadgesdefaulttruebooleanApp Store and Google Play buttons in the footer (neutral buttons with an icon and text, no brand artwork).
tabBardefaulttruebooleanThe phone tab bar: Home, Search, the raised Post, Messages and Account.
hideTabBardefaultfalsebooleanHides the tab bar for a while (a page with its own sticky bar, thumbnails).
cookieConsentdefaulttruebooleanRenders CookieConsent until the visitor decides; it sits above the tab bar.
consentStorageKeydefault"northwind-market-consent"stringThe consent cookie's name (the demo appends -demo so it never touches a real choice).
consentCategoriesConsentCategoryConfig[]The consent categories. Default: DEFAULT_CONSENT_CATEGORY_CONFIG.
ctaTonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"The fill of Post a listing, Search, the tab bar's raised action and the consent's accept button.
loginHrefdefault"/login"stringWhere Sign in points while signed out.
accountHrefdefault"/account"stringThe Cont tab and the account menu's base path.
logoReactNodeReplaces the default mark and Northwind Market wordmark.
localedefault"en-US"stringIntl locale for the counts.
tonedefault"neutral""neutral" | "brand" | "success" | "warning" | "danger" | "info"The active category chip and the active tab.
linkComponent(props: LinkComponentProps) => ReactNodeThe router link every link renders through (next/link). Default: the LinkProvider's, else <a>.
onNavigate(href: string) => voidThe router's push for the default search and the account menu (next: useRouter().push).
labelsPartial<MarketplaceShellLabels>Every visible string. English by default (DEFAULT_MARKETPLACE_SHELL_LABELS; MARKETPLACE_SHELL_LABELS_EN is the same set under its older name).
classNamesPartial<Record<"header" | "search" | "categories" | "main" | "footer" | "tabs", string>>Extra classes for the inner parts.
classNamestringExtra classes for the root. Other props spread onto it.
Parts
DEFAULT_MARKETPLACE_SHELL_LABELS
constantThe English strings for every visible label, the default of labels. Type: MarketplaceShellLabels.
MARKETPLACE_SHELL_LABELS_EN
constantThe same English strings under their older name, kept for existing imports.
MARKETPLACE_SHELL_SAMPLE
constantThe Northwind Market demo data: categories, footer links, popular and recent searches, listing titles, the listing count and the user.
MarketplaceShellProps
typeProps of MarketplaceShell, including the div attributes of the root.
MarketplaceCategory
typeA category in the strip and the search: id, label, icon and optional children.
MarketplaceSearchQuery
typeWhat the header search submits: the text, the location and the category.
Examples
Signed out
user={null}: Sign in in the header and the tab bar; zero counts hide the badges.
Minimal checkout frame
variant="minimal": logo, a back button and a trust note; no search, categories, footer or tabs.
Brand CTA with a scoped search
ctaTone="brand" and tone="brand"; the search starts in Phones, Cluj-Napoca.
Fill layout with an inbox
layout="fill": the shell is the viewport, no footer, the panes scroll inside.
Dependencies
Files
- components/blocks/marketplace-shell.tsx
- components/blocks/marketplace-shell-data.ts
FAQ
Is the React Marketplace Shell block free?
The preview, props and docs are free; copying the source needs a Pro plan. See plans.
How do I install Marketplace Shell?
Run npx wingo-ui@latest add marketplace-shell. It also adds the Wingo UI items it builds on (Badge, Bottom Tab Bar, Button, Combobox, Cookie Consent and 15 more) and the npm package lucide-react. With shadcn, add the @wingo-ui registry with your API key, then run npx shadcn@latest add @wingo-ui/marketplace-shell.
How does Marketplace Shell behave on phones?
Below 768px the header is a compact row: the logo mark, a search field that opens a full height sheet (autofocused input, the location as a row that opens its own sheet, recent searches with remove buttons, popular searches and category tiles; Escape, the handle or Cancel closes it) and the avatar.
See also
More React blocks
Articles using this component
- React Marketplace Template That Works Like an App
Build it: screens and apps15 min read