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

loading-states-and-perceived-performance — скилл для Claude Code

Скилл для ИИ-кодинга, который помогает выбрать спиннер, скелетон или прогресс-бар и сделать интерфейс быстрее на ощупь.

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

Что делает loading-states-and-perceived-performance

Скилл про состояния загрузки: спиннеры, скелетон-экраны, ступенчатое появление секций. Он подсказывает, какой паттерн брать под конкретную длительность ожидания — короткий спиннер для кнопки, скелетон для карточек и списков, детерминированный прогресс-бар для долгих операций. Внутри есть готовые CSS-фрагменты: анимация вращения, эффект мерцания через градиент, каскадное появление секций по индексу.

Отдельный блок — порядок загрузки. Сначала показывается самое ценное для пользователя, остальное подтягивается следом, а данные для вкладок и скрытых секций запрашиваются только при открытии. Есть приём с предзагрузкой предсказуемого следующего шага и оптимистичный UI, когда интерфейс обновляется до ответа сервера и откатывается при ошибке. Для ожиданий дольше пары секунд скилл советует добавить микрокопирайт в голосе бренда вместо безликого «Loading...».

Скилл подхватывается по путям components/**, **/*.tsx, **/*.jsx, **/*.css, **/*.scss — то есть в проектах на React и вёрстке он сработает сам, а в бэкендном коде его не вызовут. Скелетоны требуют дисциплины: если форма заглушки не совпадает с финальным контентом, появляется сдвиг макета, и выигрыш в восприятии теряется.

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

  • выбрать между спиннером и скелетоном для конкретного экрана
  • убрать сдвиг макета при подгрузке списка
  • показать главное число до того, как догрузится остальное
  • сделать ожидание длинной операции понятным
  • предзагрузить следующую страницу, чтобы переход был мгновенным

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

  • какое состояние загрузки подойдёт этой карточке?
  • добавь skeleton loader для этого списка
  • сделай так, чтобы страница казалась быстрее во время загрузки

Как установить loading-states-and-perceived-performance

1Через Skills CLI (Vercel)

npx skills add dembrandt/dembrandt-skills --skill loading-states-and-perceived-performance -a claude-code

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

~/.claude/skills/loading-states-and-perceived-performance/SKILL.md

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

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

Вопросы о loading-states-and-perceived-performance

Как установить loading-states-and-perceived-performance в Claude?

Выполните npx skills add dembrandt/dembrandt-skills --skill loading-states-and-perceived-performance -a claude-code. Скилл окажется в ~/.claude/skills/loading-states-and-perceived-performance/SKILL.md.

Что делает loading-states-and-perceived-performance?

Помогает выбрать паттерн загрузки под длительность ожидания и даёт CSS для спиннеров, скелетонов и ступенчатого появления секций. Ещё разбирает порядок загрузки, предзагрузку и оптимистичный UI.

Где скилл срабатывает сам?

По путям components/**, src/components/**, **/*.tsx, **/*.jsx, **/*.css, **/*.scss и design-system/**. В файлах вне этих шаблонов его нужно вызывать вручную.

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

SKILL.md · MIT
---
name: loading-states-and-perceived-performance
description: Spinners, skeletons and staggered reveals that manage wait times. Use when designing loading states, async data or the feel of a slow interface.
metadata:
  priority: 7
  pathPatterns:
    - "components/**"
    - "src/components/**"
    - "**/*.tsx"
    - "**/*.jsx"
    - "**/*.css"
    - "**/*.scss"
    - "design-system/**"
  promptSignals:
    phrases:
      - "loading state"
      - "spinner"
      - "skeleton screen"
      - "skeleton loader"
      - "perceived performance"
      - "loading animation"
      - "shimmer effect"
      - "staggered loading"
      - "prefetch"
      - "prioritise loading"
      - "progressive loading"
      - "lazy load data"
retrieval:
  aliases:
    - loading states
    - skeleton loaders
    - spinners
    - perceived performance
    - shimmy
    - glimmer
    - prefetching
    - priority loading
    - progressive data loading
  intents:
    - design a loading state
    - add a skeleton screen
    - improve perceived performance
    - choose between spinner and skeleton
    - handle slow data loading
    - adding delight to the wait
    - load the most important content first
    - prefetch the likely next step
  examples:
    - what loading state should this card use
    - add a skeleton loader for this list
    - make the page feel faster while loading
    - design a spinner for this button
    - load the key content first then stream the rest
    - prefetch the next page so it feels instant
