Skip to main content

Overview

The in.ui.components module serves as the architectural “Design System” for the ScrollLess application. It transcends basic UI widgets by providing a collection of interactive, state-aware, and gamified components designed to make digital wellbeing data engaging. From a user perspective, this module provides the “feel” of the app: the 3D warp transitions, the reactive “PixelPet” mascot, the Tinder-style swipeable tips, and the fluid bubble charts that visualize screen time.

Architecture & Data Flow

The module follows a strict pattern. Most components are stateless, accepting data models (like AppUsageUiItem or LimitInfo) and emitting events via lambdas.

Key Components

1. The Structural Backbone (ScreenScaffold)

The ScreenScaffold is the primary entry point for every screen. It handles:
  • Edge-to-Edge Layout: Uses WindowInsets to ensure content flows behind system bars.
  • Expressive Navigation: Features a back button with randomized (Clovers, Cookies, Stars).
  • Scroll Orchestration: Integrates with TopAppBarScrollBehavior to collapse headers dynamically.

2. Gamified Feedback (PixelPet & FocusSpirit)

To reduce the “clinical” feel of usage tracking, the module includes mascots:
  • PixelPet: A grid-based sprite that reacts to user “Moods” (Idle, Eating, Confused). It features a “Phosphor Glow” effect using RenderEffect (Android 12+).
  • FocusSpirit: A fluid, physics-based blob that uses paths and spring physics to “lag” behind movement, creating a jelly-like feel.

3. Data Visualization (HeroAppUsageCard)

Instead of standard bar charts, screen time is visualized via a Premium Packed Bubble Chart:
  • Physics-based Packing: Uses a custom algorithm to calculate non-overlapping circles based on usage weight.
  • Interactive Scrubbing: Users can long-press and “scrub” through bubbles, triggering proportional to the app’s usage intensity.

4. Interactive Guidance (TutorialScaffold)

A “Spotlight” system that guides users through the UI:
  • Target Tracking: Components use the .spotlightTarget() modifier to report their coordinates to a centralized TutorialState.
  • Dynamic Masking: Uses PathOperation.Difference to cut a “hole” in a dark overlay, highlighting specific UI elements.

Operational Logic

State Management & Haptics

The module relies on a centralized HapticsManager provided via CompositionLocalProvider.
  • Slider Scrubbing: Components like the MaterialTimePickerDialog and BubbleChart use performSliderScrub, which maps a 0.0-1.0 progress value to varying haptic intensities.
  • Confirmation: Destructive actions (like the DestructiveCountdownButton) trigger a “Confirm” haptic only after a 5-second safety countdown.

The “Warp” Tunnel (WarpBackground)

A high-performance 3D background used in premium or transition states. It projects 2D lines into a 3D perspective using a custom projection function: scale=1/zscale = 1 / z This creates the illusion of moving through a digital tunnel, with “beams” that fade in from the distance (ZmaxZ_{max}) and fly past the viewer (ZnearZ_{near}).

Data Engineering & Transformation

Usage Item Mapping

The AppUsageUiItem acts as the bridge between the database and the UI.
  • Icon Handling: Icons are loaded as File objects (cached on disk) and rendered via the Coil library.
  • Normalization: The HeroAppUsageCard normalizes raw milliseconds into a “Fill Ratio” to determine bubble sizes relative to the available screen real estate.

Heatmap Logic

The InteractiveCalendarHeatmap transforms a Map<LocalDate, Int> into a color-coded grid:
  • Luminance Interpolation: It calculates the monthMax and uses Color.lerp to interpolate between a neutral surface color and the primary theme color based on usage density.

Dependencies

  • Coil: For asynchronous image loading of app icons.
  • Lottie: For complex vector animations (e.g., the “Infinity Loader”).
  • Konfetti: For celebratory particle effects when unlocking “Developer Mode”.
  • AndroidX Graphics Shapes: For the polygon-based expressive UI elements.
  • Hilt: For injecting the SettingsViewModel into the AppFooter.
// Example of the UDF pattern used in the module
@Composable
fun SettingsSwitchItem(
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    // ...
)
Last modified on January 22, 2026