Skip to content
Native Animation
Sliced World Clock animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add sliced-world-clock

Sliced World Clock

A world clock with cropped numeral bands and a rotating city wheel, with configurable cities, labels, colors, and fonts.

$9 for this animation

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.

About this animation

A world clock with cropped numeral bands and a rotating city wheel, with configurable cities, labels, colors, and fonts.

Why this one

World clocks usually bury small times in a list. This clock makes time the poster: choosing a city turns all three bands in a staggered mechanical sequence. Warm paper, tonal numerals, and a single glowing orange city marker give the demo its own identity. Northwind is a fictional wordmark from the demo brand kit.

How it works

  1. The host provides cities with IANA time zones or fixed UTC offsets in minutes. IANA formatting respects daylight saving time; an invalid zone falls back to the supplied offset, or UTC.
  2. A one-second timer calculates the local digits and updates six shared values. Numeral text is already mounted, so React does not render numeral text on each tick. Only the hidden accessible time changes once a second; the period label changes at noon and midnight.
  3. Each column translates through two copies of the ten digits, fades by distance, and normalizes to the exact final digit. Each band clips the giant glyphs intentionally, with 1.1× line height.
  4. Dragging controls one continuous wheel position. Release projects velocity to an index, then an interruptible, critically damped spring snaps to that city. Tap a neighboring name or use the grid control to select without dragging.
  5. A city change rolls hours, minutes, and seconds with 45 ms row delays. Changing hour format rolls only the hours unless a normal clock carry happens at the same time.
  6. Reduced motion uses 200 ms numeral fades, immediate wheel placement, and a fading city title. All timers and numeral animations are cleaned up.

Install

npx expo install @shopify/react-native-skia expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-worklets

Validated dependency versions: Skia 2.14.0, LinearGradient ~58.0.3, Gesture Handler ~3.3.0, Reanimated 4.7.1, Worklets 0.13.0. Wrap your screen in GestureHandlerRootView. For web, initialize Skia/CanvasKit before mounting this component, following the Skia web setup; this repository's viewer uses a withSkia lazy wrapper. Icons: Lucide (ISC), copied from the project kit.

Usage

import { SlicedWorldClock } from './sliced-world-clock';

const cities = [
  { id: 'lis', name: 'Lisbon', country: 'Portugal', abbreviation: 'LIS', timeZone: 'Europe/Lisbon' },
  { id: 'tokyo', name: 'Tokyo', country: 'Japan', abbreviation: 'TOKYO', timeZone: 'Asia/Tokyo' },
];

<SlicedWorldClock cities={cities} city="lis" />;
const clock = useRef<SlicedWorldClockRef>(null);

<SlicedWorldClock
  ref={clock}
  cities={cities}
  brand="Your world"
  colorScheme="auto"
  duration={400}
  fontFamily="YourInterfaceFont"
  numeralFontFamily="YourLightFont"
  monoFontFamily="YourMonoFont"
  colors={{ accent: '#F28705' }}
  onCityChange={(id) => saveSelectedCity(id)}
  accessibilityLabel={(city, time) => `${city.name}, local time ${time}`}
/>;
// In an event handler:
clock.current?.setCity('tokyo');
clock.current?.setFormat('24h');

Load custom fonts in your host. The component has no theme imports or assets outside its folder. The catalog demo passes Geist Regular, Geist Light, and Geist Mono.

Props

PropTypeDefaultPurpose
citiesreadonly ClockCity[]requiredOrdered wheel entries; IDs must be unique
citystringfirst cityExternal selection; ref and user input also select internally
onCityChange(id: string) => void—Semantic selection callback
format'12h' | '24h''12h'Initial/external hour format
onFormatChange(format) => void—Format callback
onInteraction() => void—Touch-start hook for stopping host autoplay
brandstring'World clock'Header wordmark
colorsPartial<ClockColors>warm light paletteBackground, ink, hours, minutes, rule, accent, surface, selectedText
colorScheme'light' | 'dark' | 'auto''light'Complete base palette
fontFamilystringsystemUI font
numeralFontFamilystringsystemGiant numeral font
monoFontFamilystringsystemWheel and labels font
labelsobjecth, min, sec, AM, PM, 12h, 24hhours, minutes, seconds, am, pm, twelveHour, twentyFourHour, wheel, hint, grid, empty
accessibilityLabel(city, time) => stringcity and local timeAccessible clock text formatter
now() => numberDate.nowTimestamp source
durationnumber450Automatic roll duration in milliseconds
styleStyleProp<ViewStyle>—Root style
testIDstring'sliced-world-clock'Root ID; -next, -12h, -24h, -wheel suffixes

ClockCity: id, name, country, abbreviation, optional timeZone, optional utcOffsetMinutes. An empty list leaves the wheel inert. Keep abbreviations short and the list stable. For controlled integration, mirror the callbacks into city and format.

Ref methods: setCity(id) (unknown IDs ignored), setFormat('12h' | '24h').

Layout and demo

The root fills its host and measures with onLayout. It caps content width at 520 pt and uses a compact layout below 520 pt height. Numerals use the smaller of width and available height. The host applies safe-area insets; the component does not add them. Below 350 pt width, the controls move onto a second header row. Content scrolls when text scaling needs extra space. Header controls reserve 40 pt on the right for the catalog viewer's close button. Controls are 48×48 pt; the wheel is at least 90 pt tall.

The autoplay loop starts in Lisbon, turns to Tokyo at 2 s and NYC at 5 s, switches to 24h at 6.2 s, returns to Lisbon at 8.5 s and 12h at 10 s, and repeats at 12 s. User touch stops the loop; the real clock continues running.

Compatibility

Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, Worklets 0.13.0, Skia 2.14.0. Uses Expo Go bundled modules. Web requires CanvasKit initialization. Supports iOS, Android, and web.

Accessibility

All controls have button roles, labels, selected states, and activation actions. The wheel exposes an adjustable role with increment/decrement actions and tap alternatives. Selection and format changes are announced; second ticks are not live announcements. The hidden clock label includes the complete time. Reduced motion removes spatial transitions and replaces numeral changes with a 200 ms fade. Intentional giant glyph cropping is part of the pattern; the accessible time remains complete.