GitHub

Wandering eyes

A playful pair of animated eyes for expressive or brand-led loading states.

WanderingEyes renders two animated eyes that look around and blink. It works best for search, discovery, queue watching, and brand-led waiting states where a standard spinner would feel too mechanical.

Loading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesDemo() {

Installation

pnpm dlx shadcn@latest add @loading-ui/wandering-eyes

Usage

import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";
<WanderingEyes className="h-12 w-[108px]" />

Customization

WanderingEyes uses a container query box with a fixed 9 / 4 aspect ratio. Set both height and width for predictable layout, inherit color from the surrounding text, and use --duration for the full look-and-blink cycle.

Size

Keep the width about 2.25 times the height so the eyes have room to move.

LoadingLoadingLoading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesSize() {

Color

By default, the eye shape is a faint version of currentColor and the pupil is solid currentColor.

LoadingLoadingLoading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesColor() {

Color Variables

Set --eye-color and --pupil-color when the loader should look more illustrative than inherited.

LoadingLoadingLoading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesVariables() {

Duration

Set --duration to make the gaze feel quick and curious or slower and more ambient.

LoadingLoadingLoading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesDuration() {

Expression

Use eyeScale, gapScale, pupilScale, blinkScale, and travelScale to tune the expression without editing the component.

LoadingLoadingLoading
import { WanderingEyes } from "@/components/loading-ui/wandering-eyes";

export function WanderingEyesExpression() {