File Preview Cards
Every file shown as a card with a real preview: a document cover page, a photo, a slide, a spreadsheet, a video frame. An S / M / L switch in the corner resizes the cards; selected cards get an outline.
Taken from the page template Nook Mac App Website. Use it on its own, or combine it with the other components from the same template to rebuild the full page.
Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds File Preview Cards to your project in your colors.
Where to use it
Sections that present information in groups: features, case studies and work, team members, article lists.
Install
With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.
Code
Source for File Preview Cards. Motion uses only transform and opacity and respects the Reduce motion setting.
<div class="x-fpc">
<div class="x-fpc__in" style="width:580px;height:340px">
<div class="x-fpc__hd"><div><b>Shown as cards, with real previews</b><span>Small, medium and large, or use ⌘+ / ⌘− Switch</span></div>
<div class="x-fpc__sz" role="group" aria-label="Card size"><button type="button" data-s="s" aria-pressed="false">S</button><button type="button" data-s="m" aria-pressed="true">M</button><button type="button" data-s="l" aria-pressed="false">L</button></div></div>
<div class="x-fpc__g">
<button type="button" class="x-fpc__c on"><span class="x-fpc__pv pg" style="--c:#E5484D"><i></i></span><span class="x-fpc__ci"><b>Brand guidelines</b><small>PDF · 4.6 MB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv ph" style="--g:linear-gradient(160deg,#F6B26B,#E0605E)"></span><span class="x-fpc__ci"><b>Mood board</b><small>JPEG · 2.8 MB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv sl"><i>Launch event</i></span><span class="x-fpc__ci"><b>Launch event slides</b><small>Keynote · 16.2 MB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv xl"><i></i></span><span class="x-fpc__ci"><b>Qingyou quote</b><small>Excel · 88 KB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv ph" style="--g:linear-gradient(160deg,#C8B6FF,#7B61E8)"></span><span class="x-fpc__ci"><b>Key visual</b><small>PNG · 5.4 MB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv pg" style="--c:#3D5BF0"><i></i></span><span class="x-fpc__ci"><b>Invoices 2026-047</b><small>PDF · 176 KB</small></span></button>
<button type="button" class="x-fpc__c"><span class="x-fpc__pv vd"><i></i></span><span class="x-fpc__ci"><b>Trailer</b><small>Movies · 52.1 MB</small></span></button>
….x-fpc{position:relative;flex:none}
.x-fpc__in{position:absolute;left:0;top:0;transform-origin:0 0;display:flex;flex-direction:column;gap:14px;padding:20px;border-radius:22px;background:var(--d-card,#14141c);border:1px solid var(--d-line,rgba(255,255,255,.1));color:var(--d-fg,#fff);font-family:var(--d-font,system-ui,sans-serif);overflow:hidden;box-sizing:border-box}
.x-fpc__hd{display:flex;align-items:flex-start;justify-content:space-between;gap:16px}
.x-fpc__hd b{display:block;font-size:17px;letter-spacing:-.01em}.x-fpc__hd span{display:block;margin-top:3px;font-size:12.5px;color:var(--d-muted,#9b9ba8)}
.x-fpc__sz{flex:none;display:inline-flex;padding:3px;border-radius:10px;background:color-mix(in srgb,var(--d-fg,#fff) 7%,transparent)}
.x-fpc__sz button{width:34px;height:28px;border:0;border-radius:7px;background:transparent;font:600 12.5px/1 inherit;color:var(--d-muted,#9b9ba8);cursor:pointer;transition:background .2s,color .2s}
.x-fpc__sz button[aria-pressed=true]{background:var(--d-bg,#09090d);color:var(--d-fg,#fff);box-shadow:0 1px 3px rgba(0,0,0,.18)}
.x-fpc__g{flex:1;min-height:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--cw,118px),1fr));gap:10px;align-content:start;grid-auto-rows:max-content;overflow:hidden;padding:3px;margin:-3px;-webkit-mask:linear-gradient(#000 82%,transparent);mask:linear-gradient(#000 82%,transparent)}
.x-fpc__c{display:block;padding:0;border:0;border-radius:12px;background:var(--d-bg,#09090d);color:inherit;font:inherit;text-align:left;overflow:hidden;cursor:pointer;box-shadow:0 0 0 1px var(--d-line,rgba(255,255,255,.1)),0 6px 16px rgba(0,0,0,.08);transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s}
.x-fpc__c:hover{transform:translateY(-2px)}
.x-fpc__c.on{box-shadow:0 0 0 2.5px var(--d-accent,#4D74FF),0 8px 20px color-mix(in srgb,var(--d-accent,#4D74FF) 25%,transparent)}
.x-fpc__c:focus-visible,.x-fpc__sz button:focus-visible{outline:2px solid var(--d-accent,#4D74FF);outline-offset:2px}
…const init = (root) => {
const fit = (box, W, H) => {
const inner = box.firstElementChild;
const run = () => {
const cs = getComputedStyle(root);
const aw = root.clientWidth - parseFloat(cs.paddingLeft) - parseFloat(cs.paddingRight);
const ah = root.clientHeight - parseFloat(cs.paddingTop) - parseFloat(cs.paddingBottom);
if (aw <= 0 || ah <= 0) return;
const s = Math.max(0.2, Math.min(aw / W, ah / H, 1));
box.style.width = W * s + 'px'; box.style.height = H * s + 'px'; inner.style.transform = `scale(${s})`;
};
const ro = new ResizeObserver(run); ro.observe(root); run();
…