Skip to content

Commit 4437de9

Browse files

File tree

8 files changed

+223
-223
lines changed

8 files changed

+223
-223
lines changed

docs/circuitx.md

Lines changed: 6 additions & 222 deletions
Original file line numberDiff line numberDiff line change
@@ -12,225 +12,9 @@ These packages differ from Circuit's core artifacts in a few ways:
1212
- These artifacts are under the `com.slack.circuitx` package prefix.
1313
- These artifacts may be platform-specific where appropriate.
1414

15-
## Android
16-
17-
The `circuitx-android` artifact contains Android-specific extensions for Circuit.
18-
19-
```kotlin
20-
dependencies {
21-
implementation("com.slack.circuit:circuitx-android:<version>")
22-
}
23-
```
24-
25-
### Navigation
26-
27-
It can be important for Circuit to be able to navigate to Android targets, such as other activities
28-
or custom tabs. To support this, decorate your existing `Navigator` instance
29-
with `rememberAndroidScreenAwareNavigator()`.
30-
31-
```kotlin
32-
class MainActivity : Activity {
33-
override fun onCreate(savedInstanceState: Bundle?) {
34-
setContent {
35-
val backStack = rememberSaveableBackStack(root = HomeScreen)
36-
val navigator = rememberAndroidScreenAwareNavigator(
37-
rememberCircuitNavigator(backstack), // Decorated navigator
38-
this@MainActivity
39-
)
40-
CircuitCompositionLocals(circuit) {
41-
NavigableCircuitContent(navigator, backstack)
42-
}
43-
}
44-
}
45-
}
46-
```
47-
48-
`rememberAndroidScreenAwareNavigator()` has two overloads - one that accepts a `Context` and one
49-
that accepts an `AndroidScreenStarter`. The former is just a shorthand for the latter that only
50-
supports `IntentScreen`. You can also implement your own starter that supports other screen types.
51-
52-
`AndroidScreen` is the base `Screen` type that this navigator and `AndroidScreenStarter` interact
53-
with. There is a built-in `IntentScreen` implementation that wraps an `Intent` and an
54-
options `Bundle` to pass to `startActivity()`. Custom `AndroidScreens` can be implemented separately
55-
and route through here, but you should be sure to implement your own `AndroidScreenStarter` to
56-
handle them accordingly.
57-
58-
## Effects
59-
60-
CircuitX provides some effects for use with logging/analytics. These effects are typically used in
61-
Circuit presenters for tracking `impressions` and will run only once until forgotten based on the
62-
current circuit-retained strategy.
63-
64-
```kotlin
65-
dependencies {
66-
implementation("com.slack.circuit:circuitx-effects:<version>")
67-
}
68-
```
69-
70-
### ImpressionEffect
71-
72-
`ImpressionEffect` is a simple single fire side effect useful for logging or analytics.
73-
This `impression` will run only once until it is forgotten based on the current `RetainedStateRegistry`.
74-
75-
```kotlin
76-
ImpressionEffect {
77-
// Impression
78-
}
79-
```
80-
81-
### LaunchedImpressionEffect
82-
83-
This is useful for async single fire side effects like logging or analytics. This effect will run a
84-
suspendable `impression` once until it is forgotten based on the `RetainedStateRegistry`.
85-
86-
```kotlin
87-
LaunchedImpressionEffect {
88-
// Impression
89-
}
90-
```
91-
92-
### RememberImpressionNavigator
93-
94-
A `LaunchedImpressionEffect` that is useful for async single fire side effects like logging or
95-
analytics that need to be navigation aware. This will run the `impression` again if it re-enters
96-
the composition after a navigation event.
97-
98-
```kotlin
99-
val navigator = rememberImpressionNavigator(
100-
navigator = Navigator()
101-
) {
102-
// Impression
103-
}
104-
```
105-
106-
## Gesture Navigation
107-
108-
CircuitX provides `NavDecoration` implementation which support navigation through appropriate
109-
gestures on certain platforms.
110-
111-
```kotlin
112-
dependencies {
113-
implementation("com.slack.circuit:circuitx-gesture-navigation:<version>")
114-
}
115-
```
116-
117-
To enable gesture navigation support, you can use the use the `GestureNavigationDecoration`function:
118-
119-
```kotlin
120-
NavigableCircuitContent(
121-
navigator = navigator,
122-
backStack = backstack,
123-
decoration = GestureNavigationDecoration(
124-
// Pop the back stack once the user has gone 'back'
125-
navigator::pop
126-
)
127-
)
128-
```
129-
130-
### Android
131-
132-
On Android, this supports the [Predictive back gesture](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) which is available on Android 14 and later (API level 34+). On older platforms, Circuit's default
133-
`NavDecoration` decoration is used instead.
134-
135-
<figure>
136-
<video controls width="300" loop=true>
137-
<source src="../images/gesturenav_android.mp4" type="video/mp4" />
138-
</video>
139-
<figcaption><a href="https://github.com/slackhq/circuit/tree/main/samples/star">Star sample</a> running on an Android 14 device</figcaption>
140-
</figure>
141-
142-
### iOS
143-
144-
On iOS, this simulates iOS's 'Interactive Pop Gesture' in Compose UI, allowing the user to swipe Circuit UIs away. As this is
145-
a simulation of the native behavior, it does not match the native functionality perfectly. However, it is a good approximation.
146-
147-
<figure>
148-
<video controls width="300" loop=true>
149-
<source src="../images/gesturenav_ios.mp4" type="video/mp4" />
150-
</video>
151-
<figcaption><a href="https://github.com/chrisbanes/tivi">Tivi</a> app running on iPhone</figcaption>
152-
</figure>
153-
154-
### Other platforms
155-
156-
On other platforms we defer to Circuit's default `NavDecoration` decoration.
157-
158-
## Overlays
159-
160-
CircuitX provides a few out-of-the-box `Overlay` implementations that you can use to build common
161-
UIs.
162-
163-
```kotlin
164-
dependencies {
165-
implementation("com.slack.circuit:circuitx-overlays:<version>")
166-
}
167-
```
168-
169-
### `BottomSheetOverlay`
170-
171-
`BottomSheetOverlay` is an overlay that shows a bottom sheet with a strongly-typed API for the input
172-
model to the sheet content and result type. This allows you to easily use a bottom sheet to prompt
173-
for user input and suspend the underlying Circuit content until that result is returned.
174-
175-
```kotlin
176-
/** A hypothetical bottom sheet of available actions when long-pressing a list item. */
177-
suspend fun OverlayHost.showLongPressActionsSheet(): Action {
178-
return show(
179-
BottomSheetOverlay(
180-
model = listOfActions()
181-
) { actions, overlayNavigator ->
182-
ActionsSheet(
183-
actions,
184-
overlayNavigator::finish // Finish the overlay with the clicked Action
185-
)
186-
}
187-
)
188-
}
189-
190-
@Composable
191-
fun ActionsSheet(actions: List<Action>, onActionClicked: (Action) -> Unit) {
192-
Column {
193-
actions.forEach { action ->
194-
TextButton(onClick = { onActionClicked(action) }) {
195-
Text(action.title)
196-
}
197-
}
198-
}
199-
}
200-
```
201-
202-
### Dialog Overlays
203-
204-
`alertDialogOverlay` is function that returns an Overlay that shows a simple confirmation dialog with configurable inputs. This acts more or less as an `Overlay` shim over the Material 3 `AlertDialog` API.
205-
206-
```kotlin
207-
/** A hypothetical confirmation dialog. */
208-
suspend fun OverlayHost.showConfirmationDialog(): Action {
209-
return show(
210-
alertDialogOverlay(
211-
titleText = { Text("Are you sure?") },
212-
confirmButton = { onClick -> Button(onClick = onClick) { Text("Yes") } },
213-
dismissButton = { onClick -> Button(onClick = onClick) { Text("No") } },
214-
)
215-
)
216-
}
217-
```
218-
219-
There are also more generic `BasicAlertDialog` and `BasicDialog` implementations that allow more customization.
220-
221-
### `FullScreenOverlay`
222-
223-
Sometimes it's useful to have a full-screen overlay that can be used to show a screen in full above
224-
the current content. This API is fairly simple to use and just takes a `Screen` input of what
225-
content you want to show in the overlay.
226-
227-
```kotlin
228-
overlayHost.showFullScreenOverlay(
229-
ImageViewerScreen(id = url, url = url, placeholderKey = name)
230-
)
231-
```
232-
233-
!!! info "When to use `FullScreenOverlay` vs navigating to a `Screen`?"
234-
While they achieve similar results, the key difference is that `FullScreenOverlay` is
235-
inherently an ephemeral UI that is _controlled_ by an underlying primary UI. It cannot
236-
navigate elsewhere and it does not participate in the backstack.
15+
| Artifact | Documentation |
16+
|--------------------------------------------------|------------------------------------------------------|
17+
| `com.slack.circuitx:circuitx-android` | [Android](circuitx/android.md) |
18+
| `com.slack.circuitx:circuitx-effects` | [Effects](circuitx/effects.md) |
19+
| `com.slack.circuitx:circuitx-gesture-navigation` | [Gesture Navigation](circuitx/gesture-navigation.md) |
20+
| `com.slack.circuitx:circuitx-overlays` | [Overlays](circuitx/overlays.md) |

