Skip to content

Releases: slackhq/circuit

0.31.0

05 Nov 01:15

Choose a tag to compare

Breaking Changes:

Remove kotlinx-immutable dependency. With Compose's strong skipping mode, we no longer feel this is necessary.

Result delivery is now handled by NavigableCircuitContent via an internal AnsweringResultNavigator wrapper, and result handling APIs have been removed from BackStack and SaveableBackStack as this is now purely a navigation concern. This separates result handling concerns from the backstack implementation and provides better encapsulation.

The callback block in rememberAnsweringNavigator is no longer suspendable as it was never intended for any long running operations.

Behaviour Changes:

On iOS GestureNavigationDecorationFactory now uses IOSPredictiveBackNavDecorator instead of CupertinoGestureNavigationDecorator. This new decorator uses the Compose multi-platform PredictiveBackHandler to drive the back animation, instead of a custom swipe gesture or nested scroll.

The Navigator.resetRoot API is now using a StateOptions class to allow saving, restoring, and clearing of back stack state. The previous resetRoot function with saveState and restoreState booleans is available as an extension function.

Misc:

  • Switched Compose uses to depend on Compose Multiplatform over Jetpack Compose
  • Android minimum SDK is now minSdk 23
  • Added saved state peek/remove to Backstack
  • Fixed Navigator.onNavEvent() not passing all arguments to resetRoot()
  • Fixes to rememberCircuitNavigator() capturing onRootPop and not recreating if a new backstack was provided
  • Update Compose Multiplatform to 1.9.2.
  • Update to Kotlin 2.2.21.
  • Update to Molecule 2.2.0.
  • Build against KSP 2.2.20-2.0.4.

What's Changed

New Contributors

Full Changelog: 0.30.0...0.31.0

0.30.0

02 Aug 00:18

Choose a tag to compare

Updates to ViewModelBackStackRecordLocalProvider

ViewModelBackStackRecordLocalProvider has moved from the backstack module to the circuit-foundation module while also changing to use the multiplatform ViewModel implementation. ViewModelBackStackRecordLocalProvider is now provided as a default through the Circuit instance, enabling customization of the default BackStackRecordLocalProviders.

Also added backStackHostViewModel() to access a ViewModel located in the ViewModelStoreOwner of NavigableCircuitContent.

Behaviour Changes:

  • Rebuilt continuityRetainedStateRegistry as a common lifecycleRetainedStateRegistry and made ViewModel an implementation detail of it.
  • AnimatedNavDecoration is now using the full back stack to determine the transition animation.

Misc:

  • [gesture-navigation] Fix a crash when using AndroidPredictiveBackNavDecorator and having previously called resetRoot() with restoreState=false.
  • [code gen] Added support for CircuitContext as an assisted param in code gen
  • Update dagger to v2.57.
  • Update Compose Android BOM to 2025.07.00.
  • Update androidx.lifecycle to 2.9.2.

Special thanks to @CamiloVega and @kvaster for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.29.1...0.30.0

0.29.1

30 Jun 18:29

Choose a tag to compare

  • Fix @AssistedFactory code gen for Metro to use standard nested class semantics.

What's Changed

Full Changelog: 0.29.0...0.29.1

0.29.0

26 Jun 23:39

Choose a tag to compare

  • Update to Kotlin 2.2.0.
  • Update to KSP 2.2.0-2.0.2.
  • Support @AssistedFactory in code gen for Metro.
  • Add seekable transition support to AnimatedOverlay.
  • Add predictive back support to FullScreenOverlay.
  • Compile against Android SDK 36.

What's Changed

New Contributors

Full Changelog: 0.28.1...0.29.0

0.28.1

09 Jun 19:11

Choose a tag to compare

Behaviour Changes:

Replacing rememberContinuityCanRetainChecker() with CanRetainChecker.Always, which changes the Android rememberRetained behaviour to retain based on the ViewModel lifecycle. This should fix rememberRetained not functioning as expected when used in a fragment. Previously rememberRetained would only retain if the Activity was in a configuration change.

