{"id":"5ecce615-4eb6-42a9-a71f-6d9d0e598b99","shortId":"6FHNAn","kind":"skill","title":"component-family-consistency","tagline":"Buttons, inputs, pills, badges, calendars, and other interactive components form a visual family — they share the same border-radius, colour logic, shadow scale, border style, and spacing rhythm. Inconsistency between them breaks the sense of a coherent product. Use when building","description":"# Component Family Consistency\n\nEvery interactive component in a product — buttons, inputs, selects, checkboxes, radio buttons, pills, badges, tags, calendars, date pickers, sliders, toggles — belongs to the same visual family. They share a common design DNA. A user should be able to look at any component and feel that it belongs to the same product as every other component.\n\nWhen components are designed in isolation without shared tokens, the product feels assembled from parts rather than built as a whole.\n\n## The Shared DNA\n\nDefine these tokens once. Every component inherits from them.\n\n### Border-Radius\nAll interactive components use the same base radius token. Variations are derived, not invented.\n\n```css\n--radius-base:    8px;   /* buttons, inputs, selects */\n--radius-sm:      4px;   /* checkboxes, small badges */\n--radius-lg:      12px;  /* cards, modals, large panels */\n--radius-full:    9999px; /* pills, tags, avatar chips */\n```\n\nA button and an input on the same form must have the same radius. A pill is always `--radius-full`. A badge is `--radius-sm` or `--radius-full` depending on brand tone — but consistent across all badges.\n\n### Border Style\n\nBorders across all form components and containers should use a highly restricted set of tokens.\n\n**The 2-Step Rule:** Limit border widths to at most two options (e.g., `1px` and `4px`, or `1px` and `8px`). Do not use an incremental scale like `1px, 2px, 3px, 4px...`. A limited choice makes the hierarchy clear and the product feel intentional.\n\n```css\n--border-width-thin:   1px;   /* Default for inputs, cards, dividers */\n--border-width-thick:  4px;   /* Featured items, bold accents, active indicators */\n\n--border-color:        var(--color-border);\n--border-color-focus:  var(--color-primary);\n--border-color-error:  var(--color-error);\n```\n\nAn input border and a select border are identical at rest. Focus state uses `--border-color-focus` everywhere. Error state uses `--border-color-error` everywhere.\n\n### Spacing and Height\nComponents at the same visual scale share height and internal padding.\n\n```css\n/* Default (md) size */\n--component-height-md:    40px;\n--component-padding-x-md: 12px;\n--component-padding-y-md: 8px;\n\n/* Small */\n--component-height-sm:    32px;\n--component-padding-x-sm: 8px;\n--component-padding-y-sm: 6px;\n\n/* Large */\n--component-height-lg:    48px;\n--component-padding-x-lg: 16px;\n--component-padding-y-lg: 10px;\n```\n\nA button and an input placed next to each other must be the same height. This is not cosmetic — mismatched heights break form layouts and signal disorder.\n\n### Shadow\nInteractive components use a consistent shadow logic:\n\n- At rest: no shadow, or `--shadow-xs` for floating components (select dropdown trigger)\n- On focus: focus ring via `outline`, not `box-shadow` (unless using `box-shadow` as the focus ring consistently)\n- Elevated (dropdowns, popovers opening from components): `--shadow-md`\n\n### Colour Logic\nThe same colour roles apply uniformly across all components:\n\n| State | Colour token |\n|---|---|\n| Rest border | `--color-border` |\n| Focus border / ring | `--color-primary` |\n| Error border | `--color-error` |\n| Disabled | `--color-text-secondary` at reduced opacity |\n| Selected / active fill | `--color-primary` |\n| Hover background | `--color-primary` at 8–12% opacity |\n\n## Component Family Members\n\n| Component | Shares radius | Shares height | Shares border | Shares colour logic |\n|---|---|---|---|---|\n| Button | ✓ | ✓ | — (filled) | ✓ |\n| Input / textarea | ✓ | ✓ | ✓ | ✓ |\n| Select | ✓ | ✓ | ✓ | ✓ |\n| Checkbox | `--radius-sm` | — | ✓ | ✓ |\n| Radio | `--radius-full` | — | ✓ | ✓ |\n| Toggle / switch | `--radius-full` | ✓ | — | ✓ |\n| Pill / tag | `--radius-full` | ✓ | ✓ optional | ✓ |\n| Badge | `--radius-sm` or `--radius-full` | — | — | ✓ |\n| Date picker / calendar | `--radius-base` | ✓ | ✓ | ✓ |\n| Slider | `--radius-full` (track + thumb) | — | — | ✓ |\n| Search input | ✓ | ✓ | ✓ | ✓ |\n| Combobox | ✓ | ✓ | ✓ | ✓ |\n\n## Gradients in Components\n\nIf the brand uses gradients, apply them consistently:\n\n- A gradient on a primary button should use the same gradient angle and stops as gradient usage elsewhere in the product\n- Hover state: slightly shift the gradient lightness, not the hue\n- Do not use gradients on some button variants and flat colour on others — pick one approach per variant and apply it universally\n\n## Review Checklist\n\n- [ ] Do buttons and inputs on the same form share the same height?\n- [ ] Do all bordered components use at most two border-width options (e.g., 1px and 4px)?\n- [ ] Does focus state look identical across all focusable components?\n- [ ] Does error state look identical across all components that can have errors?\n- [ ] Are all radius values derived from the same base token — not set independently per component?\n- [ ] Do pills and tags use `--radius-full` consistently?\n- [ ] Is gradient usage (if any) consistent across all button variants?\n- [ ] Could a new component be added to the library using only existing tokens?","tags":["component","family","consistency","dembrandt","skills","accessibility","agent-skills","claude-code-skills","claude-skills","cursor-skills","design-system","design-tokens"],"capabilities":["skill","source-dembrandt","skill-component-family-consistency","topic-accessibility","topic-agent-skills","topic-claude-code-skills","topic-claude-skills","topic-cursor-skills","topic-design-system","topic-design-tokens","topic-enterprise-ux","topic-gestalt","topic-skills-sh","topic-typography","topic-ui-design"],"categories":["dembrandt-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/dembrandt/dembrandt-skills/component-family-consistency","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add dembrandt/dembrandt-skills","source_repo":"https://github.com/dembrandt/dembrandt-skills","install_from":"skills.sh"}},"qualityScore":"0.454","qualityRationale":"deterministic score 0.45 from registry signals: · indexed on github topic:agent-skills · 9 github stars · SKILL.md body (5,017 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-18T19:08:26.443Z","embedding":null,"createdAt":"2026-05-18T13:14:00.679Z","updatedAt":"2026-05-18T19:08:26.443Z","lastSeenAt":"2026-05-18T19:08:26.443Z","tsv":"'10px':428 '12':558 '12px':173,386 '16px':422 '1px':256,260,270,291,711 '2':244 '2px':271 '32px':398 '3px':272 '40px':380 '48px':416 '4px':166,258,273,301,713 '6px':410 '8':557 '8px':159,262,392,404 '9999px':181 'abl':86 'accent':305 'across':223,229,515,719,728,765 'activ':306,546 'ad':774 'alway':203 'angl':642 'appli':513,628,681 'approach':677 'assembl':117 'avatar':184 'background':552 'badg':8,63,169,208,225,597 'base':147,158,610,743 'belong':70,96 'bold':304 'border':23,29,139,226,228,248,288,298,309,314,316,324,333,337,346,354,522,525,527,533,569,700,707 'border-color':308 'border-color-error':323,353 'border-color-focus':315,345 'border-radius':22,138 'border-width':706 'border-width-thick':297 'border-width-thin':287 'box':486,491 'box-shadow':485,490 'brand':219,625 'break':37,450 'build':46 'built':122 'button':5,56,61,160,187,430,573,636,668,687,767 'calendar':9,65,607 'card':174,295 'checkbox':59,167,578 'checklist':685 'chip':185 'choic':276 'clear':280 'coher':42 'color':310,313,317,321,325,329,347,355,524,530,535,539,549,554 'color-bord':312,523 'color-error':328,534 'color-primari':320,529,548,553 'color-text-secondari':538 'colour':25,507,511,519,571,672 'combobox':619 'common':79 'compon':2,13,47,52,91,104,106,134,143,232,361,377,382,388,395,400,406,413,418,424,458,474,503,517,560,563,622,701,722,730,749,772 'component-family-consist':1 'component-height-lg':412 'component-height-md':376 'component-height-sm':394 'component-padding-x-lg':417 'component-padding-x-md':381 'component-padding-x-sm':399 'component-padding-y-lg':423 'component-padding-y-md':387 'component-padding-y-sm':405 'consist':4,49,222,461,497,630,758,764 'contain':234 'cosmet':447 'could':769 'css':155,286,372 'date':66,605 'default':292,373 'defin':129 'depend':217 'deriv':152,739 'design':80,108 'disabl':537 'disord':455 'divid':296 'dna':81,128 'dropdown':476,499 'e.g':255,710 'elev':498 'elsewher':648 'error':326,330,350,356,532,536,724,734 'everi':50,102,133 'everywher':349,357 'exist':780 'famili':3,17,48,75,561 'featur':302 'feel':93,116,284 'fill':547,574 'flat':671 'float':473 'focus':318,342,348,479,480,495,526,715,721 'form':14,194,231,451,693 'full':180,206,216,585,590,595,604,614,757 'gradient':620,627,632,641,646,657,665,760 'height':360,368,378,396,414,443,449,567,697 'hierarchi':279 'high':238 'hover':551,652 'hue':661 'ident':339,718,727 'inconsist':34 'increment':267 'independ':747 'indic':307 'inherit':135 'input':6,57,161,190,294,332,433,575,618,689 'intent':285 'interact':12,51,142,457 'intern':370 'invent':154 'isol':110 'item':303 'larg':176,411 'layout':452 'lg':172,415,421,427 'librari':777 'light':658 'like':269 'limit':247,275 'logic':26,463,508,572 'look':88,717,726 'make':277 'md':374,379,385,391,506 'member':562 'mismatch':448 'modal':175 'must':195,439 'new':771 'next':435 'one':676 'opac':544,559 'open':501 'option':254,596,709 'other':674 'outlin':483 'pad':371,383,389,401,407,419,425 'panel':177 'part':119 'per':678,748 'pick':675 'picker':67,606 'pill':7,62,182,201,591,751 'place':434 'popov':500 'primari':322,531,550,555,635 'product':43,55,100,115,283,651 'radio':60,582 'radius':24,140,148,157,164,171,179,199,205,211,215,565,580,584,589,594,599,603,609,613,737,756 'radius-bas':156,608 'radius-ful':178,204,214,583,588,593,602,612,755 'radius-lg':170 'radius-sm':163,210,579,598 'rather':120 'reduc':543 'rest':341,465,521 'restrict':239 'review':684 'rhythm':33 'ring':481,496,528 'role':512 'rule':246 'scale':28,268,366 'search':617 'secondari':541 'select':58,162,336,475,545,577 'sens':39 'set':240,746 'shadow':27,456,462,467,470,487,492,505 'shadow-md':504 'shadow-x':469 'share':19,77,112,127,367,564,566,568,570,694 'shift':655 'signal':454 'size':375 'skill' 'skill-component-family-consistency' 'slider':68,611 'slight':654 'sm':165,212,397,403,409,581,600 'small':168,393 'source-dembrandt' 'space':32,358 'state':343,351,518,653,716,725 'step':245 'stop':644 'style':30,227 'switch':587 'tag':64,183,592,753 'text':540 'textarea':576 'thick':300 'thin':290 'thumb':616 'toggl':69,586 'token':113,131,149,242,520,744,781 'tone':220 'topic-accessibility' 'topic-agent-skills' 'topic-claude-code-skills' 'topic-claude-skills' 'topic-cursor-skills' 'topic-design-system' 'topic-design-tokens' 'topic-enterprise-ux' 'topic-gestalt' 'topic-skills-sh' 'topic-typography' 'topic-ui-design' 'track':615 'trigger':477 'two':253,705 'uniform':514 'univers':683 'unless':488 'usag':647,761 'use':44,144,236,265,344,352,459,489,626,638,664,702,754,778 'user':83 'valu':738 'var':311,319,327 'variant':669,679,768 'variat':150 'via':482 'visual':16,74,365 'whole':125 'width':249,289,299,708 'without':111 'x':384,402,420 'xs':471 'y':390,408,426","prices":[{"id":"4bd0c660-72c7-4404-988a-68da5a060f50","listingId":"5ecce615-4eb6-42a9-a71f-6d9d0e598b99","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"dembrandt","category":"dembrandt-skills","install_from":"skills.sh"},"createdAt":"2026-05-18T13:14:00.679Z"}],"sources":[{"listingId":"5ecce615-4eb6-42a9-a71f-6d9d0e598b99","source":"github","sourceId":"dembrandt/dembrandt-skills/component-family-consistency","sourceUrl":"https://github.com/dembrandt/dembrandt-skills/tree/main/skills/component-family-consistency","isPrimary":false,"firstSeenAt":"2026-05-18T13:14:00.679Z","lastSeenAt":"2026-05-18T19:08:26.443Z"}],"details":{"listingId":"5ecce615-4eb6-42a9-a71f-6d9d0e598b99","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"dembrandt","slug":"component-family-consistency","github":{"repo":"dembrandt/dembrandt-skills","stars":9,"topics":["accessibility","agent-skills","claude-code-skills","claude-skills","cursor-skills","design-system","design-tokens","enterprise-ux","gestalt","skills-sh","typography","ui-design","ux","wcag"],"license":"mit","html_url":"https://github.com/dembrandt/dembrandt-skills","pushed_at":"2026-05-14T22:34:06Z","description":"UX and design system skills for AI agents based on 20 years of experience","skill_md_sha":"1f666718525f96ab42bae562bd94433d55b96331","skill_md_path":"skills/component-family-consistency/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/dembrandt/dembrandt-skills/tree/main/skills/component-family-consistency"},"layout":"multi","source":"github","category":"dembrandt-skills","frontmatter":{"name":"component-family-consistency","description":"Buttons, inputs, pills, badges, calendars, and other interactive components form a visual family — they share the same border-radius, colour logic, shadow scale, border style, and spacing rhythm. Inconsistency between them breaks the sense of a coherent product. Use when building or reviewing a component library, design system, or any set of UI components."},"skills_sh_url":"https://skills.sh/dembrandt/dembrandt-skills/component-family-consistency"},"updatedAt":"2026-05-18T19:08:26.443Z"}}