ux-feedback-patterns

UX Feedback Patterns Skill

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ux-feedback-patterns" with this command: npx skills add matthewharwood/fantasy-phonics/matthewharwood-fantasy-phonics-ux-feedback-patterns

UX Feedback Patterns Skill

User feedback mechanisms for communicating state changes, success, errors, and progress. This skill covers visual, auditory, and haptic feedback patterns.

Related Skills

  • material-symbols-v3 : Icon names for status indicators (check_circle , error , warning )

  • ux-iconography : Icon + text patterns for feedback

  • ux-animation-motion : Anime.js animations for feedback effects

Feedback Types

  1. Inline Feedback

Immediate feedback near the action:

<button>Save</button> <span class="inline-feedback" role="status" aria-live="polite"> Saved successfully </span>

.inline-feedback { font-size: var(--step--1); color: var(--color-success); opacity: 0; transition: opacity 0.2s ease; }

.inline-feedback.visible { opacity: 1; }

  1. Toast Notifications

Non-blocking temporary messages as a web component:

class ToastContainer extends HTMLElement { #container; // Direct reference - NO querySelector

constructor() { super(); this.attachShadow({ mode: 'open' });

// Build and store direct reference
this.#container = document.createElement('div');
this.#container.className = 'toast-container';
this.#container.setAttribute('part', 'container');

this.shadowRoot.appendChild(this.#container);

}

show(message, type = 'info', duration = 3000) { const toast = document.createElement('div'); toast.className = toast toast-${type}; toast.setAttribute('role', 'alert'); toast.setAttribute('part', 'toast'); toast.textContent = message;

this.#container.appendChild(toast);  // Direct reference

// Auto-dismiss
setTimeout(() => {
  toast.classList.add('exiting');
  toast.addEventListener('animationend', () => toast.remove());
}, duration);

} }

customElements.define('toast-container', ToastContainer);

.toast { padding: var(--space-s) var(--space-m); background: var(--theme-surface-variant); border-radius: var(--space-2xs); animation: slideIn 0.2s ease; }

.toast-success { border-left: 4px solid var(--color-success); }

.toast-error { border-left: 4px solid var(--color-error); }

.toast.exiting { animation: slideOut 0.2s ease forwards; }

  1. Confirmation Dialogs

For destructive or important actions:

<dialog class="confirm-dialog"> <h2>Confirm Action</h2> <p>Are you sure you want to proceed?</p> <div class="dialog-actions"> <button class="btn-secondary">Cancel</button> <button class="btn-danger">Delete</button> </div> </dialog>

  1. Progress Indicators

For long-running operations:

<!-- Determinate progress --> <progress value="60" max="100" aria-label="Upload progress">60%</progress>

<!-- Indeterminate/spinner --> <div class="spinner" role="status" aria-label="Loading"> <span class="sr-only">Loading...</span> </div>

Success Feedback

Visual Patterns

/* Success color */ .success { color: var(--color-success); }

/* Success icon - use Material Symbol / / <span class="icon" aria-hidden="true">check_circle</span> */ .icon-success { color: var(--color-success); }

/* Success border */ .input-success { border-color: var(--color-success); }

Animation

import { successBounce, glow } from '../../utils/animations.js';

// On successful action successBounce(element); glow(element, { color: 'rgba(74, 222, 128, 0.6)' });

Announcements

announce(message) { // For screen readers this.#announcer.textContent = ''; requestAnimationFrame(() => { this.#announcer.textContent = message; }); }

// Usage this.announce('Word completed! 3 points earned.');

Error Feedback

Visual Patterns

/* Error color */ .error { color: var(--color-error); }

/* Error state */ [aria-invalid="true"] { border-color: var(--color-error); }

/* Error message */ .error-message { color: var(--color-error); font-size: var(--step--1); }

Shake Animation

import { shake } from '../../utils/animations.js';

// On validation failure shake(inputContainer, { intensity: 6 });

Error Message Structure

<div class="field"> <input aria-invalid="true" aria-describedby="error-1"> <span id="error-1" class="error-message" role="alert"> Please enter a valid email address </span> </div>

Loading States

Button Loading

.button[aria-busy="true"] { position: relative; color: transparent; pointer-events: none; }

.button[aria-busy="true"]::after { content: ''; position: absolute; inset: 0; margin: auto; width: 1em; height: 1em; border: 2px solid currentColor; border-right-color: transparent; border-radius: 50%; animation: spin 0.6s linear infinite; }

Skeleton Loading

.skeleton { background: linear-gradient( 90deg, var(--theme-surface-variant) 25%, var(--theme-surface) 50%, var(--theme-surface-variant) 75% ); background-size: 200% 100%; animation: shimmer 1.5s infinite; border-radius: var(--space-2xs); }

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

Page Loading

<div class="loading-overlay" role="status"> <div class="spinner"></div> <span class="sr-only">Loading game...</span> </div>

Progress Indicators

Linear Progress

.progress-bar { height: 4px; background: var(--theme-outline-variant); border-radius: 2px; overflow: hidden; }

.progress-fill { height: 100%; background: var(--theme-primary); transition: width 0.3s ease; }

Step Progress

<ol class="steps" aria-label="Progress"> <li data-status="complete" aria-current="false">Step 1</li> <li data-status="current" aria-current="step">Step 2</li> <li data-status="pending" aria-current="false">Step 3</li> </ol>

.steps [data-status="complete"] { color: var(--color-success); }

.steps [data-status="current"] { color: var(--theme-primary); font-weight: 600; }

.steps [data-status="pending"] { color: var(--theme-on-surface-variant); }

Circular Progress

.progress-circle { --progress: 0; width: 60px; height: 60px; border-radius: 50%; background: conic-gradient( var(--theme-primary) calc(var(--progress) * 1%), var(--theme-outline-variant) 0 ); }

Live Regions

Status Updates

<div role="status" aria-live="polite" aria-atomic="true"> Score: 42 points </div>

Alerts

<div role="alert" aria-live="assertive"> Session expired. Please log in again. </div>

Implementation

class Announcer { #region;

constructor() { this.#region = document.createElement('div'); this.#region.setAttribute('role', 'status'); this.#region.setAttribute('aria-live', 'polite'); this.#region.setAttribute('aria-atomic', 'true'); this.#region.className = 'sr-only'; document.body.appendChild(this.#region); }

announce(message, priority = 'polite') { this.#region.setAttribute('aria-live', priority); this.#region.textContent = ''; requestAnimationFrame(() => { this.#region.textContent = message; }); } }

Timing Guidelines

Feedback Type Duration Use Case

Micro-animation 100-200ms Button press, toggle

State transition 200-300ms Page change, modal

Toast display 3-5 seconds Success message

Error display Until dismissed Validation error

Loading indicator Immediate Any async operation

Accessibility Checklist

  • Success/error announced to screen readers

  • Focus moved to relevant element after action

  • Loading states communicated with aria-busy

  • Progress communicated with proper ARIA

  • Animations respect prefers-reduced-motion

  • Color is not the only indicator of state

  • Error messages are associated with inputs

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

ux-spacing-layout

No summary provided by upstream source.

Repository SourceNeeds Review
General

animejs-v4

No summary provided by upstream source.

Repository SourceNeeds Review
General

audio-design

No summary provided by upstream source.

Repository SourceNeeds Review
General

web-components-architecture

No summary provided by upstream source.

Repository SourceNeeds Review