Add single provider and single account screens

Bug: 301206470
Test: N/A - feature not fully implemented yet

Change-Id: I25f54e2bcb8228b46a8ca7a89f63753c639a26ef
diff --git a/packages/CredentialManager/horologist/Android.bp b/packages/CredentialManager/horologist/Android.bp
index bb324bb..bb255bd 100644
--- a/packages/CredentialManager/horologist/Android.bp
+++ b/packages/CredentialManager/horologist/Android.bp
@@ -16,6 +16,7 @@
         "androidx.compose.foundation_foundation",
         "androidx.compose.runtime_runtime",
         "androidx.compose.ui_ui",
+        "androidx.compose.ui_ui-tooling",
         "androidx.navigation_navigation-compose",
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.lifecycle_lifecycle-runtime-ktx",
diff --git a/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/layout/BelowTimeTextPreview.kt b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/layout/BelowTimeTextPreview.kt
new file mode 100644
index 0000000..e6025fc
--- /dev/null
+++ b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/layout/BelowTimeTextPreview.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2022 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
+ *
+ *      https://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 com.google.android.horologist.compose.layout
+
+import androidx.compose.runtime.Composable
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+public fun belowTimeTextPreview(): ScalingLazyColumnState {
+    return ScalingLazyColumnDefaults.belowTimeText().create()
+}
diff --git a/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Button.kt b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Button.kt
new file mode 100644
index 0000000..57e0c10
--- /dev/null
+++ b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Button.kt
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.google.android.horologist.compose.material
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.Dp
+import androidx.wear.compose.material.Button
+import androidx.wear.compose.material.ButtonColors
+import androidx.wear.compose.material.ButtonDefaults
+import androidx.wear.compose.material.ButtonDefaults.DefaultButtonSize
+import androidx.wear.compose.material.ButtonDefaults.DefaultIconSize
+import androidx.wear.compose.material.ButtonDefaults.LargeButtonSize
+import androidx.wear.compose.material.ButtonDefaults.LargeIconSize
+import androidx.wear.compose.material.ButtonDefaults.SmallButtonSize
+import androidx.wear.compose.material.ButtonDefaults.SmallIconSize
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+
+/**
+ * This component is an alternative to [Button], providing the following:
+ * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
+ * by the Wear guidelines;
+ */
+@ExperimentalHorologistApi
+@Composable
+public fun Button(
+    imageVector: ImageVector,
+    contentDescription: String,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+    buttonSize: ButtonSize = ButtonSize.Default,
+    iconRtlMode: IconRtlMode = IconRtlMode.Default,
+    enabled: Boolean = true,
+) {
+    Button(
+        icon = imageVector,
+        contentDescription = contentDescription,
+        onClick = onClick,
+        modifier = modifier,
+        colors = colors,
+        buttonSize = buttonSize,
+        iconRtlMode = iconRtlMode,
+        enabled = enabled,
+    )
+}
+
+/**
+ * This component is an alternative to [Button], providing the following:
+ * - a convenient way of providing an icon and choosing its size from a range of sizes recommended
+ * by the Wear guidelines;
+ */
+@ExperimentalHorologistApi
+@Composable
+public fun Button(
+    @DrawableRes id: Int,
+    contentDescription: String,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+    buttonSize: ButtonSize = ButtonSize.Default,
+    iconRtlMode: IconRtlMode = IconRtlMode.Default,
+    enabled: Boolean = true,
+) {
+    Button(
+        icon = id,
+        contentDescription = contentDescription,
+        onClick = onClick,
+        modifier = modifier,
+        colors = colors,
+        buttonSize = buttonSize,
+        iconRtlMode = iconRtlMode,
+        enabled = enabled,
+    )
+}
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+internal fun Button(
+    icon: Any,
+    contentDescription: String,
+    onClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    colors: ButtonColors = ButtonDefaults.primaryButtonColors(),
+    buttonSize: ButtonSize = ButtonSize.Default,
+    iconRtlMode: IconRtlMode = IconRtlMode.Default,
+    enabled: Boolean = true,
+) {
+    Button(
+        onClick = onClick,
+        modifier = modifier.size(buttonSize.tapTargetSize),
+        enabled = enabled,
+        colors = colors,
+    ) {
+        val iconModifier = Modifier
+            .size(buttonSize.iconSize)
+            .align(Alignment.Center)
+
+        Icon(
+            icon = icon,
+            contentDescription = contentDescription,
+            modifier = iconModifier,
+            rtlMode = iconRtlMode,
+        )
+    }
+}
+
+@ExperimentalHorologistApi
+public sealed class ButtonSize(
+    public val iconSize: Dp,
+    public val tapTargetSize: Dp,
+) {
+    public object Default :
+        ButtonSize(iconSize = DefaultIconSize, tapTargetSize = DefaultButtonSize)
+
+    public object Large : ButtonSize(iconSize = LargeIconSize, tapTargetSize = LargeButtonSize)
+    public object Small : ButtonSize(iconSize = SmallIconSize, tapTargetSize = SmallButtonSize)
+
+    /**
+     * Custom sizes should follow the [accessibility principles and guidance for touch targets](https://developer.android.com/training/wearables/accessibility#set-minimum).
+     */
+    public data class Custom(val customIconSize: Dp, val customTapTargetSize: Dp) :
+        ButtonSize(iconSize = customIconSize, tapTargetSize = customTapTargetSize)
+}
+
diff --git a/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Icon.kt b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Icon.kt
new file mode 100644
index 0000000..74e54c0
--- /dev/null
+++ b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/Icon.kt
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.google.android.horologist.compose.material
+
+import androidx.annotation.DrawableRes
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.scale
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.platform.LocalLayoutDirection
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.unit.LayoutDirection
+import androidx.wear.compose.material.Icon
+import androidx.wear.compose.material.LocalContentAlpha
+import androidx.wear.compose.material.LocalContentColor
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+
+/**
+ * This component is an alternative to [Icon], providing the following:
+ * - a convenient way of setting the icon to be mirrored in RTL mode;
+ */
+@ExperimentalHorologistApi
+@Composable
+public fun Icon(
+    imageVector: ImageVector,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+    rtlMode: IconRtlMode = IconRtlMode.Default,
+) {
+    val shouldMirror =
+        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+    Icon(
+        modifier = modifier.scale(
+            scaleX = if (shouldMirror) -1f else 1f,
+            scaleY = 1f,
+        ),
+        imageVector = imageVector,
+        contentDescription = contentDescription,
+        tint = tint,
+    )
+}
+
+/**
+ * This component is an alternative to [Icon], providing the following:
+ * - a convenient way of setting the icon to be mirrored in RTL mode;
+ */
+@ExperimentalHorologistApi
+@Composable
+public fun Icon(
+    @DrawableRes id: Int,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+    rtlMode: IconRtlMode = IconRtlMode.Default,
+) {
+    val shouldMirror =
+        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+
+    Icon(
+        painter = painterResource(id = id),
+        contentDescription = contentDescription,
+        modifier = modifier.scale(
+            scaleX = if (shouldMirror) -1f else 1f,
+            scaleY = 1f,
+        ),
+        tint = tint,
+    )
+}
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+internal fun Icon(
+    icon: Any,
+    contentDescription: String?,
+    modifier: Modifier = Modifier,
+    tint: Color = LocalContentColor.current.copy(alpha = LocalContentAlpha.current),
+    rtlMode: IconRtlMode = IconRtlMode.Default,
+) {
+    val shouldMirror =
+        rtlMode == IconRtlMode.Mirrored && LocalLayoutDirection.current == LayoutDirection.Rtl
+
+    val iconModifier = modifier.scale(
+        scaleX = if (shouldMirror) -1f else 1f,
+        scaleY = 1f,
+    )
+    when (icon) {
+        is ImageVector -> {
+            Icon(
+                imageVector = icon,
+                modifier = iconModifier,
+                contentDescription = contentDescription,
+                tint = tint,
+            )
+        }
+
+        is Int -> {
+            Icon(
+                painter = painterResource(id = icon),
+                contentDescription = contentDescription,
+                modifier = iconModifier,
+                tint = tint,
+            )
+        }
+
+        else -> throw IllegalArgumentException("Type not supported.")
+    }
+}
+
+@ExperimentalHorologistApi
+public enum class IconRtlMode {
+    Default,
+    Mirrored,
+}
diff --git a/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/util/A11y.kt b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/util/A11y.kt
new file mode 100644
index 0000000..39de2e1
--- /dev/null
+++ b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/material/util/A11y.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2022 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
+ *
+ *      https://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 com.google.android.horologist.compose.material.util
+
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+
+/**
+ * Make explicit that a conscious decision was made to mark an element as decorative, so it does not
+ * have associated actions or state.
+ *
+ * https://developer.android.com/jetpack/compose/accessibility#describe-visual
+ */
+@ExperimentalHorologistApi
+public val DECORATIVE_ELEMENT_CONTENT_DESCRIPTION: String? = null
diff --git a/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/tools/WearPreview.kt b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/tools/WearPreview.kt
new file mode 100644
index 0000000..0bfceee
--- /dev/null
+++ b/packages/CredentialManager/horologist/src/com/google/android/horologist/compose/tools/WearPreview.kt
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 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
+ *
+ *      https://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 com.google.android.horologist.compose.tools
+
+import androidx.compose.ui.tooling.preview.Preview
+
+@Preview(
+    backgroundColor = 0xff000000,
+    showBackground = true,
+)
+public annotation class WearPreview
diff --git a/packages/CredentialManager/shared/Android.bp b/packages/CredentialManager/shared/Android.bp
index ae4281e..38d98a9 100644
--- a/packages/CredentialManager/shared/Android.bp
+++ b/packages/CredentialManager/shared/Android.bp
@@ -14,5 +14,6 @@
     static_libs: [
         "androidx.core_core-ktx",
         "androidx.credentials_credentials",
+        "guava",
     ],
 }
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/IntentParser.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/IntentParser.kt
index 6627af5..43d8fb3 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/IntentParser.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/IntentParser.kt
@@ -17,11 +17,15 @@
 package com.android.credentialmanager.ui
 
 import android.content.Intent
