Add "View avatar" content description to all clickable Avatar that will open the avatar preview. (#4948)
* Add "View avatar" content description to all clickable Avatar that will open the avatar preview. * Improve accessibility of avatar images.
This commit is contained in:
@@ -23,13 +23,16 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.CompositingStrategy
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import io.element.android.libraries.designsystem.modifiers.a11yClickLabel
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.preview.PreviewGroup
|
||||
import io.element.android.libraries.designsystem.text.toPx
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
/** Ratio between the box size (120 on Figma) and the avatar size (75 on Figma). */
|
||||
private const val SIZE_RATIO = 1.6f
|
||||
@@ -49,6 +52,7 @@ fun DmAvatars(
|
||||
val boxSizePx = boxSize.toPx()
|
||||
val otherAvatarRadius = otherUserAvatarData.size.dp.toPx() / 2
|
||||
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
|
||||
val actionView = stringResource(CommonStrings.action_view)
|
||||
Box(
|
||||
modifier = modifier.size(boxSize),
|
||||
) {
|
||||
@@ -56,6 +60,7 @@ fun DmAvatars(
|
||||
Avatar(
|
||||
avatarData = userAvatarData,
|
||||
avatarType = AvatarType.User,
|
||||
contentDescription = userAvatarData.url?.let { stringResource(CommonStrings.a11y_your_avatar) },
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomStart)
|
||||
.graphicsLayer {
|
||||
@@ -82,11 +87,13 @@ fun DmAvatars(
|
||||
.clickable(enabled = userAvatarData.url != null) {
|
||||
userAvatarData.url?.let { openAvatarPreview(it) }
|
||||
}
|
||||
.a11yClickLabel(userAvatarData.url?.let { actionView })
|
||||
)
|
||||
// Draw other user avatar
|
||||
Avatar(
|
||||
avatarData = otherUserAvatarData,
|
||||
avatarType = AvatarType.User,
|
||||
contentDescription = otherUserAvatarData.url?.let { stringResource(CommonStrings.a11y_other_user_avatar) },
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.clip(CircleShape)
|
||||
@@ -94,6 +101,7 @@ fun DmAvatars(
|
||||
otherUserAvatarData.url?.let { openOtherAvatarPreview(it) }
|
||||
}
|
||||
.testTag(TestTags.memberDetailAvatar)
|
||||
.a11yClickLabel(otherUserAvatarData.url?.let { actionView })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.semantics.onClick
|
||||
import androidx.compose.ui.semantics.semantics
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
fun Modifier.clickableIfNotNull(onClick: (() -> Unit)? = null): Modifier = this.then(
|
||||
@@ -29,3 +31,18 @@ fun Modifier.niceClickable(
|
||||
.clickable { onClick() }
|
||||
.padding(horizontal = 4.dp)
|
||||
}
|
||||
|
||||
fun Modifier.a11yClickLabel(
|
||||
label: String?,
|
||||
): Modifier = then(
|
||||
if (label != null) {
|
||||
Modifier.semantics {
|
||||
onClick(
|
||||
label = label,
|
||||
action = null,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<string name="a11y_jump_to_bottom">"Jump to bottom"</string>
|
||||
<string name="a11y_notifications_mentions_only">"Mentions only"</string>
|
||||
<string name="a11y_notifications_muted">"Muted"</string>
|
||||
<string name="a11y_other_user_avatar">"Other user avatar"</string>
|
||||
<string name="a11y_page_n">"Page %1$d"</string>
|
||||
<string name="a11y_pause">"Pause"</string>
|
||||
<string name="a11y_paused_voice_message">"Voice message, duration: %1$s, current position: %2$s"</string>
|
||||
@@ -30,15 +31,18 @@
|
||||
<string name="a11y_read_receipts_tap_to_show_all">"Tap to show all"</string>
|
||||
<string name="a11y_remove_reaction">"Remove reaction: %1$s"</string>
|
||||
<string name="a11y_remove_reaction_with">"Remove reaction with %1$s"</string>
|
||||
<string name="a11y_room_avatar">"Room avatar"</string>
|
||||
<string name="a11y_send_files">"Send files"</string>
|
||||
<string name="a11y_show_password">"Show password"</string>
|
||||
<string name="a11y_start_call">"Start a call"</string>
|
||||
<string name="a11y_user_avatar">"User avatar"</string>
|
||||
<string name="a11y_user_menu">"User menu"</string>
|
||||
<string name="a11y_view_avatar">"View avatar"</string>
|
||||
<string name="a11y_view_details">"View details"</string>
|
||||
<string name="a11y_voice_message">"Voice message, duration: %1$s"</string>
|
||||
<string name="a11y_voice_message_record">"Record voice message."</string>
|
||||
<string name="a11y_voice_message_stop_recording">"Stop recording"</string>
|
||||
<string name="a11y_your_avatar">"Your avatar"</string>
|
||||
<string name="action_accept">"Accept"</string>
|
||||
<string name="action_add_caption">"Add caption"</string>
|
||||
<string name="action_add_to_timeline">"Add to timeline"</string>
|
||||
@@ -137,6 +141,7 @@
|
||||
<string name="action_tap_for_options">"Tap for options"</string>
|
||||
<string name="action_try_again">"Try again"</string>
|
||||
<string name="action_unpin">"Unpin"</string>
|
||||
<string name="action_view">"View"</string>
|
||||
<string name="action_view_in_timeline">"View in timeline"</string>
|
||||
<string name="action_view_source">"View source"</string>
|
||||
<string name="action_yes">"Yes"</string>
|
||||
|
||||
Reference in New Issue
Block a user