`; document.body.appendChild(el); return el; } const bubble = ensureBubble(); const elH = bubble.querySelector("#tt-title"); const elB = bubble.querySelector("#tt-body"); const elClose = bubble.querySelector(".tt-close"); // ---------------- Parse [[term|heading|body]] anywhere ---------------- const TOKEN_RE = /\[\[([^|\]]+)\|([^|\]]+)\|([^\]]+)\]\]/g; const BLOCK_SKIP = new Set(["SCRIPT","STYLE","NOSCRIPT","TEXTAREA","INPUT","SELECT","CODE","PRE","TEMPLATE","IFRAME"]); function shouldSkipTextNode(n){ let el = n.parentElement; while (el){ if (BLOCK_SKIP.has(el.tagName) || el.isContentEditable) return true; el = el.parentElement; } return false; } const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT); const textNodes = []; while (walker.nextNode()){ const n = walker.currentNode; if (!n.nodeValue || shouldSkipTextNode(n)) continue; if (TOKEN_RE.test(n.nodeValue)) textNodes.push(n); TOKEN_RE.lastIndex = 0; } textNodes.forEach(node => { const frag = document.createDocumentFragment(); const insideLink = !!node.parentElement.closest("a"); let text = node.nodeValue, last = 0; TOKEN_RE.lastIndex = 0; let m; while ((m = TOKEN_RE.exec(text))){ if (m.index > last) frag.appendChild(document.createTextNode(text.slice(last, m.index))); const term=m[1].trim(), heading=m[2].trim(), body=m[3].trim(); const t = insideLink ? document.createElement("span") : document.createElement("button"); if (insideLink){ t.setAttribute("role","button"); t.setAttribute("tabindex","0"); } else { t.type="button"; } t.className="tt-trigger"; t.textContent=term; t.setAttribute("data-tt-h", heading); t.setAttribute("data-tt-b", body); t.setAttribute("aria-haspopup","dialog"); t.setAttribute("aria-expanded","false"); frag.appendChild(t); last = TOKEN_RE.lastIndex; } if (last = 2) return el; el = el.parentElement; } // Fallback: nearest non-inline container el = trigger.parentElement || document.body; while (el && el !== document.body){ const d = getComputedStyle(el).display; if (d !== "inline" && d !== "contents") return el; el = el.parentElement; } return document.body; } // Utility: child of `ancestor` that contains `target` (direct child) function directChildContaining(ancestor, target){ for (const ch of ancestor.children){ if (ch === target || ch.contains(target)) return ch; } return null; } function getElementTarget(e) { // If target is already an Element, use it if (e.target instanceof Element) return e.target; // Otherwise, walk the composed/path for the first Element const path = (typeof e.composedPath === 'function') ? e.composedPath() : []; for (const n of path) if (n instanceof Element) return n; return null; } // ---------------- Dim everything except the trigger branch (sibling branches only) ---------------- function dimAllOtherBranches(container, trigger){ undim(); // clear previous const dimEls = []; const wrappedTexts = []; const pathEls = []; // Build ELEMENT-only path [container -> ... -> trigger] const path = []; for (let el = trigger; el && el !== container; el = el.parentElement) path.push(el); path.push(container); path.reverse(); // At each ancestor level, find the *direct* child that leads to the trigger for (let i = 0; i { if (node.nodeType !== 3) return; // text only if (!node.nodeValue || !node.nodeValue.trim()) return; // If this text node sits inside branchChild, skip if (branchChild && branchChild.contains && branchChild.contains(node)) return; const span = document.createElement("span"); span.style.transition = `opacity ${DIM_EASE_MS}ms ease`; span.style.opacity = String(DIM_OPACITY); span.textContent = node.nodeValue; node.parentNode.replaceChild(span, node); wrappedTexts.push(span); }); // Keep a reference to the path elements (so we can explicitly restore opacity if needed) if (anc && anc.nodeType === 1) pathEls.push(anc); } // Hard-guard: explicitly set opacity:1 on the entire path to neutralize any inherited fade pathEls.forEach(el => { el.style.opacity = "1"; }); dimCtx = { container, dimEls, wrappedTexts, pathEls }; } function undim(){ if (!dimCtx) return; const { dimEls, wrappedTexts, pathEls } = dimCtx; // Animate back dimEls.forEach(el => { el.style.transition = `opacity ${DIM_EASE_MS}ms ease`; el.style.opacity = "1"; // remove inline style after the animation so we don't override site CSS setTimeout(() => { if (el) el.style.opacity = ""; }, DIM_EASE_MS + 50); }); wrappedTexts.forEach(span => { span.style.transition = `opacity ${DIM_EASE_MS}ms ease`; span.style.opacity = "1"; span.addEventListener("transitionend", () => { if (!span.parentNode) return; span.parentNode.replaceChild(document.createTextNode(span.textContent || ""), span); }, { once:true }); }); // Clear hard-guard on path pathEls.forEach(el => { if (el) el.style.opacity = ""; }); dimCtx = null; } // ---------------- Positioning (centered, edge-aware, flip) ---------------- function clamp(v,min,max){ return Math.max(min,Math.min(max,v)); } function measureBubbleForPlacement(){ const wasOpen = bubble.classList.contains("is-open"); if (!wasOpen){ bubble.style.visibility="hidden"; bubble.classList.add("is-open"); } const rect = bubble.getBoundingClientRect(); if (!wasOpen){ bubble.classList.remove("is-open"); bubble.style.visibility=""; } return { w: rect.width, h: rect.height }; } function placeAnchored(trigger){ const vw=innerWidth, vh=innerHeight; const r = trigger.getBoundingClientRect(); const { w, h } = measureBubbleForPlacement(); let left = r.left + (r.width/2) - (w/2); left = clamp(left, EDGE_PADDING, Math.max(EDGE_PADDING, vw - EDGE_PADDING - w)); const topBelow = r.bottom + OFFSET_Y; const spaceBelow = vh - topBelow - EDGE_PADDING; const placeBelow = spaceBelow >= h; let top = placeBelow ? topBelow : (r.top - h - OFFSET_Y); top = clamp(top, EDGE_PADDING, Math.max(EDGE_PADDING, vh - EDGE_PADDING - h)); bubble.style.left = left + "px"; bubble.style.top = top + "px"; const br = bubble.getBoundingClientRect(); if (br.bottom > vh - EDGE_PADDING){ bubble.style.maxHeight = (vh - 2*EDGE_PADDING) + "px"; bubble.style.overflowY = "auto"; } else { bubble.style.maxHeight = "none"; bubble.style.overflowY = "visible"; } } // ---------------- Open / Close (place → fade/scale) ---------------- function animateIn(){ bubble.style.transition = "none"; bubble.style.opacity = "0"; bubble.style.transform = "scale(0.95)"; void bubble.offsetWidth; bubble.style.transition = "opacity .18s ease, transform .18s ease"; bubble.style.opacity = "1"; bubble.style.transform = "scale(1)"; } function animateOut(done){ bubble.style.transition = "opacity .16s ease, transform .16s ease"; bubble.style.opacity = "0"; bubble.style.transform = "scale(0.95)"; const end = () => { bubble.removeEventListener("transitionend", end); done && done(); }; bubble.addEventListener("transitionend", end); setTimeout(end, 260); } function openFromTrigger(trigger){ if (current && current !== trigger) forceClose(); current = trigger; trigger.setAttribute("aria-expanded","true"); elH.textContent = trigger.getAttribute("data-tt-h") || ""; elB.textContent = trigger.getAttribute("data-tt-b") || ""; bubble.classList.add("is-open"); bubble.setAttribute("aria-hidden","false"); placeAnchored(trigger); animateIn(); const container = findTextContainer(trigger); dimAllOtherBranches(container, trigger); hoverCount = 0; cancelCloseTimer(); } function forceClose(){ if (!current) return; bubble.classList.remove("is-open"); bubble.setAttribute("aria-hidden","true"); current.setAttribute("aria-expanded","false"); current = null; undim(); hoverCount = 0; cancelCloseTimer(); } function closeWithAnim(){ if (!current) return; const t = current; animateOut(() => { bubble.classList.remove("is-open"); bubble.setAttribute("aria-hidden","true"); t.setAttribute("aria-expanded","false"); current = null; undim(); }); } function scheduleClose(){ cancelCloseTimer(); closeTimer = setTimeout(() => { if (hoverCount { if (isCoarse()) return; const target = getElementTarget(e); if (!target) return; const t = target.closest(".tt-trigger"); if (!t) return; onZoneEnter(); if (!current || current !== t) openFromTrigger(t); }; const handleLeave = (e) => { if (isCoarse()) return; const target = getElementTarget(e); if (!target) return; const t = target.closest(".tt-trigger"); if (!t) return; onZoneLeave(); }; document.addEventListener("pointerenter", handleEnter, true); document.addEventListener("mouseenter", handleEnter, true); document.addEventListener("pointerleave", handleLeave, true); document.addEventListener("mouseleave", handleLeave, true); // ---------------- Keyboard ---------------- document.addEventListener("focusin", (e) => { if (!e.target) return; const t = e.target.closest(".tt-trigger"); if (t) openFromTrigger(t); }); document.addEventListener("focusout", (e) => { if (!e.target) return; const t = e.target.closest(".tt-trigger"); if (t && current === t) closeWithAnim(); }); // ---------------- Mobile / coarse ---------------- document.addEventListener("pointerdown", (e) => { if (!isCoarse()) return; const t = e.target.closest(".tt-trigger"); if (!t) return; e.preventDefault(); e.stopPropagation(); if (current === t && bubble.classList.contains("is-open")) { closeWithAnim(); return; } openFromTrigger(t); }, true); document.addEventListener("click", (e) => { if (!isCoarse()) return; if (!bubble.classList.contains("is-open")) return; const inBubble = !!e.target.closest(".tt-bubble"); const onTrigger = !!e.target.closest(".tt-trigger"); if (!inBubble && !onTrigger) closeWithAnim(); }, true); // Close button + ESC elClose.addEventListener("click", closeWithAnim); document.addEventListener("keydown", (e) => { if (e.key === "Escape") closeWithAnim(); }); // Reposition on resize/scroll while open const reposition = () => { if (!current) return; placeAnchored(current); }; addEventListener("resize", reposition, { passive: true }); addEventListener("scroll", reposition, { passive: true }); });
Claude Design stays on brand for daily work
Next

New design system import, editor and Claude Code sync, higher shared limits, more connected apps.

See what's new

Claude Design

Your idea, designed with Claude

Explore more directions than a deadline allows. Describe a prototype, deck, or one-pager, and Claude builds a draft. Refine it yourself, or hand it off to your tools or Claude Code. You're the designer, from start to finish.

Start designing
Play video

Frontier intelligence for every type of design work

Prototypes

Turn a static mockup into a shareable, interactive prototype you can test with real people. No PRs, no code review.

Wireframes and mockups

Sketch a feature flow, then hand it to Claude Code to build or to a designer to refine.

Design explorations

Generate a dozen directions in minutes, then narrow down in your primary tool.

Pitch decks

Go from a rough outline to a finished, on-brand deck. Export to PPTX or send it where you work.

Marketing collateral

Landing pages, social assets, and campaign visuals, ready for a designer to polish.

Documents

Create a resume or a one-pager and export to PDF.

How it works

Idea to visual in minutes

Tell Claude what you need. It builds a first version you can react to, and you refine until it's yours.

Build in your design system.

Import from GitHub, design files, or your local codebase so Claude can build with your real components. The output looks like your company, not a template.

Move between Claude Design and Claude Code

Pull in your design system from Claude Code using /design-sync or work directly in Claude Code with /design.

Fine-grained control

Comment on any element, edit text directly, or use the adjustment sliders Claude creates to tune spacing and color. Use rich layout controls for quick visual and aesthetic shifts, including to drag, resize, and align elements directly.

From the canvas to the tools you use

Export reliably to PDF and PowerPoint or send your work to the apps you already use—the list of connectors now includes Adobe, Canva and more.

Prev
Next

"Adobe’s mission is to empower everyone to create — wherever they choose to work. We're excited to build on our Anthropic collaboration, making it possible for anyone to start their concepts in Claude and use the Adobe for creativity connector to take social posts, presentations, flyers and more from draft to done in Adobe Express. Marketers can also turn an idea from Claude Design into a personalized, on-brand website or email campaign ready to deliver to customers in just a few clicks with Adobe Experience Manager and Adobe Journey Optimizer."

Govind Balakrishnan, Senior Vice President, Express Product Group, Creativity & Productivity

"At Lovable, we believe the people closest to a problem should have the power to solve it themselves. Through our partnership with Claude Design, we're excited to see even more people sketching out solutions for the world around them. Now they can seamlessly bring those ideas to life inside Lovable as production-ready applications."

Fabian Hedin, Co-founder

“Replit and Anthropic share a belief that anyone, anywhere should be able to bring their ideas to life with AI. Our mutual goal is to meet builders wherever ideas begin. The Claude Design MCP integration is a natural next step: builders can now design on-brand apps in Claude Design and build, refine, and ship them in Replit, all in one seamless experience.”

Michele Catasta, President & Head of AI

"Miro is where teams come together to turn ideas into impactful decisions, on a shared canvas built for collaboration. Connecting with Claude Design means a concept can land on that canvas early, ready for the whole team to refine and build on together. It's been great working with Anthropic to make that first step from idea to alignment feel effortless."

Jeff Chow, Chief Product and Technology Officer

“Wix has always been a home for designers - we're now excited to be taking that one step further with Anthropic. Claude Design connects seamlessly to Wix Headless, giving designers a straight path to Wix's backend infrastructure without leaving their creative process. The design community can now take their UX vision from first sketch to a fully functional, scalable product - exactly the way they imagined it.”

Hagit Kauffman, VP of Brand and Design

“At Vercel, we're focused on shortening the path from idea to production. That's why we like Claude Design. Designers and developers can take a first concept all the way to a polished, on-brand interface, then push it straight to Vercel to ship.”

Andrew Qu, Chief of Software

“Generating a deck is the easy part now; making it yours has always been the hard part. Connecting Claude Design to Gamma closes that gap, we built this with Anthropic so anything you design in Claude can move straight into Gamma, fully editable, the moment you want to take it further.”

Jon Noronha, Co-founder
Prev
0/5
Next

FAQ

Claude Design is an Anthropic beta product that lets users collaborate with Claude to create on-brand visual work like designs, decks, and prototypes.It's early, and we're shipping improvements often.

Claude Design is in beta on Claude Pro, Max, Team, and Enterprise plans and included with your subscription. Start designing at claude.ai/design.

It's off by default. An admin can enable it in Organization settings. See the admin guide in the Help Center.

Import from your codebase, a web capture, or DOCX, PPTX, and XLSX files. Export to PPTX, PDF, or HTML, share an org-scoped link, hand off to Claude Code, or send to the apps you already use daily. The list of connectors now includes Adobe, Base44, Canva, Gamma, Lovable, Miro, Replit, Vercel and Wix, with more destinations coming soon.

Bring in one or several design systems from a GitHub repo, design files, or raw uploads. Claude builds with your components, checks its output against your design system, and makes corrections before you see it. For larger teams, a new admin role can approve one standard system and lock down edits, so the work always matches your company guidelines.

Claude Design shares usage limits with chat, Claude Cowork, and Claude Code. See the Help Center for current details.

Prev
Next

Start your next design with Claude

Start designing