v0.1 public beta early access on GitHub
Home / Screens / productivity-alarm-clock
Screen template

Alarm Clock Screen

Dark alarm list: huge time numerals, schedules, and toggles plus bedtime card

pro Expo Go ✓ iosandroid gestures: tap · scroll haptics: light · selection
$ npx lumioui add productivity-alarm-clock
import { AlarmClockScreen } from "@/screens/productivity/alarm-clock";
Registry dependencies4
Native packages installed6
@lumioui/ui@latest@lumioui/core@latestreact-native-safe-area-context@*react-native-reanimated@*react-native-svg@*nativewind@*
productivity/alarm-clock.tsxsource · yours to edit
import * as React from "react";
import { useState } from "react";
import { Pressable, ScrollView, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Button, Icon, Switch, Text } from "@lumioui/ui";
import { GlowSpot, Mount, World } from "../shared";
import { cn, useHaptic } from "@lumioui/core";

interface Alarm {
  id: string;
  time: string;
  label: string;
  days: string;
  enabled: boolean;
}

export interface AlarmClockScreenProps {
  alarms?: Alarm[];
  onToggle?: (id: string, enabled: boolean) => void;
  onAdd?: () => void;
  onAlarmPress?: (id: string) => void;
}

const DEFAULT_ALARMS: Alarm[] = [
  { id: "1", time: "6:30 AM", label: "Morning run", days: "Mon · Wed · Fri", enabled: true },
  { id: "2", time: "7:15 AM", label: "Wake up", days: "Every day", enabled: true },
  { id: "3", time: "8:00 AM", label: "Standup", days: "Weekdays", enabled: true },
  { id: "4", time: "10:00 PM", label: "Wind down", days: "Every day", enabled: false },
];

/** Alarm clock — the sleep-app idiom: near-black canvas, one row per alarm
 *  with a huge thin time numeral, schedule underneath, and a working toggle. */
export function AlarmClockScreen({
  alarms = DEFAULT_ALARMS,
  onToggle,
  onAdd,
  onAlarmPress,
}: AlarmClockScreenProps) {
  const haptics = useHaptic();
  const [enabled, setEnabled] = useState<Record<string, boolean>>(() =>
    Object.fromEntries(alarms.map((a) => [a.id, a.enabled]))
  );

  const toggle = (id: string, v: boolean) => {
    haptics.selection();
    setEnabled((e) => ({ ...e, [id]: v }));
    onToggle?.(id, v);
  };

  return (
    <World primary="#BEF04C">
    {/* Dark-first — clock/bedtime apps are dark in both schemes. */}
    <SafeAreaView className="flex-1 bg-neutral-950" edges={["top"]}>
      <GlowSpot color="#BEF04C" size={300} className="-top-20 right-[-80px]" />
      <GlowSpot color="#8B5CF6" size={220} className="bottom-[30%] left-[-100px]" />
      <View className="flex-row items-center justify-between px-6 pb-2 pt-3">
        <View>
          <Text variant="h2" className="text-white" accessibilityRole="header">
            Alarms
          </Text>
          {/* Next-ring countdown — the only question alarms answer. */}
          <Text className="text-xs text-white/50">
            Next: 6:30 AM · in 8h 14m
          </Text>
        </View>
        <Button
          variant="ghost"
          size="icon"
          haptic="light"
          onPress={onAdd}
          accessibilityLabel="Add alarm"
          className="h-10 w-10 rounded-full bg-white/10"
        >
          <Icon name="plus" size="md" color="#FFF" />
        </Button>
      </View>

      <ScrollView showsVerticalScrollIndicator={false} contentContainerClassName="gap-2 px-5 pb-10">
        {/* Next-ring hero — iOS Clock's one-line answer to "when do I wake
            up", rendered in the accent before the list. */}
        <Mount>
          <View className="mb-2 flex-row items-center gap-3 rounded-2xl bg-[#BEF04C]/15 px-4 py-3.5">
            <Icon name="clock" size="md" color="#BEF04C" />
            <View className="flex-1">
              <Text className="text-sm font-semibold text-[#BEF04C]">Next alarm 6:30 AM</Text>
              <Text className="text-xs text-white/40">Morning run · rings in 8h 12m</Text>
            </View>
          </View>
        </Mount>

        {alarms.map((alarm) => {
          const on = enabled[alarm.id] ?? alarm.enabled;
          return (
            <Pressable
              key={alarm.id}
              onPress={() => {
                haptics.selection();
                onAlarmPress?.(alarm.id);
              }}
              accessibilityRole="button"
              accessibilityLabel={`${alarm.time}, ${alarm.label}, ${alarm.days}, ${on ? "on" : "off"}`}
              accessibilityState={{ checked: on }}
              className="flex-row items-center gap-4 rounded-2xl px-4 py-5"
            >
              <View className="flex-1">
                <Text
                  className={cn("text-5xl font-extralight tracking-tight tabular-nums", on ? "text-white" : "text-white/30")}
                >
                  {alarm.time}
                </Text>
                <Text className={cn("pt-1 text-sm", on ? "text-white/60" : "text-white/25")}>
                  {alarm.label} · {alarm.days}
                </Text>
              </View>
              <Switch
                checked={on}
                onCheckedChange={(v) => toggle(alarm.id, v)}
                accessibilityLabel={`${alarm.time} alarm`}
              />
            </Pressable>
          );
        })}

        {/* Bedtime card */}
        <Mount className="mt-6 gap-3 rounded-2xl bg-white/5 p-5">
          <View className="flex-row items-center justify-between">
            <Text className="font-semibold text-white">Bedtime</Text>
            <Icon name="moon" size="sm" color="#FFF" />
          </View>
          <View className="flex-row items-center justify-between">
            <View>
              <Text className="text-3xl font-extralight text-white tabular-nums">10:30 PM</Text>
              <Text className="text-xs text-white/50">Sleep goal 7h 30m</Text>
            </View>
            <View className="rounded-full bg-white/10 px-3 py-1.5">
              <Text className="text-xs font-medium text-white">Edit</Text>
            </View>
          </View>
        </Mount>
      </ScrollView>
    </SafeAreaView>
    </World>
  );
}
AlarmClockScreen.displayName = "AlarmClockScreen";
agent prompt — paste into Claude Code, Cursor, Devin…
Recreate the "Alarm Clock Screen" screen in React Native using LumioUI.

