Your browsing history is cleared.
@use 'sprucecss/scss/spruce' as *;
.recently-viewed {
@include layout-stack('m');
&__header {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: spacer('xs') spacer('s');
}
&__title {
font-size: font-size('h4');
margin-inline-end: auto;
}
&__controls {
display: flex;
gap: spacer('xxs');
&[hidden] {
display: none;
}
}
&__track {
display: grid;
gap: spacer('m');
grid-auto-columns: minmax(10rem, calc((100% - #{spacer('m')} * 4) / 5));
grid-auto-flow: column;
list-style: none;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding: 0 0 spacer('s');
scroll-padding-inline: 0;
scroll-snap-type: inline mandatory;
scrollbar-width: thin;
&:focus-visible {
outline: 2px solid color('focus-ring');
outline-offset: 4px;
}
@include motion-safe {
scroll-behavior: smooth;
}
> li {
margin-block: 0;
padding-block: 0;
}
}
&__item {
scroll-snap-align: start;
}
&__link {
color: color('heading');
display: flex;
flex-direction: column;
gap: spacer('xxs');
text-decoration: none;
img {
aspect-ratio: 1;
background-color: color('surface-muted');
border-radius: radius('md');
inline-size: 100%;
margin-block-end: spacer('xxs');
object-fit: cover;
@include transition($property: 'opacity');
}
&:hover {
img {
opacity: 0.85;
}
.recently-viewed__name {
text-decoration: underline;
}
}
}
&__name {
font-size: config('font-size-sm', $typography);
font-weight: 600;
}
&__price {
color: color('muted');
font-size: config('font-size-sm', $typography);
}
&__cleared {
color: color('muted');
}
}
[dir='rtl'] .recently-viewed__arrow svg {
scale: -1 1;
}
<section class="recently-viewed" aria-labelledby="recently-viewed-title" data-recently-viewed>
<header class="recently-viewed__header">
<h2 class="recently-viewed__title" id="recently-viewed-title">Recently viewed</h2>
<div class="recently-viewed__controls" hidden data-recently-viewed-controls>
<button class="btn btn--secondary btn--icon btn--sm recently-viewed__arrow" type="button" data-direction="-1"><svg class="btn__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m15 18-6-6 6-6"/></svg><span class="sr-only">Scroll back</span></button>
<button class="btn btn--secondary btn--icon btn--sm recently-viewed__arrow" type="button" data-direction="1"><svg class="btn__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="m9 18 6-6-6-6"/></svg><span class="sr-only">Scroll forward</span></button>
</div>
<button class="btn btn--ghost-primary btn--sm" type="button" data-recently-viewed-clear>Clear history</button>
</header>
<ul class="recently-viewed__track" role="list" tabindex="0" aria-labelledby="recently-viewed-title" data-recently-viewed-track>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1553062407-98eeb64c6a62?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Everyday Backpack</span>
<span class="recently-viewed__price">$89</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1495474472287-4d71bcdd2085?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Ceramic Pour-Over</span>
<span class="recently-viewed__price">$42</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Wireless Headphones</span>
<span class="recently-viewed__price">$199</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1507473885765-e6ed057f782c?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Desk Lamp</span>
<span class="recently-viewed__price">$79</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1523275335684-37898b6baf30?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Smart Watch</span>
<span class="recently-viewed__price">$299</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1547949003-9792a18a2601?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Leather Weekender</span>
<span class="recently-viewed__price">$249</span>
</a>
</li>
<li class="recently-viewed__item">
<a class="recently-viewed__link" href="#">
<img src="https://images.unsplash.com/photo-1572635196237-14b3f281503f?auto=format&fit=crop&w=400&q=70" alt="" width="400" height="400" loading="lazy">
<span class="recently-viewed__name">Sunglasses</span>
<span class="recently-viewed__price">$129</span>
</a>
</li>
</ul>
<p class="recently-viewed__cleared" tabindex="-1" hidden data-recently-viewed-cleared>Your browsing history is cleared.</p>
</section>
(() => {
document.querySelectorAll('[data-recently-viewed]').forEach((section) => {
const track = section.querySelector('[data-recently-viewed-track]');
const controls = section.querySelector('[data-recently-viewed-controls]');
const [back, forward] = controls.querySelectorAll('[data-direction]');
const update = () => {
const position = Math.abs(track.scrollLeft);
const max = track.scrollWidth - track.clientWidth;
controls.hidden = max <= 1;
back.disabled = position <= 1;
forward.disabled = position >= max - 1;
};
controls.addEventListener('click', (event) => {
const button = event.target.closest('[data-direction]');
if (!button) return;
const isRtl = getComputedStyle(track).direction === 'rtl';
track.scrollBy({ left: track.clientWidth * 0.8 * button.dataset.direction * (isRtl ? -1 : 1) });
});
section.querySelector('[data-recently-viewed-clear]').addEventListener('click', (event) => {
const cleared = section.querySelector('[data-recently-viewed-cleared]');
track.remove();
controls.remove();
event.currentTarget.remove();
cleared.hidden = false;
cleared.focus();
});
track.addEventListener('scroll', update, { passive: true });
new ResizeObserver(update).observe(track);
});
})();