---

# Loading States and Perceived Performance

Users don't mind waiting as much if they understand *what* they are waiting for and *how much* progress is being made. Perceived performance is the design work of making a system feel faster than it actually is.

---

## Choosing the Right Loading State

| Wait Duration | Best Pattern | Use for |
|---|---|---|
| **Short (< 1s)** | **Inline Spinner / Loader** | Button actions, small updates, quick data fetches |
| **Medium (1s – 3s)** | **Skeleton Screen** | Cards, lists, dashboards, profile pages |
| **Long (> 3s)** | **Determinate Progress Bar** | File uploads, complex exports, heavy processing |
| **Full Page** | **Staggered Entry / Animated Sections** | Initial app load, hero sections, immersive transitions |

---

## Simple Cases: Spinners and Loaders

Use spinners for small, contained actions where the layout doesn't change significantly.

- **Button Spinners:** Replace button text or sit alongside it. The button should enter a `disabled` state to prevent double-submissions.
- **Micro-Loaders:** A small 16–24px circle for inline updates (e.g., saving a single field).
- **Animation Tip:** A "spring-loaded" rotation (easing in and out) feels more premium than a constant linear rotation.

```css
@keyframes spin {
  0%   { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
.spinner {
  animation: spin 800ms cubic-bezier(0.4, 0, 0.2, 1) infinite;
}
```

---

## Skeleton Screens (Glimmer/Shimmer)

Skeleton screens provide a visual placeholder that mimics the layout of the final content. This reduces "layout shift" (CLS) and signals to the user exactly where the content will appear.

### The Shimmer Effect
A subtle, moving gradient that travels across the skeleton elements.

```css
.skeleton {
  background: var(--color-grey-100);
  background-image: linear-gradient(
    90deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 255, 255, 0.5) 50%,
    rgba(255, 255, 255, 0) 100%
  );
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

@keyframes shimmer {
  0%   { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
```

### Rules for Skeletons
- **Match the shape:** If the final content is a round avatar, use a round skeleton. If it's a 2-line heading, use two bars of varying widths.
- **Stay Recessive:** Skeletons should use your most subtle grey (`--color-grey-100` or `grey-50`). They should not draw focus.
- **Fade into Reality:** When data arrives, fade the actual content in over the skeleton (150–200ms) rather than snapping.

---

## Fully Animated Sections

For major page transitions or initial loads, use a coordinated animation strategy.

### Staggered Entry (Cascading)
Instead of the whole page appearing at once, animate sections in a sequence. This guides the user's eye from the most important content (hero) down to secondary areas.

```css
.section {
  opacity: 0;
  transform: translateY(10px);
  animation: slide-up 400ms ease-out forwards;
}
/* Stagger by index */
.section:nth-child(1) { animation-delay: 100ms; }
.section:nth-child(2) { animation-delay: 200ms; }
.section:nth-child(3) { animation-delay: 300ms; }

@keyframes slide-up {
  to { opacity: 1; transform: translateY(0); }
}
```

### Hero Section "Bloom"
For hero sections, you might use a more complex animation:
1. **Background image** fades in slowly.
2. **Heading** slides in with a slight overshoot (spring).
3. **CTA button** appears last with a crisp fade-in or subtle color transition.

---

## Load in Priority Order — and Prefetch What's Next

Don't wait for everything before showing anything. Load in the order of **value to the user**, so the thing they came for appears first and the rest fills in around it. This is both a perceived-performance win and a code-efficiency one: you fetch and render less up front.

- **First, the highest-value content** — the key figure, the primary record, the above-the-fold answer. Render it the moment it's ready.
- **Then the next tier, then the next** — secondary panels, related lists, and below-the-fold sections stream in behind it (skeletons hold their space so nothing shifts — see the skeleton section above).
- **Fetch only what the current view needs.** Defer data for tabs, drawers, and off-screen sections until they're opened, rather than loading the whole page's worth of data at once.

