diff --git a/.github/workflows/build-index.yml b/.github/workflows/build-index.yml index 4dc5116e..40a707dd 100644 --- a/.github/workflows/build-index.yml +++ b/.github/workflows/build-index.yml @@ -33,117 +33,113 @@ jobs: process.exit(0); } - const categoryDirs = fs.readdirSync(skillsDir, { withFileTypes: true }) - .filter(d => d.isDirectory()); - - for (const categoryDir of categoryDirs) { - const categoryPath = path.join(skillsDir, categoryDir.name); - const skillDirs = fs.readdirSync(categoryPath, { withFileTypes: true }) - .filter(d => d.isDirectory()); - - for (const skillDir of skillDirs) { - const skillFile = path.join(categoryPath, skillDir.name, 'SKILL.md'); - if (!fs.existsSync(skillFile)) continue; - - const content = fs.readFileSync(skillFile, 'utf8'); - const fmMatch = content.match(/^---\s*([\s\S]*?)\s*---\s*/); - if (!fmMatch) continue; - - const fm = {}; - let currentKey = null; - for (const line of fmMatch[1].split(/\r?\n/)) { - if (!line.trim()) continue; - const arrMatch = line.match(/^\s*-\s+(.*)$/); - if (arrMatch && currentKey) { - if (!Array.isArray(fm[currentKey])) fm[currentKey] = []; - fm[currentKey].push(arrMatch[1].trim()); - continue; - } - const kvMatch = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/); - if (!kvMatch) continue; - const key = kvMatch[1]; - const val = kvMatch[2]; - if (val === '') { - fm[key] = []; - currentKey = key; - } else { - const trimmed = val.trim(); - const isInlineArray = - (key === 'requires' || key === 'examples') && - trimmed.startsWith('[') && - trimmed.endsWith(']'); - - if (isInlineArray) { - let arr = null; - try { - const parsed = JSON.parse(trimmed); - if (Array.isArray(parsed)) { - arr = parsed.map((x) => String(x)); - } - } catch (_) {} - - if (!arr) { - const inner = trimmed.slice(1, -1).trim(); - if (!inner) { - arr = []; - } else { - const parts = []; - let buf = ''; - let quote = null; - for (let i = 0; i < inner.length; i++) { - const ch = inner[i]; - if (quote) { - if (ch === quote && inner[i - 1] !== '\\') { - quote = null; - } - buf += ch; - continue; - } - - if (ch === '"' || ch === "'") { - quote = ch; - buf += ch; - continue; - } - - if (ch === ',') { - parts.push(buf.trim()); - buf = ''; - continue; + const skillDirs = fs.readdirSync(skillsDir, { withFileTypes: true }) + .filter(d => d.isDirectory()) + .sort((a, b) => a.name.localeCompare(b.name)); + + for (const skillDir of skillDirs) { + const skillFile = path.join(skillsDir, skillDir.name, 'SKILL.md'); + if (!fs.existsSync(skillFile)) continue; + + const content = fs.readFileSync(skillFile, 'utf8'); + const fmMatch = content.match(/^---\s*([\s\S]*?)\s*---\s*/); + if (!fmMatch) continue; + + const fm = {}; + let currentKey = null; + for (const line of fmMatch[1].split(/\r?\n/)) { + if (!line.trim()) continue; + const arrMatch = line.match(/^\s*-\s+(.*)$/); + if (arrMatch && currentKey) { + if (!Array.isArray(fm[currentKey])) fm[currentKey] = []; + fm[currentKey].push(arrMatch[1].trim()); + continue; + } + const kvMatch = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/); + if (!kvMatch) continue; + const key = kvMatch[1]; + const val = kvMatch[2]; + if (val === '') { + fm[key] = []; + currentKey = key; + } else { + const trimmed = val.trim(); + const isInlineArray = + (key === 'requires' || key === 'examples') && + trimmed.startsWith('[') && + trimmed.endsWith(']'); + + if (isInlineArray) { + let arr = null; + try { + const parsed = JSON.parse(trimmed); + if (Array.isArray(parsed)) { + arr = parsed.map((x) => String(x)); + } + } catch (_) {} + + if (!arr) { + const inner = trimmed.slice(1, -1).trim(); + if (!inner) { + arr = []; + } else { + const parts = []; + let buf = ''; + let quote = null; + for (let i = 0; i < inner.length; i++) { + const ch = inner[i]; + if (quote) { + if (ch === quote && inner[i - 1] !== '\\') { + quote = null; } + buf += ch; + continue; + } + if (ch === '"' || ch === "'") { + quote = ch; buf += ch; + continue; + } + + if (ch === ',') { + parts.push(buf.trim()); + buf = ''; + continue; } - if (buf.trim()) parts.push(buf.trim()); - arr = parts - .map((s) => s.replace(/^['\"]|['\"]$/g, '').trim()) - .filter(Boolean); + buf += ch; } + if (buf.trim()) parts.push(buf.trim()); + + arr = parts + .map((s) => s.replace(/^['\"]|['\"]$/g, '').trim()) + .filter(Boolean); } + } - fm[key] = arr; + fm[key] = arr; + } else { + let scalar = trimmed; + if (trimmed.startsWith('"') && trimmed.endsWith('"')) { + try { + scalar = JSON.parse(trimmed); + } catch (_) { + scalar = trimmed.replace(/^['\"]|['\"]$/g, ''); + } } else { - fm[key] = val.replace(/^['\"]|['\"]$/g, ''); + scalar = trimmed.replace(/^['\"]|['\"]$/g, ''); } - currentKey = null; + fm[key] = scalar; } + currentKey = null; } - - const body = content.slice(fmMatch[0].length).trim(); - - skills.push({ - skillId: fm.id || skillDir.name, - name: fm.name || skillDir.name, - description: fm.description || '', - instructions: body, - author: fm.author || 'community', - version: fm.version || '1.0.0', - category: fm.category || 'other', - requires: Array.isArray(fm.requires) ? fm.requires : [], - examples: Array.isArray(fm.examples) ? fm.examples : [], - }); } + + skills.push({ + name: fm.name || skillDir.name, + description: fm.description || '', + }); } skills.sort((a, b) => a.name.localeCompare(b.name)); diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8f15e15..b3a428c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,14 +15,18 @@ A skill is a set of natural language instructions that guide an AI agent's behav ## Skill File Format -Each skill lives in its own directory: `skills/{skill-id}/SKILL.md` +Each skill lives in its own directory directly under `skills/`, with a `SKILL.md` entrypoint. Support folders such as `scripts/`, `references/`, and `assets/` belong to that skill and are not indexed separately: + +- `skills/{skill-id}/SKILL.md` +- `skills/{skill-id}/references/{supporting-file}` +- `skills/{skill-id}/scripts/{supporting-script}` ```markdown --- id: your-skill-id name: Your Skill Name description: A concise description of what this skill does (shown to the LLM). -category: productivity +category: Development author: your-github-username version: 1.0.0 requires: [] @@ -41,10 +45,10 @@ Include any specific formatting, steps, or constraints. | Field | Type | Description | |-------|------|-------------| -| `id` | string | Unique identifier (lowercase, hyphens). Must match the directory name. | +| `id` | string | Unique identifier (lowercase, hyphens). Must match the skill directory name. | | `name` | string | Human-readable display name | | `description` | string | What the skill does (max 200 chars). This is shown to the LLM as the tool description. | -| `category` | string | One of: `productivity`, `development`, `communication`, `writing`, `research`, `other` | +| `category` | string | One of the supported Skills Store categories listed below. | ### Optional Frontmatter Fields @@ -57,12 +61,18 @@ Include any specific formatting, steps, or constraints. ### Categories -- **productivity** -- Task management, planning, organization -- **development** -- Coding, debugging, code review, DevOps -- **communication** -- Email drafting, messaging, social media -- **writing** -- Content creation, editing, summarization -- **research** -- Data analysis, fact-checking, literature review -- **other** -- Everything else +- **Lifestyle** +- **Blockchain** +- **Databases** +- **Research** +- **Content & Media** +- **Documentation** +- **Testing & Security** +- **DevOps** +- **Data & AI** +- **Business** +- **Development** +- **Tools** ## Guidelines diff --git a/README.md b/README.md index 9ca6e06d..271d8203 100644 --- a/README.md +++ b/README.md @@ -38,31 +38,33 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed instructions on how to creat skills/ prep-meeting/ SKILL.md - contract-review/ - SKILL.md - draft-reply/ + scripts/ + references/ + react-performance/ SKILL.md + assets/ ... index.json # Auto-generated manifest (do not edit manually) ``` +Each skill directory lives directly under `skills/`. Support folders such as `scripts/`, `references/`, and `assets/` belong to that skill and are not indexed separately. + ## Categories Each skill declares a `category` in its frontmatter. Categories help users browse the Skills Store and should reflect the user-facing purpose of the skill. Common categories you’ll see: -- Productivity -- Communication -- Business - Lifestyle -- Content & Media -- Development -- Data & AI +- Blockchain +- Databases - Research +- Content & Media - Documentation -- Design -- DevOps - Testing & Security +- DevOps +- Data & AI +- Business +- Development - Tools Use the most specific, user-friendly category that matches the skill’s primary intent. If a skill spans multiple domains, pick the category users would most likely search. diff --git a/index.json b/index.json index c30f56b6..26b5dbac 100644 --- a/index.json +++ b/index.json @@ -1,15830 +1,710 @@ [ { - "skillId": "dotnet-backend-patterns", - "name": ".NET Backend Patterns", - "description": "Step-by-step guidance for .net backend patterns.", - "instructions": "# .NET Backend Patterns\n\nSupport .net backend patterns workflows with clear steps and best practices.\n\n## When to Use\n\n- You need help with .net backend patterns.\n- You want a clear, actionable next step.\n\n## Output\n\n- Brief plan or checklist\n- Key recommendations and caveats", - "author": "community", - "version": "1.0.0", - "category": "Development", - "requires": [], - "examples": [] - }, - { - "skillId": "ab-test-setup", "name": "A/B Test Setup", - "description": "When the user wants to set up, improve, or audit analytics tracking and measurement. Also.", - "instructions": "# Analytics Tracking\n\nYou are an expert in analytics implementation and measurement. Your goal is to help set up tracking that provides actionable insights for marketing and product decisions.\n\n## Initial Assessment\n\nBefore implementing tracking, understand:\n\n1. **Business Context**\n - What decisions will this data inform?\n - What are the key conversion actions?\n - What questions need answering?\n\n2. **Current State**\n - What tracking exists?\n - What tools are in use (GA4, Mixpanel, Amplitude, etc.)?\n - What's working/not working?\n\n3. **Technical Context**\n - What's the tech stack?\n - Who will implement and maintain?\n - Any privacy/compliance requirements?\n\n---\n\n## Core Principles\n\n### 1. Track for Decisions, Not Data\n- Every event should inform a decision\n- Avoid vanity metrics\n- Quality > quantity of events\n\n### 2. Start with the Questions\n- What do you need to know?\n- What actions will you take based on this data?\n- Work backwards to what you need to track\n\n### 3. Name Things Consistently\n- Naming conventions matter\n- Establish patterns before implementing\n- Document everything\n\n### 4. Maintain Data Quality\n- Validate implementation\n- Monitor for issues\n- Clean data > more data\n\n---\n\n## Tracking Plan Framework\n\n### Structure\n\n```\nEvent Name | Event Category | Properties | Trigger | Notes\n---------- | ------------- | ---------- | ------- | -----\n```\n\n### Event Types\n\n**Pageviews**\n- Automatic in most tools\n- Enhanced with page metadata\n\n**User Actions**\n- Button clicks\n- Form submissions\n- Feature usage\n- Content interactions\n\n**System Events**\n- Signup completed\n- Purchase completed\n- Subscription changed\n- Errors occurred\n\n**Custom Conversions**\n- Goal completions\n- Funnel stages\n- Business-specific milestones\n\n---\n\n## Event Naming Conventions\n\n### Format Options\n\n**Object-Action (Recommended)**\n```\nsignup_completed\nbutton_clicked\nform_submitted\narticle_read\n```\n\n**Action-Object**\n```\nclick_button\nsubmit_form\ncomplete_signup\n```\n\n**Category_Object_Action**\n```\ncheckout_payment_completed\nblog_article_viewed\nonboarding_step_completed\n```\n\n### Best Practices\n\n- Lowercase with underscores\n- Be specific: `cta_hero_clicked` vs. `button_clicked`\n- Include context in properties, not event name\n- Avoid spaces and special characters\n- Document decisions\n\n---\n\n## Essential Events to Track\n\n### Marketing Site\n\n**Navigation**\n- page_view (enhanced)\n- outbound_link_clicked\n- scroll_depth (25%, 50%, 75%, 100%)\n\n**Engagement**\n- cta_clicked (button_text, location)\n- video_played (video_id, duration)\n- form_started\n- form_submitted (form_type)\n- resource_downloaded (resource_name)\n\n**Conversion**\n- signup_started\n- signup_completed\n- demo_requested\n- contact_submitted\n\n### Product/App\n\n**Onboarding**\n- signup_completed\n- onboarding_step_completed (step_number, step_name)\n- onboarding_completed\n- first_key_action_completed\n\n**Core Usage**\n- feature_used (feature_name)\n- action_completed (action_type)\n- session_started\n- session_ended\n\n**Monetization**\n- trial_started\n- pricing_viewed\n- checkout_started\n- purchase_completed (plan, value)\n- subscription_cancelled\n\n### E-commerce\n\n**Browsing**\n- product_viewed (product_id, category, price)\n- product_list_viewed (list_name, products)\n- product_searched (query, results_count)\n\n**Cart**\n- product_added_to_cart\n- product_removed_from_cart\n- cart_viewed\n\n**Checkout**\n- checkout_started\n- checkout_step_completed (step)\n- payment_info_entered\n- purchase_completed (order_id, value, products)\n\n---\n\n## Event Properties (Parameters)\n\n### Standard Properties to Consider\n\n**Page/Screen**\n- page_title\n- page_location (URL)\n- page_referrer\n- content_group\n\n**User**\n- user_id (if logged in)\n- user_type (free, paid, admin)\n- account_id (B2B)\n- plan_type\n\n**Campaign**\n- source\n- medium\n- campaign\n- content\n- term\n\n**Product** (e-commerce)\n- product_id\n- product_name\n- category\n- price\n- quantity\n- currency\n\n**Timing**\n- timestamp\n- session_duration\n- time_on_page\n\n### Best Practices\n\n- Use consistent property names\n- Include relevant context\n- Don't duplicate GA4 automatic properties\n- Avoid PII in properties\n- Document expected values\n\n---\n\n## GA4 Implementation\n\n### Configuration\n\n**Data Streams**\n- One stream per platform (web, iOS, Android)\n- Enable enhanced measurement\n\n**Enhanced Measurement Events**\n- page_view (automatic)\n- scroll (90% depth)\n- outbound_click\n- site_search\n- video_engagement\n- file_download\n\n**Recommended Events**\n- Use Google's predefined events when possible\n- Correct naming for enhanced reporting\n- See: https://support.google.com/analytics/answer/9267735\n\n### Custom Events (GA4)\n\n```javascript\n// gtag.js\ngtag('event', 'signup_completed', {\n 'method': 'email',\n 'plan': 'free'\n});\n\n// Google Tag Manager (dataLayer)\ndataLayer.push({\n 'event': 'signup_completed',\n 'method': 'email',\n 'plan': 'free'\n});\n```\n\n### Conversions Setup\n\n1. Collect event in GA4\n2. Mark as conversion in Admin > Events\n3. Set conversion counting (once per session or every time)\n4. Import to Google Ads if needed\n\n### Custom Dimensions and Metrics\n\n**When to use:**\n- Properties you want to segment by\n- Metrics you want to aggregate\n- Beyond standard parameters\n\n**Setup:**\n1. Create in Admin > Custom definitions\n2. Scope: Event, User, or Item\n3. Parameter name must match\n\n---\n\n## Google Tag Manager Implementation\n\n### Container Structure\n\n**Tags**\n- GA4 Configuration (base)\n- GA4 Event tags (one per event or grouped)\n- Conversion pixels (Facebook, LinkedIn, etc.)\n\n**Triggers**\n- Page View (DOM Ready, Window Loaded)\n- Click - All Elements / Just Links\n- Form Submission\n- Custom Events\n\n**Variables**\n- Built-in: Click Text, Click URL, Page Path, etc.\n- Data Layer variables\n- JavaScript variables\n- Lookup tables\n\n### Best Practices\n\n- Use folders to organize\n- Consistent naming (Tag_Type_Description)\n- Version notes on every publish\n- Preview mode for testing\n- Workspaces for team collaboration\n\n### Data Layer Pattern\n\n```javascript\n// Push custom event\ndataLayer.push({\n 'event': 'form_submitted',\n 'form_name': 'contact',\n 'form_location': 'footer'\n});\n\n// Set user properties\ndataLayer.push({\n 'user_id': '12345',\n 'user_type': 'premium'\n});\n\n// E-commerce event\ndataLayer.push({\n 'event': 'purchase',\n 'ecommerce': {\n 'transaction_id': 'T12345',\n 'value': 99.99,\n 'currency': 'USD',\n 'items': [{\n 'item_id': 'SKU123',\n 'item_name': 'Product Name',\n 'price': 99.99\n }]\n }\n});\n```\n\n---\n\n## UTM Parameter Strategy\n\n### Standard Parameters\n\n| Parameter | Purpose | Example |\n|-----------|---------|---------|\n| utm_source | Where traffic comes from | google, facebook, newsletter |\n| utm_medium | Marketing medium | cpc, email, social, referral |\n| utm_campaign | Campaign name | spring_sale, product_launch |\n| utm_content | Differentiate versions | hero_cta, sidebar_link |\n| utm_term | Paid search keywords | running+shoes |\n\n### Naming Conventions\n\n**Lowercase everything**\n- google, not Google\n- email, not Email\n\n**Use underscores or hyphens consistently**\n- product_launch or product-launch\n- Pick one, stick with it\n\n**Be specific but concise**\n- blog_footer_cta, not cta1\n- 2024_q1_promo, not promo\n\n### UTM Documentation\n\nTrack all UTMs in a spreadsheet or tool:\n\n| Campaign | Source | Medium | Content | Full URL | Owner | Date |\n|----------|--------|--------|---------|----------|-------|------|\n| ... | ... | ... | ... | ... | ... | ... |\n\n### UTM Builder\n\nProvide a consistent UTM builder link to team:\n- Google's URL builder\n- Internal tool\n- Spreadsheet formula\n\n---\n\n## Debugging and Validation\n\n### Testing Tools\n\n**GA4 DebugView**\n- Real-time event monitoring\n- Enable with ?debug_mode=true\n- Or via Chrome extension\n\n**GTM Preview Mode**\n- Test triggers and tags\n- See data layer state\n- Validate before publish\n\n**Browser Extensions**\n- GA Debugger\n- Tag Assistant\n- dataLayer Inspector\n\n### Validation Checklist\n\n- [ ] Events firing on correct triggers\n- [ ] Property values populating correctly\n- [ ] No duplicate events\n- [ ] Works across browsers\n- [ ] Works on mobile\n- [ ] Conversions recorded correctly\n- [ ] User ID passing when logged in\n- [ ] No PII leaking\n\n### Common Issues\n\n**Events not firing**\n- Trigger misconfigured\n- Tag paused\n- GTM not loaded on page\n\n**Wrong values**\n- Variable not configured\n- Data layer not pushing correctly\n- Timing issues (fire before data ready)\n\n**Duplicate events**\n- Multiple GTM containers\n- Multiple tag instances\n- Trigger firing multiple times\n\n---\n\n## Privacy and Compliance\n\n### Considerations\n\n- Cookie consent required in EU/UK/CA\n- No PII in analytics properties\n- Data retention settings\n- User deletion capabilities\n- Cross-device tracking consent\n\n### Implementation\n\n**Consent Mode (GA4)**\n- Wait for consent before tracking\n- Use consent mode for partial tracking\n- Integrate with consent management platform\n\n**Data Minimization**\n- Only collect what you need\n- IP anonymization\n- No PII in custom dimensions\n\n---\n\n## Output Format\n\n### Tracking Plan Document\n\n```\n# [Site/Product] Tracking Plan\n\n## Overview\n- Tools: GA4, GTM\n- Last updated: [Date]\n- Owner: [Name]\n\n## Events\n\n### Marketing Events\n\n| Event Name | Description | Properties | Trigger |\n|------------|-------------|------------|---------|\n| signup_started | User initiates signup | source, page | Click signup CTA |\n| signup_completed | User completes signup | method, plan | Signup success page |\n\n### Product Events\n[Similar table]\n\n## Custom Dimensions\n\n| Name | Scope | Parameter | Description |\n|------|-------|-----------|-------------|\n| user_type | User | user_type | Free, trial, paid |\n\n## Conversions\n\n| Conversion | Event | Counting | Google Ads |\n|------------|-------|----------|------------|\n| Signup | signup_completed | Once per session | Yes |\n\n## UTM Convention\n\n[Guidelines]\n```\n\n### Implementation Code\n\nProvide ready-to-use code snippets\n\n### Testing Checklist\n\nSpecific validation steps\n\n---\n\n## Questions to Ask\n\nIf you need more context:\n1. What tools are you using (GA4, Mixpanel, etc.)?\n2. What key actions do you want to track?\n3. What decisions will this data inform?\n4. Who implements - dev team or marketing?\n5. Are there privacy/consent requirements?\n6. What's already tracked?\n\n---\n\n## Related Skills\n\n- **ab-test-setup**: For experiment tracking\n- **seo-audit**: For organic traffic analysis\n- **page-cro**: For conversion optimization (uses this data)", - "author": "community", - "version": "1.0.0", - "category": "Research", - "requires": [], - "examples": [] - }, - { - "skillId": "academic-researcher", - "name": "Academic Researcher", - "description": "Academic research assistant for literature reviews, paper analysis, and scholarly writing.", - "instructions": "# Academic Researcher\n\nYou are an academic research assistant with expertise across disciplines for literature reviews, paper analysis, and scholarly writing.\n\n## When to Apply\n\nUse this skill when:\n- Conducting literature reviews\n- Summarizing research papers \n- Analyzing research methodologies\n- Structuring academic arguments\n- Formatting citations (APA, MLA, Chicago, etc.)\n- Identifying research gaps\n- Writing research proposals\n\n## Paper Analysis Framework\n\nWhen reviewing academic papers, address:\n\n### 1. **Research Question & Significance**\n- What is the core research question?\n- Why does this research matter?\n- What gap does it fill?\n- How does it contribute to the field?\n\n### 2. **Methodology**\n- What research design was used?\n- What is the sample/dataset?\n- What are the key variables?\n- Are methods appropriate for the question?\n- What are methodological limitations?\n\n### 3. **Key Findings**\n- What are the main results?\n- Are results statistically significant?\n- How strong is the effect size?\n- Are findings consistent with hypotheses?\n\n### 4. **Interpretation & Implications**\n- How do authors interpret results?\n- What are theoretical implications?\n- What are practical applications?\n- How does this relate to prior research?\n\n### 5. **Limitations & Future Directions**\n- What are study limitations?\n- What questions remain?\n- What should future research address?\n\n## Citation Formats\n\n### APA (7th Edition)\n```\nJournal article:\nAuthor, A. A., & Author, B. B. (Year). Title of article. Title of Periodical, volume(issue), pages. https://doi.org/xxx\n\nBook:\nAuthor, A. A. (Year). Title of book (Edition). Publisher.\n```\n\n### MLA (9th Edition)\n```\nJournal article:\nAuthor Last Name, First Name. \"Title of Article.\" Title of Journal, vol. #, no. #, Year, pages.\n\nBook:\nAuthor Last Name, First Name. Title of Book. Publisher, Year.\n```\n\n### Chicago (17th Edition - Notes)\n```\nFootnote:\n1. First Name Last Name, \"Title of Article,\" Title of Journal vol, no. # (Year): pages.\n\nBibliography:\nLast Name, First Name. \"Title of Article.\" Title of Journal vol, no. # (Year): pages.\n```\n\n## Literature Review Structure\n\n```markdown\n## Introduction\n- Define the research question or topic\n- Explain significance and scope\n- Preview organization\n\n## Theoretical Framework \n- Key theories and concepts\n- How they relate to the topic\n\n## [Theme 1]\n- Synthesize relevant studies\n- Note patterns and trends\n- Identify agreements and disagreements\n\n## [Theme 2]\n[Continue for each theme/subtopic]\n\n## Research Gaps\n- What's missing from current literature\n- Limitations of existing studies\n- Opportunities for future research\n\n## Conclusion\n- Summary of key insights\n- Implications for theory and practice\n\n## References\n[Formatted citation list]\n```\n\n## Academic Writing Standards\n\n### Language\n- Use precise, formal language\n- Avoid colloquialisms and contractions\n- Write in third person (or first person plural for own research)\n- Use discipline-specific terminology correctly\n\n### Argumentation\n- Make claims supported by evidence\n- Acknowledge counterarguments\n- Distinguish between fact and interpretation\n- Note study limitations honestly\n\n### Structure\n- Clear topic sentences\n- Logical flow between paragraphs\n- Smooth transitions\n- Parallel structure in lists\n\n## Output Format\n\nFor paper summaries:\n\n```markdown\n## Citation\n[Full formatted citation]\n\n## Research Question\n[What the study investigates]\n\n## Methodology\n- **Design**: [Experimental, survey, qualitative, etc.]\n- **Participants/Data**: [Sample description]\n- **Measures**: [Key variables and instruments]\n- **Analysis**: [Statistical or analytical methods]\n\n## Key Findings\n1. [Main finding with brief explanation]\n2. [Second finding]\n3. [Additional findings]\n\n## Significance\n[Why this research matters]\n\n## Limitations\n- [Methodological limitation]\n- [Generalizability concerns]\n- [Other caveats]\n\n## Future Directions\n[Suggested areas for future research]\n\n## Personal Notes\n[Optional: Connections to other work, questions, critiques]\n```\n\n## Example\n\n**User Request:** \"Summarize research on spaced repetition for learning\"\n\n**Response:**\n\n## Literature Summary: Spaced Repetition in Learning\n\n### Overview\nSpaced repetition is a learning technique where review sessions are distributed over increasing time intervals. Extensive research demonstrates its superiority to massed practice (cramming) for long-term retention across diverse materials and populations.\n\n### Foundational Research\n\n**Ebbinghaus (1885)** - Original discovery\n- Pioneering work on memory and forgetting curves\n- Demonstrated exponential decay of memory over time\n- Showed spacing effect in nonsense syllable learning\n- Laid foundation for modern spacing research\n\n**Cepeda et al. (2006)** - Meta-analysis\n- Analyzed 254 studies on the spacing effect\n- Found robust effects across materials, ages, and retention intervals\n- Optimal gap: approximately 10-20% of desired retention interval\n- Effect size: d = 0.42 (moderate to large)\n\n*Citation:* Cepeda, N. J., Pashler, H., Vul, E., Wixted, J. T., & Rohrer, D. (2006). Distributed practice in verbal recall tasks: A review and quantitative synthesis. *Psychological Bulletin, 132*(3), 354-380. https://doi.org/10.1037/0033-2909.132.3.354\n\n### Mechanisms\n\n**Karpicke & Roediger (2008)** - Retrieval practice\n- Compared spaced retrieval vs. repeated study\n- Spaced testing: 80% retention after 1 week\n- Repeated study: 36% retention after 1 week \n- Highlighted importance of active retrieval over passive review\n\n**Three proposed mechanisms:**\n\n1. **Encoding Variability Hypothesis** - Different contexts during spaced sessions create multiple retrieval paths\n2. **Study-Phase Retrieval** - Spacing intervals force retrieval at optimal difficulty\n3. **Consolidation** - Time between sessions allows memory consolidation processes\n\n### Practical Applications\n\n**Effective implementations:**\n- **Flashcard systems**: Anki, SuperMemo (algorithm-based scheduling)\n- **Language learning**: Duolingo, Memrise (adaptive spacing)\n- **Medical education**: Spaced questions in board exam prep\n- **Certification training**: Professional licensure programs\n\n**Optimal scheduling:**\n- Initial review: 1-2 days after learning\n- Subsequent reviews: Increasing intervals (3 days, 1 week, 2 weeks, 1 month)\n- Adjust based on retrieval difficulty\n\n### Limitations and Caveats\n\n1. **Requires planning and commitment** - Can't cram night before exam\n2. **Individual differences** - Optimal spacing varies by person, material\n3. **Type of learning** - More effective for declarative than procedural knowledge\n4. **Initial learning** - Still need effective initial encoding\n5. **Motivation** - Long-term commitment needed for maximum benefit\n\n### Research Gaps\n\n- Optimal spacing for different content types\n- Individual adaptive algorithms\n- Integration with other learning techniques\n- Long-term studies (years rather than weeks)\n- Neural mechanisms underlying spacing effect\n\n### Recommendations for Practice\n\nBased on current evidence:\n1. Start reviewing within 24-48 hours of initial learning\n2. Use active retrieval (testing) not passive review\n3. Gradually increase intervals between reviews\n4. Adjust difficulty - items should be challenging but retrievable\n5. Combine with other effective techniques (elaboration, interleaving)\n\n### Key References\n\n*Note: Full citations in APA format*\n\nCepeda, N. J., Pashler, H., Vul, E., Wixted, J. T., & Rohrer, D. (2006). Distributed practice in verbal recall tasks: A review and quantitative synthesis. *Psychological Bulletin, 132*(3), 354-380.\n\nKarpicke, J. D., & Roediger, H. L. (2008). The critical importance of retrieval for learning. *Science, 319*(5865), 966-968.\n\nDunlosky, J., Rawson, K. A., Marsh, E. J., Nathan, M. J., & Willingham, D. T. (2013). Improving students' learning with effective learning techniques. *Psychological Science in the Public Interest, 14*(1), 4-58.", - "author": "community", - "version": "1.0.0", - "category": "Research", - "requires": [], - "examples": [] - }, - { - "skillId": "accessibility", + "description": "Use this skill when setting up, improving, or auditing analytics measurement for experiments, conversion tracking, event instrumentation, funnel analysis, or A/B test readiness." + }, + { "name": "Accessibility", - "description": "Accessibility guidelines for VS Code features — covers accessibility help dialogs, accessible views, verbosity settings, accessibility signals, ARIA alerts/status announcements, keyboard navigation, and ARIA labels/roles. Applies to both new interactive UI surfaces and updates to existing features.", - "instructions": "When adding a **new interactive UI surface** to VS Code — a panel, view, widget, editor overlay, dialog, or any rich focusable component the user interacts with — you **must** provide three accessibility components (if they do not already exist for the feature):\n\n1. **An Accessibility Help Dialog** — opened via the accessibility help keybinding when the feature has focus.\n2. **An Accessible View** — a plain-text read-only editor that presents the feature's content to screen reader users (when the feature displays non-trivial visual content).\n3. **An Accessibility Verbosity Setting** — a boolean setting that controls whether the \"open accessibility help\" hint is announced.\n\nExamples of existing features that have all three: the **terminal**, **chat panel**, **notebook**, **diff editor**, **inline completions**, **comments**, **debug REPL**, **hover**, and **notifications**. Features with only a help dialog (no accessible view) include **find widgets**, **source control input**, **keybindings editor**, **problems panel**, and **walkthroughs**.\n\nSections 4–7 below (signals, ARIA announcements, keyboard navigation, ARIA labels) apply more broadly to **any UI change**, including modifications to existing features.\n\nWhen **updating an existing feature** — for example, adding new commands, keyboard shortcuts, or interactive capabilities — you must also update the feature's existing accessibility help dialog (`provideContent()`) to document the new functionality. Screen reader users rely on the help dialog as the primary way to discover available actions.\n\n---\n\n## 1. Accessibility Help Dialog\n\nAn accessibility help dialog tells the user what the feature does, which keyboard shortcuts are available, and how to interact with it via a screen reader.\n\n### Steps\n\n1. **Create a class implementing `IAccessibleViewImplementation`** with `type = AccessibleViewType.Help`.\n - Set a `priority` (higher = shown first when multiple providers match).\n - Set `when` to a `ContextKeyExpression` that matches when the feature is focused.\n - `getProvider(accessor)` returns an `AccessibleContentProvider`.\n\n2. **Create a content-provider class** implementing `IAccessibleViewContentProvider`.\n - `id` — add a new entry in the `AccessibleViewProviderId` enum in `src/vs/platform/accessibility/browser/accessibleView.ts`.\n - `verbositySettingKey` — reference the new `AccessibilityVerbositySettingId` entry (see §3).\n - `options` — `{ type: AccessibleViewType.Help }`.\n - `provideContent()` — return localized, multi-line help text.\n\n3. **Implement `onClose()`** to restore focus to whatever element was focused before the help dialog opened. This ensures keyboard users and screen reader users return to their previous context.\n\n4. **Register** the implementation:\n ```ts\n AccessibleViewRegistry.register(new MyFeatureAccessibilityHelp());\n ```\n in the feature's `*.contribution.ts` file.\n\n### Example skeleton\n\nThe simplest approach is to return an `AccessibleContentProvider` directly from `getProvider()`. This is the most common pattern in the codebase (used by chat, inline chat, quick chat, etc.):\n\n```ts\nimport { AccessibleViewType, AccessibleContentProvider, AccessibleViewProviderId } from '…/accessibleView.js';\nimport { IAccessibleViewImplementation } from '…/accessibleViewRegistry.js';\nimport { AccessibilityVerbositySettingId } from '…/accessibilityConfiguration.js';\nimport { AccessibleViewType, AccessibleContentProvider, AccessibleViewProviderId, IAccessibleViewContentProvider, IAccessibleViewOptions } from '../../../../platform/accessibility/browser/accessibleView.js';\nimport { IAccessibleViewImplementation } from '../../../../platform/accessibility/browser/accessibleViewRegistry.js';\nimport { AccessibilityVerbositySettingId } from '../../../../platform/accessibility/common/accessibilityConfiguration.js';\n\nexport class MyFeatureAccessibilityHelp implements IAccessibleViewImplementation {\n\treadonly priority = 100;\n\treadonly name = 'my-feature';\n\treadonly type = AccessibleViewType.Help;\n\treadonly when = MyFeatureContextKeys.isFocused;\n\n\tgetProvider(accessor: ServicesAccessor) {\n\t\tconst helpText = [\n\t\t\tlocalize('myFeature.help.overview', \"You are in My Feature. …\"),\n\t\t\tlocalize('myFeature.help.key1', \"- {0}: Do something\", ''),\n\t\t].join('\\n');\n\t\treturn new AccessibleContentProvider(\n\t\t\tAccessibleViewProviderId.MyFeature,\n\t\t\t{ type: AccessibleViewType.Help },\n\t\t\t() => helpText,\n\t\t\t() => { /* onClose — refocus whatever was focused before */ },\n\t\t\tAccessibilityVerbositySettingId.MyFeature,\n\t\t);\n\t}\n}\n```\n\nAlternatively, if the provider needs injected services or must track state (e.g., storing a reference to the previously focused element), create a custom class that extends `Disposable` and implements `IAccessibleViewContentProvider`, then instantiate it via `IInstantiationService` (see `CommentsAccessibilityHelpProvider` for an example):\n\n```ts\nclass MyFeatureAccessibilityHelpProvider extends Disposable implements IAccessibleViewContentProvider {\n\treadonly id = AccessibleViewProviderId.MyFeature;\n\treadonly verbositySettingKey = AccessibilityVerbositySettingId.MyFeature;\n\treadonly options: IAccessibleViewOptions = { type: AccessibleViewType.Help };\n\n\tprovideContent(): string { /* … */ }\n\tonClose(): void { /* … */ }\n}\n\n// In getProvider():\ngetProvider(accessor: ServicesAccessor) {\n\treturn accessor.get(IInstantiationService).createInstance(MyFeatureAccessibilityHelpProvider);\n}\n```\n\n---\n\n## 2. Accessible View\n\nAn accessible view presents the feature's visual content as plain text in a read-only editor. It is required when the feature renders rich or visual content that a screen reader cannot directly read (for example: chat responses, hover tooltips, notifications, terminal output, inline completions).\n\nIf the feature is purely keyboard-driven with native text input/output (e.g., a simple input field), an accessible view is not needed — only an accessibility help dialog is required.\n\n### Steps\n\n1. **Create a class implementing `IAccessibleViewImplementation`** with `type = AccessibleViewType.View`.\n2. **Create a content-provider** similar to the help dialog, but:\n - `options` — `{ type: AccessibleViewType.View }`, optionally with a `language` for syntax highlighting.\n - `provideContent()` — return the feature's current content as plain text.\n - Optionally implement `provideNextContent()` / `providePreviousContent()` for item-by-item navigation.\n - Implement `onClose()` to restore focus to whatever was focused before the accessible view was opened.\n - Optionally provide `actions` for actions the user can take from the accessible view.\n3. **Register** alongside the help dialog:\n ```ts\n AccessibleViewRegistry.register(new MyFeatureAccessibleView());\n ```\n\n### Example skeleton\n\n```ts\nexport class MyFeatureAccessibleView implements IAccessibleViewImplementation {\n\treadonly priority = 100;\n\treadonly name = 'my-feature';\n\treadonly type = AccessibleViewType.View;\n\treadonly when = MyFeatureContextKeys.isFocused;\n\n\tgetProvider(accessor: ServicesAccessor) {\n\t\t// Retrieve services, build content from the feature's current state\n\t\tconst content = getMyFeatureContent();\n\t\tif (!content) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new AccessibleContentProvider(\n\t\t\tAccessibleViewProviderId.MyFeature,\n\t\t\t{ type: AccessibleViewType.View },\n\t\t\t() => content,\n\t\t\t() => { /* onClose — refocus whatever was focused before the accessible view opened */ },\n\t\t\tAccessibilityVerbositySettingId.MyFeature,\n\t\t);\n\t}\n}\n```\n\n---\n\n## 3. Accessibility Verbosity Setting\n\nA verbosity setting controls whether a hint such as \"press Alt+F1 for accessibility help\" is announced when the feature gains focus. Users who already know the shortcut can disable it.\n\n### Steps\n\n1. **Add an entry** to `AccessibilityVerbositySettingId` in\n `src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts`:\n ```ts\n export const enum AccessibilityVerbositySettingId {\n // … existing entries …\n MyFeature = 'accessibility.verbosity.myFeature'\n }\n ```\n\n2. **Register the configuration property** in the same file's `configuration.properties` object:\n ```ts\n [AccessibilityVerbositySettingId.MyFeature]: {\n description: localize('verbosity.myFeature.description',\n 'Provide information about how to access the My Feature accessibility help menu when My Feature is focused.'),\n ...baseVerbosityProperty\n },\n ```\n The `baseVerbosityProperty` gives it `type: 'boolean'`, `default: true`, and `tags: ['accessibility']`.\n\n3. **Reference the setting key** in both the help-dialog provider (`verbositySettingKey`) and the accessible-view provider so the runtime can check whether to show the hint.\n\n---\n\n## 4. Accessibility Signals (Sounds & Announcements)\n\nAccessibility signals provide audible and spoken feedback for events that happen visually. Use `IAccessibilitySignalService` to play signals when something important occurs (e.g., an error appears, a task completes, content changes).\n\n### When to use\n\n- **Use an existing signal** when the event already has one defined (see `AccessibilitySignal.*` static members — e.g., `AccessibilitySignal.error`, `AccessibilitySignal.terminalQuickFix`, `AccessibilitySignal.clear`).\n- **If no existing signal fits**, reach out to @meganrogge to discuss adding a new one. Do not register new signals without coordinating first.\n\n### How signals work\n\nEach signal has two modalities controlled by user settings:\n- **Sound** — a short audio cue, configurable to `auto` (on when screen reader attached), `on`, or `off`.\n- **Announcement** — a spoken message via `aria-live`, configurable to `auto` or `off`.\n\n### Usage\n\n```ts\n// Inject the service via constructor parameter\nconstructor(\n\t@IAccessibilitySignalService private readonly _accessibilitySignalService: IAccessibilitySignalService\n) { }\n\n// Play a signal\nthis._accessibilitySignalService.playSignal(AccessibilitySignal.terminalQuickFix);\n\n// Play with options\nthis._accessibilitySignalService.playSignal(AccessibilitySignal.error, { userGesture: true });\n```\n\n---\n\n## 5. ARIA Alerts vs. Status Messages\n\nUse the `alert()` and `status()` functions from `src/vs/base/browser/ui/aria/aria.ts` to announce dynamic changes to screen readers.\n\n### `alert(msg)` — Assertive live region (`role=\"alert\"`)\n- **Use for**: Urgent, important information that the user must know immediately.\n- **Examples**: Errors, warnings, critical state changes, results of a user-initiated action.\n- **Behavior**: Interrupts the screen reader's current speech.\n\n### `status(msg)` — Polite live region (`aria-live=\"polite\"`)\n- **Use for**: Non-urgent, informational updates that should be spoken when the screen reader is idle.\n- **Examples**: Progress updates, search result counts, background state changes.\n- **Behavior**: Queued and spoken after the screen reader finishes its current output.\n\n### Guidelines\n\n- **Prefer `status()` over `alert()`** unless the information is time-sensitive or the result of a direct user action. Overusing `alert()` creates a noisy, disruptive experience.\n- **Keep messages concise.** Screen readers read the entire message; long messages delay the user.\n- **Do not duplicate** — if an accessibility signal already announces the event, do not also call `alert()` / `status()` for the same information.\n- **Localize** all messages with `nls.localize()`.\n\n---\n\n## 6. Keyboard Navigation\n\nEvery interactive UI element must be fully operable via the keyboard.\n\n### Requirements\n\n- **Tab order**: All interactive elements must be reachable via `Tab` / `Shift+Tab` in a logical order.\n- **Arrow key navigation**: Lists, trees, grids, and toolbars must support arrow key navigation following WAI-ARIA patterns.\n- **Focus visibility**: Focused elements must have a visible focus indicator (VS Code's theme system provides this via `focusBorder`).\n- **No mouse-only interactions**: Every action reachable by click or hover must also be reachable via keyboard (context menus, buttons, toggles, etc.).\n- **Escape to dismiss**: Overlays, dialogs, and popups must be dismissable with `Escape`, returning focus to the previous element.\n- **Focus trapping**: Modal dialogs must trap focus within the dialog until dismissed.\n\n---\n\n## 7. ARIA Labels and Roles\n\nAll interactive UI elements must have appropriate ARIA attributes so screen readers can identify and describe them.\n\n### Requirements\n\n- **`aria-label`**: Every interactive element without visible text (icon buttons, icon-only actions, custom widgets) must have a descriptive `aria-label`. Labels should be localized.\n- **`aria-labelledby`** / **`aria-describedby`**: Use these to associate elements with existing visible text rather than duplicating strings.\n- **`role`**: Custom widgets that do not use native HTML elements must declare the correct ARIA role (e.g., `role=\"button\"`, `role=\"tree\"`, `role=\"tablist\"`).\n- **`aria-expanded`**, **`aria-selected`**, **`aria-checked`**: Toggle and selection states must be communicated via the appropriate ARIA state attributes.\n- **`aria-hidden=\"true\"`**: Decorative or redundant elements (icons next to text labels, decorative separators) must be hidden from the accessibility tree.\n\n### Guidelines\n\n- Avoid generic labels like \"button\" or \"icon\" — describe the action: \"Close panel\", \"Toggle sidebar\", \"Run task\".\n- Test with a screen reader (VoiceOver on macOS, NVDA on Windows) to verify labels are spoken correctly in context.\n- Lists and trees should use `aria-setsize` and `aria-posinset` when virtualized so screen readers report the correct count.\n\n---\n\n## Checklist for Every New Feature\n\n- [ ] New `AccessibleViewProviderId` entry added in `accessibleView.ts`\n- [ ] New `AccessibilityVerbositySettingId` entry added in `accessibilityConfiguration.ts`\n- [ ] Verbosity setting registered in the configuration properties with `...baseVerbosityProperty`\n- [ ] `IAccessibleViewImplementation` with `type = Help` created and registered\n- [ ] Content provider references the correct `verbositySettingKey`\n- [ ] Help text is fully localized using `nls.localize()`\n- [ ] Keybindings in help text use `` syntax for dynamic resolution\n- [ ] `when` context key is set so the dialog only appears when the feature is focused\n- [ ] If the feature has rich/visual content: `IAccessibleViewImplementation` with `type = View` created and registered\n- [ ] Registration calls in the feature's `*.contribution.ts` file\n- [ ] Accessibility signal played for important events (use existing `AccessibilitySignal.*` or register a new one)\n- [ ] `aria.alert()` or `aria.status()` used appropriately for dynamic changes (prefer `status()` unless urgent)\n- [ ] All interactive elements reachable and operable via keyboard\n- [ ] All interactive elements without visible text have a localized `aria-label`\n- [ ] Custom widgets declare the correct ARIA `role` and state attributes\n- [ ] Decorative elements are hidden with `aria-hidden=\"true\"`\n\n## Key Files\n\n- `src/vs/platform/accessibility/browser/accessibleView.ts` — `AccessibleViewProviderId`, `AccessibleContentProvider`, `IAccessibleViewContentProvider`\n- `src/vs/platform/accessibility/browser/accessibleViewRegistry.ts` — `AccessibleViewRegistry`, `IAccessibleViewImplementation`\n- `src/vs/workbench/contrib/accessibility/browser/accessibilityConfiguration.ts` — `AccessibilityVerbositySettingId`, verbosity setting registration\n- `src/vs/platform/accessibilitySignal/browser/accessibilitySignalService.ts` — `IAccessibilitySignalService`, `AccessibilitySignal`\n- `src/vs/base/browser/ui/aria/aria.ts` — `alert()`, `status()` for ARIA live region announcements", - "author": "community", - "version": "1.0.0", - "category": "Business", - "requires": [], - "examples": [] - }, - { - "skillId": "accessibility-compliance", - "name": "Accessibility Compliance", - "description": "Implement WCAG 2.2 compliant interfaces with mobile accessibility, inclusive design patterns, and assistive technology support.", - "instructions": "# Accessibility Compliance\n\nMaster accessibility implementation to create inclusive experiences that work for everyone, including users with disabilities.\n\n## When to Use This Skill\n\n- Implementing WCAG 2.2 Level AA or AAA compliance\n- Building screen reader accessible interfaces\n- Adding keyboard navigation to interactive components\n- Implementing focus management and focus trapping\n- Creating accessible forms with proper labeling\n- Supporting reduced motion and high contrast preferences\n- Building mobile accessibility features (iOS VoiceOver, Android TalkBack)\n- Conducting accessibility audits and fixing violations\n\n## Core Capabilities\n\n### 1. WCAG 2.2 Guidelines\n\n- Perceivable: Content must be presentable in different ways\n- Operable: Interface must be navigable with keyboard and assistive tech\n- Understandable: Content and operation must be clear\n- Robust: Content must work with current and future assistive technologies\n\n### 2. ARIA Patterns\n\n- Roles: Define element purpose (button, dialog, navigation)\n- States: Indicate current condition (expanded, selected, disabled)\n- Properties: Describe relationships and additional info (labelledby, describedby)\n- Live regions: Announce dynamic content changes\n\n### 3. Keyboard Navigation\n\n- Focus order and tab sequence\n- Focus indicators and visible focus states\n- Keyboard shortcuts and hotkeys\n- Focus trapping for modals and dialogs\n\n### 4. Screen Reader Support\n\n- Semantic HTML structure\n- Alternative text for images\n- Proper heading hierarchy\n- Skip links and landmarks\n\n### 5. Mobile Accessibility\n\n- Touch target sizing (44x44dp minimum)\n- VoiceOver and TalkBack compatibility\n- Gesture alternatives\n- Dynamic Type support\n\n## Quick Reference\n\n### WCAG 2.2 Success Criteria Checklist\n\n| Level | Criterion | Description |\n| ----- | --------- | ---------------------------------------------------- |\n| A | 1.1.1 | Non-text content has text alternatives |\n| A | 1.3.1 | Info and relationships programmatically determinable |\n| A | 2.1.1 | All functionality keyboard accessible |\n| A | 2.4.1 | Skip to main content mechanism |\n| AA | 1.4.3 | Contrast ratio 4.5:1 (text), 3:1 (large text) |\n| AA | 1.4.11 | Non-text contrast 3:1 |\n| AA | 2.4.7 | Focus visible |\n| AA | 2.5.8 | Target size minimum 24x24px (NEW in 2.2) |\n| AAA | 1.4.6 | Enhanced contrast 7:1 |\n| AAA | 2.5.5 | Target size minimum 44x44px |\n\n## Key Patterns\n\n### Pattern 1: Accessible Button\n\n```tsx\ninterface ButtonProps extends React.ButtonHTMLAttributes {\n variant?: \"primary\" | \"secondary\";\n isLoading?: boolean;\n}\n\nfunction AccessibleButton({\n children,\n variant = \"primary\",\n isLoading = false,\n disabled,\n ...props\n}: ButtonProps) {\n return (\n \n {isLoading ? (\n <>\n Loading\n \n \n ) : (\n children\n )}\n \n );\n}\n```\n\n### Pattern 2: Accessible Modal Dialog\n\n```tsx\nimport * as React from \"react\";\nimport { FocusTrap } from \"@headlessui/react\";\n\ninterface DialogProps {\n isOpen: boolean;\n onClose: () => void;\n title: string;\n children: React.ReactNode;\n}\n\nfunction AccessibleDialog({ isOpen, onClose, title, children }: DialogProps) {\n const titleId = React.useId();\n const descriptionId = React.useId();\n\n // Close on Escape key\n React.useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\" && isOpen) {\n onClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, onClose]);\n\n // Prevent body scroll when open\n React.useEffect(() => {\n if (isOpen) {\n document.body.style.overflow = \"hidden\";\n }\n return () => {\n document.body.style.overflow = \"\";\n };\n }, [isOpen]);\n\n if (!isOpen) return null;\n\n return (\n \n {/* Backdrop */}\n \n\n {/* Focus trap container */}\n \n
\n
\n

\n {title}\n

\n
{children}
\n \n \n \n
\n
\n
\n \n );\n}\n```\n\n### Pattern 3: Accessible Form\n\n```tsx\nfunction AccessibleForm() {\n const [errors, setErrors] = React.useState>({});\n\n return (\n
\n {/* Error summary for screen readers */}\n {Object.keys(errors).length > 0 && (\n \n

\n Please fix the following errors:\n

\n
    \n {Object.entries(errors).map(([field, message]) => (\n
  • \n \n {message}\n \n
  • \n ))}\n
\n \n )}\n\n {/* Required field with error */}\n
\n \n \n {errors.email ? (\n

\n {errors.email}\n

\n ) : (\n

\n We'll never share your email.\n

\n )}\n
\n\n \n \n );\n}\n```\n\n### Pattern 4: Skip Navigation Link\n\n```tsx\nfunction SkipLink() {\n return (\n