docs/circuitx/android.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
The `circuitx-android` artifact contains Android-specific extensions for Circuit.
2+
3+
```kotlin
4+
dependencies {
5+
implementation("com.slack.circuit:circuitx-android:<version>")
6+
}
7+
```
8+
9+
### Navigation
10+
11+
It can be important for Circuit to be able to navigate to Android targets, such as other activities
12+
or custom tabs. To support this, decorate your existing `Navigator` instance
13+
with `rememberAndroidScreenAwareNavigator()`.
14+
15+
```kotlin
16+
class MainActivity : Activity {
17+
override fun onCreate(savedInstanceState: Bundle?) {
18+
setContent {
19+
val backStack = rememberSaveableBackStack(root = HomeScreen)
20+
val navigator = rememberAndroidScreenAwareNavigator(
21+
rememberCircuitNavigator(backstack), // Decorated navigator
22+
this@MainActivity
23+
)
24+
CircuitCompositionLocals(circuit) {
25+
NavigableCircuitContent(navigator, backstack)
26+
}
27+
}
28+
}
29+
}
30+
```
31+
32+
`rememberAndroidScreenAwareNavigator()` has two overloads - one that accepts a `Context` and one
33+
that accepts an `AndroidScreenStarter`. The former is just a shorthand for the latter that only
34+
supports `IntentScreen`. You can also implement your own starter that supports other screen types.
35+
36+
`AndroidScreen` is the base `Screen` type that this navigator and `AndroidScreenStarter` interact
37+
with. There is a built-in `IntentScreen` implementation that wraps an `Intent` and an
38+
options `Bundle` to pass to `startActivity()`. Custom `AndroidScreens` can be implemented separately
39+
and route through here, but you should be sure to implement your own `AndroidScreenStarter` to
40+
handle them accordingly.

