E-commerceecommerceshopherolandingproduct
Store Hero
Hero de tienda con titular en degradado, CTAs, cifras de confianza y producto destacado flotante.
Vista Previa en Vivo
New season · 2026
Gear that feels made for you
Thoughtfully designed audio, wearables and everyday carry. Free shipping over $75 and 30-day returns on everything.
- from 12k reviews
- 4.9/5
- average delivery
- 48h
- free returns
- 30 days
Uso
Copia y pega este código directamente en tu componente React:
tsx
import { StoreHero } from 'react-component-kit-ui/ecommerce';
<StoreHero title="Gear that feels" highlight="made for you" primary={{ label: 'Shop now', href: '/shop/' }} />Instalación Manual
Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/StoreHero.tsx + StoreHero.css:
StoreHero.tsx
'use client';
import ProductMedia from './ProductMedia';
import ProductRating from './ProductRating';
import { formatMoney } from './cart-store';
import type { Product } from './types';
import './StoreHero.css';
/** class:list → className */
function cx(...args: unknown[]): string {
const out: string[] = [];
const walk = (v: unknown) => {
if (!v) return;
if (typeof v === 'string' || typeof v === 'number') out.push(String(v));
else if (Array.isArray(v)) v.forEach(walk);
else if (typeof v === 'object') for (const [k, on] of Object.entries(v as Record<string, unknown>)) if (on) out.push(k);
};
args.forEach(walk);
return out.join(' ');
}
interface Cta { label: string; href: string }
/**
* StoreHero — Shop landing hero: headline, CTAs, quick stats and a featured product
* stage with floating price and rating chips.
*
* @param {string} eyebrow - Small label above the title. Default 'New season · 2026'.
* @param {string} title - Headline. Default 'Gear that feels'.
* @param {string} highlight - Gradient part of the headline. Default 'made for you'.
* @param {string} subtitle - Supporting copy.
* @param {{label: string, href: string}} primary - Main CTA.
* @param {{label: string, href: string}} secondary - Secondary CTA (optional).
* @param {Array<{value: string, label: string}>} stats - Proof points below the CTAs.
* @param {Product} product - Featured product shown on the stage.
* @param {string} productHref - Featured product link.
* @param {string} currency - ISO currency. Default 'USD'.
* @param {string} locale - Number format locale. Default 'en-US'.
* @param {string} variant - Layout (split|centered). Default 'split'.
* @param {string} size - Vertical rhythm (sm|md|lg). Default 'md'.
* @param {string} className - Extra class.
*
* Accessibility: one h1; decorative stage art is aria-hidden; the featured product is a real link.
*/
export interface StoreHeroProps {
eyebrow?: string;
title?: string;
highlight?: string;
subtitle?: string;
primary?: Cta;
secondary?: Cta;
stats?: Array<{ value: string; label: string }>;
product?: Product;
productHref?: string;
currency?: string;
locale?: string;
variant?: 'split' | 'centered';
size?: 'sm' | 'md' | 'lg';
className?: string;
}
export function StoreHero({
eyebrow = 'New season · 2026',
title = 'Gear that feels',
highlight = 'made for you',
subtitle = 'Thoughtfully designed audio, wearables and everyday carry. Free shipping over $75 and 30-day returns on everything.',
primary = { label: 'Shop the collection', href: '#' },
secondary = { label: 'Explore new arrivals', href: '#' },
stats = [
{ value: '4.9/5', label: 'from 12k reviews' },
{ value: '48h', label: 'average delivery' },
{ value: '30 days', label: 'free returns' },
],
product = { slug: 'aurora-headphones', name: 'Aurora Wireless Headphones', price: 189, compareAt: 229, category: 'audio', rating: 4.8, reviews: 312, icon: 'headphones', hue: 38 },
productHref = '#',
currency = 'USD',
locale = 'en-US',
variant = 'split',
size = 'md',
className = '',
}: StoreHeroProps) {
const money = { currency, locale };
return (
<>
<section className={cx(['store-hero', `store-hero--${variant}`, `store-hero--${size}`, className])} data-rk-92f260="">
<div className="store-hero__glow" aria-hidden="true" data-rk-92f260=""></div>
<div className="store-hero__inner" data-rk-92f260="">
<div className="store-hero__copy" data-rk-92f260="">
{eyebrow && <p className="store-hero__eyebrow" data-rk-92f260=""><span aria-hidden="true" data-rk-92f260=""></span>{eyebrow}</p>}
<h1 className="store-hero__title" data-rk-92f260="">{title} <em data-rk-92f260="">{highlight}</em></h1>
{subtitle && <p className="store-hero__subtitle" data-rk-92f260="">{subtitle}</p>}
<div className="store-hero__ctas" data-rk-92f260="">
{primary && (
<a className="store-hero__btn store-hero__btn--primary" href={primary.href} data-rk-92f260="">
{primary.label}
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true" data-rk-92f260=""><path d="M5 12h14M13 6l6 6-6 6" data-rk-92f260="" /></svg>
</a>
)}
{secondary && <a className="store-hero__btn store-hero__btn--ghost" href={secondary.href} data-rk-92f260="">{secondary.label}</a>}
</div>
{stats.length > 0 && (
<dl className="store-hero__stats" data-rk-92f260="">
{stats.map((s, __i: number) => (
<div key={__i} data-rk-92f260=""><dt data-rk-92f260="">{s.label}</dt><dd data-rk-92f260="">{s.value}</dd></div>
))}
</dl>
)}
</div>
{product && (
<div className="store-hero__stage" data-rk-92f260="">
<div className="store-hero__ring" aria-hidden="true" data-rk-92f260=""></div>
<a className="store-hero__product" href={productHref} data-rk-92f260="">
<ProductMedia image={product.image} alt={product.name} icon={product.icon} hue={product.hue} size="lg" ratio="4 / 5" />
<span className="store-hero__chip store-hero__chip--price" data-rk-92f260="">
<small data-rk-92f260="">{product.name}</small>
<strong data-rk-92f260="">{formatMoney(product.price, money)}</strong>
{product.compareAt && <s data-rk-92f260=""><span className="sr-only" data-rk-92f260="">Was </span>{formatMoney(product.compareAt, money)}</s>}
</span>
{product.rating !== undefined && (
<span className="store-hero__chip store-hero__chip--rating" data-rk-92f260="">
<ProductRating value={product.rating} count={product.reviews} />
</span>
)}
</a>
</div>
)}
</div>
</section>
</>
);
}
export default StoreHero;StoreHero.css
/* StoreHero — ported from astro-component-kit (ecommerce/StoreHero.astro) */
.store-hero:where([data-rk-92f260]) {
container-type: inline-size;
--hero-pad: clamp(3rem, 7vw, 6rem);
position: relative;
overflow: hidden;
padding: var(--hero-pad) var(--sp-6, 1.5rem);
isolation: isolate;
}
.store-hero--sm:where([data-rk-92f260]) { --hero-pad: clamp(2rem, 5vw, 3.5rem); }
.store-hero--lg:where([data-rk-92f260]) { --hero-pad: clamp(4rem, 9vw, 8rem); }
.store-hero__glow:where([data-rk-92f260]) {
position: absolute;
inset: -20% -10% auto 30%;
height: 120%;
background: radial-gradient(closest-side, rgba(212, 160, 23, 0.16), transparent 70%);
z-index: -1;
pointer-events: none;
}
.store-hero__inner:where([data-rk-92f260]) {
display: grid;
grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
align-items: center;
gap: clamp(2rem, 5vw, 4rem);
max-width: 1280px;
margin: 0 auto;
}
.store-hero--centered:where([data-rk-92f260]) .store-hero__inner:where([data-rk-92f260]) { grid-template-columns: 1fr; text-align: center; justify-items: center; }
.store-hero--centered:where([data-rk-92f260]) .store-hero__ctas:where([data-rk-92f260]), .store-hero--centered:where([data-rk-92f260]) .store-hero__stats:where([data-rk-92f260]) { justify-content: center; }
.store-hero--centered:where([data-rk-92f260]) .store-hero__stage:where([data-rk-92f260]) { max-width: 420px; }
.store-hero__eyebrow:where([data-rk-92f260]) {
display: inline-flex;
align-items: center;
gap: var(--sp-2, 0.5rem);
margin: 0 0 var(--sp-4, 1rem);
padding: 0.35rem 0.85rem;
border-radius: var(--r-full, 9999px);
border: 1px solid rgba(212, 160, 23, 0.3);
background: rgba(212, 160, 23, 0.08);
color: var(--c-accent, #fef3c7);
font-size: 0.75rem;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.store-hero__eyebrow:where([data-rk-92f260]) span:where([data-rk-92f260]) { width: 6px; height: 6px; border-radius: 50%; background: var(--c-primary-light, #d4a017); box-shadow: 0 0 10px var(--c-primary-light, #d4a017); }
.store-hero__title:where([data-rk-92f260]) {
margin: 0;
font-size: clamp(2.4rem, 6vw, 4.6rem);
font-weight: 900;
line-height: 1.02;
letter-spacing: -0.04em;
color: var(--c-text-1, #fff);
}
.store-hero__title:where([data-rk-92f260]) em:where([data-rk-92f260]) {
display: block;
font-style: normal;
background: linear-gradient(100deg, var(--c-accent, #fef3c7), var(--c-primary-light, #d4a017) 55%, var(--c-primary, #b8860b));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.store-hero__subtitle:where([data-rk-92f260]) { max-width: 34rem; margin: var(--sp-5, 1.25rem) 0 0; font-size: 1.05rem; line-height: 1.65; color: var(--c-text-2, #a3a3a3); }
.store-hero--centered:where([data-rk-92f260]) .store-hero__subtitle:where([data-rk-92f260]) { margin-inline: auto; }
.store-hero__ctas:where([data-rk-92f260]) { display: flex; flex-wrap: wrap; gap: var(--sp-3, 0.75rem); margin-top: var(--sp-8, 2rem); }
.store-hero__btn:where([data-rk-92f260]) {
display: inline-flex;
align-items: center;
gap: var(--sp-2, 0.5rem);
min-height: 52px;
padding: 0 var(--sp-6, 1.5rem);
border-radius: var(--r-full, 9999px);
font-weight: 700;
font-size: 0.95rem;
text-decoration: none;
transition: transform 0.2s ease, filter 0.2s ease, background 0.2s ease;
}
.store-hero__btn--primary:where([data-rk-92f260]) { background: var(--c-primary-light, #d4a017); color: var(--c-on-primary, #050505); }
.store-hero__btn--primary:hover:where([data-rk-92f260]) { color: var(--c-on-primary, #050505); filter: brightness(1.08); transform: translateY(-2px); }
.store-hero__btn--ghost:where([data-rk-92f260]) { border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.14); color: var(--c-text-1, #fff); }
.store-hero__btn--ghost:hover:where([data-rk-92f260]) { background: rgb(var(--ink-rgb, 255 255 255) / 0.05); color: var(--c-text-1, #fff); }
.store-hero__btn:focus-visible:where([data-rk-92f260]), .store-hero__product:focus-visible:where([data-rk-92f260]) { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 3px; }
.store-hero__stats:where([data-rk-92f260]) { display: flex; flex-wrap: wrap; gap: var(--sp-8, 2rem); margin: var(--sp-10, 2.5rem) 0 0; }
.store-hero__stats:where([data-rk-92f260]) div:where([data-rk-92f260]) { display: flex; flex-direction: column-reverse; }
.store-hero__stats:where([data-rk-92f260]) dt:where([data-rk-92f260]) { font-size: 0.8rem; color: var(--c-text-2, #a3a3a3); }
.store-hero__stats:where([data-rk-92f260]) dd:where([data-rk-92f260]) { margin: 0; font-size: 1.35rem; font-weight: 800; color: var(--c-text-1, #fff); letter-spacing: -0.02em; }
.store-hero__stage:where([data-rk-92f260]) { position: relative; width: 100%; max-width: 480px; justify-self: center; }
.store-hero__ring:where([data-rk-92f260]) {
position: absolute;
inset: 8% -6%;
border-radius: 50%;
border: 1px dashed rgba(212, 160, 23, 0.25);
animation: store-hero-sh-spin 40s linear infinite;
}
.store-hero__product:where([data-rk-92f260]) {
position: relative;
display: block;
border-radius: var(--r-xl, 28px);
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
overflow: visible;
color: inherit;
text-decoration: none;
animation: store-hero-sh-float 7s ease-in-out infinite;
}
.store-hero__product:where([data-rk-92f260]) .p-media { border-radius: var(--r-xl, 28px); }
.store-hero__chip:where([data-rk-92f260]) {
position: absolute;
display: grid;
gap: 2px;
padding: var(--sp-3, 0.75rem) var(--sp-4, 1rem);
border-radius: var(--r-md, 12px);
border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
background: rgb(var(--paper-rgb, 5 5 5) / 0.78);
backdrop-filter: blur(14px);
box-shadow: 0 20px 40px -20px rgba(0, 0, 0, 0.8);
text-align: left;
}
.store-hero__chip--price:where([data-rk-92f260]) { left: -6%; bottom: 12%; }
.store-hero__chip--price:where([data-rk-92f260]) small:where([data-rk-92f260]) { font-size: 0.72rem; color: var(--c-text-2, #a3a3a3); }
.store-hero__chip--price:where([data-rk-92f260]) strong:where([data-rk-92f260]) { font-size: 1.25rem; color: var(--c-text-1, #fff); }
.store-hero__chip--price:where([data-rk-92f260]) s:where([data-rk-92f260]) { font-size: 0.78rem; color: var(--c-text-2, #a3a3a3); }
.store-hero__chip--rating:where([data-rk-92f260]) { right: -4%; top: 10%; }
@keyframes store-hero-sh-float { 50% { transform: translateY(-10px); } }
@keyframes store-hero-sh-spin { to { transform: rotate(360deg); } }
.sr-only:where([data-rk-92f260]) { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
@container (max-width: 900px) {
.store-hero__inner:where([data-rk-92f260]) { grid-template-columns: 1fr; }
.store-hero__stage:where([data-rk-92f260]) { max-width: 360px; }
.store-hero__chip--price:where([data-rk-92f260]) { left: 0; }
.store-hero__chip--rating:where([data-rk-92f260]) { right: 0; }
}
@media (prefers-reduced-motion: reduce) {
.store-hero__product:where([data-rk-92f260]), .store-hero__ring:where([data-rk-92f260]) { animation: none; }
}Información Rápida
- Categoría
- E-commerce
- Nombre de archivo
StoreHero.tsx- Dependencias
- Ninguna — React + CSS puro
- Etiquetas
- ecommerceshopherolandingproduct