Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
## 2024-05-18 - MinimalButton Accessibility
**Learning:** Custom clickable components without a specific Semantic Role assigned will not be announced correctly by screen readers. Applying `role = Role.Button` to the `clickable` modifier ensures it is recognized correctly as a button.
**Action:** Add `role = Role.Button` to the `clickable` modifier for custom interactive button components.
## 2024-05-18 - Redundant Icon Content Descriptions
**Learning:** Adding `contentDescription` to icons that are directly adjacent to `Text` components containing the same wording is an anti-pattern. Screen readers will announce the information twice (e.g., "Liked, Liked"), creating a noisy experience. Icons in this context should remain decorative (`contentDescription = null`).
**Action:** Verify if text alternatives exist near visual elements before assigning a `contentDescription` to avoid duplicate screen reader announcements.
## 2024-05-24 - Double announcements in Jetpack Compose custom buttons
**Learning:** When creating custom buttons using `clickable` in Jetpack Compose that contain both text and an icon, providing `contentDescription` on the icon can result in double announcements for screen readers if the text already conveys the meaning. Additionally, `clickable` elements acting as buttons must explicitly have `role = Role.Button` to be properly identified by screen readers.
**Action:** When implementing custom buttons with `clickable`, always add `role = Role.Button`. For decorative icons adjacent to text with the same meaning, use `contentDescription = null` to avoid redundant screen reader announcements.
16 changes: 9 additions & 7 deletions app/src/main/java/com/example/reddittube/ui/main/VideoPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.CustomAccessibilityAction
Expand Down Expand Up @@ -729,7 +730,7 @@ Box(
.clip(CircleShape)
.background(Color.Black.copy(alpha = 0.65f))
.border(1.dp, GlassBorder, CircleShape)
.clickable {
.clickable(role = Role.Button) {
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
if (exoPlayer.playbackState == Player.STATE_ENDED) {
exoPlayer.seekTo(0)
Expand Down Expand Up @@ -786,7 +787,7 @@ Box(
.size(40.dp)
.clip(CircleShape)
.background(Color.Black.copy(alpha = 0.55f))
.clickable { onBack?.invoke() },
.clickable(role = Role.Button) { onBack?.invoke() },
contentAlignment = Alignment.Center
) {
Icon(Icons.Default.ArrowBack, contentDescription = "Back", tint = Color.White, modifier = Modifier.size(22.dp))
Expand All @@ -799,7 +800,7 @@ Box(
modifier = Modifier
.fillMaxSize()
.background(Color.Black.copy(alpha = 0.85f))
.clickable {
.clickable(role = Role.Button) {
showOnboarding = false
sharedPreferences.edit().putBoolean("has_seen_onboarding", true).apply()
},
Expand Down Expand Up @@ -868,7 +869,7 @@ Box(
color = BrandRed,
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.clickable { onSubredditClick(post.subreddit) }
modifier = Modifier.clickable(role = Role.Button) { onSubredditClick(post.subreddit) }
)
Spacer(modifier = Modifier.width(6.dp))
val isSubbed = subscribedSet.contains(post.subreddit.lowercase())
Expand All @@ -877,7 +878,7 @@ Box(
.size(32.dp)
.clip(CircleShape)
.background(BrandRed.copy(alpha = if (isSubbed) 0.2f else 0.15f))
.clickable {
.clickable(role = Role.Button) {
hapticFeedback.performHapticFeedback(HapticFeedbackType.LongPress)
onSubscribeToggle(post.subreddit.lowercase())
},
Expand Down Expand Up @@ -912,6 +913,7 @@ Box(
.clickable(
interactionSource = remember { androidx.compose.foundation.interaction.MutableInteractionSource() },
indication = null,
role = Role.Button,
onClick = { if (isLongTitle) isTitleExpanded = !isTitleExpanded }
)
) {
Expand All @@ -928,7 +930,7 @@ Box(
Spacer(modifier = Modifier.height(3.dp))
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { isTitleExpanded = !isTitleExpanded }
modifier = Modifier.clickable(role = Role.Button) { isTitleExpanded = !isTitleExpanded }
) {
Text(
text = if (isTitleExpanded) "Show less" else "Show more",
Expand All @@ -938,7 +940,7 @@ Box(
)
Icon(
imageVector = if (isTitleExpanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore,
contentDescription = if (isTitleExpanded) "Show less" else "Show more",
contentDescription = null,
tint = TextSecondary,
modifier = Modifier.size(15.dp)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

Expand Down
Loading