+import android.credentials.ui.GetCredentialProviderData
 import android.credentials.ui.RequestInfo
 import com.android.credentialmanager.ui.ktx.cancelUiRequest
+import com.android.credentialmanager.ui.ktx.getCredentialProviderDataList
 import com.android.credentialmanager.ui.ktx.requestInfo
 import com.android.credentialmanager.ui.mapper.toCancel
 import com.android.credentialmanager.ui.model.Request
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.ImmutableMap
 
 fun Intent.parse(): Request {
     cancelUiRequest?.let {
@@ -32,9 +36,23 @@
         RequestInfo.TYPE_CREATE -> {
             Request.Create
         }
+
         RequestInfo.TYPE_GET -> {
-            Request.Get
+            Request.Get(
+                providers = ImmutableMap.copyOf(
+                    getCredentialProviderDataList.associateBy { it.providerFlattenedComponentName }
+                ),
+                entries = ImmutableList.copyOf(
+                    getCredentialProviderDataList.map { providerData ->
+                        check(providerData is GetCredentialProviderData) {
+                            "Invalid provider data type for GetCredentialRequest"
+                        }
+                        providerData
+                    }.flatMap { it.credentialEntries }
+                )
+            )
         }
+
         else -> {
             throw IllegalStateException("Unrecognized request type: ${requestInfo?.type}")
         }
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/factory/CredentialEntryFactory.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/factory/CredentialEntryFactory.kt
new file mode 100644
index 0000000..f01fded
--- /dev/null
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/factory/CredentialEntryFactory.kt
@@ -0,0 +1,25 @@
+package com.android.credentialmanager.ui.factory
+
+import android.app.slice.Slice
+import android.credentials.Credential
+import androidx.credentials.PublicKeyCredential
+import androidx.credentials.provider.CredentialEntry
+import androidx.credentials.provider.CustomCredentialEntry
+import androidx.credentials.provider.PasswordCredentialEntry
+import androidx.credentials.provider.PublicKeyCredentialEntry
+
+fun fromSlice(slice: Slice): CredentialEntry? =
+    try {
+        when (slice.spec?.type) {
+            Credential.TYPE_PASSWORD_CREDENTIAL -> PasswordCredentialEntry.fromSlice(slice)!!
+
+            PublicKeyCredential.TYPE_PUBLIC_KEY_CREDENTIAL ->
+                PublicKeyCredentialEntry.fromSlice(slice)!!
+
+            else -> CustomCredentialEntry.fromSlice(slice)!!
+        }
+    } catch (e: Exception) {
+        // Try CustomCredentialEntry.fromSlice one last time in case the cause was a failed
+        // password / passkey parsing attempt.
+        CustomCredentialEntry.fromSlice(slice)
+    }
\ No newline at end of file
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/ktx/IntentKtx.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/ktx/IntentKtx.kt
index a646851..b9895a0 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/ktx/IntentKtx.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/ktx/IntentKtx.kt
@@ -18,6 +18,9 @@
 
 import android.content.Intent
 import android.credentials.ui.CancelUiRequest
+import android.credentials.ui.CreateCredentialProviderData
+import android.credentials.ui.GetCredentialProviderData
+import android.credentials.ui.ProviderData
 import android.credentials.ui.RequestInfo
 
 val Intent.cancelUiRequest: CancelUiRequest?
@@ -30,4 +33,16 @@
     get() = this.extras?.getParcelable(
         RequestInfo.EXTRA_REQUEST_INFO,
         RequestInfo::class.java
-    )
\ No newline at end of file
+    )
+
+val Intent.getCredentialProviderDataList: List<ProviderData>
+    get() = this.extras?.getParcelableArrayList(
+        ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
+        GetCredentialProviderData::class.java
+    ) ?: emptyList()
+
+val Intent.createCredentialProviderDataList: List<ProviderData>
+    get() = this.extras?.getParcelableArrayList(
+        ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST,
+        CreateCredentialProviderData::class.java
+    ) ?: emptyList()
diff --git a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/model/Request.kt b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/model/Request.kt
index 3d835be..cffa2b2 100644
--- a/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/model/Request.kt
+++ b/packages/CredentialManager/shared/src/com/android/credentialmanager/ui/model/Request.kt
@@ -16,6 +16,11 @@
 
 package com.android.credentialmanager.ui.model
 
+import android.credentials.ui.Entry
+import android.credentials.ui.ProviderData
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.ImmutableMap
+
 /**
  * Represents the request made by the CredentialManager API.
  */
@@ -25,7 +30,10 @@
         val appPackageName: String?
     ) : Request()
 
