Focus Cleanup

Add Samples
Update Documentation
Remove internal references from public docs

Bug: 170154986
Bug: 190386715
Bug: 186567354
Bug: 168510304
Test: N/A
Relnote: "Removed deprecated experimental `FocusManager#moveFocusIn` and `FocusManager#moveFocusOut`"
Change-Id: I227d79e985d993d52d383d22439abaecbce9f593
diff --git a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta10.txt b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta10.txt
index e9f571b..409ec8a 100644
--- a/compose/ui/ui/api/public_plus_experimental_1.0.0-beta10.txt
+++ b/compose/ui/ui/api/public_plus_experimental_1.0.0-beta10.txt
@@ -343,8 +343,6 @@
   public interface FocusManager {
     method public void clearFocus(optional boolean force);
     method public boolean moveFocus-3ESFkO8(int focusDirection);
-    method @Deprecated @androidx.compose.ui.ExperimentalComposeUiApi public default boolean moveFocusIn();
-    method @Deprecated @androidx.compose.ui.ExperimentalComposeUiApi public default boolean moveFocusOut();
   }
 
   public final class FocusModifierKt {
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index e9f571b..409ec8a 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -343,8 +343,6 @@
   public interface FocusManager {
     method public void clearFocus(optional boolean force);
     method public boolean moveFocus-3ESFkO8(int focusDirection);
-    method @Deprecated @androidx.compose.ui.ExperimentalComposeUiApi public default boolean moveFocusIn();
-    method @Deprecated @androidx.compose.ui.ExperimentalComposeUiApi public default boolean moveFocusOut();
   }
 
   public final class FocusModifierKt {
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
index 8d4b434..5e56360 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/UiDemos.kt
@@ -20,6 +20,7 @@
 import androidx.compose.integration.demos.common.ComposableDemo
 import androidx.compose.integration.demos.common.DemoCategory
 import androidx.compose.ui.demos.autofill.ExplicitAutofillTypesDemo
+import androidx.compose.ui.demos.focus.CaptureFocusDemo
 import androidx.compose.ui.demos.focus.CustomFocusOrderDemo
 import androidx.compose.ui.demos.focus.FocusInDialogDemo
 import androidx.compose.ui.demos.focus.FocusInPopupDemo
@@ -118,7 +119,8 @@
         ComposableDemo("Reuse Focus Requester") { ReuseFocusRequesterDemo() },
         ComposableDemo("Focus Search") { FocusSearchDemo() },
         ComposableDemo("Custom Focus Order") { CustomFocusOrderDemo() },
-        ComposableDemo("FocusManager.moveFocus()") { FocusManagerMoveFocusDemo() }
+        ComposableDemo("FocusManager.moveFocus()") { FocusManagerMoveFocusDemo() },
+        ComposableDemo("Capture/Free Focus") { CaptureFocusDemo() }
     )
 )
 
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CaptureFocusDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CaptureFocusDemo.kt
new file mode 100644
index 0000000..fc4646b
--- /dev/null
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CaptureFocusDemo.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.demos.focus
+
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.height
+import androidx.compose.material.Text
+import androidx.compose.material.TextField
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.graphics.Color.Companion.Red
+import androidx.compose.ui.graphics.Color.Companion.Transparent
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun CaptureFocusDemo() {
+    Column {
+        Text(
+            "This demo demonstrates how a component can capture focus when it is in an " +
+                "invalidated state."
+        )
+
+        Spacer(Modifier.height(30.dp))
+
+        Text("Enter a word that is 5 characters or shorter")
+        val shortWord = remember { FocusRequester() }
+        var shortString by remember { mutableStateOf("apple") }
+        var shortStringBorder by remember { mutableStateOf(Transparent) }
+        TextField(
+            value = shortString,
+            onValueChange = {
+                shortString = it
+                if (shortString.length > 5) shortWord.captureFocus() else shortWord.freeFocus()
+            },
+            modifier = Modifier
+                .border(2.dp, shortStringBorder)
+                .focusRequester(shortWord)
+                .onFocusChanged { shortStringBorder = if (it.isCaptured) Red else Transparent }
+        )
+
+        Spacer(Modifier.height(30.dp))
+
+        Text("Enter a word that is longer than 5 characters")
+        val longWord = remember { FocusRequester() }
+        var longString by remember { mutableStateOf("pineapple") }
+        var longStringBorder by remember { mutableStateOf(Transparent) }
+
+        TextField(
+            value = longString,
+            onValueChange = {
+                longString = it
+                if (longString.length < 5) longWord.captureFocus() else longWord.freeFocus()
+            },
+            modifier = Modifier
+                .border(2.dp, longStringBorder)
+                .focusRequester(longWord)
+                .onFocusChanged { longStringBorder = if (it.isCaptured) Red else Transparent }
+        )
+    }
+}
\ No newline at end of file
diff --git a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CustomFocusOrderDemo.kt b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CustomFocusOrderDemo.kt
index f31814e..e0e0f56 100644
--- a/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CustomFocusOrderDemo.kt
+++ b/compose/ui/ui/integration-tests/ui-demos/src/main/java/androidx/compose/ui/demos/focus/CustomFocusOrderDemo.kt
@@ -56,7 +56,7 @@
             )
         }
         Column(Modifier.fillMaxSize(), SpaceEvenly) {
-            val (item1, item2, item3, item4) = FocusRequester.createRefs()
+            val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
             Row(Modifier.fillMaxWidth(), SpaceEvenly) {
                 FocusableText(
                     text = "1",
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/FocusSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/FocusSamples.kt
index f01d362..8f0da4a 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/FocusSamples.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/FocusSamples.kt
@@ -17,16 +17,112 @@
 package androidx.compose.ui.samples
 
 import androidx.annotation.Sampled
+import androidx.compose.foundation.border
+import androidx.compose.foundation.clickable
 import androidx.compose.foundation.focusable
+import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.size
 import androidx.compose.material.Button
 import androidx.compose.material.Text
+import androidx.compose.material.TextField
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusDirection
+import androidx.compose.ui.focus.FocusRequester
+import androidx.compose.ui.focus.focusOrder
+import androidx.compose.ui.focus.focusRequester
+import androidx.compose.ui.focus.focusTarget
+import androidx.compose.ui.focus.onFocusChanged
+import androidx.compose.ui.graphics.Color.Companion.Black
+import androidx.compose.ui.graphics.Color.Companion.Green
+import androidx.compose.ui.graphics.Color.Companion.Red
+import androidx.compose.ui.graphics.Color.Companion.Transparent
 import androidx.compose.ui.platform.LocalFocusManager
+import androidx.compose.ui.unit.dp
+
+@Sampled
+@Composable
+fun FocusableSample() {
+    var color by remember { mutableStateOf(Black) }
+    Box(
+        Modifier
+            .border(2.dp, color)
+            // The onFocusChanged should be added BEFORE the focusable that is being observed.
+            .onFocusChanged { color = if (it.isFocused) Green else Black }
+            .focusable()
+    )
+}
+
+@Sampled
+@Composable
+fun FocusableSampleUsingLowerLevelFocusTarget() {
+    var color by remember { mutableStateOf(Black) }
+    Box(
+        Modifier
+            .border(2.dp, color)
+            // The onFocusChanged should be added BEFORE the focusTarget that is being observed.
+            .onFocusChanged { color = if (it.isFocused) Green else Black }
+            .focusTarget()
+    )
+}
+
+@Sampled
+@Composable
+fun CaptureFocusSample() {
+    val focusRequester = remember { FocusRequester() }
+    var value by remember { mutableStateOf("apple") }
+    var borderColor by remember { mutableStateOf(Transparent) }
+    TextField(
+        value = value,
+        onValueChange = {
+            value = it.apply {
+                if (length > 5) focusRequester.captureFocus() else focusRequester.freeFocus()
+            }
+        },
+        modifier = Modifier
+            .border(2.dp, borderColor)
+            .focusRequester(focusRequester)
+            .onFocusChanged { borderColor = if (it.isCaptured) Red else Transparent }
+    )
+}
+
+@Sampled
+@Composable
+fun RequestFocusSample() {
+    val focusRequester = remember { FocusRequester() }
+    var color by remember { mutableStateOf(Black) }
+    Box(
+        Modifier
+            .clickable { focusRequester.requestFocus() }
+            .border(2.dp, color)
+            // The focusRequester should be added BEFORE the focusable.
+            .focusRequester(focusRequester)
+            // The onFocusChanged should be added BEFORE the focusable that is being observed.
+            .onFocusChanged { color = if (it.isFocused) Green else Black }
+            .focusable()
+    )
+}
+
+@Sampled
+@Composable
+fun ClearFocusSample() {
+    val focusManager = LocalFocusManager.current
+    Column(Modifier.clickable { focusManager.clearFocus() }) {
+        Box(Modifier.focusable().size(100.dp))
+        Box(Modifier.focusable().size(100.dp))
+        Box(Modifier.focusable().size(100.dp))
+    }
+}
 
 @Sampled
 @Composable
@@ -46,4 +142,66 @@
         Button(onClick = { focusManager.moveFocus(FocusDirection.Up) }) { Text("Up") }
         Button(onClick = { focusManager.moveFocus(FocusDirection.Down) }) { Text("Down") }
     }
-}
\ No newline at end of file
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun CreateFocusRequesterRefsSample() {
+    val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
+    Column {
+        Box(Modifier.focusRequester(item1).focusable())
+        Box(Modifier.focusRequester(item2).focusable())
+        Box(Modifier.focusRequester(item3).focusable())
+        Box(Modifier.focusRequester(item4).focusable())
+    }
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun CustomFocusOrderSample() {
+    Column(Modifier.fillMaxSize(), Arrangement.SpaceEvenly) {
+        val (item1, item2, item3, item4) = remember { FocusRequester.createRefs() }
+        Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
+            Box(
+                Modifier
+                    .focusOrder(item1) {
+                        next = item2
+                        right = item2
+                        down = item3
+                        previous = item4
+                    }
+                    .focusable()
+            )
+            Box(
+                Modifier
+                    .focusOrder(item2) {
+                        next = item3
+                        right = item1
+                        down = item4
+                        previous = item1
+                    }
+                    .focusable()
+            )
+        }
+        Row(Modifier.fillMaxWidth(), Arrangement.SpaceEvenly) {
+            Box(
+                Modifier.focusOrder(item3) {
+                    next = item4
+                    right = item4
+                    up = item1
+                    previous = item2
+                }
+            )
+            Box(
+                Modifier.focusOrder(item4) {
+                    next = item1
+                    left = item3
+                    up = item2
+                    previous = item3
+                }
+            )
+        }
+    }
+}
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/KeyInputSamples.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/KeyInputSamples.kt
new file mode 100644
index 0000000..d8a498a
--- /dev/null
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/KeyInputSamples.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.ui.samples
+
+import androidx.annotation.Sampled
+import androidx.compose.foundation.focusable
+import androidx.compose.foundation.layout.Box
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.ExperimentalComposeUiApi
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.KeyEventType.Companion.KeyDown
+import androidx.compose.ui.input.key.KeyEventType.Companion.KeyUp
+import androidx.compose.ui.input.key.KeyEventType.Companion.Unknown
+import androidx.compose.ui.input.key.isAltPressed
+import androidx.compose.ui.input.key.isCtrlPressed
+import androidx.compose.ui.input.key.isMetaPressed
+import androidx.compose.ui.input.key.isShiftPressed
+import androidx.compose.ui.input.key.key
+import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.input.key.onPreviewKeyEvent
+import androidx.compose.ui.input.key.type
+
+@Suppress("UNUSED_ANONYMOUS_PARAMETER")
+@Sampled
+@Composable
+fun KeyEventSample() {
+    // When the inner Box is focused, and the user presses a key, the key goes down the hierarchy
+    // and then back up to the parent. At any stage you can stop the propagation by returning
+    // true to indicate that you consumed the event.
+    Box(
+        Modifier
+            .onPreviewKeyEvent { keyEvent1 -> false }
+            .onKeyEvent { keyEvent4 -> false }
+    ) {
+        Box(
+            Modifier
+                .onPreviewKeyEvent { keyEvent2 -> false }
+                .onKeyEvent { keyEvent3 -> false }
+                .focusable()
+        )
+    }
+}
+
+@Sampled
+@Composable
+fun KeyEventTypeSample() {
+    Box(
+        Modifier
+            .onKeyEvent {
+                when (it.type) {
+                    KeyUp -> println(" KeyUp Pressed")
+                    KeyDown -> println(" KeyUp Pressed")
+                    Unknown -> println("Unknown key type")
+                    else -> println("New KeyTpe (For Future Use)")
+                }
+                false
+            }
+            .focusable()
+    )
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun KeyEventIsAltPressedSample() {
+    Box(
+        Modifier
+            .onKeyEvent {
+                if (it.isAltPressed && it.key == Key.A) {
+                    println("Alt + A is pressed")
+                    true
+                } else {
+                    false
+                }
+            }
+            .focusable()
+    )
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun KeyEventIsCtrlPressedSample() {
+    Box(
+        Modifier
+            .onKeyEvent {
+                if (it.isCtrlPressed && it.key == Key.A) {
+                    println("Ctrl + A is pressed")
+                    true
+                } else {
+                    false
+                }
+            }
+            .focusable()
+    )
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun KeyEventIsMetaPressedSample() {
+    Box(
+        Modifier
+            .onKeyEvent {
+                if (it.isMetaPressed && it.key == Key.A) {
+                    println("Meta + A is pressed")
+                    true
+                } else {
+                    false
+                }
+            }
+            .focusable()
+    )
+}
+
+@ExperimentalComposeUiApi
+@Sampled
+@Composable
+fun KeyEventIsShiftPressedSample() {
+    Box(
+        Modifier
+            .onKeyEvent {
+                if (it.isShiftPressed && it.key == Key.A) {
+                    println("Shift + A is pressed")
+                    true
+                } else {
+                    false
+                }
+            }
+            .focusable()
+    )
+}
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/Key.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/Key.android.kt
index 4650948..f18af37 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/Key.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/Key.android.kt
@@ -17,8 +17,8 @@
 package androidx.compose.ui.input.key
 
 import android.view.KeyEvent
-import android.view.KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP
 import android.view.KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION_MIX_DOWN
+import android.view.KeyEvent.KEYCODE_TV_AUDIO_DESCRIPTION_MIX_UP
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.input.key.Key.Companion.Number
 import androidx.compose.ui.util.packInts
@@ -28,6 +28,8 @@
  * Actual implementation of [Key] for Android.
  *
  * @param keyCode an integer code representing the key pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 @Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
 actual inline class Key(val keyCode: Long) {
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/KeyEvent.android.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/KeyEvent.android.kt
index e0a35a3..18e9190 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/KeyEvent.android.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/input/key/KeyEvent.android.kt
@@ -29,6 +29,8 @@
 
 /**
  * The key that was pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 actual val KeyEvent.key: Key
     get() = Key(nativeKeyEvent.keyCode)
@@ -54,6 +56,8 @@
 
 /**
  * The [type][KeyEventType] of key event.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventTypeSample
  */
 actual val KeyEvent.type: KeyEventType
     get() = when (nativeKeyEvent.action) {
@@ -64,24 +68,32 @@
 
 /**
  * Indicates whether the Alt key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 actual val KeyEvent.isAltPressed: Boolean
     get() = nativeKeyEvent.isAltPressed
 
 /**
  * Indicates whether the Ctrl key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsCtrlPressedSample
  */
 actual val KeyEvent.isCtrlPressed: Boolean
     get() = nativeKeyEvent.isCtrlPressed
 
 /**
  * Indicates whether the Meta key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsMetaPressedSample
  */
 actual val KeyEvent.isMetaPressed: Boolean
     get() = nativeKeyEvent.isMetaPressed
 
 /**
  * Indicates whether the Shift key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsShiftPressedSample
  */
 actual val KeyEvent.isShiftPressed: Boolean
     get() = nativeKeyEvent.isShiftPressed
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
index cc14f53..9440c6b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusChangedModifier.kt
@@ -25,9 +25,12 @@
 
 /**
  * Add this modifier to a component to observe focus state events. [onFocusChanged] is invoked
- * only when the focus state changes.
+ * when the focus state changes. The [onFocusChanged] modifier listens to the state of the first
+ * [focusTarget] following this modifier.
  *
- * If you want to be notified every time the internal focus state is written to (even if it
+ * @sample androidx.compose.ui.samples.FocusableSample
+ *
+ * Note: If you want to be notified every time the internal focus state is written to (even if it
  * hasn't changed), use [onFocusEvent] instead.
  */
 fun Modifier.onFocusChanged(onFocusChanged: (FocusState) -> Unit): Modifier =
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
index a6cc7df..782bdb4 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusManager.kt
@@ -16,7 +16,6 @@
 
 package androidx.compose.ui.focus
 
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.focus.FocusStateImpl.Active
 import androidx.compose.ui.focus.FocusStateImpl.ActiveParent
@@ -31,6 +30,8 @@
      *
      *  @param force: Whether we should forcefully clear focus regardless of whether we have
      *  any components that have Captured focus.
+     *
+     *  @sample androidx.compose.ui.samples.ClearFocusSample
      */
     fun clearFocus(force: Boolean = false)
 
@@ -41,42 +42,10 @@
      * [Modifier.focusOrder()][focusOrder].
      *
      * @return true if focus was moved successfully. false if the focused item is unchanged.
+     *
+     * @sample androidx.compose.ui.samples.MoveFocusSample
      */
     fun moveFocus(focusDirection: FocusDirection): Boolean
-
-    /**
-     * Moves focus to one of the children of the currently focused item.
-     *
-     * This function is deprecated. Use FocusManager.moveFocus(FocusDirection.In) instead.
-     *
-     * @return true if focus was moved successfully.
-     */
-    @ExperimentalComposeUiApi
-    @Deprecated(
-        message = "Use FocusManager.moveFocus(FocusDirection.In) instead",
-        ReplaceWith(
-            "moveFocus(In)",
-            "androidx.compose.ui.focus.FocusDirection.Companion.In"
-        )
-    )
-    fun moveFocusIn(): Boolean = false
-
-    /**
-     * Moves focus to the nearest focusable parent of the currently focused item.
-     *
-     *  This function is deprecated. Use FocusManager.moveFocus(FocusDirection.Out) instead.
-     *
-     * @return true if focus was moved successfully.
-     */
-    @ExperimentalComposeUiApi
-    @Deprecated(
-        message = "Use FocusManager.moveFocus(FocusDirection.Out) instead",
-        ReplaceWith(
-            "moveFocus(Out)",
-            "androidx.compose.ui.focus.FocusDirection.Companion.Out"
-        )
-    )
-    fun moveFocusOut(): Boolean = false
 }
 
 /**
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
index 5c53268..f2718af 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusModifier.kt
@@ -50,6 +50,16 @@
 
 /**
  * Add this modifier to a component to make it focusable.
+ *
+ * Focus state is stored within this modifier. The bounds of this modifier reflect the bounds of
+ * the focus box.
+ *
+ * Note: This is a low level modifier. Before using this consider using
+ * [Modifier.focusable()][androidx.compose.foundation.focusable]. It uses a [focusTarget] in
+ * its implementation. [Modifier.focusable()][androidx.compose.foundation.focusable] adds semantics
+ * that are needed for accessibility.
+ *
+ * @sample androidx.compose.ui.samples.FocusableSampleUsingLowerLevelFocusTarget
  */
 fun Modifier.focusTarget(): Modifier = composed(debugInspectorInfo { name = "focusTarget" }) {
     remember { FocusModifier(Inactive) }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
index dbd306d..d258b41 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusOrderModifier.kt
@@ -23,6 +23,8 @@
 
 /**
  * A [modifier][Modifier.Element] that can be used to set a custom focus traversal order.
+ *
+ * @see Modifier.focusOrder
  */
 interface FocusOrderModifier : Modifier.Element {
 
@@ -36,48 +38,66 @@
 
 /**
  * Specifies custom focus destinations that are used instead of the default focus traversal order.
+ *
+ * @sample androidx.compose.ui.samples.CustomFocusOrderSample
  */
 class FocusOrder {
 
     /**
-     * A custom item to be used when the user moves focus to the "next" item.
+     * A custom item to be used when the user requests a focus moves to the "next" item.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var next: FocusRequester = FocusRequester.Default
 
     /**
-     * A custom item to be used when the user moves focus to the "previous" item.
+     * A custom item to be used when the user requests a focus moves to the "previous" item.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var previous: FocusRequester = FocusRequester.Default
 
     /**
      *  A custom item to be used when the user moves focus "up".
+     *
+     *  @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var up: FocusRequester = FocusRequester.Default
 
     /**
      *  A custom item to be used when the user moves focus "down".
+     *
+     *  @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var down: FocusRequester = FocusRequester.Default
 
     /**
-     * A custom item to be used when the user moves focus to the "left" item.
+     * A custom item to be used when the user requests a focus moves to the "left" item.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var left: FocusRequester = FocusRequester.Default
 
     /**
-     * A custom item to be used when the user moves focus to the "right" item.
+     * A custom item to be used when the user requests a focus moves to the "right" item.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var right: FocusRequester = FocusRequester.Default
 
     /**
-     * A custom item to be used when the user moves focus to the "left" in LTR mode and "right"
-     * in RTL mode.
+     * A custom item to be used when the user requests a focus moves to the "left" in LTR mode and
+     * "right" in RTL mode.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var start: FocusRequester = FocusRequester.Default
 
     /**
-     * A custom item to be used when the user moves focus to the "right" in LTR mode and "left"
-     * in RTL mode.
+     * A custom item to be used when the user requests a focus moves to the "right" in LTR mode
+     * and "left" in RTL mode.
+     *
+     * @sample androidx.compose.ui.samples.CustomFocusOrderSample
      */
     var end: FocusRequester = FocusRequester.Default
 }
@@ -98,6 +118,8 @@
  * to move the current focus to the [next][FocusOrder.next] item, or wants to move
  * focus [left][FocusOrder.left], [right][FocusOrder.right], [up][FocusOrder.up] or
  * [down][FocusOrder.down].
+ *
+ * @sample androidx.compose.ui.samples.CustomFocusOrderSample
  */
 fun Modifier.focusOrder(focusOrderReceiver: FocusOrder.() -> Unit): Modifier {
     return this.then(
@@ -114,12 +136,16 @@
 /**
  * A modifier that lets you specify a [FocusRequester] for the current composable so that this
  * [focusRequester] can be used by another composable to specify a custom focus order.
+ *
+ * @sample androidx.compose.ui.samples.CustomFocusOrderSample
  */
 fun Modifier.focusOrder(focusRequester: FocusRequester): Modifier = focusRequester(focusRequester)
 
 /**
  * A modifier that lets you specify a [FocusRequester] for the current composable along with
  * [focusOrder].
+ *
+ * @sample androidx.compose.ui.samples.CustomFocusOrderSample
  */
 fun Modifier.focusOrder(
     focusRequester: FocusRequester,
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
index 0dded38..7f0d6f9 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequester.kt
@@ -21,14 +21,21 @@
 import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.node.ModifiedFocusRequesterNode
 
-private const val focusRequesterNotInitialized = "FocusRequester is not initialized. One reason " +
-    "for this is that you requesting focus changes during composition. Focus requesters should " +
-    "not be made during composition, but should be made in response to some event."
+private const val focusRequesterNotInitialized = """
+   FocusRequester is not initialized. Here are some possible fixes:
+
+   1. Remember the FocusRequester: val focusRequester = remember { FocusRequester() }
+   2. Did you forget to add a Modifier.focusRequester() ?
+   3. Are you attempting to request focus during composition? Focus requests should be made in
+   response to some event. Eg Modifier.clickable { focusRequester.requestFocus() }
+"""
 
 /**
  * The [FocusRequester] is used in conjunction with
- * [Modifier.focusRequester][androidx.compose.ui.focus.focusRequester] to send requests for focus
- * state change.
+ * [Modifier.focusRequester][androidx.compose.ui.focus.focusRequester] to send requests to
+ * change focus.
+ *
+ * @sample androidx.compose.ui.samples.RequestFocusSample
  *
  * @see androidx.compose.ui.focus.focusRequester
  */
@@ -38,8 +45,10 @@
 
     /**
      * Use this function to request focus. If the system grants focus to a component associated
-     * with this [FocusRequester], its [state][FocusState] will be set to
-     * [Active][FocusState.Active].
+     * with this [FocusRequester], its [onFocusChanged] modifiers will receive a [FocusState] object
+     * where [FocusState.isFocused] is true.
+     *
+     * @sample androidx.compose.ui.samples.RequestFocusSample
      */
     fun requestFocus() {
         check(focusRequesterNodes.isNotEmpty()) { focusRequesterNotInitialized }
@@ -49,15 +58,17 @@
     /**
      * Deny requests to clear focus.
      *
-     * Use this function to send a request to capture the focus. If a component is captured,
-     * its [state][FocusState] will be set to [Captured][FocusState.Captured]. When a
-     * component is in this state, it holds onto focus until [freeFocus] is called. When a
-     * component is in the [Captured][FocusState.Captured] state, all focus requests from
-     * other components are declined.
+     * Use this function to send a request to capture focus. If a component captures focus,
+     * it will send a [FocusState] object to its associated [onFocusChanged]
+     * modifiers where [FocusState.isCaptured]() == true.
+     *
+     * When a component is in a Captured state, all focus requests from other components are
+     * declined.
      *
      * @return true if the focus was successfully captured by one of the
-     * [focus][androidx.compose.ui.focus] modifiers associated with this [FocusRequester].
-     * false otherwise.
+     * [focus][focusTarget] modifiers associated with this [FocusRequester]. False otherwise.
+     *
+     * @sample androidx.compose.ui.samples.CaptureFocusSample
      */
     fun captureFocus(): Boolean {
         check(focusRequesterNodes.isNotEmpty()) { focusRequesterNotInitialized }
@@ -73,19 +84,18 @@
     }
 
     /**
-     * Use this function to send a request to release focus when one of the components associated
-     * with this [FocusRequester] is in a [Captured][FocusState.Captured] state.
+     * Use this function to send a request to free focus when one of the components associated
+     * with this [FocusRequester] is in a Captured state. If a component frees focus,
+     * it will send a [FocusState] object to its associated [onFocusChanged]
+     * modifiers where [FocusState.isCaptured]() == false.
      *
-     * When the node is in the [Captured][FocusState.Captured] state, it rejects all requests to
-     * clear focus. Calling
-     * [freeFocus] puts the node in the [Active][FocusState.Active] state, where it is no longer
-     * preventing other
-     * nodes from requesting focus.
+     * When a component is in a Captured state, all focus requests from other components are
+     * declined.
+     *.
+     * @return true if the captured focus was successfully released. i.e. At the end of this
+     * operation, one of the components associated with this [focusRequester] freed focus.
      *
-     * @return true if the focus was successfully released. i.e. At the end of this operation,
-     * one of the components associated with this
-     * [focusRequester][androidx.compose.ui.focus.focusRequester] is in the
-     * [Active][FocusState.Active] state. false otherwise.
+     * @sample androidx.compose.ui.samples.CaptureFocusSample
      */
     fun freeFocus(): Boolean {
         check(focusRequesterNodes.isNotEmpty()) { focusRequesterNotInitialized }
@@ -103,13 +113,15 @@
     companion object {
         /**
          * Default [focusRequester], which when used in [Modifier.focusOrder][focusOrder] implies
-         * that we want to use the default system focus order, that is based on the location on
+         * that we want to use the default system focus order, that is based on the position of the
          * items on the screen.
          */
         val Default = FocusRequester()
 
         /**
          * Convenient way to create multiple [FocusRequester] instances.
+         *
+         * @sample androidx.compose.ui.samples.CreateFocusRequesterRefsSample
          */
         @ExperimentalComposeUiApi
         object FocusRequesterFactory {
@@ -134,6 +146,8 @@
         /**
          * Convenient way to create multiple [FocusRequester]s, which can to be used to request
          * focus, or to specify a focus traversal order.
+         *
+         * @sample androidx.compose.ui.samples.CreateFocusRequesterRefsSample
          */
         @ExperimentalComposeUiApi
         fun createRefs() = FocusRequesterFactory
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
index 739030d..8f193ed 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusRequesterModifier.kt
@@ -22,14 +22,19 @@
 import androidx.compose.ui.platform.debugInspectorInfo
 
 /**
- * A [modifier][Modifier.Element] that can be used to pass in a [FocusRequester] that can be used
- * to request focus state changes.
+ * A [modifier][Modifier.Element] that is used to pass in a [FocusRequester] that can be used to
+ * request focus state changes.
+ *
+ * @sample androidx.compose.ui.samples.RequestFocusSample
  *
  * @see FocusRequester
+ * @see Modifier.focusRequester
  */
 interface FocusRequesterModifier : Modifier.Element {
     /**
      * An instance of [FocusRequester], that can be used to request focus state changes.
+     *
+     * @sample androidx.compose.ui.samples.RequestFocusSample
      */
     val focusRequester: FocusRequester
 }
@@ -40,7 +45,9 @@
 ) : FocusRequesterModifier, InspectorValueInfo(inspectorInfo)
 
 /**
- * Add this modifier to a component to observe changes to focus state.
+ * Add this modifier to a component to request changes to focus.
+ *
+ * @sample androidx.compose.ui.samples.RequestFocusSample
  */
 fun Modifier.focusRequester(focusRequester: FocusRequester): Modifier {
     return this.then(
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusState.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusState.kt
index 5f2f046..390eba2 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusState.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusState.kt
@@ -19,14 +19,19 @@
 /**
  * The focus state of a [FocusModifier]. Use [onFocusChanged] or [onFocusEvent] modifiers to
  * access [FocusState].
+ *
+ * @sample androidx.compose.ui.samples.FocusableSample
  */
 interface FocusState {
     /**
      * Whether the component is focused or not.
      *
+     * @sample androidx.compose.ui.samples.FocusableSample
+     *
      * @return true if the component is focused, false otherwise.
      */
     val isFocused: Boolean
+
     /**
      * Whether the focus modifier associated with this [FocusState] has a child that is focused.
      *
@@ -36,13 +41,16 @@
 
     /**
      * Whether focus is captured or not. A focusable component is in a captured state when it
-     * wants to hold onto focus. (Eg. when a text field has an invalid phone number]. When we are
-     * in a captured state, clicking outside the focused item does not clear focus.
+     * wants to hold onto focus. (Eg. when a text field has an invalid phone number). When we are
+     * in a captured state, clicking on other focusable items does not clear focus from the
+     * currently focused item.
      *
      * You can capture focus by calling [focusRequester.captureFocus()][captureFocus] and free
      * focus by calling [focusRequester.freeFocus()][freeFocus].
      *
      *  @return true if focus is captured, false otherwise.
+     *
+     *  @sample androidx.compose.ui.samples.CaptureFocusSample
      */
     val isCaptured: Boolean
 }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
index fdd5444..94a823b 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/focus/FocusTraversal.kt
@@ -39,8 +39,8 @@
 private const val invalidFocusDirection = "Invalid FocusDirection"
 
 /**
- * The [FocusDirection] is used to specify direction when a focus change request is made via
- * [moveFocus].
+ * The [FocusDirection] is used to specify the direction for a [FocusManager.moveFocus]
+ * request.
  *
  * @sample androidx.compose.ui.samples.MoveFocusSample
  */
@@ -67,36 +67,48 @@
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the next
          *  focusable item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Next: FocusDirection = FocusDirection(1)
 
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the previous
          *  focusable item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Previous: FocusDirection = FocusDirection(2)
 
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the next
          *  focusable item to the left of the currently focused item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Left: FocusDirection = FocusDirection(3)
 
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the next
          *  focusable item to the right of the currently focused item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Right: FocusDirection = FocusDirection(4)
 
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the next
          *  focusable item that is above the currently focused item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Up: FocusDirection = FocusDirection(5)
 
         /**
          *  Direction used in [moveFocus] to indicate that you are searching for the next
          *  focusable item that is below the currently focused item.
+         *
+         *  @sample androidx.compose.ui.samples.MoveFocusSample
          */
         val Down: FocusDirection = FocusDirection(6)
 
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/Key.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/Key.kt
index c420f17..9612a0d 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/Key.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/Key.kt
@@ -23,6 +23,8 @@
  *
  * @param keyCode a Long value representing the key pressed. Note: This keycode can be used to
  * uniquely identify a hardware key. It is different from the native keycode.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 @Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
 expect inline class Key(val keyCode: Long) {
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyEvent.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyEvent.kt
index 48845cfb..efd3ce9 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyEvent.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyEvent.kt
@@ -22,14 +22,21 @@
 expect class NativeKeyEvent
 
 /**
- * When a user presses a key on a hardware keyboard, a [KeyEvent] is sent to the
- * [KeyInputModifier] that is currently active.
+ * When a user presses a key on a hardware keyboard, a [KeyEvent] is sent to the item that is
+ * currently focused. Any parent composable can intercept this [key event][KeyEvent] on its way to
+ * the focused item by using [Modifier.onPreviewKeyEvent()]][onPreviewKeyEvent]. If the item is
+ * not consumed, it returns back to each parent and can be intercepted by using
+ * [Modifier.onKeyEvent()]][onKeyEvent].
+ *
+ * @sample androidx.compose.ui.samples.KeyEventSample
  */
 @Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
 inline class KeyEvent(val nativeKeyEvent: NativeKeyEvent)
 
 /**
  * The key that was pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 expect val KeyEvent.key: Key
 
@@ -53,31 +60,43 @@
 
 /**
  * The [type][KeyEventType] of key event.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventTypeSample
  */
 expect val KeyEvent.type: KeyEventType
 
 /**
  * Indicates whether the Alt key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsAltPressedSample
  */
 expect val KeyEvent.isAltPressed: Boolean
 
 /**
  * Indicates whether the Ctrl key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsCtrlPressedSample
  */
 expect val KeyEvent.isCtrlPressed: Boolean
 
 /**
  * Indicates whether the Meta key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsMetaPressedSample
  */
 expect val KeyEvent.isMetaPressed: Boolean
 
 /**
  * Indicates whether the Shift key is pressed.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventIsShiftPressedSample
  */
 expect val KeyEvent.isShiftPressed: Boolean
 
 /**
  * The type of Key Event.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventTypeSample
  */
 @Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
 inline class KeyEventType internal constructor(@Suppress("unused") private val value: Int) {
@@ -94,16 +113,22 @@
     companion object {
         /**
          * Unknown key event.
+         *
+         * @sample androidx.compose.ui.samples.KeyEventTypeSample
          */
         val Unknown: KeyEventType = KeyEventType(0)
 
         /**
          * Type of KeyEvent sent when the user lifts their finger off a key on the keyboard.
+         *
+         * @sample androidx.compose.ui.samples.KeyEventTypeSample
          */
         val KeyUp: KeyEventType = KeyEventType(1)
 
         /**
          * Type of KeyEvent sent when the user presses down their finger on a key on the keyboard.
+         *
+         * @sample androidx.compose.ui.samples.KeyEventTypeSample
          */
         val KeyDown: KeyEventType = KeyEventType(2)
     }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
index 4519562..7aeab72 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/input/key/KeyInputModifier.kt
@@ -24,11 +24,13 @@
 
 /**
  * Adding this [modifier][Modifier] to the [modifier][Modifier] parameter of a component will
- * allow it to intercept hardware key events.
+ * allow it to intercept hardware key events when it (or one of its children) is focused.
  *
  * @param onKeyEvent This callback is invoked when the user interacts with the hardware keyboard.
  * While implementing this callback, return true to stop propagation of this event. If you return
  * false, the key event will be sent to this [onKeyEvent]'s parent.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventSample
  */
 // TODO: b/191017532 remove Modifier.composed
 @Suppress("UnnecessaryComposedModifier")
@@ -43,13 +45,15 @@
 
 /**
  * Adding this [modifier][Modifier] to the [modifier][Modifier] parameter of a component will
- * allow it to intercept hardware key events.
+ * allow it to intercept hardware key events when it (or one of its children) is focused.
  *
  * @param onPreviewKeyEvent This callback is invoked when the user interacts with the hardware
  * keyboard. It gives ancestors of a focused component the chance to intercept a [KeyEvent].
  * Return true to stop propagation of this event. If you return false, the key event will be sent
  * to this [onPreviewKeyEvent]'s child. If none of the children consume the event, it will be
  * sent back up to the root [KeyInputModifier] using the onKeyEvent callback.
+ *
+ * @sample androidx.compose.ui.samples.KeyEventSample
  */
 // TODO: b/191017532 remove Modifier.composed
 @Suppress("UnnecessaryComposedModifier")