Beach Ball
A beach ball is a loading/waiting indicator component, inspired by the colorful spinning cursor on macOS that appears when the system is busy. It provides a visual cue that a process is in progress and communicates to users that the system is working on a task.
This headless component renders a <div> with role="status" and aria-live="polite" for non-blocking screen reader announcements of loading state changes. The active prop controls whether the indicator is currently showing, and an inner <span> element serves as the animation target for consumer-applied CSS.
Implementation Notes
- Renders as a
<div>withrole="status"andaria-live="polite"for non-blocking loading announcements aria-busyreflects theactiveprop, signaling to assistive technologies whether loading is in progressdata-activeattribute mirrors the active state for CSS state selectors (e.g.,[data-active="true"])- Inner
<span aria-hidden="true">is only rendered when active; consumers target it for spinning/animation CSS - Uses props for prop destructuring with rest props spread
- No hardcoded strings; all text comes through props for internationalization
Props
label: string (required) -- accessible description of what is loading, viaaria-labelactive: boolean (default:true) -- whether the loading indicator is currently active...restProps: any -- additional HTML attributes spread onto the<div>element
Usage
<BeachBall label="Loading your dashboard" />
<BeachBall label="Processing payment" active={isProcessing} />
<!-- Conditional loading with a fallback message -->
<BeachBall label="Fetching search results" active={isSearching} />
{#if !isSearching}
<p>Showing {results.length} results</p>
{/if}
Keyboard Interactions
- None -- this is a passive informational indicator, not interactive
ARIA
role="status"-- identifies this as a status region that announces updates to screen readersaria-live="polite"-- ensures loading announcements do not interrupt the user's current taskaria-busy-- set totruewhen active, signaling to assistive technologies that content is loadingaria-label-- provides the accessible name describing what is loading, set from thelabelprop
When to Use
- Use as a decorative animated loading indicator for playful or celebratory UI moments
- Use when you want a whimsical, macOS-inspired waiting indicator as an alternative to a standard spinner
- Use during page loads, data fetching, or background processing where the duration is indeterminate
When Not to Use
- Do not use on clinical or transactional pages -- decorative animations are distracting in serious contexts
- Do not use for progress that has a known completion percentage -- use Progress or ProgressCircle instead
- Do not use when placeholder content is more appropriate -- use Skeleton for layout-matching loading states
- Do not use without a
prefers-reduced-motionmedia query -- respect user motion preferences by pausing or hiding the animation
Headless
This component provides role="status", aria-live="polite", aria-busy, and a data-active attribute with an inner <span> animation target, all with zero visual styling. The consumer is responsible for all CSS including the spinning animation, colors, size, and any backdrop or overlay effects.
Styles
The consumer provides all CSS styling. The component renders with a .beach-ball class for targeting. No default styles are included — this is a fully headless component.
Testing
- Verify the component renders a
<div>element with classbeach-ball - Verify role="status"` -- identifies this as a status region that announces updates to screen readers
- Verify aria-label
-- provides the accessible name describing what is loading, set from thelabel` prop - Verify keyboard interactions work correctly
- Verify pass-through attributes are applied
Advice
- Designers: Keep the indicator visually lightweight so it does not overwhelm the content area. Ensure the animation is smooth and not distracting at small sizes.
- Developers: Use the
activeprop to control visibility rather than mounting/unmounting the component, so the live region remains in the DOM for consistent screen reader announcements.
Related components
loading— a loading indicator, such as text, or image, or animationprogress-spinner— an indeterminate spinning progress indicator
References
- WAI-ARIA Status Role: https://www.w3.org/TR/wai-aria-1.2/#status
- ARIA aria-busy: https://www.w3.org/TR/wai-aria-1.2/#aria-busy