-    data object Get : Request()
+    data class Get(
+        val providers: ImmutableMap<String, ProviderData>,
+        val entries: ImmutableList<Entry>,
+    ) : Request()
 
     data object Create : Request()
 }
diff --git a/packages/CredentialManager/wear/Android.bp b/packages/CredentialManager/wear/Android.bp
index 36340fa..c0dff16 100644
--- a/packages/CredentialManager/wear/Android.bp
+++ b/packages/CredentialManager/wear/Android.bp
@@ -32,6 +32,7 @@
         "androidx.compose.material_material-icons-extended",
         "androidx.compose.runtime_runtime",
         "androidx.compose.ui_ui",
+        "androidx.compose.ui_ui-tooling",
         "androidx.core_core-ktx",
         "androidx.lifecycle_lifecycle-extensions",
         "androidx.lifecycle_lifecycle-livedata",
diff --git a/packages/CredentialManager/wear/res/drawable/passkey_icon.xml b/packages/CredentialManager/wear/res/drawable/passkey_icon.xml
new file mode 100644
index 0000000..be366bf
--- /dev/null
+++ b/packages/CredentialManager/wear/res/drawable/passkey_icon.xml
@@ -0,0 +1,21 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M23,10.5H17V13.5H23V10.5Z"
+        android:fillColor="#188038"/>
+    <path
+        android:pathData="M6.5,17.5C3.5,17.5 1,15 1,12C1,9 3.5,6.5 6.5,6.5C9.5,6.5 12,9 12,12C12,15 9.5,17.5 6.5,17.5ZM6.5,9.5C5.1,9.5 4,10.6 4,12C4,13.4 5.1,14.5 6.5,14.5C7.9,14.5 9,13.4 9,12C9,10.6 7.9,9.5 6.5,9.5Z"
+        android:fillColor="#4285F4"/>
+    <path
+        android:pathData="M21,13.5H19H17V16.5H19V15.5C19,14.9 19.4,14.5 20,14.5C20.6,14.5 21,14.9 21,15.5V16.5H23V13.5H21Z"
+        android:fillColor="#34A853"/>
+    <path
+        android:pathData="M11.8,10.5H8.5C8.8,10.9 9,11.4 9,12C9,12.6 8.8,13.1 8.5,13.5H11.8C11.9,13 12,12.5 12,12C12,11.5 11.9,11 11.8,10.5Z"
+        android:fillColor="#EA4335"/>
+    <path
+        android:pathData="M17,10.5H11.8C11.9,11 12,11.5 12,12C12,12.5 11.9,13 11.8,13.5H17V10.5Z"
+        android:fillColor="#FBBC04"/>
+</vector>
diff --git a/packages/CredentialManager/wear/res/values/strings.xml b/packages/CredentialManager/wear/res/values/strings.xml
index 10ea918..109644f 100644
--- a/packages/CredentialManager/wear/res/values/strings.xml
+++ b/packages/CredentialManager/wear/res/values/strings.xml
@@ -18,4 +18,14 @@
   <!-- The name of this application. Credential Manager is a service that centralizes and provides
   access to a user's credentials used to sign in to various apps. [CHAR LIMIT=80] -->
   <string name="app_name">Credential Manager</string>
