8pt

Shortcut Keycaps

Shortcut Keycaps•Data display
Overview

Keyboard shortcuts as 3D keycap cards. When idle each card demos a key press; once the pointer is inside, pressing ⌘, ⌥, ⇧ or a letter on your real keyboard presses the matching keycap, and a card lights up when its whole combo is held.

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 Shortcut Keycaps to your project in your colors.

Where to use it

Dashboards, data tables, chart cards, comparison tables and status panels.

Install

With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.

$ npm i -g @8pt-dev/cli && 8pt add shortcut-keycaps
mcp › Use 8pt MCP to call get_component("shortcut-keycaps")

Code

Source for Shortcut Keycaps. Motion uses only transform and opacity and respects the Reduce motion setting.

<div class="x-kcap">
  <div class="x-kcap__in" style="width:660px;height:252px">
    <div class="x-kcap__k"><p><kbd>⌘</kbd><kbd>D</kbd></p><span>Split into two panes</span></div>
    <div class="x-kcap__k"><p><kbd>⌘</kbd><kbd>L</kbd></p><span>Enter a path, Tab to complete</span></div>
    <div class="x-kcap__k"><p><kbd>⌥</kbd><kbd>⌘</kbd><kbd>T</kbd></p><span>Tidy this folder</span></div>
    <div class="x-kcap__k"><p><kbd>⌘</kbd><kbd>Z</kbd></p><span>Undo the last file action</span></div>
    <div class="x-kcap__k"><p><kbd>Space</kbd></p><span>Quick Look files</span></div>
    <div class="x-kcap__k"><p><kbd>⌥</kbd><kbd>⇧</kbd><kbd>⌘</kbd><kbd>T</kbd></p><span>Open in Terminal</span></div>
    <div class="x-kcap__k"><p><kbd>⌘</kbd><kbd>K</kbd></p><span>Jump to any folder</span></div>
    <div class="x-kcap__k"><p><kbd>⌃</kbd><kbd>1</kbd></p><span>Open your first workspace</span></div>
  </div>
</div>
.x-kcap{position:relative;flex:none}
.x-kcap__in{position:absolute;left:0;top:0;transform-origin:0 0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;color:var(--d-fg,#fff);font-family:var(--d-font,system-ui,sans-serif)}
.x-kcap__k{display:flex;flex-direction:column;justify-content:space-between;gap:12px;padding:16px 14px;border-radius:16px;background:var(--d-card,#14141c);border:1px solid var(--d-line,rgba(255,255,255,.1));box-shadow:inset 0 1px 0 color-mix(in srgb,#fff 10%,transparent),0 10px 26px rgba(0,0,0,.08);transition:transform .25s cubic-bezier(.16,1,.3,1),border-color .25s,box-shadow .25s}
.x-kcap__k:hover{transform:translateY(-2px)}
.x-kcap__k.hit{border-color:var(--d-accent,#4D74FF);box-shadow:0 0 0 1px var(--d-accent,#4D74FF),0 12px 30px color-mix(in srgb,var(--d-accent,#4D74FF) 28%,transparent)}
.x-kcap__k p{display:flex;flex-wrap:nowrap;gap:4px;margin:0}
.x-kcap__k span{font-size:13px;line-height:1.35;color:var(--d-muted,#9b9ba8)}
.x-kcap kbd{display:inline-grid;place-items:center;min-width:28px;height:30px;padding:0 7px;box-sizing:border-box;border-radius:8px;background:linear-gradient(180deg,color-mix(in srgb,var(--d-fg,#fff) 4%,var(--d-bg,#09090d)),var(--d-bg,#09090d));box-shadow:0 0 0 1px var(--d-line,rgba(255,255,255,.14)),0 2px 0 color-mix(in srgb,var(--d-fg,#fff) 22%,transparent);font:600 14px/1 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--d-fg,#fff);transition:transform .12s,box-shadow .12s,background .12s,color .12s}
.x-kcap kbd.down{transform:translateY(2px);background:var(--d-accent,#4D74FF);color:#fff;box-shadow:0 0 0 1px var(--d-accent,#4D74FF),0 0 0 transparent}
@media (prefers-reduced-motion:reduce){.x-kcap__k,.x-kcap kbd{transition:none}}
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();
…
Subscribe to Builder to see the full source.See pricing

Other components from this template

View all

Mac File Window

Disk Cleanup Panel

Glass Folder

File Preview Cards

Ticket Pricing

Compare Table

Floating Folders CTA

More data display components

View all

Agent Chat Window

Mac File Window

Disk Cleanup Panel

Compare Table

Orbit Timeline

Avatar Stack

Kanban Column

Code Diff Card

More components

View all

AI Prompt Composer

Film Strip Carousel

Auto Tab Showcase

Media Bento Grid

Model Pill Marquee

Director Art Cards

Glass Folder

File Preview Cards

Keep exploring