This replaces visibility booleans and error state fields with nullable `searchPanelState`/`devicePanelState` and action-based error toasts for one-shot UI effects. Made-with: Cursor
42 lines
1.2 KiB
Plaintext
42 lines
1.2 KiB
Plaintext
---
|
|
description: Screen UI contract structure for State, Action, and Event
|
|
alwaysApply: false
|
|
---
|
|
# Screen UI Contract Rule
|
|
|
|
Every screen must define its contract in a `*ScreenContract.kt` file using `State`, `Action`, and `Event`.
|
|
|
|
## Required structure
|
|
|
|
1. Define `State` with all static UI data required to render the screen.
|
|
2. Define `Action` (enum or sealed interface) for what the ViewModel does.
|
|
3. Define `Event` (enum or sealed interface) for user interactions.
|
|
|
|
## State guidelines
|
|
|
|
- `State` must include stable screen data (for example `deviceName`, `deviceId`, `isSharingEnabled`).
|
|
- Do not put user interaction triggers in `State`; those belong to `Event`.
|
|
|
|
## Action guidelines
|
|
|
|
- Use `Action` for ViewModel-driven outcomes such as navigation or side effects.
|
|
- Example: `Action.NavigateTo*Screen`, `Action.Show*Toast`
|
|
|
|
## Event guidelines
|
|
|
|
- Use `Event` for user-originated input.
|
|
- Examples: `Event.*ButtonClicked`, `Event.*InputChanged(value)`.
|
|
|
|
## Example
|
|
|
|
```kotlin
|
|
data class State(val deviceName: String, val deviceId: String, val isSharingEnabled: Boolean)
|
|
|
|
sealed interface Action { data object NavigateToScreenX : Action }
|
|
|
|
sealed interface Event {
|
|
data object XButtonClicked : Event
|
|
data class InputChanged(val value: String) : Event
|
|
}
|
|
```
|