docs/circuitx/effects.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
CircuitX provides some effects for use with logging/analytics. These effects are typically used in
2+
Circuit presenters for tracking `impressions` and will run only once until forgotten based on the
3+
current circuit-retained strategy.
4+
5+
```kotlin
6+
dependencies {
7+
implementation("com.slack.circuit:circuitx-effects:<version>")
8+
}
9+
```
10+
11+
### ImpressionEffect
12+
13+
`ImpressionEffect` is a simple single fire side effect useful for logging or analytics.
14+
This `impression` will run only once until it is forgotten based on the current `RetainedStateRegistry`.
15+
16+
```kotlin
17+
ImpressionEffect {
18+
// Impression
19+
}
20+
```
21+
22+
### LaunchedImpressionEffect
23+
24+
This is useful for async single fire side effects like logging or analytics. This effect will run a
25+
suspendable `impression` once until it is forgotten based on the `RetainedStateRegistry`.
26+
27+
```kotlin
28+
LaunchedImpressionEffect {
29+
// Impression
30+
}
31+
```
32+
33+
### RememberImpressionNavigator
34+
35+
A `LaunchedImpressionEffect` that is useful for async single fire side effects like logging or
36+
analytics that need to be navigation aware. This will run the `impression` again if it re-enters
37+
the composition after a navigation event.
38+
39+
```kotlin
40+
val navigator = rememberImpressionNavigator(
41+
navigator = Navigator()
42+
) {
43+
// Impression
44+
}
45+
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
CircuitX provides `NavDecoration` implementation which support navigation through appropriate
2+
gestures on certain platforms.
3+
4+
```kotlin
5+
dependencies {
6+
implementation("com.slack.circuit:circuitx-gesture-navigation:<version>")
7+
}
8+
```
9+
10+
To enable gesture navigation support, you can use the use the `GestureNavigationDecoration`function:
11+
12+
```kotlin
13+
NavigableCircuitContent(
14+
navigator = navigator,
15+
backStack = backstack,
16+
decoration = GestureNavigationDecoration(
17+
// Pop the back stack once the user has gone 'back'
18+
navigator::pop
19+
)
20+
)
21+
```
22+
23+
### Android
24+
25+
On Android, this supports the [Predictive back gesture](https://developer.android.com/guide/navigation/custom-back/predictive-back-gesture) which is available on Android 14 and later (API level 34+). On older platforms, Circuit's default
26+
`NavDecoration` decoration is used instead.
27+
28+
<figure>
29+
<video controls width="300" loop=true>
30+
<source src="../../videos/gesturenav_android.mp4" type="video/mp4" />
31+
</video>
32+
<figcaption><a href="https://github.com/slackhq/circuit/tree/main/samples/star">Star sample</a> running on an Android 14 device</figcaption>
33+
</figure>
34+
35+
### iOS
36+
37+
On iOS, this simulates iOS's 'Interactive Pop Gesture' in Compose UI, allowing the user to swipe Circuit UIs away. As this is
38+
a simulation of the native behavior, it does not match the native functionality perfectly. However, it is a good approximation.
39+
40+
<figure>
41+
<video controls width="300" loop=true>
42+
<source src="../../videos/gesturenav_ios.mp4" type="video/mp4" />
43+
</video>
44+
<figcaption><a href="https://github.com/chrisbanes/tivi">Tivi</a> app running on iPhone</figcaption>
45+
</figure>
46+
47+
### Other platforms
48+
49+
On other platforms we defer to Circuit's default `NavDecoration` decoration.

0 commit comments

Comments
 (0)