{"id":"41dc8613-9d91-4e20-81ca-e644dcf716c7","shortId":"yESQCe","kind":"skill","title":"frontend-component-build","tagline":"Build production-ready frontend components with accessible markup, sensible props, defined states, and tested behavior. Use this skill whenever the user wants to build a component from scratch, refactor an existing one, design a component API, or implement a UI element with prope","description":"# Frontend Component Build\n\nBuild production-ready components. Stack-agnostic principles. Most patterns translate to React, Vue, Svelte, or vanilla web components.\n\nThis skill is about implementing a component well. For broader system design see `design-system`. For day-to-day visual decisions see `design-standards`.\n\n---\n\n## When to use\n\n- Building a new component from scratch\n- Refactoring an existing component\n- Designing a component API (props, slots, events)\n- Adding accessibility to an existing component\n- Implementing a component from a design\n\n## When NOT to use\n\n- Building a full design system (use `design-system`)\n- Page-level design decisions (use `design-standards`)\n- Backend or data work (use `code-review-web`)\n- Performance-only optimization (use `performance-optimization`)\n\n---\n\n## Required inputs\n\n- The component's purpose (what UI need it serves)\n- The design (or willingness to design it)\n- The framework or technical context\n- The states the component must support\n- Accessibility requirements\n\n---\n\n## The framework: 6 dimensions\n\nA complete component handles six dimensions. Skip any one and the component is incomplete.\n\n### 1. Anatomy\n\nIdentify the parts that make up the component before writing any markup.\n\n**Common anatomies:**\n- Button: container + label + (optional) icon + (optional) loading indicator\n- Modal: backdrop + container + header + body + footer + close affordance\n- Form input: label + input + (optional) help text + (optional) error message\n- Card: container + (optional) header + body + (optional) footer + (optional) media\n\nNaming the parts up front makes the API obvious.\n\n### 2. Variants\n\nWhat variations does the component support?\n\n- **Visual variants** (primary, secondary, ghost, danger)\n- **Size variants** (small, medium, large)\n- **Functional variants** (with icon, without icon, icon-only)\n\nVariants should be a managed set, not a free-for-all. Document the supported set; reject requests for new variants without a real use case.\n\n### 3. States\n\nWhat states must the component handle?\n\n- **Default**\n- **Hover** (when pointer is supported)\n- **Focus** (always - keyboard navigation requires it)\n- **Active / pressed**\n- **Disabled**\n- **Loading** (where applicable)\n- **Error** (for inputs, forms, validation-bound components)\n- **Empty** (for components that display data)\n\nEvery state needs visual treatment AND accessibility treatment.\n\n### 4. Props / API\n\nDesign the component's contract.\n\n**API design principles:**\n\n- **Required props minimal.** What's truly needed every time? That's required. Everything else has a sensible default.\n- **Boolean props are red flags.** Three booleans means seven combinations. Prefer enum strings: `variant: \"primary\" | \"secondary\" | \"ghost\"` over `primary={true} ghost={false}`.\n- **Children > props.** Where content is content, accept children. Don't invent `headerText` and `bodyText` props when slots work.\n- **Composition > configuration.** A component that does 5 things via 12 props often should be 5 smaller components.\n- **Type the props.** TypeScript or PropTypes or JSDoc. The type is documentation that won't go out of date.\n\n### 5. Accessibility\n\nBuild it accessible from the start. Adding accessibility later is 5x harder.\n\n**Universal:**\n- Semantic HTML elements (`<button>`, `<a>`, `<nav>`, `<form>`, etc.) over generic `<div>`\n- Keyboard navigable (Tab, Shift+Tab, Enter/Space for buttons)\n- Focus visible\n- Tap targets minimum 44 by 44 pixels\n- ARIA only where semantic HTML is insufficient\n\n**Component-specific:**\n\n- **Button:** use `<button>`. Don't fake one with a `<div>`.\n- **Modal:** focus trap, ESC to close, returns focus to trigger on close, `role=\"dialog\"` and `aria-labelledby`.\n- **Form input:** label associated via `for`/`id` or `aria-labelledby`. Error messages linked via `aria-describedby`. `aria-invalid` when in error state.\n- **Toggles:** `<button>` with `aria-pressed` for two-state, or `role=\"switch\"` for on/off.\n- **Tabs:** `role=\"tablist\"` / `role=\"tab\"` / `role=\"tabpanel\"` with `aria-selected` and arrow-key navigation.\n- **Tooltips and popovers:** triggered by focus AND hover. Dismissible with ESC.\n- **Loading states:** announce with `aria-live` so screen readers know something changed.\n\n### 6. Tests\n\nVerify the component works before declaring it done.\n\n**Test types by priority:**\n\n1. **Visual regression.** Renders correctly across variants and states. (Storybook + visual diff tools, or manual screenshots.)\n2. **Accessibility.** Passes axe or equivalent automated checks.\n3. **Keyboard navigation.** Tab, Enter, Escape, arrow keys all work as expected.\n4. **Component logic.** Props produce expected output. Events fire correctly. (Unit tests.)\n5. **Integration.** Component works inside its expected parent contexts.\n\nA component without at least automated accessibility testing is not done.\n\n---\n\n## Workflow\n\n1. **Understand the use case.** What UI need does this component serve? Where will it appear? Adjacent components?\n2. **Sketch the anatomy.** Name the parts.\n3. **List variants and states.** Match the design system or define new ones if needed.\n4. **Design the API.** Required props, optional props, children, events. Type it.\n5. **Build the markup with semantic HTML.** Choose the right elements. Avoid generic `<div>` for interactive things.\n6. **Style with tokens.** No hardcoded colors, spacing, or sizes.\n7. **Add interaction.** Focus management, keyboard handlers, ARIA.\n8. **Add states.** Hover, focus, active, disabled, loading, error.\n9. **Test.** Automated accessibility, keyboard navigation, visual regression.\n10. **Document.** Usage, API, examples, anti-patterns.\n\n---\n\n## Failure patterns\n\n- **Building with `<div onClick>`.** Loses keyboard accessibility, screen reader semantics, and focus. Use `<button>` or `<a>`.\n- **Hardcoding colors and sizes.** Tokens exist for a reason. Hardcoded values resist theming and consistency.\n- **Boolean prop explosion.** `<Button primary large rounded fullWidth disabled icon />`. Too many booleans means you actually need fewer variants designed more thoughtfully.\n- **Forgetting focus states.** Hover gets attention; focus gets neglected. Keyboard users see invisible buttons.\n- **Skipping disabled-state thought.** A disabled button should look obviously disabled AND be `aria-disabled` AND not respond to clicks.\n- **Inventing ARIA.** ARIA roles and properties have specific behaviors. Made-up ARIA is worse than no ARIA. Use semantic HTML first.\n- **Loading state that doesn't announce.** Screen readers don't know the spinner appeared. Use `aria-live=\"polite\"` or `role=\"status\"`.\n- **Tooltip-only critical content.** Hover-only content is invisible to keyboard and touch users. Critical content goes in the visible UI.\n- **Component without docs.** Future-you, your teammate, or the next maintainer cannot use what they cannot understand.\n\n---\n\n## Output format\n\nA complete component delivery includes:\n\n- **Component code** (in the appropriate framework)\n- **Storybook (or equivalent) entry** showing all variants and states\n- **Documentation:**\n  - Anatomy diagram or description\n  - Props/API table\n  - Usage examples (basic, advanced, edge cases)\n  - When to use vs. when to use an alternative\n  - Anti-patterns (what to avoid)\n  - Accessibility notes\n- **Tests** (visual regression + accessibility + logic)\n\n---\n\n## Reference files\n\n- [`references/component-spec-template.md`](references/component-spec-template.md) - Template for documenting a component (props, states, accessibility, edge cases) before building.\n- [`references/component-api-patterns.md`](references/component-api-patterns.md) - Common patterns for designing flexible component APIs (compound components, controlled vs uncontrolled, polymorphic `as` prop, render props, slots).\n- [`references/accessibility-patterns.md`](references/accessibility-patterns.md) - ARIA patterns for common interactive components.","tags":["frontend","component","build","claude","skills","rampstackco","agent-skills","anthropic","awesome-claude-code","awesome-claude-prompts","awesome-claude-skills","claude-code"],"capabilities":["skill","source-rampstackco","skill-frontend-component-build","topic-agent-skills","topic-anthropic","topic-awesome-claude-code","topic-awesome-claude-prompts","topic-awesome-claude-skills","topic-claude","topic-claude-code","topic-claude-skills","topic-good-first-issue","topic-mcp","topic-product-management","topic-seo"],"categories":["claude-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/rampstackco/claude-skills/frontend-component-build","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add rampstackco/claude-skills","source_repo":"https://github.com/rampstackco/claude-skills","install_from":"skills.sh"}},"qualityScore":"0.540","qualityRationale":"deterministic score 0.54 from registry signals: · indexed on github topic:agent-skills · 181 github stars · SKILL.md body (7,918 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T18:55:16.541Z","embedding":null,"createdAt":"2026-04-30T01:01:28.628Z","updatedAt":"2026-05-18T18:55:16.541Z","lastSeenAt":"2026-05-18T18:55:16.541Z","tsv":"'1':219,653,722 '10':825 '12':459 '2':279,669,740 '3':333,677,747 '4':381,689,762 '44':520,522 '5':456,464,486,701,774 '5x':498 '6':203,639,790 '7':800 '8':808 '9':817 'accept':438 'access':12,120,199,379,487,490,495,670,716,820,839,1048,1053,1066 'across':658 'activ':353,813 'actual':870 'ad':119,494 'add':801,809 'adjac':738 'advanc':1030 'afford':250 'agnost':59 'altern':1041 'alway':348 'anatomi':220,234,743,1021 'announc':628,940 'anti':831,1043 'anti-pattern':830,1042 'api':41,115,277,383,389,765,828,1079 'appear':737,948 'applic':358 'appropri':1009 'aria':524,558,569,576,579,588,608,631,807,906,914,915,925,930,951,1093 'aria-describedbi':575 'aria-dis':905 'aria-invalid':578 'aria-l':630,950 'aria-labelledbi':557,568 'aria-press':587 'aria-select':607 'arrow':612,683 'arrow-key':611 'associ':563 'attent':882 'autom':675,715,819 'avoid':785,1047 'axe':672 'backdrop':244 'backend':153 'basic':1029 'behavior':20,921 'bodi':247,265 'bodytext':445 'boolean':410,416,862,867 'bound':365 'broader':81 'build':4,5,29,51,52,102,135,488,775,835,1070 'button':235,514,534,890,898 'cannot':992,996 'card':261 'case':332,726,1032,1068 'chang':638 'check':676 'children':432,439,770 'choos':781 'click':912 'close':249,547,553 'code':159,1006 'code-review-web':158 'color':796,848 'combin':419 'common':233,1073,1096 'complet':206,1001 'compon':3,10,31,40,50,56,71,78,105,111,114,124,127,173,196,207,216,228,285,339,366,369,386,453,466,532,643,690,703,711,732,739,980,1002,1005,1063,1078,1081,1098 'component-specif':531 'composit':450 'compound':1080 'configur':451 'consist':861 'contain':236,245,262 'content':435,437,961,965,974 'context':192,709 'contract':388 'control':1082 'correct':657,698 'critic':960,973 'danger':292 'data':155,372 'date':485 'day':90,92 'day-to-day':89 'decis':94,148 'declar':646 'default':341,409 'defin':16,757 'deliveri':1003 'describedbi':577 'descript':1024 'design':38,83,86,97,112,130,138,142,147,151,182,186,384,390,754,763,874,1076 'design-standard':96,150 'design-system':85,141 'diagram':1022 'dialog':555 'diff':664 'dimens':204,210 'disabl':355,814,893,897,902,907 'disabled-st':892 'dismiss':623 'display':371 'doc':982 'document':319,478,826,1020,1061 'doesn':938 'done':648,720 'edg':1031,1067 'element':46,503,784 'els':405 'empti':367 'enter':681 'enter/space':512 'entri':1014 'enum':421 'equival':674,1013 'error':259,359,571,583,816 'esc':545,625 'escap':682 'etc':504 'event':118,696,771 'everi':373,399 'everyth':404 'exampl':829,1028 'exist':36,110,123,852 'expect':688,694,707 'explos':864 'failur':833 'fake':538 'fals':431 'fewer':872 'file':1056 'fire':697 'first':934 'flag':414 'flexibl':1077 'focus':347,515,543,549,620,803,812,844,878,883 'footer':248,267 'forget':877 'form':251,362,560 'format':999 'framework':189,202,1010 'free':316 'free-for-al':315 'front':274 'frontend':2,9,49 'frontend-component-build':1 'full':137 'function':298 'futur':984 'future-you':983 'generic':506,786 'get':881,884 'ghost':291,426,430 'go':482 'goe':975 'handl':208,340 'handler':806 'hardcod':795,847,856 'harder':499 'header':246,264 'headertext':443 'help':256 'hover':342,622,811,880,963 'hover-on':962 'html':502,528,780,933 'icon':239,301,303,305 'icon-on':304 'id':566 'identifi':221 'implement':43,76,125 'includ':1004 'incomplet':218 'indic':242 'input':171,252,254,361,561 'insid':705 'insuffici':530 'integr':702 'interact':788,802,1097 'invalid':580 'invent':442,913 'invis':889,967 'jsdoc':474 'key':613,684 'keyboard':349,507,678,805,821,838,886,969 'know':636,945 'label':237,253,562 'labelledbi':559,570 'larg':297 'later':496 'least':714 'level':146 'link':573 'list':748 'live':632,952 'load':241,356,626,815,935 'logic':691,1054 'look':900 'lose':837 'made':923 'made-up':922 'maintain':991 'make':225,275 'manag':311,804 'mani':866 'manual':667 'markup':13,232,777 'match':752 'mean':417,868 'media':269 'medium':296 'messag':260,572 'minim':394 'minimum':519 'modal':243,542 'must':197,337 'name':270,744 'navig':350,508,614,679,822 'need':178,375,398,729,761,871 'neglect':885 'new':104,326,758 'next':990 'note':1049 'obvious':278,901 'often':461 'on/off':598 'one':37,213,539,759 'optim':165,169 'option':238,240,255,258,263,266,268,768 'output':695,998 'page':145 'page-level':144 'parent':708 'part':223,272,746 'pass':671 'pattern':62,832,834,1044,1074,1094 'perform':163,168 'performance-on':162 'performance-optim':167 'pixel':523 'pointer':344 'polit':953 'polymorph':1085 'popov':617 'prefer':420 'press':354,589 'primari':289,424,428 'principl':60,391 'prioriti':652 'produc':693 'product':7,54 'production-readi':6,53 'prop':15,116,382,393,411,433,446,460,469,692,767,769,863,1064,1087,1089 'prope':48 'properti':918 'props/api':1025 'proptyp':472 'purpos':175 'react':65 'reader':635,841,942 'readi':8,55 'real':330 'reason':855 'red':413 'refactor':34,108 'refer':1055 'references/accessibility-patterns.md':1091,1092 'references/component-api-patterns.md':1071,1072 'references/component-spec-template.md':1057,1058 'regress':655,824,1052 'reject':323 'render':656,1088 'request':324 'requir':170,200,351,392,403,766 'resist':858 'respond':910 'return':548 'review':160 'right':783 'role':554,595,600,602,604,916,955 'scratch':33,107 'screen':634,840,941 'screenshot':668 'secondari':290,425 'see':84,95,888 'select':609 'semant':501,527,779,842,932 'sensibl':14,408 'serv':180,733 'set':312,322 'seven':418 'shift':510 'show':1015 'six':209 'size':293,799,850 'sketch':741 'skill':23,73 'skill-frontend-component-build' 'skip':211,891 'slot':117,448,1090 'small':295 'smaller':465 'someth':637 'source-rampstackco' 'space':797 'specif':533,920 'spinner':947 'stack':58 'stack-agnost':57 'standard':98,152 'start':493 'state':17,194,334,336,374,584,593,627,661,751,810,879,894,936,1019,1065 'status':956 'storybook':662,1011 'string':422 'style':791 'support':198,286,321,346 'svelt':67 'switch':596 'system':82,87,139,143,755 'tab':509,511,599,603,680 'tabl':1026 'tablist':601 'tabpanel':605 'tap':517 'target':518 'teammat':987 'technic':191 'templat':1059 'test':19,640,649,700,717,818,1050 'text':257 'theme':859 'thing':457,789 'thought':876,895 'three':415 'time':400 'toggl':585 'token':793,851 'tool':665 'tooltip':615,958 'tooltip-on':957 'topic-agent-skills' 'topic-anthropic' 'topic-awesome-claude-code' 'topic-awesome-claude-prompts' 'topic-awesome-claude-skills' 'topic-claude' 'topic-claude-code' 'topic-claude-skills' 'topic-good-first-issue' 'topic-mcp' 'topic-product-management' 'topic-seo' 'touch':971 'translat':63 'trap':544 'treatment':377,380 'trigger':551,618 'true':429 'truli':397 'two':592 'two-stat':591 'type':467,476,650,772 'typescript':470 'ui':45,177,728,979 'uncontrol':1084 'understand':723,997 'unit':699 'univers':500 'usag':827,1027 'use':21,101,134,140,149,157,166,331,535,725,845,931,949,993,1035,1039 'user':26,887,972 'valid':364 'validation-bound':363 'valu':857 'vanilla':69 'variant':280,288,294,299,307,327,423,659,749,873,1017 'variat':282 'verifi':641 'via':458,564,574 'visibl':516,978 'visual':93,287,376,654,663,823,1051 'vs':1036,1083 'vue':66 'want':27 'web':70,161 'well':79 'whenev':24 'willing':184 'without':302,328,712,981 'won':480 'work':156,449,644,686,704 'workflow':721 'wors':927 'write':230","prices":[{"id":"283a2ca2-e115-41b0-9808-5ffb6ac5328b","listingId":"41dc8613-9d91-4e20-81ca-e644dcf716c7","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"rampstackco","category":"claude-skills","install_from":"skills.sh"},"createdAt":"2026-04-30T01:01:28.628Z"}],"sources":[{"listingId":"41dc8613-9d91-4e20-81ca-e644dcf716c7","source":"github","sourceId":"rampstackco/claude-skills/frontend-component-build","sourceUrl":"https://github.com/rampstackco/claude-skills/tree/main/skills/frontend-component-build","isPrimary":false,"firstSeenAt":"2026-04-30T01:01:28.628Z","lastSeenAt":"2026-05-18T18:55:16.541Z"}],"details":{"listingId":"41dc8613-9d91-4e20-81ca-e644dcf716c7","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"rampstackco","slug":"frontend-component-build","github":{"repo":"rampstackco/claude-skills","stars":181,"topics":["agent-skills","anthropic","awesome-claude-code","awesome-claude-prompts","awesome-claude-skills","claude","claude-code","claude-skills","good-first-issue","mcp","product-management","seo","show-hn","showcase","showdev","web-design","web-development"],"license":"mit","html_url":"https://github.com/rampstackco/claude-skills","pushed_at":"2026-05-10T22:40:22Z","description":"Stack-agnostic Claude Skills covering the full website lifecycle: brand, design, content, SEO, dev, ops, growth, and research. Build, ship, audit, optimize.","skill_md_sha":"fb5f5f7478c88fcec1bc72798291be5e2c2fc07b","skill_md_path":"skills/frontend-component-build/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/rampstackco/claude-skills/tree/main/skills/frontend-component-build"},"layout":"multi","source":"github","category":"claude-skills","frontmatter":{"name":"frontend-component-build","description":"Build production-ready frontend components with accessible markup, sensible props, defined states, and tested behavior. Use this skill whenever the user wants to build a component from scratch, refactor an existing one, design a component API, or implement a UI element with proper states and accessibility. Triggers on build a component, create a button, create a modal, create a form input, component API, props design, component states, refactor component, accessible component. Also triggers when implementing UI from a design that needs to be reusable."},"skills_sh_url":"https://skills.sh/rampstackco/claude-skills/frontend-component-build"},"updatedAt":"2026-05-18T18:55:16.541Z"}}