Skip to content
Native Animation
Smart Widget Stack animation preview
Glass

Smart Widget Stack

A polished vertical stack of glass widgets driven by one continuous, interruptible position.

$9 for this animation

Checkout opens soon. Leave your email and we will tell you the moment you can buy it.

One email when checkout opens. No spam.

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

npx nativeanimation add smart-widget-stack

About this animation

A polished vertical stack of glass widgets driven by one continuous, interruptible position.

How it works

  1. onLayout converts the container into responsive card geometry, so the stack also works inside sheets and tablet layouts.
  2. A single Reanimated shared position drives the swipe, depth order, card transforms, opacity, and every content reveal.
  3. Gesture velocity is projected before the nearest widget is selected, then a spring settles the stack without blocking another gesture.
  4. Weather, calendar, activity, and music are real layouts instead of static mockups. Calendar rails, activity rings, rolling metrics, and music progress derive from the same position.
  5. The front card uses expo-blur, a translucent tint, a highlight edge, and two shadow scales to create depth.

Why this one

Most widget stacks stop at a card transition. This one turns the pattern into a credible home-screen product moment: useful data, continuous 3D depth, accessible point controls, velocity-aware snapping, and an Activity reveal with synchronized ring glows.

Install

npx expo install expo-blur expo-image @shopify/react-native-skia react-native-gesture-handler react-native-reanimated react-native-worklets

Wrap your application with GestureHandlerRootView as described by React Native Gesture Handler. Skia web apps also need CanvasKit initialization before this component is loaded.

Usage

import { SmartWidgetStack } from './SmartWidgetStack';

export function HomeWidgets() {
  return <SmartWidgetStack artwork={require('./cover.jpg')} />;
}
const stackRef = useRef<SmartWidgetStackRef>(null);

<SmartWidgetStack
  ref={stackRef}
  initialIndex={1}
  activityRings={[
    { value: '420/600 cal', progress: 0.7, color: '#FF5C7A' },
    { value: '28/30 min', progress: 0.93, color: '#8BE26A' },
    { value: '9/12 h', progress: 0.75, color: '#48D9F4' },
  ]}
  onIndexChange={(index) => setActiveWidget(index)}
/>

Props

PropTypeDefaultDescription
initialIndexnumber0Initially active widget.
weatherLocationstringSan FranciscoWeather location.
weatherTemperaturestring64°FCurrent temperature.
weatherRangestringH:68° L:56°Daily high and low.
weatherHoursWeatherHour[]Five-hour forecastCompact forecast data.
calendarDatestringFriday, October 10Calendar date.
calendarEventsCalendarEvent[]Two sample eventsSchedule entries.
activityRingsActivityRing[]Three goalsOuter-to-inner ring values.
artworkImageSourcePropType—Music artwork.
trackTitlestringAfterglowTrack title.
artiststringLumen FieldsArtist name.
trackProgressnumber0.58Music progress from zero to one.
fontFamilystringSystemBody typeface.
mediumFontFamilystringSystemHeading typeface.
monoFontFamilystringSystemFigure typeface.
onIndexChange(index: number) => void—Called when snapping changes the active widget.
onWidgetPress(index: number) => void—Called when the front widget is tapped.
accessibilityLabelstringSmart widget stackScreen-reader label.
styleStyleProp<ViewStyle>—Outer container style.
testIDstring—Test identifier.

The ref exposes next(), previous(), and goTo(index).

Compatibility

  • Expo SDK 57
  • React Native 0.86.3
  • Reanimated 4.5.1 and Worklets 0.10.1
  • Skia 2.6.2
  • iOS, Android, and web: unverified
  • Expo Go: supported by the SDK 57 bundled modules; use a development build after adding native dependencies to another Expo project

Accessibility

The stack is exposed as an adjustable control with increment and decrement actions. Every indicator has a 44-point hit area, and tapping the front widget is a button alternative to the swipe gesture. Reduced Motion switches to immediate state changes, disables 3D travel and spring movement, and leaves widget content in its final state.