Patterns from production · Streams that hold still

Keep the anchor

Content above the viewport can change without moving the visible row.

Keep the anchorLive demo

Try the controls to see the rule.

The rule

Before inserting or changing rows above the viewport, remember the first visible row and its screen position. Restore that position after the patch.

Tokens used

  • space.md12px
  • motion.duration.fast180ms
  • size.tap44px
  • motion.duration.base260ms

Native spec · generated from this pattern and the shared token registry

SwiftUI
struct OvKeepAnchor: View {
    let status: String
    @Environment(\.accessibilityReduceMotion) private var reduceMotion
    var body: some View {
        HStack(spacing: OvScale.spaceMd) {
            Text(status).font(.body)
        }
        .frame(minHeight: OvScale.sizeTap)
        .animation(reduceMotion ? .none : .easeOut(duration: OvScale.motionDurationBase), value: status)
    }
}
// Tokens: space.md=12px, motion.duration.fast=180ms, size.tap=44px, motion.duration.base=260ms
Compose
@Composable
fun OvKeepAnchor(status: String, reduceMotion: Boolean) {
    Row(
        modifier = Modifier.defaultMinSize(minHeight = OvScale.SizeTap),
        horizontalArrangement = Arrangement.spacedBy(OvScale.SpaceMd),
    ) {
        Text(status, style = MaterialTheme.typography.bodyMedium)
    }
    // Apply motion only when !reduceMotion.
}
// Tokens: space.md=12px, motion.duration.fast=180ms, size.tap=44px, motion.duration.base=260ms