GitHunt
BE

bernaferrari/diagonal-wipe-icon

A one-file icon transition component for Compose

Diagonal wipe icon animation in action

Diagonal Wipe Icon

One-file icon transition component for Compose Multiplatform

Diagonal wipe icon static preview

πŸš€ Live Demo

πŸ“– What Is This?

Apple's SF Symbols makes it easy to add wipe icon transitions to iOS apps. In Compose, achieving this built-in behavior is tediousβ€”it often requires creating animated drawables manually or relying on third-party editors every single time.

Diagonal Wipe Icon bridges this gap. It provides a polished component that emulates this behavior using two standard icons and a mask. Perfect for:

  • πŸŽ›οΈ Toggle controls (on/off, enabled/disabled, visible/hidden)
  • βš™οΈ Settings screens with stateful icons
  • ✨ Anywhere you want polished micro-interactions

Zero dependencies. Just copy a single file.

οΏ½ Quick Start

Grab the file:

curl -O https://raw.githubusercontent.com/bernaferrari/diagonal-wipe-icon/main/composeApp/src/commonMain/kotlin/com/bernaferrari/diagonalwipeicon/DiagonalWipeIcon.kt

Drop it into your commonMain/kotlin folder, and wrap it in your preferred click listener:

@Composable
fun FavoriteButton() {
    var isFavorite by remember { mutableStateOf(false) }

    IconButton(onClick = { isFavorite = !isFavorite }) {
        DiagonalWipeIcon(
            isWiped = !isFavorite,
            baseIcon = Icons.Outlined.Favorite,
            wipedIcon = Icons.Outlined.FavoriteBorder,
            contentDescription = "Favorite Toggle"
        )
    }
}

🎨 Customization

You can deeply customize the transition feel using motion parameter or custom Painters.

DiagonalWipeIcon(
    // State and Icons
    isWiped = isMuted,
    baseIcon = Icons.Outlined.VolumeUp,
    wipedIcon = Icons.Outlined.VolumeOff,
    
    // Optional Colors
    baseTint = Color.Unspecified,
    wipedTint = Color.Unspecified,
    
    // Motion Presets
    motion = DiagonalWipeIconDefaults.gentle() // default, smooth feel
    // motion = DiagonalWipeIconDefaults.snappy() // fast and responsive feel
    // motion = DiagonalWipeIconDefaults.gentle(direction = WipeDirection.TopToBottom) // 8 cardinal/diagonal directions supported
    // motion = DiagonalWipeIconDefaults.spring(wipeInStiffness = Spring.StiffnessLow) // organic, physics-based motion
)

Note: Overloads exist for both ImageVector and Painter.

Diagonal wipe icon animation in action

Diagonal wipe icon static preview

⚑ Performance & Under The Hood

A moving clip path reveals one icon while concealing the other through smooth interpolations over 8 supported directions.

Scenario Performance
At Rest (isWiped settled) Same as rendering a single static icon.
During Transition ~2x cost (rendering two layers + dynamic clip path).
Normal Usage (5-10 icons) Flawless and smooth on modern devices.
  • βœ… Settled states bypass compositing entirely
  • βœ… Tint filters cached and reused
  • βœ… Path buffers pooled across frames

❓ FAQ

  • Can I use my own icons? Yes. Any ImageVector or Painter.
  • Does it work on iOS? Yes, it works seamlessly in Compose Multiplatform commonMain.
  • What about accessibility? Pass contentDescription and it respects semantics.
  • Run the Demo Locally:
    • Web: ./gradlew :composeApp:jsBrowserDevelopmentRun
    • Android: ./gradlew :androidApp:installDebug

πŸ“ License

MIT Β© Bernardo Ferrari

Languages

Kotlin91.4%Shell5.2%HTML1.7%Python1.4%Swift0.3%

Contributors

MIT License
Created March 1, 2026
Updated March 9, 2026
bernaferrari/diagonal-wipe-icon | GitHunt