Misc:

  • Update to Kotlin 2.1.21.
  • Build against KSP 2.1.21-2.0.1.
  • Fix not being able to provide a custom ViewModel to continuityRetainedStateRegistry()
  • Fix rememberCircuitNavigator and rememberInterceptingNavigator replaying a root pop at the same screen
  • Update Compose Android BOM to 2025.06.00.
  • Update Compose Android to 1.8.2.
  • Update to Compose Multiplatform to 1.8.1.
  • Update androidx.lifecycle to 2.9.1

What's Changed

New Contributors

Full Changelog: 0.28.0...0.28.1

0.28.0

13 May 01:37

Choose a tag to compare

Compose 1.8

This release updates to Compose 1.8 🎉
As part of this update the published jvmTarget has moved to 11 to match the upstream change.

Behaviour Changes

The Android version of rememberCircuitNavigator() that could handle back navigation was changed to delay the root Navigator.pop by a composition such that its BackHandler could be fully disabled first. This change fixed an issue where a root pop would not propagate to outer BackHandler's or OnBackPressedCallback's. With the addition of compose:ui-backhandler, this variant of rememberCircuitNavigator() was moved from the Android to the common circuit-foundation artifact.

New circuitx-navigation adding navigation interception capabilities

We've added a new navigation intercepting system to CircuitX that lets you hook into and modify navigation before it happens. The InterceptingNavigator sits before a regular Circuit Navigator, giving you a chance to inspect or change navigation events. With the NavigationInterceptor interface, you can handle goTo, pop, and resetRoot calls and decide if they should proceed, fail, be skipped, or be rewritten to navigate somewhere else. There's also aNavigationEventListener if you just want to know when navigation happens without changing it.
This new system is handy for advanced routing, blocking navigation, or tracking navigation events for analytics.

dependencies {
  implementation("com.slack.circuit:circuitx-navigation:<version>")
}

Docs: https://slackhq.github.io/circuit/circuitx/navigation

Misc:

  • Fix the provided Modifier not being used in NavigatorDefaults.EmptyDecoration
  • [docs] Add more alternative state designs.
  • [docs] Split up the Circuitx docs into sub pages

What's Changed

Full Changelog: 0.27.1...0.28.0

0.27.1

15 Apr 00:18

Choose a tag to compare

  • Fix: Crash caused by calling resetRoot while the same Screen was still in the composition
  • New: Added a sample app demonstrating bottom bar navigation
  • [gesture-navigation] Update AndroidPredictiveBackNavDecorator to behave more like the Android predictive back motion spec
  • [gesture-navigation] Change the Compose Material dependency to not be exposed as an api
  • Update compose-bom to 2025.04.00
  • Update dagger to 2.56.1
  • Update kotlinInject.anvil to 0.1.3
  • Update kotlinx-coroutines to 1.10.2
  • Update androidx.core to 1.16.0
  • [samples] Update mosaic to 0.17.0

Special thanks to @OSemenovBoyarka and @asapha for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.27.0...0.27.1

0.27.0

01 Mar 06:28

Choose a tag to compare

Screen based animation overrides

We have added experimental support for animations based on the source/target screens and the type of navigation event. This can be accomplished with the the new AnimatedScreenTransform interface, allowing customization of the ContentTransform used when transitioning between screens. Having support for screen based animation overrides is especially important for use with shared element transitions, as it provides the ability to replace the transition before the shared elements are loaded.

See this PR for more details and example implementations. Please share feedback in this discussion.

Behaviour Changes

State retention logic was simplified by removing LocalCanRetainChecker with CanRetainChecker becoming an implementation detail of a RetainedStateRegistry. This potentially impacts uses of rememberRetained that depended on LocalCanRetainChecker as rememberRetained would use the composition local before using rememberCanRetainChecker. Also, as rememberCanRetainChecker was only needed for Continuity it has been renamed to rememberContinuityCanRetainChecker.

Fixes

Fixed a crash caused by calling resetRoot while NavigableCircuitContent was animating. This was commonly encountered in a bottom nav bar scenario while rapidly changing tabs and calling resetRoot. Prior to 0.26.0 this was resulting in state loss.

What's Changed

New Contributors

  • @ansehoon1999 made their first contribution in #1957

Full Changelog: 0.26.1...0.27.0

0.26.1

13 Feb 20:19