**Prefetch the predictable next step** — next page, a hovered row's detail, the next wizard step — in the background so it's instant. Don't speculatively load everything; only where there's an obvious next move.

## Advanced: Optimistic UI

The fastest UI is one that doesn't wait for the server at all.
- **The Pattern:** Update the UI immediately assuming the server call will succeed. If it fails, roll back and show an error.
- **Use for:** Liking a post, toggling a switch, renaming a folder, deleting a message.
- **Benefit:** Instant gratification for the user, making the app feel "lightning fast."

---

## Adding Delight to the Wait

Loading doesn't have to be a neutral experience. For waits longer than 2 seconds, consider adding brand personality and "delight" to keep the user engaged.

### Brand-Aligned Micro-copy
Replace generic "Loading..." text with wording that reflects the brand's voice.
- **Technical:** "Compiling data...", "Syncing with cloud..."
- **Playful:** "Gathering pixels...", "Brewing your dashboard...", "Almost there!"
- **Professional:** "Preparing your report...", "Verifying details..."

### Branded Animations (Lottie/SVG)
For significant loading moments (initial app boot, complex data processing), replace the standard spinner with a small, brand-specific animation. 
- A designer's tool might show a pencil drawing a line.
- A fitness app might show a pulsing heart or a moving runner icon.
- A financial tool might show coins stacking or a chart line moving upward.

### Progressive Storytelling
If a wait is consistently long (3s+), use the loading area to tell a small story or provide value:
- **Tips & Tricks:** "Did you know you can use Ctrl+K to search?"
- **Process Transparency:** Show what the system is doing: "Checking database..." → "Optimising results..." → "Finalising view..."

### Visual Transitions (Arrival)

When transitioning from a loading state to content, use a crisp fade-in (150ms) to make the arrival feel like a reward. Avoid scaling the incoming content, as it can cause layout instability.

## The Cursor Is Not a Loading State

The cursor signals affordance: the arrow for ordinary content, `pointer` for something that can be acted on. It never signals progress. A `cursor: wait` or `cursor: progress` puts the status where the user is not looking, says nothing about what is loading or how far along it is, and disappears the moment the pointer moves. Show progress in the element or region that is actually waiting, which [[button-states]] covers for a control and the skeleton and progress patterns above cover for a region.

## What a Loading State Cannot Do

A loading state buys patience. It does not buy time, and it cannot rescue a request that is going to fail. The thresholds below are the long-established response-time limits, not a new finding; what follows from them is the part usually skipped.

- **Up to about 10 seconds:** a spinner or skeleton carries the wait.
- **Beyond that:** the interface needs real progress and a way to cancel. An indeterminate animation has stopped being information and become decoration over an unknown.
- **Past about 30 seconds:** people read the application as stuck whatever is animating, and start reloading or leaving.

**When a request routinely crosses those thresholds, the fix is the request.** If it is heading for a backend timeout, a richer indicator only delays the error the user was always going to get, while hiding from the team that the product is broken. The spinner moves the failure later, so nobody fixes the cause, and people abandon the task anyway.

**When the wait is genuinely irreducible, the fix is not the request either.** A large export, a model call, a video transcode: some work takes the time it takes, and no indicator shortens it. There the answer is to take the work out of the view. Accept the job, tell the user it is running, release them to do something else, and notify them when it lands, with the result waiting somewhere they can find it. Holding a person in front of a progress bar for two minutes is a choice, and it is rarely the one they would make. The failure to avoid is treating an irreducible wait as a performance bug and an optimisable one as a fact of life; they need opposite responses, so decide which you have before you design the wait.

---

## Review Checklist

- [ ] Is the loading state appropriate for the expected wait duration (spinner vs skeleton)?
- [ ] Does the skeleton screen match the physical layout of the incoming content?
- [ ] Is there a subtle shimmer animation on skeletons to signal "active loading"?
- [ ] Are buttons disabled during loading to prevent duplicate actions?
- [ ] Does content fade in over skeletons (150–200ms) rather than blinking into existence?
- [ ] For full-page loads, is a staggered entry used to guide the eye?
- [ ] Is `prefers-reduced-motion` respected for all loading animations?
- [ ] In "Optimistic UI" moments, is there a clear rollback path if the action fails?
- [ ] Does content load in priority order (highest-value first, rest streaming in), fetching only what the current view needs rather than everything up front?
- [ ] Where the next step is predictable, is it prefetched so it feels instant — without speculatively loading everything?

