button-states
Rest, hover, active, focus, disabled and loading states, derived from the base colour.
Skill by dembrandt
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/dembrandt-button-states
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: frontend, backend
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/button-states
What's inside
- Skill name
button-states- Description
- Rest, hover, active, focus, disabled and loading states, derived from the base colour. Use when designing buttons, links, inputs or any clickable component.
- License
- MIT
- Metadata
- priority: 8
- Instructions
- 151 lines in SKILL.md · view on GitHub
Files (1)
- SKILL.md
SKILL.md (first lines)
# Button and Interactive Element States
Every interactive component must have a complete, visually distinct state for each interaction mode. Missing or ambiguous states make the UI feel unfinished and reduce user confidence.
## The Six States
| State | Trigger | Visual signal |
|---|---|---|
| **Rest** | Default | Base colour, cursor: pointer |
| **Hover** | Mouse over | Slightly darker, subtle background shift |
| **Active / Pressed** | Mouse down / tap | Noticeably darker, slight scale-down |
| **Focus** | Keyboard navigation | Visible focus ring, no change to fill |
| **Disabled** | Not available | Low contrast, cursor: not-allowed, no interaction |
| **Loading** | Async action in progress | Spinner or pulse, non-interactive |
## Deriving State Colours Algorithmically
State colours are not chosen independently — they are derived from the base colour by adjusting lightness in HSL. This guarantees coherence across the entire palette.
```
base: hsl(H, S%, L%)
hover: hsl(H, S%, L% - 8%) ← darken 8%
active: hsl(H, S%, L% - 14%) ← darken 14%
```
### Example: primary button `#635BFF` (hsl 243, 100%, 68%)
```css
.btn-primary {
background: hsl(243, 100%, 68%); /* rest #635BFF */
}
.btn-primary:hover {
background: hsl(243, 100%, 60%); /* hover #4A40FF */
}
.btn-primary:active {
background: hsl(243, 100%, 54%); /* active #3429FF */
}
```
For light buttons on dark backgrounds, invert the logic — lighten on hover instead of darkening.
### Secondary / outlined buttons
```css
.btn-secondary {
background: transparent;
border: 1px solid var(--color-border);
color: var(--color-text);
}
.btn-secondary:hover {
background: var(--color-grey-100); /* subtle fill */
border-color: var(--color-grey-300);
}
.btn-secondary:active {
background: var(--color-grey-200);
}
```
## Focus State
Focus is a keyboard navigation requirement (WCAG 2.2). It must be visible and must not rely on the hover style alone — keyboard users do not trigger hover.
```css
.btn:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 3px;
}
```
- Use `outline`, not `box-shadow`, for focus rings — `outline` respects `border-radius` in modern browsers and does not affect layout
- `outline-offset: 2–4px` gives the ring breathing room from the component edge
- Never use `outline: none` without a replacement focus style
## Disabled State
```css
.btn:disabled,
.btn[aria-disabled="true"] {
opacity: 0.4;
cursor: not-allowed;
pointer-events: none;
}
```
- Disabled elements are exempt from WCAG contrast requirements — low opacity is correct and intentional
- Use `pointer-events: none` to prevent click events even if JS is bypassed
- Do not change the shape or size of a disabled button — only colour and cursor change
## Loading State
When a button triggers an async action, replace the label with a spinner and prevent re-submission.
```css
.btn--loading {
pointer-events: none;
opacity: 0.7;
}
```
**The cursor does not change while loading.** It signals affordance, not progress: the arrow for ordinary content, `pointer` for something you can act on. Progress belongs to the element and the loading region, which the user is already looking at, rather than to wherever the mouse happens to rest. `cursor: wait` is also inert next to `pointer-events: none`, so the rule reads as deliberate while doing nothing.
- Keep the button width stable during loading — avoid layout shift when label is replaced by spinner
- Return to rest state on completion (success or error)
- For long-running operations, pair with a status message — a spinner alone does not tell the user what is happening
## Scale on Active (Optional)
A subtle scale-down on press adds physical feedback — borrowed from Disney's squash principle.
```css
.btn:active {
transform: scale(0.97);
transition: transform 80ms ease-out;
}
```
Keep the scale value between `0.95–0.98`. Below `0.95` feels like the button is breaking.
## Complete Button CSS ReferenceFrom dembrandt/dembrandt-skills, MIT.
More from dembrandt/dembrandt-skills
- 0.785score
algorithmic-color-palette
dembrandt
Derive a full UI palette from one or two brand colours — state variants, brand-tinted greys, semantic colours.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
sticky-and-fixed-elements
dembrandt
Sticky headers, bottom toolbars, floating action buttons and pinned table headers.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
authentic-product-representation
dembrandt
Product visuals must show the real product with real data.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
brand-visual-language
dembrandt
Shape language across type, radius and icons carries brand personality.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
app-shell
dembrandt
Top bar, sidebar rail, app launcher, tenant and environment cue, status bar.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
component-family-consistency
dembrandt
Buttons, inputs, badges and pills share radius, colour logic, shadow, border and spacing.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
data-display-and-selection
dembrandt
View modes, row selection, mass actions, sorting, filters, search and table patterns.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
domain-expert-configuration
dembrandt
Settings for experts who are not developers — domain language, sane defaults, grouping by professional concept.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
elevation-and-depth
dembrandt
Shadows and layering that lift elements above the surface.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
extract-design
dembrandt
Extract colours, typography, spacing, components and W3C design tokens from a live website with Dembrandt.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
color-mode-and-theme
dembrandt
Light, dark or both, and when a theme selector is worth it.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
generate-ui-from-brand
dembrandt
Pipeline from a URL or DESIGN.md to tokens, decisions and a UI spec.
SkillAFreshness: A★ 160Claude Code +9
Signals
- Stars
- 160
- Forks
- 20
- Open issues
- 0
- Last commit (this folder)
- Oct 1, 2026 (26 days ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/dembrandt/dembrandt-skills
- Website
- www.dembrandt.com/skills
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from dembrandt
- 0.792score
Dembrandt
dembrandt
Design tokens from any live site: colours, type, spacing, components, drift against a baseline.
ConnectorAFreshness: ALocal★ 3.8KClaude Code +5 - 0.785score
app-shell
dembrandt
Top bar, sidebar rail, app launcher, tenant and environment cue, status bar.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
authentic-product-representation
dembrandt
Product visuals must show the real product with real data.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
brand-visual-language
dembrandt
Shape language across type, radius and icons carries brand personality.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
color-mode-and-theme
dembrandt
Light, dark or both, and when a theme selector is worth it.
SkillAFreshness: A★ 160Claude Code +9 - 0.785score
algorithmic-color-palette
dembrandt
Derive a full UI palette from one or two brand colours — state variants, brand-tinted greys, semantic colours.
SkillAFreshness: A★ 160Claude Code +9
Cite this page
button-states skill. Agent Mart. https://agentmart.dev/skills/dembrandt-button-states (last updated 2026-10-24)