Goal: Dark alarm list: huge time numerals, schedules, and toggles plus bedtime card Match the reference implementation's layout, behavior, and motion exactly — this is a production screen, not a mockup.

## Setup

Fastest path — install the screen plus its component deps:

```bash
npx lumioui add productivity-alarm-clock
```

Or pull just the components: `npx lumioui add button icon switch text`

Native packages:
- @lumioui/ui@latest
- @lumioui/core@latest
- react-native-safe-area-context@*
- react-native-reanimated@*
- react-native-svg@*
- nativewind@*

Stack assumptions: Expo SDK 54 / RN 0.81, Reanimated 4, NativeWind v4, TypeScript strict, Expo Go compatible.

## Components — how, where, when

### `button` — Tactile pill button with press spring, ink wash and async loading.
- `<Button>` ×1

### `icon` — Lucide icon set mapped to theme colors and sizes.
- `<Icon>` ×3

### `switch` — iOS-size toggle with spring thumb and haptics.
- `<Switch>` ×1

### `text` — Themed type scale from caption to display.
- `<Text>` ×10

## Conventions (non-negotiable)

- Styling via NativeWind `className` with semantic tokens only: `bg-background`, `text-foreground`, `bg-card`, `text-card-foreground`, `bg-secondary`, `bg-muted`, `text-muted-foreground`, `bg-accent`, `bg-destructive`, `border-border`. Hard-coded colors only inside media overlays (`text-white`, `bg-black/N`).
- Motion via the token presets from `@lumioui/core` (`spring.press`, `spring.surface`, `spring.glide`, `timing.fast`, `timing.slow`, …) — no bespoke spring configs or durations.
- Gate transform motion behind `useReducedMotion()`; keep opacity/color feedback, drop travel and overshoot.
- Haptics via `useHaptic()`: `light` on press, `selection` on toggle/select, `warning` on invalid input. Never import expo-haptics directly.
- Press feedback via `usePressAnimation()` (~0.97 scale), not `activeOpacity` tricks.
- a11y: `accessibilityRole` + `accessibilityLabel` on every control, touch targets ≥44pt.
- Entrance choreography: staggered `Mount` wrappers (delay 0/60/120…) so regions land in sequence instead of popping in at once.
- Wrap the screen in `SafeAreaView`; keep dark mode working via the semantic tokens.

## Deliverable

One file: `screens/productivity/alarm-clock.tsx` exporting AlarmClockScreen. Preserve the props interface — the host app wires the callbacks (navigation, submit handlers) through them.

## Reference implementation

The LumioUI source for this screen — reproduce it faithfully:

