Best for
- Use when building or reviewing a component library, design system, or any set of UI components.
dembrandt/dembrandt-skills/skills/component-family-consistency/SKILL.md
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.
Decision brief
Every 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…
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/dembrandt/dembrandt-skills --skill "skills/component-family-consistency"Inspect the Agent Skill "component-family-consistency" from https://github.com/dembrandt/dembrandt-skills/blob/643a0b75f2bacc2d77dd6bae07601ab40128bb12/skills/component-family-consistency/SKILL.md at commit 643a0b75f2bacc2d77dd6bae07601ab40128bb12. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
[ ] Do buttons and inputs on the same form share the same height?
Before creating any component, audit what already exists — a new-from-scratch component is another mouth to feed: another entry in the family that must stay consistent (radius, height, states, motion) and another thing to maintain. Building fresh should be the last resort, not t…
Define these tokens once. Every component inherits from them.
All interactive components use the same base radius token. Variations are derived, not invented.
Borders across all form components and containers should use a highly restricted set of tokens.
Permission review
No configured static risk pattern was detected
This is not proof of safety. Runtime behavior, indirect dependencies, and hidden external systems are outside the static scan.
Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 95/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 47 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Every 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.
When components are designed in isolation without shared tokens, the product feels assembled from parts rather than built as a whole.
Before creating any component, audit what already exists — a new-from-scratch component is another mouth to feed: another entry in the family that must stay consistent (radius, height, states, motion) and another thing to maintain. Building fresh should be the last resort, not the first move. Work down this order:
Button beats PrimaryButton, BigButton, and CtaButton living in parallel.Parallel one-offs — three near-identical buttons, two cards with different radius — are how a design system drifts. Before adding a component, ask: does this exist, or is it one refactor from existing?
The inverse also holds: a visual treatment that appears independently in 2–3 places has earned promotion — name it and make it a shared component or token before a fourth copy appears. And when pages from different design eras disagree, migrate old toward new: the newest components are the best evidence of current intent, but confirm before deprecating a style — see generate-ui-from-brand for the consolidation pass.
Find the inconsistency automatically (dembrandt engine, optional). Spotting where a live product has already diverged — five near-identical button radii, three greys that should be one — is tedious by eye.
get_findingsruns a design-system lint over a real extraction and reports consistency and duplication issues to consolidate. (Andcompute_driftscores how far two extractions have drifted apart — e.g. this product vs. its reference, or before vs. after a cleanup.) Use them to audit an existing product before deciding what to reuse. Seeextract-design.
Define these tokens once. Every component inherits from them.
All interactive components use the same base radius token. Variations are derived, not invented.
--radius-base: 8px; /* buttons, inputs, selects */
--radius-sm: 4px; /* checkboxes, small badges */
--radius-lg: 12px; /* cards, modals, large panels */
--radius-full: 9999px; /* pills, tags, avatar chips */
A 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.
Borders across all form components and containers should use a highly restricted set of tokens.
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.
--border-width-thin: 1px; /* Default for inputs, cards, dividers */
--border-width-thick: 4px; /* Featured items, bold accents, active indicators */
--border-color: var(--color-border);
--border-color-focus: var(--color-primary);
--border-color-error: var(--color-error);
An input border and a select border are identical at rest. Focus state uses --border-color-focus everywhere. Error state uses --border-color-error everywhere.
Components at the same visual scale share height and internal padding.
/* Default (md) size */
--component-height-md: 40px;
--component-padding-x-md: 12px;
--component-padding-y-md: 8px;
/* Small */
--component-height-sm: 32px;
--component-padding-x-sm: 8px;
--component-padding-y-sm: 6px;
/* Large */
--component-height-lg: 48px;
--component-padding-x-lg: 16px;
--component-padding-y-lg: 10px;
A 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.
Interactive components use a consistent shadow logic:
--shadow-xs for floating components (select dropdown trigger)outline, not box-shadow (unless using box-shadow as the focus ring consistently)--shadow-mdThe same colour roles apply uniformly across all components:
| State | Colour token |
|---|---|
| Rest border | --color-border |
| Focus border / ring | --color-primary |
| Error border | --color-error |
| Disabled | --color-text-secondary at reduced opacity |
| Selected / active fill | --color-primary |
| Hover background | --color-primary at 8–12% opacity |
The colour table above defines what each state looks like; this rule governs how many interaction patterns a product is allowed to have. Pick one and reuse it — don't run 3–4 different hover/active/interaction patterns within the same product.
The user already knows what site they're on. Variety between products is expected; variety within one is taxing — every new pattern is another thing to learn mid-task. So converge:
micro-interactions).A tight, repeated interaction vocabulary is what makes a product feel learnable: the user learns the pattern once and trusts it everywhere.
| Component | Shares radius | Shares height | Shares border | Shares colour logic |
|---|---|---|---|---|
| Button | ✓ | ✓ | — (filled) | ✓ |
| Input / textarea | ✓ | ✓ | ✓ | ✓ |
| Select | ✓ | ✓ | ✓ | ✓ |
| Checkbox | --radius-sm | — | ✓ | ✓ |
| Radio | --radius-full | — | ✓ | ✓ |
| Toggle / switch | --radius-full | ✓ | — | ✓ |
| Pill / tag | --radius-full | ✓ | ✓ optional | ✓ |
| Badge | --radius-sm or --radius-full | — | — | ✓ |
| Date picker / calendar | --radius-base | ✓ | ✓ | ✓ |
| Slider | --radius-full (track + thumb) | — | — | ✓ |
| Search input | ✓ | ✓ | ✓ | ✓ |
| Combobox | ✓ | ✓ | ✓ | ✓ |
Shared DNA makes components look related — it must not make them look interchangeable. The riskiest pairs are the ones that share the most: a pill-shaped button next to a pill-shaped badge, a bordered button next to a bordered input. When they blur, users click badges that do nothing and skip buttons that looked like labels.
The rule: role must be readable before interaction. From appearance alone, the user can tell what is clickable, what is editable, and what is read-only.
cursor: pointer, a hover response.Distinguish through at least two visual channels (fill + size, border + cursor) — never by colour alone. Squint test: with labels unreadable, can you still sort the buttons from the badges from the inputs? If not, the family has collapsed into one component.
Generic Badge components lead to misuse — the same component ends up used for statuses, code tokens, keyboard shortcuts, and categorical labels, with style overrides scattered across the codebase.
The pattern: one component per meaning, not one component with many variants.
A product's inline labels typically fall into a small set of distinct meanings. Define a component for each one. Common examples:
| Component | Meaning | Shape |
|---|---|---|
Tag | Categorical label, status, filter | Pill (rounded-full) |
Code | Inline literal, path, key | <code>, mono, tight radius |
Kbd | Keyboard shortcut | <kbd>, mono, tight radius |
Metric | Measured value (1.2s, 42px) | Mono, tight radius |
Add product-specific types as needed (e.g. Flag for CLI products, Token for API products). Each new type gets its own component — not a new variant prop on an existing one.
Each component encodes exactly one meaning. Appearance follows from it — callers never pass colour or shape props.
Sizing: use em-relative padding so a chip renders at the right size for whatever text context it sits in (heading, body, caption) without per-context overrides.
const BASE = "inline-flex items-center align-middle whitespace-nowrap border leading-none";
const PILL = "text-[0.85em] px-[0.6em] py-[0.25em] rounded-full font-medium";
const CHIP = "text-[0.85em] px-[0.5em] py-[0.2em] rounded-[0.4em] font-mono";
export function Tag({ children }: { children: ReactNode }) {
return <span className={`chip-tag ${BASE} ${PILL}`}>{children}</span>;
}
export function Code({ children }: { children: ReactNode }) {
return <code className={`chip-code ${BASE} ${CHIP}`}>{children}</code>;
}
export function Kbd({ children }: { children: ReactNode }) {
return <kbd className={`chip-kbd ${BASE} ${CHIP}`}>{children}</kbd>;
}
Colour: keep per-semantic colours in CSS classes (chip-tag, chip-code, etc.) in one file. Do not inline colour props. This keeps light/dark mode in one place and lets you audit the full chip palette at a glance.
.chip-tag, .chip-code, .chip-kbd, .chip-metric {
background-color: rgba(255, 255, 255, 0.05);
border-color: rgba(255, 255, 255, 0.09);
color: var(--text-secondary);
}
.chip-tag { color: var(--text-primary); }
Back-compat: if existing call sites use a generic Badge, re-export the most common semantic variant as the default so old imports keep working without a migration.
When a line mixes element types — label, badge, status dot, value, icon — they must read as one aligned row, not a jumble of differently-sized pieces.
leading-none and align-middle (as in the chip BASE above) so every element sits on a shared centre line.The smaller the component, the less it can carry. Restraint that looks plain at large sizes is what keeps small components legible.
If the brand uses gradients, apply them consistently:
--radius-full consistently?em-relative sizing so they scale with their text context?Frequently asked questions
Every 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…
The source record exposes this install command: npx skills add https://github.com/dembrandt/dembrandt-skills --skill "skills/component-family-consistency". Inspect the command and pinned source before running it.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
prowler-cloud/prowler
PostgreSQL indexing best practices for Prowler: index design, partial indexes, partitioned table indexing, EXPLAIN ANALYZE validation, concurrent operations, monitoring, and maintenance. Trigger: When creating or modifying PostgreSQL indexes, analyzing query performance with EXPLAIN, debugging slow queries, reviewing index usage statistics, reindexing, dropping indexes, or working with partitioned table indexes. Also trigger when discussing index strategies, partial indexes, or index maintenance
oaustegard/claude-skills
Generate hierarchical _FEATURES.md files that describe what a codebase DOES from a user/consumer perspective, anchored to source symbols via tree-sitting. Supports large complex codebases through feature-driven decomposition into sub-feature files. Uses a multi-pass synthesis: orientation → detail → overview rewrite. Use when someone says "what does this do", "document features", "feature inventory", "_FEATURES.md", or needs to understand a codebase's purpose before modifying it. Complements tre