+  <!-- Title of a screen prompting if the user would like to use their saved passkey.
+  [CHAR LIMIT=80] -->
+  <string name="use_passkey_title">Use passkey?</string>
+  <!-- Title of a screen prompting if the user would like to use their saved password.
+  [CHAR LIMIT=80] -->
+  <string name="use_password_title">Use password?</string>
+  <!-- Content description for the cancel button of a screen. [CHAR LIMIT=NONE] -->
+  <string name="dialog_cancel_button_cd">Cancel</string>
+  <!-- Content description for the OK button of a screen. [CHAR LIMIT=NONE] -->
+  <string name="dialog_ok_button_cd">OK</string>
 </resources>
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorActivity.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorActivity.kt
index 2c05755..a93fa81 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorActivity.kt
@@ -47,7 +47,7 @@
                             // to the user.
                         }
 
-                        CredentialSelectorUiState.Get -> {
+                        is CredentialSelectorUiState.Get -> {
                             // TODO: b/301206470 - Implement get flow
                             setContent {
                                 MaterialTheme {
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorViewModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorViewModel.kt
index e46fcae..c61bb2e 100644
--- a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorViewModel.kt
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/CredentialSelectorViewModel.kt
@@ -23,6 +23,9 @@
 import androidx.lifecycle.viewModelScope
 import com.android.credentialmanager.ui.ktx.appLabel
 import com.android.credentialmanager.ui.ktx.requestInfo
+import com.android.credentialmanager.ui.mapper.toGet
+import com.android.credentialmanager.ui.model.PasskeyUiModel
+import com.android.credentialmanager.ui.model.PasswordUiModel
 import com.android.credentialmanager.ui.model.Request
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -62,8 +65,8 @@
                         _uiState.value = CredentialSelectorUiState.Create
                     }
 
-                    Request.Get -> {
-                        _uiState.value = CredentialSelectorUiState.Get
+                    is Request.Get -> {
+                        _uiState.value = request.toGet()
                     }
                 }
             }
@@ -103,9 +106,15 @@
 }
 
 sealed class CredentialSelectorUiState {
-    object Idle : CredentialSelectorUiState()
-    object Get : CredentialSelectorUiState()
-    object Create : CredentialSelectorUiState()
+    data object Idle : CredentialSelectorUiState()
+    sealed class Get : CredentialSelectorUiState() {
+        data class SingleProviderSinglePasskey(val passkeyUiModel: PasskeyUiModel) : Get()
+        data class SingleProviderSinglePassword(val passwordUiModel: PasswordUiModel) : Get()
+
+        // TODO: b/301206470 add the remaining states
+    }
+
+    data object Create : CredentialSelectorUiState()
     data class Cancel(val appName: String) : CredentialSelectorUiState()
-    object Finish : CredentialSelectorUiState()
+    data object Finish : CredentialSelectorUiState()
 }
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt
new file mode 100644
index 0000000..c20ee0c
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/AccountRow.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.android.credentialmanager.ui.components
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import com.google.android.horologist.compose.tools.WearPreview
+
+@Composable
+fun AccountRow(
+    name: String,
+    email: String,
+    modifier: Modifier = Modifier,
+) {
+    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+        Text(
+            text = name,
+            color = Color(0xFFE6FF7B),
+            overflow = TextOverflow.Ellipsis,
+            maxLines = 1,
+            style = MaterialTheme.typography.title2
+        )
+        Text(
+            text = email,
+            modifier = Modifier.padding(top = 7.dp),
+            color = Color(0xFFCAC5BC),
+            overflow = TextOverflow.Ellipsis,
+            maxLines = 2,
+            style = MaterialTheme.typography.body1,
+        )
+    }
+}
+
+@WearPreview
+@Composable
+fun AccountRowPreview() {
+    AccountRow(
+        name = "Elisa Beckett",
+        email = "beckett_bakery@gmail.com",
+    )
+}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/DialogButtonsRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/DialogButtonsRow.kt
new file mode 100644
index 0000000..5cb3c15
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/DialogButtonsRow.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.android.credentialmanager.ui.components
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Check
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.ButtonDefaults
+import com.google.android.horologist.compose.material.Button
+import com.google.android.horologist.compose.tools.WearPreview
+import com.android.credentialmanager.R
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+fun DialogButtonsRow(
+    onCancelClick: () -> Unit,
+    onOKClick: () -> Unit,
+    modifier: Modifier = Modifier,
+    cancelButtonIcon: ImageVector = Icons.Default.Close,
+    okButtonIcon: ImageVector = Icons.Default.Check,
+    cancelButtonContentDescription: String = stringResource(R.string.dialog_cancel_button_cd),
+    okButtonContentDescription: String = stringResource(R.string.dialog_ok_button_cd),
+) {
+    Row(
+        modifier = modifier,
+        horizontalArrangement = Arrangement.Center,
+    ) {
+        Button(
+            imageVector = cancelButtonIcon,
+            contentDescription = cancelButtonContentDescription,
+            onClick = onCancelClick,
+            colors = ButtonDefaults.secondaryButtonColors(),
+        )
+        Button(
+            imageVector = okButtonIcon,
+            contentDescription = okButtonContentDescription,
+            onClick = onOKClick,
+            modifier = Modifier.padding(start = 20.dp)
+        )
+    }
+}
+
+@WearPreview
+@Composable
+fun DialogButtonsRowPreview() {
+    DialogButtonsRow(onCancelClick = {}, onOKClick = {})
+}
+
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt
new file mode 100644
index 0000000..97900b7
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/PasswordRow.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.android.credentialmanager.ui.components
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.style.TextOverflow
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import com.google.android.horologist.compose.tools.WearPreview
+
+@Composable
+fun PasswordRow(
+    email: String,
+    modifier: Modifier = Modifier,
+) {
+    Column(modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+        Text(
+            text = email,
+            color = Color(0xFFE6FF7B),
+            overflow = TextOverflow.Ellipsis,
+            maxLines = 2,
+            style = MaterialTheme.typography.title2
+        )
+        Text(
+            text = "••••••••••••••",
+            modifier = Modifier.padding(top = 7.dp),
+            color = Color(0xFFCAC5BC),
+            overflow = TextOverflow.Ellipsis,
+            maxLines = 1,
+            style = MaterialTheme.typography.body1,
+        )
+    }
+}
+
+@WearPreview
+@Composable
+fun PasswordRowPreview() {
+    PasswordRow(
+        email = "beckett_bakery@gmail.com",
+    )
+}
+
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
new file mode 100644
index 0000000..956c56b
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/components/SignInHeader.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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 com.android.credentialmanager.ui.components
+
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.material.MaterialTheme
+import androidx.wear.compose.material.Text
+import com.android.credentialmanager.R
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+import com.google.android.horologist.compose.material.Icon
+import com.google.android.horologist.compose.material.util.DECORATIVE_ELEMENT_CONTENT_DESCRIPTION
+import com.google.android.horologist.compose.tools.WearPreview
+
+@OptIn(ExperimentalHorologistApi::class)
+@Composable
+fun SignInHeader(
+    @DrawableRes icon: Int,
+    title: String,
+    modifier: Modifier = Modifier,
+) {
+    SignInHeader(
+        iconContent = {
+            Icon(
+                id = icon,
+                contentDescription = DECORATIVE_ELEMENT_CONTENT_DESCRIPTION
+            )
+        },
+        title = title,
+        modifier = modifier,
+    )
+}
+
+@Composable
+fun SignInHeader(
+    iconContent: @Composable ColumnScope.() -> Unit,
+    title: String,
+    modifier: Modifier = Modifier,
+) {
+    Column(
+        modifier = modifier,
+        horizontalAlignment = Alignment.CenterHorizontally
+    ) {
+        iconContent()
+        Text(
+            text = title,
+            modifier = Modifier
+                .padding(top = 6.dp)
+                .padding(horizontal = 10.dp),
+            style = MaterialTheme.typography.title3
+        )
+    }
+}
+
+@WearPreview
+@Composable
+fun SignInHeaderPreview() {
+    SignInHeader(
+        icon = R.drawable.passkey_icon,
+        title = stringResource(R.string.use_passkey_title)
+    )
+}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mapper/CredentialSelectorUiStateGetMapper.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mapper/CredentialSelectorUiStateGetMapper.kt
new file mode 100644
index 0000000..1fe1e55
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/mapper/CredentialSelectorUiStateGetMapper.kt
@@ -0,0 +1,51 @@
+package com.android.credentialmanager.ui.mapper
+
+import androidx.credentials.provider.CustomCredentialEntry
+import androidx.credentials.provider.PasswordCredentialEntry
+import androidx.credentials.provider.PublicKeyCredentialEntry
+import com.android.credentialmanager.ui.CredentialSelectorUiState
+import com.android.credentialmanager.ui.factory.fromSlice
+import com.android.credentialmanager.ui.model.PasswordUiModel
+import com.android.credentialmanager.ui.model.Request
+
+fun Request.Get.toGet(): CredentialSelectorUiState.Get {
+    if (this.providers.isEmpty()) {
+        throw IllegalStateException("Invalid GetCredential request with empty list of providers.")
+    }
+
+    if (this.entries.isEmpty()) {
+        throw IllegalStateException("Invalid GetCredential request with empty list of entries.")
+    }
+
+    if (this.providers.size == 1) {
+        if (this.entries.size == 1) {
+            val slice = this.entries.first().slice
+            when (val credentialEntry = fromSlice(slice)) {
+                is PasswordCredentialEntry -> {
+                    return CredentialSelectorUiState.Get.SingleProviderSinglePassword(
+                        PasswordUiModel(credentialEntry.displayName.toString())
+                    )
+                }
+
+                is PublicKeyCredentialEntry -> {
+                    TODO("b/301206470 - to be implemented")
+                }
+
+                is CustomCredentialEntry -> {
+                    TODO("b/301206470 - to be implemented")
+                }
+
+                else -> {
+                    throw IllegalStateException(
+                        "Encountered unrecognized credential entry (${slice.spec?.type}) for " +
+                            "GetCredential request with single account"
+                    )
+                }
+            }
+        } else {
+            TODO("b/301206470 - to be implemented")
+        }
+    } else {
+        TODO("b/301206470 - to be implemented")
+    }
+}
\ No newline at end of file
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasskeyUiModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasskeyUiModel.kt
new file mode 100644
index 0000000..a368de2
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasskeyUiModel.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 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.0N
+ *
+ * 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 com.android.credentialmanager.ui.model
+
+data class PasskeyUiModel(
+    val name: String,
+    val email: String,
+)
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt
new file mode 100644
index 0000000..514dca8
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/model/PasswordUiModel.kt
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2023 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.0N
+ *
+ * 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 com.android.credentialmanager.ui.model
+
+data class PasswordUiModel(val name: String)
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SingleAccountScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SingleAccountScreen.kt
new file mode 100644
index 0000000..f344ad0
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SingleAccountScreen.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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.
+ */
+
+@file:OptIn(ExperimentalHorologistApi::class)
+
+package com.android.credentialmanager.ui.screens
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.wear.compose.foundation.lazy.ScalingLazyListScope
+import com.android.credentialmanager.R
+import com.android.credentialmanager.ui.components.AccountRow
+import com.android.credentialmanager.ui.components.DialogButtonsRow
+import com.android.credentialmanager.ui.components.SignInHeader
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+import com.google.android.horologist.compose.layout.ScalingLazyColumn
+import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+import com.google.android.horologist.compose.layout.belowTimeTextPreview
+import com.google.android.horologist.compose.tools.WearPreview
+
+@Composable
+fun SingleAccountScreen(
+    headerContent: @Composable () -> Unit,
+    accountContent: @Composable () -> Unit,
+    columnState: ScalingLazyColumnState,
+    modifier: Modifier = Modifier,
+    content: ScalingLazyListScope.() -> Unit,
+) {
+    ScalingLazyColumn(
+        columnState = columnState,
+        modifier = modifier.fillMaxSize(),
+    ) {
+        item { headerContent() }
+        item { accountContent() }
+        content()
+    }
+}
+
+@WearPreview
+@Composable
+fun SingleAccountScreenPreview() {
+    SingleAccountScreen(
+        headerContent = {
+            SignInHeader(
+                icon = R.drawable.passkey_icon,
+                title = stringResource(R.string.use_passkey_title),
+            )
+        },
+        accountContent = {
+            AccountRow(
+                name = "Elisa Beckett",
+                email = "beckett_bakery@gmail.com",
+                modifier = Modifier.padding(top = 10.dp)
+            )
+        },
+        columnState = belowTimeTextPreview(),
+    ) {
+        item {
+            DialogButtonsRow(
+                onCancelClick = {},
+                onOKClick = {},
+                modifier = Modifier.padding(top = 10.dp)
+            )
+        }
+    }
+}
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasskeyScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasskeyScreen.kt
new file mode 100644
index 0000000..c8f871e
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasskeyScreen.kt
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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.
+ */
+
+@file:OptIn(ExperimentalHorologistApi::class)
+
+package com.android.credentialmanager.ui.screens
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
+import com.android.credentialmanager.ui.components.AccountRow
+import com.android.credentialmanager.ui.components.DialogButtonsRow
+import com.android.credentialmanager.ui.components.SignInHeader
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+import com.google.android.horologist.compose.layout.belowTimeTextPreview
+import com.google.android.horologist.compose.tools.WearPreview
+
+@Composable
+fun SinglePasskeyScreen(
+    name: String,
+    email: String,
+    onCancelClick: () -> Unit,
+    onOKClick: () -> Unit,
+    columnState: ScalingLazyColumnState,
+    modifier: Modifier = Modifier,
+) {
+    SingleAccountScreen(
+        headerContent = {
+            SignInHeader(
+                icon = R.drawable.passkey_icon,
+                title = stringResource(R.string.use_passkey_title),
+            )
+        },
+        accountContent = {
+            AccountRow(
+                name = name,
+                email = email,
+                modifier = Modifier.padding(top = 10.dp),
+            )
+        },
+        columnState = columnState,
+        modifier = modifier.padding(horizontal = 10.dp)
+    ) {
+        item {
+            DialogButtonsRow(
+                onCancelClick = onCancelClick,
+                onOKClick = onOKClick,
+                modifier = Modifier.padding(top = 10.dp)
+            )
+        }
+    }
+}
+
+@WearPreview
+@Composable
+fun SinglePasskeyScreenPreview() {
+    SinglePasskeyScreen(
+        name = "Elisa Beckett",
+        email = "beckett_bakery@gmail.com",
+        onCancelClick = {},
+        onOKClick = {},
+        columnState = belowTimeTextPreview(),
+    )
+}
+
diff --git a/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasswordScreen.kt b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasswordScreen.kt
new file mode 100644
index 0000000..d863d3c
--- /dev/null
+++ b/packages/CredentialManager/wear/src/com/android/credentialmanager/ui/screens/SinglePasswordScreen.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2023 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
+ *
+ *      https://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.
+ */
+
+@file:OptIn(ExperimentalHorologistApi::class)
+
+package com.android.credentialmanager.ui.screens
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.credentialmanager.R
+import com.android.credentialmanager.ui.components.DialogButtonsRow
+import com.android.credentialmanager.ui.components.PasswordRow
+import com.android.credentialmanager.ui.components.SignInHeader
+import com.google.android.horologist.annotations.ExperimentalHorologistApi
+import com.google.android.horologist.compose.layout.ScalingLazyColumnState
+import com.google.android.horologist.compose.layout.belowTimeTextPreview
+import com.google.android.horologist.compose.tools.WearPreview
+
+@Composable
+fun SinglePasswordScreen(
+    email: String,
+    onCancelClick: () -> Unit,
+    onOKClick: () -> Unit,
+    columnState: ScalingLazyColumnState,
+    modifier: Modifier = Modifier,
+) {
+    SingleAccountScreen(
+        headerContent = {
+            SignInHeader(
+                icon = R.drawable.passkey_icon,
+                title = stringResource(R.string.use_password_title),
+            )
+        },
+        accountContent = {
+            PasswordRow(
+                email = email,
+                modifier = Modifier.padding(top = 10.dp),
+            )
+        },
+        columnState = columnState,
+        modifier = modifier.padding(horizontal = 10.dp)
+    ) {
+        item {
+            DialogButtonsRow(
+                onCancelClick = onCancelClick,
+                onOKClick = onOKClick,
+                modifier = Modifier.padding(top = 10.dp)
+            )
+        }
+    }
+}
+
+@WearPreview
+@Composable
+fun SinglePasswordScreenPreview() {
+    SinglePasswordScreen(
+        email = "beckett_bakery@gmail.com",
+        onCancelClick = {},
+        onOKClick = {},
+        columnState = belowTimeTextPreview(),
+    )
+}
+