Feedback UI
Fedo ships two UI entry points on each platform:
| Android (Compose) | iOS (SwiftUI) | |
|---|---|---|
| Full feedback board (list, details, editor) | FedoFeedbackScreen() | FedoFeedbackView() |
| Submission-only sheet | FedoCreateFeedbackSheet() | .presentFedoCreateFeedback(isPresented:) |
Signatureโ
- Kotlin
- Swift
@Composable
fun FedoFeedbackScreen(
modifier: Modifier = Modifier,
onDismiss: () -> Unit,
)
| Parameter | Type | Description |
|---|---|---|
modifier | Modifier | Compose modifier for sizing/padding |
onDismiss | () -> Unit | Called when user navigates back from the root screen |
struct FedoFeedbackView: View {
init()
}
No parameters: the view reads everything it needs from the SDK singleton.
It pushes its screens onto the enclosing NavigationStack, so present it
with a NavigationLink:
NavigationLink("Feedbacks List") {
FedoFeedbackView()
}
NavigationView is not supported: rows open, but the "+" and Edit
actions do nothing under it.
To show it modally, give it its own NavigationStack. Don't use
fullScreenCover: the view has no close button, so the user can't
dismiss it.
.sheet(isPresented: $showFeedbacks) {
NavigationStack {
FedoFeedbackView()
}
}
There is no onDismiss: back navigation is the system's. If the SDK was
never initialized, the view shows a "Feedback isn't available right now"
placeholder instead of the list.
Screensโ
The board manages its own internal navigation with three screens (identical on both platforms):
1. Feedback Listโ
- Shows feedback items in a vertical list with pull-to-refresh
- Status filter: All, In review, Planned, In progress, Done (Shipped on iOS), Closed (tabs on Android; a toolbar menu with a count per status on iOS)
- FAB to create new feedback
- Vote buttons on each item
Android
iOS
The board follows each platform's own conventions, so Android and iOS look different by design.
2. Feedback Detailsโ
- Full feedback description
- Comments section
- Vote on the feedback
- Edit/delete own feedback (when status allows)
Android
3. Feedback Editorโ
- Create new feedback (title + description)
- Edit existing feedback (pre-populated fields)
- Validation before submit
- Asks before discarding unsaved changes
Android
Navigationโ
Back navigation is automatic. On Android:
- Editor โ Details / List
- Details โ List
- List โ
onDismissfires
The onDismiss lambda is only called when the user presses back on the root list screen. Your app handles this by popping its own navigation stack.
On iOS there is no onDismiss: FedoFeedbackView pushes onto your
NavigationStack, so the system back button pops it for you.
State handlingโ
The screen handles loading, error, and empty states internally. No extra UI work needed.
If the SDK has not been initialized, FedoFeedbackScreen() renders a full-screen "Fedo not initialized" placeholder in place of the board. On iOS, FedoFeedbackView() shows a "Feedback isn't available right now" placeholder and logs an error to OSLog. Neither crashes.
Feedback Sheetโ
The submission sheet is built per platform. On Android, FedoCreateFeedbackSheet() renders a self-contained creation form (title + details fields) as a ModalBottomSheet, with its own submit state and validation - no navigation setup or FedoFeedbackScreen() host required. On iOS, the equivalent is the .presentFedoCreateFeedback(isPresented:) view modifier, which presents the same sheet without requiring a NavigationStack or FedoFeedbackView host. Use it when you want a lightweight "suggest a feature" entry point (e.g. from a menu or FAB) instead of the full feedback flow.
Signatureโ
- Kotlin
- Swift
@Composable
fun FedoCreateFeedbackSheet(
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
)
| Parameter | Type | Description |
|---|---|---|
onDismiss | () -> Unit | Called when the sheet is dismissed by the user (swipe/scrim/close button) or automatically after a successful submit |
modifier | Modifier | Compose modifier applied to the ModalBottomSheet container |
There's no visible param - toggle composition yourself:
@Composable
fun MyScreen() {
var showFeedbackSheet by remember { mutableStateOf(false) }
Button(onClick = { showFeedbackSheet = true }) {
Text("Suggest a feature")
}
if (showFeedbackSheet) {
FedoCreateFeedbackSheet(
onDismiss = { showFeedbackSheet = false }
)
}
}
On success, the form is replaced with a brief thank-you message before the sheet auto-dismisses, which fires onDismiss.
extension View {
func presentFedoCreateFeedback(isPresented: Binding<Bool>) -> some View
}
| Parameter | Type | Description |
|---|---|---|
isPresented | Binding<Bool> | Drives presentation, exactly like SwiftUI's sheet(isPresented:content:). Set back to false on swipe-down, close button, or auto-dismiss after a successful submit |
struct SettingsView: View {
@State private var showFeedbackSheet = false
var body: some View {
Button("Suggest a feature") {
showFeedbackSheet = true
}
.presentFedoCreateFeedback(isPresented: $showFeedbackSheet)
}
}
No NavigationStack or FedoFeedbackView host required.
If Fedo.initialize has not been called, FedoCreateFeedbackSheet() shows the same "Fedo not initialized" error inside the sheet, while FedoFeedbackScreen() shows it full-screen. On iOS, the sheet shows the same "Feedback isn't available right now" placeholder as FedoFeedbackView(). On both platforms, calls to user-management methods (setUserID, setUserEmail, etc.) are silent no-ops โ they do not throw.
Android