К основному содержанию
скилл CX Codex

button-states — скилл для Claude Code: состояния кнопок

Скилл описывает шесть состояний интерактивных элементов и выводит цвета hover и active из базового цвета по HSL. Пригодится, когда кнопки в проекте выглядят незаконченными.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add dembrandt/dembrandt-skills --skill button-states -a claude-code
Открыть на GitHub

Что делает button-states

Скилл задаёт шесть состояний: rest, hover, active (pressed), focus, disabled и loading. Для каждого указан триггер и визуальный сигнал — от курсора pointer в покое до спиннера при асинхронной операции. Цвета hover и active не подбираются на глаз: они считаются из базового цвета сдвигом светлоты в HSL, hover темнее на 8%, active на 14%. Для светлых кнопок на тёмном фоне логика переворачивается — светлеть при наведении.

Внутри есть готовые блоки CSS: основной и вторичный вариант кнопки, focus через outline с отступом 2–4px, disabled с opacity: 0.4 и pointer-events: none, loading с сохранением ширины кнопки, чтобы не дёргался layout. Отдельно разобран масштаб при нажатии: держите scale в диапазоне 0.95–0.98, ниже кнопка выглядит сломанной. Скилл подхватывается по путям вроде components/**, **/*.css, **/*.tsx и по фразам вроде «hover state» или «loading state».

Фокусное кольцо обязательно для навигации с клавиатуры, и на hover тут полагаться нельзя — клавиатурный пользователь его не вызывает. Поэтому правило outline: none без замены скилл считает ошибкой. Курсор во время загрузки не меняется: прогресс показывает сам элемент, а не место, где стоит мышь. В конце идёт чек-лист из восьми пунктов для ревью компонента.

Какие задачи решает

  • дорисовать hover и active для кнопки из базового цвета
  • сделать видимое фокусное кольцо для навигации с клавиатуры
  • показать загрузку на кнопке и заблокировать повторную отправку
  • привести disabled к единому виду во всех компонентах
  • проверить состояния интерактивных элементов перед ревью

Примеры запросов агенту

  • какого цвета должен быть hover у этой кнопки
  • сделай все состояния для этой кнопки
  • как показать состояние загрузки на кнопке

Как установить button-states

1Через Skills CLI (Vercel)

npx skills add dembrandt/dembrandt-skills --skill button-states -a claude-code

2Вручную: положить файлы

~/.claude/skills/button-states/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/button-states/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Из того же набора34

user-flows-and-guided-paths Скилл помогает проектировать пошаговые сценарии, визарды, экраны онбординга и чекаута. Подсказывает, как выстроить навигацию и сохранить контекст пользователя. CX Codex +1 879установок responsive-paradigms Задаёт для ИИ-агента правила адаптивной вёрстки: делит мобильные, планшетные и десктопные интерфейсы на разные парадигмы взаимодействия, а не просто масштабирует один макет. CX Codex +1 875установок gestalt-ui-organisation Скилл раскладывает контролы по принципам гештальта, чтобы пользователь видел, что к чему относится, без чтения подписей. Пригодится при вёрстке тулбаров, форм, навигации и дашбордов. CX Codex +1 879установок visual-emphasis-and-hierarchy Задаёт правила визуальной иерархии в интерфейсе: акценты на кнопках, контраст, отступы и выделение текста. Пригодится при вёрстке дашбордов, карточек и баннеров. CX Codex +1 874установок component-family-consistency Скилл следит, чтобы кнопки, поля ввода, бейджи и пилюли делили радиус, цвета, тени, границы и отступы. Пригодится при сборке или ревизии библиотеки компонентов. CX Codex +1 874установок loading-states-and-perceived-performance Скилл для ИИ-кодинга, который помогает выбрать спиннер, скелетон или прогресс-бар и сделать интерфейс быстрее на ощупь. CX Codex +1 871установок generate-ui-from-brand Превращает URL сайта или файл DESIGN.md в дизайн-токены, решения по UX и готовую спецификацию интерфейса. CX Codex +1 870установок micro-interactions Скилл для мелких осмысленных анимаций: переключатели, иконки, моменты успеха. Пригодится, когда интерфейсу не хватает отклика. CX Codex +1 869установок

Похожие

buttons-ctas dylantarre Скилл для ИИ-кодинга, который подсказывает агенту, как анимировать кнопки и CTA: состояния, тайминги, CSS-переходы. CX Codex +1 550установок editorial typeui.sh Скилл задаёт правила редакционного дизайна: серифная типографика, 8pt-сетка, токены цветов и проверки доступности. Пригодится, когда верстаете лонгрид или документацию. CX Codex +1 2 700установок claymorphism typeui.sh Скилл задаёт ИИ-агенту правила дизайн-системы claymorphism: мягкие объёмные формы, палитра, типографика, состояния компонентов. CX Codex +1 2 400установок tailwind-design-system sickn33 Скилл задаёт агенту рамки работы с Tailwind: токены, варианты компонентов, адаптивные паттерны и доступность. Пригодится, когда UI в проекте разъезжается. CX Codex +1 1 600установок ui-ux-polish oakoss Скилл для итеративной доводки интерфейса веб-приложения: отдельно десктоп и мобильные, паттерны вроде glassmorphism и проверка доступности. CX Codex +1 539установок beam-glow-states MengTo Скилл для React-интерфейсов: подключает анимированное свечение границ из пакета border-beam к состояниям загрузки, выбора и фокуса. CX Codex +1 1 300установок

Рядом в теме «Фронтенд и UI»

Всё по теме «Фронтенд и UI» →

Вопросы о button-states

Как установить button-states в Claude?

Выполните npx skills add dembrandt/dembrandt-skills --skill button-states -a claude-code. Файл скилла окажется в ~/.claude/skills/button-states/SKILL.md.

Что делает button-states?

Описывает шесть состояний кнопок и ссылок и показывает, как вывести цвета hover и active из базового цвета через HSL. Плюс даёт готовый CSS для focus, disabled и loading.

На чём скилл ломается?

На outline: none без замены: фокусное кольцо пропадёт, и навигация с клавиатуры станет невидимой. Ещё он не советует менять курсор во время загрузки — прогресс показывает сам элемент.

Исходный текст

SKILL.md · MIT
---
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.
metadata:
  priority: 8
  pathPatterns:
    - "components/**"
    - "src/components/**"
    - "**/*.css"
    - "**/*.scss"
    - "**/tokens/**"
    - "**/*.tsx"
    - "**/*.jsx"
    - "design-system/**"
  promptSignals:
    phrases:
      - "hover state"
      - "active state"
      - "focus state"
      - "disabled"
      - "button states"
      - "interactive states"
      - "loading state"
      - "pressed"