Choose a tag to compare

  • Fix crash on right side back gesture.
  • Update CupertinoGestureNavigationDecoration to be a AnimatedNavDecorator.
  • Fix value restoration after removeState call in RetainedStateHolder.
  • Update Android compose artifacts to 1.7.8.
  • [docs] Add tutorial for how to use Circuit shared elements.
  • [docs] Added basic reference guide on deep-linking using circuit for Android platform.

Special thanks to @vulpeszerda for contributing to this release!

What's Changed

Full Changelog: 0.26.0...0.26.1

0.26.0

07 Feb 04:21

Choose a tag to compare

Happy new year!

Shared Elements API!

After a lot of iteration and work, this release adds support for Compose's new shared elements APIs.

These are still experimental and subject to change, both in Circuit and the underlying Compose APIs.

See this PR for full details as well as sample integrations: #1550. Please share feedback in this discussion. More formal docs to come as well, we'll publish updates there!

For now, the easiest way to support shared element transitions is to wrap your content with a SharedElementTransitionLayout.

CircuitCompositionLocals(circuit) {
  SharedElementTransitionLayout {
    NavigableCircuitContent(
      navigator = navigator,
      backStack = backStack,
    )
  }
}

SharedElementTransitionLayout creates and provides a SharedElementTransitionScope to content within it, and in turn exposes a SharedTransitionScope for use with standard compose shared elements/bounds animations. This is supported in NavigableCircuitContent and overlays.

There is also a PreviewSharedElementTransitionLayout for help with Compose previews.

Behaviour Changes: rememberRetained

Previously, rememberRetained could sometimes restore values when a composable was re-added, depending on whether its parent RetainedStateRegistry had been saved (#1783).
Now, rememberRetained aligns with remember and rememberSaveable: if a composable is removed and later re-added, its value will not be restored unless it is explicitly saved and then restored via the registry.

Update rememberRetained to allow CanRetainChecker to be updated in place.

Behaviour Change: RetainedStateRegistry

  • saveAll now returns the saved values.
  • RetainedStateRegistry.Entry.unregister now returns whether the unsaved valueProvider was actually removed.
  • saveAll and saveValue now skip storing child values when CanRetainChecker returns false.

New: RetainedStateHolder

Similar to SaveableStateHolder, RetainedStateHolder provides a mechanism to maintain separate RetainedStateRegistry entries for specific keys. This allows saving the state defined with rememberRetained for a subtree before it is disposed, so that the subtree can later be recomposed with its state restored.

val retainedStateHolder = rememberRetainedStateHolder()
var currentTab by remember { mutableStateOf(TabA) }

retainedStateHolder.RetainedStateProvider(key = currentTab.name) {
  // rememberRetained values in tab content are preserved across tab switches
  when (currentTab) {
    TabA -> {
      TabAContent()
    }
    TabB -> {
      TabBContent()
    }
    TabC -> {
      TabCContent()
    }
  }
}

Implementation Changes: NavigableCircuitContent

  • The approach of managing a separate RetainedStateRegistry for each record has been changed to use RetainedStateHolder instead.
  • Change SaveableStateHolder to release saved states of removed records.

Misc

  • Fixe an issue causing codegen to fail for class @Inject annotations.
  • Compile against Android SDK 35.
  • Update Compose Android BOM to 2025.01.01.
  • Update to androidx.annotation 1.9.1.
  • Update to androidx.activity 1.10.0.
  • Update to Compose Android 1.7.7.
  • Update to Compose Multiplatform 1.7.3.
  • Update to Kotlin 1.9.10.
  • [code gen] Update to KSP 1.9.10-1.0.29.
  • [code gen] Update to Dagger 2.55.
  • [code gen] Update to KotlinPoet 2.0.0.
  • [code gen] Build against Anvil-KSP 0.4.1. Should still be compatible with square/anvil as well.
  • [code gen] Build against kotlin-inject-anvil 0.1.2. Should still be compatible with square/anvil as well.
  • [samples] Update mosaic + modernize mosaic counter sample to fully use effects.
  • [docs] Fix variable casing in Navigation documentation example.

Special thanks to @vulpeszerda, @rharter, @alexvanyo, and @easyhooon for contributing to this release!

What's Changed

Read more