Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

bernaferrari/diagonal-wipe-icon

Open more actions menu

Repository files navigation

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

Releases

Packages

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.