Skip to main content

Visual Overview

The ChangelogScreen provides a narrative-driven history of the app’s development. It utilizes a vertical timeline layout with a dynamic “progress beam” that fills as the user scrolls. The screen distinguishes between the Latest Release (highlighted with a high-contrast card and pulse animation) and Historical Versions (minimalist list items).

UI Structure

The screen is built using a pattern, specifically a custom ScreenScaffold to handle the collapsing top bar.
  • Root: ChangelogScreen
    • Scaffold: ScreenScaffold with AppBarType.Large.
    • Header: A “Story Card” using AnnotatedString for rich text formatting and a call-to-action button.
    • Timeline Container: A Box containing:
      • The Beam: A custom-drawn vertical line using drawBehind that reacts to the .
      • Timeline Items: A list of TimelineItem components.
        • Latest Item: Uses MaterialTheme.colorScheme.primaryContainer and a pulse animation.
        • Regular Item: A standard layout with version numbers and dates.
        • Features: ExpandableFeatureItem (Accordion style) for detailed release notes.

State & Interaction

The UI manages its own local for interactions that don’t require business logic processing.
  • Accordion Logic: The screen uses to track which feature is currently expanded (expandedFeature). Tapping a feature title toggles its description via AnimatedVisibility.
  • Scroll-Driven Drawing: The “Beam” line uses the scrollState.value to calculate its height dynamically. As the user scrolls, the primary-colored line “follows” the viewport, creating a sense of progression.
  • Event Bubbling:
    • Navigation: Clicks on “Read My Story” bubble up to the NavController.
    • Expansion: Taps on features trigger a state change in the Timeline parent, which then flows back down to the ExpandableFeatureItem.

Design System Usage

This module heavily leverages the :
  • Typography: Uses DisplayFontFamily (Black weight) for version numbers to create a strong visual hierarchy and BodyFontFamily for descriptions.
  • Shapes: The ScreenScaffold utilizes MaterialShapes (Expressive API) to generate randomized, playful shapes for the back button (e.g., Sunny, Clover, Cookie).
  • Colors: Uses surfaceContainer for the app bar when scrolled and primaryContainer for the featured “Latest” release card.

Preview & Testing

The UI is designed to be responsive to:
  • Dark Mode: Uses isSystemInDarkTheme() logic indirectly through the MaterialTheme color palette.
  • Dynamic Content: The timeline is built from a list of TimelineEntry objects, making it easy to update without changing the layout logic.
  • Accessibility: Each expandable section includes a contentDescription for the chevron icon, indicating whether the section is “Expand” or “Collapse”.
// Example of the dynamic beam calculation logic
val tipPositionInContent = scrollOffset + (viewportH * 0.85f) - headerOffsetPx
val filledHeight = tipPositionInContent.coerceIn(0f, size.height)

Components

ScreenScaffold

A reusable wrapper that provides a consistent experience. It supports three modes: Small, Large, and Hidden. It also manages the nestedScroll connection required for the app bar to collapse smoothly as the user scrolls the content.

ExpandableFeatureItem

A stateless that renders a single feature bullet. It uses animateFloatAsState to rotate the chevron icon 180 degrees when expanded, providing clear visual feedback.
Last modified on January 22, 2026