From design
Evaluate designs for usability, visual hierarchy, consistency, and adherence to design principles. Trigger with "what do you think of this design", "give me feedback on", "critique this", "review this mockup", or when the user shares a design and asks for opinions.
npx claudepluginhub hanniyausmani/xd-skills --plugin designThis skill uses the workspace's default tool permissions.
Provide structured, actionable design feedback.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
Provide structured, actionable design feedback.
When a Figma URL or node is provided, always output the critique directly onto the Figma canvas using mcp__c559ff4b-9d7d-4192-8308-d9036a7e621f__use_figma. Do NOT output the critique as text in the conversation — place it in Figma instead. Only fall back to text output if no Figma file is available.
rgb(255,255,255)) — never dark backgrounds; text becomes invisible on darklayoutMode = "VERTICAL" auto-layout on the panel or its children. Auto-layout frames collapse to height 10 in the Plugin API and are unreliablet.textAutoResize = "HEIGHT" BEFORE calling t.resize(fixedWidth, t.height). If you call resize(w, 999) first, the text node gets stuck at height 999panel.resize(PW, cy + PAD) where cy is the final Y cursor and PAD is bottom paddingfigma.viewport.scrollAndZoomIntoView([targetNode, panel]) at the end so both are visiblecy Y-cursor)bg: rgb(255,255,255) // panel background — always white
surf: rgb(246,246,251) // card/item surface
line: rgb(218,218,236) // dividers and borders
h1: rgb(12,12,30) // primary headings
h2: rgb(35,35,65) // item labels
body: rgb(70,70,105) // body text
muted: rgb(135,135,175) // subtitles, metadata
pur: rgb(100,50,230) // purple accent
grn: rgb(22,150,70) // positive / works well
amb: rgb(158,108,0) // warning / quick win
red: rgb(188,35,35) // issue
pgb: rgb(237,228,255) // purple pill background
ggb: rgb(213,250,226) // green pill background
agb: rgb(255,242,195) // amber pill background
rgb_: rgb(254,222,222) // red pill background
The order of operations matters. Set textAutoResize before resize():
function mkT(str, size, style, color, fixW) {
const t = figma.createText();
t.fontName = { family: "Inter", style };
t.fontSize = size;
t.fills = [{ type: "SOLID", color }];
t.characters = str;
if (fixW) {
t.textAutoResize = "HEIGHT"; // MUST come before resize()
t.resize(fixW, t.height); // sets width; height auto-calculates correctly
}
return t; // t.height is now the real rendered height — safe to use in layout math
}
Calculate card height from real text heights, then create the frame at that exact size. Never rely on auto-layout:
const pill = mkPill(tagLabel, tagTc, tagBg); // always 20px tall
const lbl = mkT(item.label, 13, "Semi Bold", C.h2, IW - 32);
const bod = mkT(item.body, 12, "Regular", C.body, IW - 32);
const iH = 12 + pill.height + 6 + lbl.height + 5 + bod.height + 12;
const card = figma.createFrame();
card.resize(IW, iH);
card.fills = [{ type: "SOLID", color: C.surf }];
card.cornerRadius = 8;
card.clipsContent = false;
pill.x = 16; pill.y = 12;
lbl.x = 16; lbl.y = 12 + pill.height + 6;
bod.x = 16; bod.y = 12 + pill.height + 6 + lbl.height + 5;
card.appendChild(pill); card.appendChild(lbl); card.appendChild(bod);
card.x = PAD; card.y = cy;
panel.appendChild(card);
cy += iH + 8;
// Before building — remove any old panel
figma.currentPage.children.forEach(n => {
if (n.name === "🎨 Design Critique") n.remove();
});
// After building — size panel and zoom to show both
panel.resize(PW, cy + PAD);
panel.x = targetNode.x + targetNode.width + 80;
panel.y = targetNode.y;
figma.currentPage.appendChild(panel);
figma.viewport.scrollAndZoomIntoView([targetNode, panel]);
Always load these before creating any text nodes:
await figma.loadFontAsync({ family: "Inter", style: "Bold" });
await figma.loadFontAsync({ family: "Inter", style: "Semi Bold" });
await figma.loadFontAsync({ family: "Inter", style: "Regular" });