retrieval:
  aliases:
    - button states
    - hover state
    - interactive states
    - focus ring
    - disabled state
    - loading button
  intents:
    - design button states
    - add hover and active states
    - style focus ring
    - handle disabled state
    - add loading state to button
  examples:
    - what colour should the hover state be
    - design all states for this button
    - how do I show a loading state on a button
    - make the focus ring visible
---

# 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 Reference

```css
.btn {
  cursor: pointer;
  background: var(--color-primary);
  color: white;
  border-radius: var(--radius-button);
  padding: var(--component-padding-y-md) var(--component-padding-x-md);
  height: var(--component-height-md);
  border: none;
  transition: background 120ms ease-out, transform 80ms ease-out;
}

.btn:hover           { background: var(--color-primary-hover); }
.btn:active          { background: var(--color-primary-active); transform: scale(0.97); }
.btn:focus-visible   { outline: 2px solid var(--color-primary); outline-offset: 3px; }
.btn:disabled        { opacity: 0.4; cursor: not-allowed; pointer-events: none; }
.btn.btn--loading    { opacity: 0.7; pointer-events: none; }
```

## Review Checklist

- [ ] Does every interactive element have all six states defined?
- [ ] Are hover and active colours derived from the base by lightness adjustment (not chosen arbitrarily)?
- [ ] Is focus state visible and using `outline` (not removed)?
- [ ] Is disabled state low-opacity with `cursor: not-allowed`?
- [ ] Does loading state prevent re-submission?
- [ ] Are transition durations 80–150ms — not instant, not slow?
- [ ] Does `cursor: pointer` appear on all interactive elements at rest?
- [ ] Does the cursor stay unchanged while an action runs, with progress shown by the element itself?

© dembrandt · MIT · dembrandt/dembrandt-skills

Смотрите также

Спонсоры проекта

Компании, которые помогают держать аналитику открытой