Skip to content

Releases: slackhq/circuit

0.33.1

20 Feb 04:43

Choose a tag to compare

New

  • Added ProvideRecordLifecycle to safely override the LocalRecordLifecycle behaviour of NavigableCircuitContent where only the currently active record in the NavStack is not paused.
  • Added rememberSaveableNavStack(NavStackList) overload to initialize a nav stack from an existing snapshot.
  • Added a Presenter.test variant that provides composition local values to the Presenter under test

Fixes

  • Fixes an issue where retained values where not getting saved at the correct time.

Docs

  • New "Scaling Presenters" guide covering best practices for structuring presenters as they grow, including extracting sub-presenters, modularizing event handling, and testing strategies.

Contributors

Special thanks to the following contributors for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.33.0...0.33.1

0.33.0

11 Feb 02:19

Choose a tag to compare

New Navigation Architecture

Circuit now supports bidirectional navigation with browser-style forward/backward capabilities! Checkout the migration guide.

val navStack = rememberSaveableNavStack(root = HomeScreen)
val navigator = rememberCircuitNavigator(navStack)
navigator.backward() // Move back without removing history
navigator.forward()  // Move forward to a previously visited screen

Navigation changes:

  • Navigator.forward(): Move forward in navigation history
  • Navigator.backward(): Move backward in navigation history
  • Navigator.peekNavStack(): Immutable snapshot of the current navigation stack state
  • NavigableCircuitContent is aware of the full navigation stack and provides NavStackList to
    decorations, enabling them to render forward stack records.

SaveableNavStack:

  • New implementation in circuit-foundation providing full bidirectional navigation state
  • The existing SaveableBackStack implementation has been updated to extend NavStack

New circuit-runtime-navigation artifact:

  • NavStack: Core navigation stack supporting push/pop and forward/backward traversal
  • NavStackList: Immutable snapshot of navigation state

circuitx-navigation:

  • InterceptingNavigator now supports forward() and backward() navigation methods
  • Updated to use NavStack and NavStackList instead of BackStack and List<Screen>
  • Rewrite interceptors can now rewrite to any NavEvent (not just specific navigation types like InterceptedGoToResult.Rewrite or InterceptedResetRootResult.Rewrite)
  • FailureNotifier interface updated with forwardFailure() and backwardFailure() methods with default implementations

Updates

New

  • Add mingwX64() target to circuit-codegen-annotations.

Fixes

  • Fix an issue where AnsweringResultHandler was not correctly parceling pending results.

Changes

  • Compile against kotlin-inject-anvil 0.1.7.
  • NavigationEventHandler usage is now disabled by default when no NavigationEventDispatcherOwner is available, preventing crashes in environments with dynamic navigation event support. This behaviour can be configured with the Circuit.lenientNavigationEventDispatcherOwner option.
  • BottomSheetOverlay now exposes contentWindowInsets, mirroring ModalBottomSheet

Contributors

Special thanks to the following contributors for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.32.0...0.33.0

0.32.0

14 Jan 01:24

Choose a tag to compare

Enhancements

  • New produceAndCollectAsRetainedState that produces and collects values from a Flow.

Changes

  • Update to Kotlin 2.3.0.
  • Update Compose Multiplatform to 1.10.0.
  • Circuits BackHandler uses now depend on org.jetbrains.androidx.navigationevent.

Code-gen

  • Generate @Origin annotations for kotlin-inject-anvil and Metro code gen.
  • Switch to jakarta.inject types for Dagger/Anvil code gen. This should have no source-breaking changes to users since this only affected generated code, but note that the square/anvil implementation may not support this in factory generation (the KSP fork does). If you need to only use javax annotations, use the circuit.codegen.useJavaxOnly=true KSP option.
  • Drop KSP1 support.
  • Fix not using named parameters with the kotlin-inject Anvil codegen mode.

Contributors

Special thanks to the following contributors for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.31.0...0.32.0

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