## Common Anti-Patterns

| Anti-pattern | Problem | Fix |
|---|---|---|
| A global spinner that blocks the whole app | High frustration, user cannot browse other areas | Use contextual loaders or skeletons |
| Skeletons that don't match the final layout | Massive layout shift (CLS) when data arrives | Match shapes and sizes exactly |
| Too many spinners on one page | Visual noise, feels like the whole app is broken | Group loading states into a single container skeleton |
| Faster-than-light skeletons | Shimmer animation that is too fast or high-contrast | Keep shimmer slow (1.5s+) and very subtle |

© dembrandt · MIT · dembrandt/dembrandt-skills

Похожие скиллы

Всё по теме «Фронтенд и UI» →
loading-states Owl-Listener Проектирует состояния ожидания: скелетоны, индикаторы, постепенную загрузку и оптимистичные обновления. Нужен, когда контент или действие не завершаются сразу. CX Codex +1 2 200установок animate emilkowalski Создаёт анимации интерфейса с нуля по принципам Эмиля Ковальски. Пригодится при верстке переходов или оживлении компонентов. CX Codex +1 172 700установок hallmark Nutlope Скилл для ИИ-кодинга, который заставляет сгенерированные интерфейсы выглядеть сделанными, а не сгенерированными. Пригодится, когда просишь агента собрать новую страницу или сайт. CX Codex +1 70 800установок daisyui saadeghi Скилл подключает к ИИ-агенту справочник компонентов daisyUI 5, чтобы тот писал разметку на готовых классах, а не выдумывал свои. CX Codex +1 12 100установок frontend-design cline Скилл задаёт агенту смелое визуальное направление и заставляет доводить код до продакшн-уровня. Пригодится, когда интерфейс не должен выглядеть как типовой вывод нейросети. CX Codex +1 7 300установок uncodixfy cyxzdev Учит агента не генерировать типичный «кодексовый» интерфейс: без градиентов, плавающих панелей и декоративных заголовков. Пригодится, когда фронтенд от ИИ выглядит слишком шаблонно. CX Codex +1 5 600установок

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

gestalt-ui-organisation Скилл раскладывает контролы по принципам гештальта, чтобы пользователь видел, что к чему относится, без чтения подписей. Пригодится при вёрстке тулбаров, форм, навигации и дашбордов. CX Codex +1 879установок visual-emphasis-and-hierarchy Задаёт правила визуальной иерархии в интерфейсе: акценты на кнопках, контраст, отступы и выделение текста. Пригодится при вёрстке дашбордов, карточек и баннеров. CX Codex +1 874установок button-states Скилл описывает шесть состояний интерактивных элементов и выводит цвета hover и active из базового цвета по HSL. Пригодится, когда кнопки в проекте выглядят незаконченными. CX Codex +1 877установок component-family-consistency Скилл следит, чтобы кнопки, поля ввода, бейджи и пилюли делили радиус, цвета, тени, границы и отступы. Пригодится при сборке или ревизии библиотеки компонентов. CX Codex +1 874установок generate-ui-from-brand Превращает URL сайта или файл DESIGN.md в дизайн-токены, решения по UX и готовую спецификацию интерфейса. CX Codex +1 870установок micro-interactions Скилл для мелких осмысленных анимаций: переключатели, иконки, моменты успеха. Пригодится, когда интерфейсу не хватает отклика. CX Codex +1 869установок status-colors-and-errors Скилл задаёт правила для семантических цветов статусов и текстов ошибок: сколько цветов держать, что каждый значит и как написать сообщение с выходом из ситуации. CX Codex +1 859установок elevation-and-depth Задаёт правила для теней, скруглений и глубины интерфейса в CSS. Помогает агенту правильно оформлять карточки, модальные окна, выпадающие списки и тултипы. CX Codex +1 854установок

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

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