Install
$ agentstack add skill-atezer-fmcp-figma-a11y-audit ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Figma A11y Audit — Erişilebilirlik Denetimi
> Design Token Kuralı: Bu skill'deki kod örneklerinde geçen font adları, renk kodları, piksel boyutları yalnızca FORMAT gösterimidir. Çalışma anında tüm design token değerleri (font, renk, boyut, spacing, radius, gölge) kayıtlı kütüphaneden (figma_get_variables, figma_get_styles) veya kullanıcıdan okunmalıdır. Hardcoded token değeri kullanma. Detay: project-context.md → "Design Token Kuralı".
Overview
Bu skill, Figma ekranını erişilebilirlik (a11y) standartlarına göre denetler. Platform-bazlı (iOS VoiceOver, Android TalkBack, Web ARIA) raporlar üretir. Topluluk "Uber a11y ekran okuyucu spesifikasyonları" örneğinden esinlenilmiştir.
Okuma + Yazma — Denetim sonuçlarını okur, isteğe bağlı olarak annotation frame ekler.
Prerequisites
- F-MCP Bridge plugin bağlı olmalı
- Hedef ekranın node ID'si veya URL'i bilinmeli
F-MCP skill koordinasyonu
- Önce (isteğe bağlı):
audit-figma-design-system(DS uyum denetimi) — a11y audit'ten bağımsız ama birlikte değerli - Sonra: Bulgular varsa
fix-figma-design-system-findingveyaapply-figma-design-systemile düzeltme; kod tarafındaimplement-designçıktısında a11y attribute'ları - İlişkili:
generate-figma-libraryFaz 4 (a11y denetimi) bu skill'i referans alır
WCAG 2.1/2.2 AA Hızlı Referans
Denetim sırasında bu 4 prensip ve 12 kriter referans alınmalıdır:
Algılanabilir (Perceivable)
- 1.1.1 Metin Dışı İçerik: Görseller, ikonlar ve dekoratif öğeler için alternatif metin veya
aria-hidden - 1.3.1 Bilgi ve İlişkiler: Başlık hiyerarşisi (H1→H2→H3), form etiketleri, tablo başlıkları programatik olarak belirlenmeli
- 1.4.3 Kontrast (Minimum): Normal metin ≥4.5:1, büyük metin (≥18px veya ≥14px bold) ≥3:1
- 1.4.11 Metin Dışı Kontrast: UI bileşenleri (buton kenarları, input border, ikon) ve grafik öğeleri ≥3:1 — sadece metin değil!
İşletilebilir (Operable)
- 2.1.1 Klavye: Tüm işlevsellik klavyeyle erişilebilir olmalı
- 2.4.3 Odak Sırası: Fokus sırası mantıksal ve anlamlı olmalı (görsel sırayla tutarlı)
- 2.4.7 Görünür Odak: Klavye fokus göstergesi açıkça görünür olmalı (ör. 2px solid ring, minimum 3:1 kontrast)
- 2.5.5 Dokunma Hedefi (WCAG 2.2): Tıklanabilir/dokunulabilir öğeler ≥44×44 CSS px (WCAG 2.2: ≥24×24 CSS px minimum)
Anlaşılabilir (Understandable)
- 3.1.1 Sayfa Dili: İçerik dili tanımlanmalı (lang attribute)
- 3.2.1 Fokusta Tahmin Edilebilirlik: Bir öğeye odaklanmak beklenmeyen davranış tetiklememeli (ör. otomatik form submit)
- 3.3.1 Hata Tanımlama: Hata tespit edildiğinde kullanıcıya metin olarak açıkça bildirilmeli
- 3.3.2 Etiketler veya Talimatlar: Form alanlarında açık etiket ve gerektiğinde yardım metni
Sağlam (Robust)
- 4.1.2 Ad, Rol, Değer: Tüm UI bileşenlerinin adı (label), rolü (role) ve durumu (state) programatik olarak belirlenebilir olmalı
Yaygın Sorunlar Kontrol Listesi
Denetimde sıkça karşılaşılan 8 sorun — her biri Step 4-8'de kontrol edilmelidir:
- Yetersiz renk kontrastı — metin/arka plan oranı WCAG AA'yı karşılamıyor
- Eksik form etiketleri — placeholder tek başına etiket yerine geçmez
- Klavye erişimi yok — fare olmadan ulaşılamayan etkileşimli öğeler
- Alt text eksik — bilgi taşıyan görsellerde alternatif metin yok
- Focus trap hatalı — modal/drawer'da odak tuzağı eksik veya bozuk
- ARIA landmark eksik — sayfa bölümleri (nav, main, footer) işaretlenmemiş
- Otomatik oynatılan medya — ses/video otomatik başlıyor, durdurma kontrolü yok
- Zaman limitleri — oturum zaman aşımı uzatma seçeneği sunulmuyor
Test Yaklaşımı Sırası
A11y denetimi aşağıdaki sırayla yürütülmelidir:
| Aşama | Ne Yapılır | İlgili Step | |-------|-----------|-------------| | 1. Otomatik tarama | Kontrast hesaplama, dokunma hedefi boyutu, metin boyutu | Step 4, 5, 6 | | 2. Klavye-only navigasyon | Fokus sırası, görünür fokus göstergesi, focus trap | Step 7c, 7e | | 3. Ekran okuyucu testi | Başlık hiyerarşisi, form ilişkilendirme, alt text | Step 7a, 7b, 7d | | 4. Kontrast doğrulama | Gradient/overlay kaçırılanlar, UI bileşen kontrastı | Screenshot kontrolü | | 5. %200 zoom testi | İçerik kaybı, yatay kaydırma oluşmamalı | Responsive kontrol |
Required Workflow
Step 1: Plugin Bağlantısını Doğrula
figma_get_status()
Step 2: Hedef Ekranı Belirle
Figma URL veya node ID. node-id=72-293 → 72:293 normalize et.
Step 3: Yapı ve Görsel Veri Topla
figma_get_design_context(
nodeId="",
depth=2,
verbosity="full",
includeLayout=true,
includeVisual=true,
includeTypography=true
)
figma_capture_screenshot(nodeId="")
figma_get_design_context(nodeId="", depth=3)
Step 4: Kontrast Analizi
figma_execute ile renk çiftlerini çıkar ve kontrast oranı hesapla:
function luminance(r, g, b) {
const [rs, gs, bs] = [r, g, b].map(c =>
c ");
const textNodes = root.findAll(n => n.type === "TEXT");
const results = [];
for (const node of textNodes.slice(0, 50)) {
if (!node.fills || !node.fills.length) continue;
const fill = node.fills[0];
if (fill.type !== "SOLID") continue;
let parent = node.parent;
let bgColor = null;
while (parent && !bgColor) {
if (parent.fills && parent.fills.length) {
const pFill = parent.fills[0];
if (pFill.type === "SOLID") bgColor = pFill.color;
}
parent = parent.parent;
}
if (!bgColor) bgColor = { r: 1, g: 1, b: 1 };
const ratio = contrastRatio(
luminance(fill.color.r, fill.color.g, fill.color.b),
luminance(bgColor.r, bgColor.g, bgColor.b)
);
const fontSize = node.fontSize;
const isLarge = fontSize >= 18 || (fontSize >= 14 && node.fontWeight >= 700);
const passAA = isLarge ? ratio >= 3 : ratio >= 4.5;
const passAAA = isLarge ? ratio >= 4.5 : ratio >= 7;
if (!passAA) {
results.push({
nodeId: node.id,
name: node.name,
ratio: Math.round(ratio * 100) / 100,
required: isLarge ? 3 : 4.5,
level: "FAIL_AA",
fontSize
});
}
}
return { contrastIssues: results, totalTextNodes: textNodes.length };
Step 5: Dokunma Hedefi Kontrolü (WCAG 2.5.5)
> Referans: WCAG 2.5.5 Target Size — iOS HIG: 44×44pt, Android Material: 48×48dp, Web WCAG 2.2: min 24×24 CSS px
const interactiveTypes = ["INSTANCE", "FRAME"];
const interactiveNames = /button|btn|link|input|toggle|switch|checkbox|radio|tab|chip/i;
const root = await figma.getNodeByIdAsync("");
const nodes = root.findAll(n =>
interactiveTypes.includes(n.type) && interactiveNames.test(n.name)
);
const issues = [];
for (const node of nodes) {
const w = node.width;
const h = node.height;
if (w ");
const textNodes = root.findAll(n => n.type === "TEXT");
const smallText = textNodes.filter(n => {
const size = typeof n.fontSize === "number" ? n.fontSize : 0;
return size > 0 && size ({
nodeId: n.id,
name: n.name,
fontSize: n.fontSize,
recommendation: "Minimum 12px (body 14-16px önerilir)"
}));
return { smallTextIssues: smallText };
Step 7: Erişilebilirlik Notları (Annotation) Üretimi
Referans: Indeed Figma Accessibility Annotation Kit yaklaşımı. Denetim sonuçlarına göre, Figma tasarımına geliştirici notları eklenir. Bu notlar tasarım dosyasında kalır ve geliştirici handoff'unda kritik bilgi sağlar.
figma_execute ile ekranın yanına annotation frame'i oluştur.
> Font kuralı: Annotation metinlerinde de DS fontunu kullan. Kayıtlı kütüphane varsa (.claude/libraries/) text style'lardan font ailesini oku. Bulunamazsa kullanıcıya sor. Kullanıcı "sen seç" derse Inter kullan. Aşağıdaki örnekte FONT_FAMILY kütüphaneden okunan font adıdır.
// FONT_FAMILY'yi kütüphaneden veya kullanıcıdan belirle
const FONT_FAMILY = "KütüphanedenOkunanFont";
await figma.loadFontAsync({ family: FONT_FAMILY, style: "Regular" });
await figma.loadFontAsync({ family: FONT_FAMILY, style: "Bold" });
const screen = await figma.getNodeByIdAsync("");
// Annotation frame — ekranın sağına yerleştir
const annotFrame = figma.createFrame();
annotFrame.name = "A11y Annotations";
annotFrame.layoutMode = "VERTICAL";
annotFrame.primaryAxisSizingMode = "AUTO";
annotFrame.counterAxisSizingMode = "AUTO";
annotFrame.itemSpacing = 16;
annotFrame.paddingLeft = 24;
annotFrame.paddingRight = 24;
annotFrame.paddingTop = 24;
annotFrame.paddingBottom = 24;
// Aşağıdaki renkler annotation UI'a özel değerlerdir, DS token'ı değildir — ancak DS'de karşılığı varsa oradan okunması tercih edilir
annotFrame.fills = [{ type: "SOLID", color: { r: 0.98, g: 0.95, b: 0.85 } }];
annotFrame.cornerRadius = 12;
annotFrame.x = screen.x + screen.width + 40;
annotFrame.y = screen.y;
// Helper: add annotation item
function addAnnotation(parent, emoji, title, body) {
const item = figma.createFrame();
item.name = "Annotation: " + title;
item.layoutMode = "VERTICAL";
item.primaryAxisSizingMode = "AUTO";
item.itemSpacing = 4;
item.fills = [];
parent.appendChild(item);
item.layoutSizingHorizontal = "FILL";
const heading = figma.createText();
heading.characters = emoji + " " + title;
heading.fontSize = 14;
heading.fontName = { family: FONT_FAMILY, style: "Bold" };
// Annotation metin renkleri — DS'de karşılığı varsa oradan okunması tercih edilir
heading.fills = [{ type: "SOLID", color: { r: 0.1, g: 0.1, b: 0.1 } }];
item.appendChild(heading);
const desc = figma.createText();
desc.characters = body;
desc.fontSize = 12;
desc.fontName = { family: FONT_FAMILY, style: "Regular" };
// Annotation açıklama rengi — DS'de karşılığı varsa oradan okunması tercih edilir
desc.fills = [{ type: "SOLID", color: { r: 0.3, g: 0.3, b: 0.3 } }];
item.appendChild(desc);
desc.layoutSizingHorizontal = "FILL";
}
return { annotFrameId: annotFrame.id };
7a. Gesture Erişilebilirlik Kontrolleri
Mobil ve dokunmatik arayüzlerde gesture-bazlı etkileşimler klavye/switch kullanıcıları için erişilebilir alternatifler gerektir:
| Gesture | Gerekli Alternatif | Platform Notu | |---------|-------------------|---------------| | Swipe (kaydırma) | Buton / ok kontrolü | iOS VoiceOver: swipe gesture'lar yeniden atanır | | Long-press (uzun basma) | Context menu butonu | Android: onLongClick + contentDescription | | Pinch (çimdikleme) | +/- zoom butonları | Web: wheel event alternatifi | | Pull-to-refresh | Yenile butonu | Ekran okuyucu ile pull gesture kullanılamaz | | Drag & drop | Taşı butonu / sıralama menüsü | Klavye ile sürükle-bırak erişilemez |
Annotation: Gesture kullanan öğeleri tespit et ve alternatif kontrolün mevcut olup olmadığını raporla:
addAnnotation(annotFrame, "👆", "Gesture Kontrolü",
"Swipe left → Sil butonu mevcut mi? Long-press → Context menu alternatifi var mı?");
7b. Başlık Hiyerarşisi Notları
Ekrandaki metin elemanlarını analiz et ve başlık seviyelerini belirle. Geliştirici hangi metnin `, , ` olduğunu bilmeli:
Başlık Hiyerarşisi:
H1: "Hoş Geldiniz" (24px, Semi Bold) — Sayfa ana başlığı
H2: "Hesabınıza giriş yapın" (16px, Regular) — Alt başlık / açıklama
Body: Input placeholder, link, buton metinleri (14px)
Kural: Ekranda yalnızca 1 adet H1 olmalı. Başlık seviyeleri atlanmamalı (H1 → H3 yanlış, H1 → H2 → H3 doğru).
7c. Form Alan-Etiket İlişkilendirme Notları
Form alanları ile etiketlerinin programatik olarak ilişkilendirilmesi gerekir. Aksi takdirde ekran okuyucu kullanıcıları alanın ne için olduğunu anlayamaz:
Form İlişkilendirme:
Input "E-posta adresi":
- label: "E-posta adresi" (for/id ilişkisi)
- type: email
- autocomplete: email
- required: true
- error: "Geçerli bir e-posta girin" (aria-describedby)
Input "Şifre":
- label: "Şifre" (for/id ilişkisi)
- type: password
- autocomplete: current-password
- required: true
- toggle: "Şifreyi göster/gizle" butonu (aria-label)
Kural: Her form alanının bir `` ile ilişkilendirilmesi zorunludur. Placeholder tek başına etiket yerine geçmez.
7d. Odak Sırası (Focus Order) Notları
Ekrandaki etkileşimli öğelerin odak sırası görsel sıradan farklı olabilir. Bu notlar geliştiriciye doğru tabindex sırasını bildirir:
Odak Sırası:
1. "Hoş Geldiniz" (başlık — ekran okuyucu ilk buraya odaklanır)
2. "E-posta adresi" input
3. "Şifre" input
4. "Giriş Yap" butonu
5. "Şifremi unuttum" link
6. "Google ile Giriş Yap" butonu
7. "Kayıt Ol" link
Kural: Mantıksal akış yukarıdan aşağıya olmalı. Görsel olarak yan yana olan elemanlar (ör. iş ilanı + favori ikonu) için sıra açıkça belirtilmeli.
7d.1. Prototip Odak Sırası Çapraz Kontrolü (v1.9.9+)
Ekranda prototip bağlantıları varsa, figma_get_prototype_connections ile tüm ON_CLICK reaction source'larını listele ve 7d'deki focus sırası ile karşılaştır:
const proto = await figma_get_prototype_connections({ nodeId: });
const clickableSources = proto.connections
.filter(c => c.reactions.some(r => r.trigger?.type === "ON_CLICK"))
.map(c => ({ id: c.nodeId, name: c.name }));
Kontrol kuralı:
- 7d'deki focus sırası listesi (ör.
[email, password, loginBtn, forgotLink, signupLink]) clickableSourceslistesi (ör.[loginBtn, signupLink, forgotLink])
Prototype'ta clickable olan ama a11y focus sırasında yer almayan veya sıralaması farklı olan elementler varsa UYARI ver:
⚠️ A11y focus sırası ile prototip etkileşim sırası uyuşmuyor.
- Focus sırasında: forgotLink #4, signupLink #5
- Prototype'ta tıklanabilir: signupLink (#5 ama prototipte önce geliyor)
- Öneri: tabindex gözden geçir veya DOM sırasını değiştir.
Bu kontrol klavye-only kullanıcılar için kritik: prototype'ta "Giriş Yap" → "Kayıt Ol" beklenirken tabindex bunu sağlamıyorsa erişilebilirlik bozulur.
7e. Görsel Alternatif Metin Notları
Her görsel için alt text veya dekoratif işaretleme:
Görsel Notları:
Logo (Ellipse): alt="MyApp logosu" (bilgi taşıyan görsel)
Divider çizgileri: role="presentation" (dekoratif — ekran okuyucudan gizle)
Kural: İçerik taşıyan görseller alt text almalı. Sadece estetik amaçlı görseller role="presentation" veya aria-hidden="true" ile gizlenmeli.
7f. Modal/Dialog ve Dinamik İçerik Notları
Eğer ekranda modal, toast, alert gibi dinamik öğeler varsa:
Dinamik İçerik Notları:
- Modal açıldığında: odak modal'a taşınmalı (focus trap)
- Modal kapandığında: odak tetikleyen elemana dönmeli
- Toast/alert: role="alert" veya aria-live="polite"
- Loading: aria-busy="true", tamamlanınca aria-busy="false"
Kural: Dinamik içerik değişiklikleri aria-live region ile duyurulmalı. Modal'larda fokus tuzağı (focus trap) zorunludur.
Step 8: Erişebilirlik-Tasarım Tutarlılık Kontrolü
Annotation'lar üretildikten sonra, gerçek tasarımın erişebilirlik kurallarıyla tutarlı olduğunu doğrula. figma_execute ile otomatik kontrol:
const screen = await figma.getNodeByIdAsync("");
const checks = [];
// 1. Başlık hiyerarşisi — max 1 adet H1 (>= 24px)
const allText = screen.findAll(n => n.type === "TEXT");
const h1Count = allText.filter(n => n.fontSize >= 24).length;
checks.push({ rule: "Single H1", pass: h1Count typeof n.fontSize === "number" && n.fontSize n.fontSize >= 12 && n.fontSize
n.type === "INSTANCE" || (n.type === "FRAME" && /input|button|btn/i.test(n.name))
);
const smallTargets = interactive.filter(n => n.width n.type === "FRAME" && /input/i.test(n.name));
const smallInputs = inputs.filter(n => n.height 0 && node.fills[0].type === "SOLID") {
if (!node.boundVariables?.fills) hardCoded++;
}
if (node.children && node.type !== "INSTANCE") node.children.forEach(c => chk(c));
}
chk(screen);
checks.push({ rule: "Colors token-bound", pass: hardCoded === 0 });
// 7. Auto-layout (responsive) — tüm content frame'ler
const noLayout = screen.findAll(n => n.type === "FRAME" && n.name !== "_spacer" && (!n.layoutMode || n.layoutMode === "NONE"));
checks.push({ rule: "Auto-layout", pass: noLayout.length =
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [atezer](https://github.com/atezer)
- **Source:** [atezer/FMCP](https://github.com/atezer/FMCP)
- **License:** MIT
- **Homepage:** https://www.npmjs.com/package/@atezer/figma-mcp-bridge
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.