```tsx
import * as React from "react";
import { useState } from "react";
import { Pressable, ScrollView, View } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { Button, Icon, Switch, Text } from "@lumioui/ui";
import { GlowSpot, Mount, World } from "../shared";
import { cn, useHaptic } from "@lumioui/core";

interface Alarm {
  id: string;
  time: string;
  label: string;
  days: string;
  enabled: boolean;
}

export interface AlarmClockScreenProps {
  alarms?: Alarm[];
  onToggle?: (id: string, enabled: boolean) => void;
  onAdd?: () => void;
  onAlarmPress?: (id: string) => void;
}

const DEFAULT_ALARMS: Alarm[] = [
  { id: "1", time: "6:30 AM", label: "Morning run", days: "Mon · Wed · Fri", enabled: true },
  { id: "2", time: "7:15 AM", label: "Wake up", days: "Every day", enabled: true },
  { id: "3", time: "8:00 AM", label: "Standup", days: "Weekdays", enabled: true },
  { id: "4", time: "10:00 PM", label: "Wind down", days: "Every day", enabled: false },
];

/** Alarm clock — the sleep-app idiom: near-black canvas, one row per alarm
 *  with a huge thin time numeral, schedule underneath, and a working toggle. */
export function AlarmClockScreen({
  alarms = DEFAULT_ALARMS,
  onToggle,
  onAdd,
  onAlarmPress,
}: AlarmClockScreenProps) {
  const haptics = useHaptic();
  const [enabled, setEnabled] = useState<Record<string, boolean>>(() =>
    Object.fromEntries(alarms.map((a) => [a.id, a.enabled]))
  );

  const toggle = (id: string, v: boolean) => {
    haptics.selection();
    setEnabled((e) => ({ ...e, [id]: v }));
    onToggle?.(id, v);
  };

  return (
    <World primary="#BEF04C">
    {/* Dark-first — clock/bedtime apps are dark in both schemes. */}
    <SafeAreaView className="flex-1 bg-neutral-950" edges={["top"]}>
      <GlowSpot color="#BEF04C" size={300} className="-top-20 right-[-80px]" />
      <GlowSpot color="#8B5CF6" size={220} className="bottom-[30%] left-[-100px]" />
      <View className="flex-row items-center justify-between px-6 pb-2 pt-3">
        <View>
          <Text variant="h2" className="text-white" accessibilityRole="header">
            Alarms
          </Text>
          {/* Next-ring countdown — the only question alarms answer. */}
          <Text className="text-xs text-white/50">
            Next: 6:30 AM · in 8h 14m
          </Text>
        </View>
        <Button
          variant="ghost"
          size="icon"
          haptic="light"
          onPress={onAdd}
          accessibilityLabel="Add alarm"
          className="h-10 w-10 rounded-full bg-white/10"
        >
          <Icon name="plus" size="md" color="#FFF" />
        </Button>
      </View>

      <ScrollView showsVerticalScrollIndicator={false} contentContainerClassName="gap-2 px-5 pb-10">
        {/* Next-ring hero — iOS Clock's one-line answer to "when do I wake
            up", rendered in the accent before the list. */}
        <Mount>
          <View className="mb-2 flex-row items-center gap-3 rounded-2xl bg-[#BEF04C]/15 px-4 py-3.5">
            <Icon name="clock" size="md" color="#BEF04C" />
            <View className="flex-1">
              <Text className="text-sm font-semibold text-[#BEF04C]">Next alarm 6:30 AM</Text>
              <Text className="text-xs text-white/40">Morning run · rings in 8h 12m</Text>
            </View>
          </View>
        </Mount>

        {alarms.map((alarm) => {
          const on = enabled[alarm.id] ?? alarm.enabled;
          return (
            <Pressable
              key={alarm.id}
              onPress={() => {
                haptics.selection();
                onAlarmPress?.(alarm.id);
              }}
              accessibilityRole="button"
              accessibilityLabel={`${alarm.time}, ${alarm.label}, ${alarm.days}, ${on ? "on" : "off"}`}
              accessibilityState={{ checked: on }}
              className="flex-row items-center gap-4 rounded-2xl px-4 py-5"
            >
              <View className="flex-1">
                <Text
                  className={cn("text-5xl font-extralight tracking-tight tabular-nums", on ? "text-white" : "text-white/30")}
                >
                  {alarm.time}
                </Text>
                <Text className={cn("pt-1 text-sm", on ? "text-white/60" : "text-white/25")}>
                  {alarm.label} · {alarm.days}
                </Text>
              </View>
              <Switch
                checked={on}
                onCheckedChange={(v) => toggle(alarm.id, v)}
                accessibilityLabel={`${alarm.time} alarm`}
              />
            </Pressable>
          );
        })}

        {/* Bedtime card */}
        <Mount className="mt-6 gap-3 rounded-2xl bg-white/5 p-5">
          <View className="flex-row items-center justify-between">
            <Text className="font-semibold text-white">Bedtime</Text>
            <Icon name="moon" size="sm" color="#FFF" />
          </View>
          <View className="flex-row items-center justify-between">
            <View>
              <Text className="text-3xl font-extralight text-white tabular-nums">10:30 PM</Text>
              <Text className="text-xs text-white/50">Sleep goal 7h 30m</Text>
            </View>
            <View className="rounded-full bg-white/10 px-3 py-1.5">
              <Text className="text-xs font-medium text-white">Edit</Text>
            </View>
          </View>
        </Mount>
      </ScrollView>
    </SafeAreaView>
    </World>
  );
}
AlarmClockScreen.displayName = "AlarmClockScreen";
```

Screen: https://lumioui.dev/screens/productivity-alarm-clock
iPhone 17 · iOS
9:41
Live preview — the real screen via Expo Web · open full ↗