Skip to content

Conversation

validcube
Copy link
Member

@validcube validcube commented Jul 5, 2025

Add TooltipWrap to well... wrap a composable component using TooltipBox.

Extended FAB aren't wrapped because they have text shown in the button.

Icon Button, Small FAB and regular FAB are wrapped because they do not have text shown.

partially fix - #2555

Axelen123 and others added 30 commits May 20, 2025 14:00
@validcube
Copy link
Member Author

I thought the contentDescription of the icon was enough for accessibility purposes but I assume there is a good reason for it.

contentDescription is for accessibility purposes (TalkBack), but Tooltip is for feature discovery purposes (let users know what this button will do before they press on it)

lwix5iqu-1.png

The pattern of wrapping an IconButton in a TooltipWrap appears a lot. Consider making a new composable to handle it.

Agree, willco on Sunday weekends.

@validcube
Copy link
Member Author

Done™️!

@validcube validcube requested review from Axelen123 and Copilot July 11, 2025 09:14
Copilot

This comment was marked as outdated.

@validcube validcube requested review from Axelen123 and Copilot August 27, 2025 16:04
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds tooltip functionality to improve accessibility for unobvious UI elements by wrapping icon buttons, floating action buttons, and small floating action buttons with tooltip components. The changes introduce new TooltipWrap composable components and their specialized variants for different button types.

  • Introduces new TooltipWrap component and specialized tooltip variants (TooltipIconButton, TooltipFloatingActionButton, TooltipSmallFloatingActionButton)
  • Replaces regular buttons with tooltip-wrapped equivalents across multiple screens to provide contextual help text
  • Adds haptic feedback support to tooltip components for enhanced user experience

Reviewed Changes

Copilot reviewed 23 out of 24 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
TooltipWrap.kt New base tooltip wrapper component with string and resource ID variants
TooltipIconButton.kt IconButton wrapper with tooltip functionality
TooltipFloatingActionButton.kt FloatingActionButton wrapper with tooltip functionality
TooltipSmallFloatingActionButton.kt SmallFloatingActionButton wrapper with tooltip functionality
HapticSmallFloatingActionButton.kt New haptic feedback component for small FABs
Various screen files Updated to use tooltip-wrapped buttons instead of regular buttons

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

* Wraps a composable with a tooltip.
*
* @param modifier the [Modifier] to applied to Tooltip.
* @param tooltip [String] text to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [String] text.

Copilot uses AI. Check for mistakes.

* Wraps a composable with a tooltip.
*
* @param modifier the [Modifier] to applied to tooltip.
* @param tooltip [Int] or `id` string resource to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [Int] or id.

Suggested change
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param tooltip the string resource ID to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [IconButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [String] text.

Suggested change
* @param tooltip [String] text to show in a tooltip.
* @param tooltip Text to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [IconButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [Int] or id.

Suggested change
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param tooltip tooltip string resource to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [HapticFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [String] text.

Suggested change
* @param tooltip [String] text to show in a tooltip.
* @param tooltip Text to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [HapticFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [Int] or id.

Suggested change
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param tooltip String resource ID to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [HapticSmallFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [String] text to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [String] text.

Suggested change
* @param tooltip [String] text to show in a tooltip.
* @param tooltip Text to show in a tooltip.

Copilot uses AI. Check for mistakes.

/**
* [HapticSmallFloatingActionButton] with tooltip-specific params.
*
* @param tooltip [Int] or `id` string resource to show in a tooltip.
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter description uses incorrect formatting. It should be tooltip instead of [Int] or id.

Suggested change
* @param tooltip [Int] or `id` string resource to show in a tooltip.
* @param tooltip Resource id of the string to show in a tooltip.

Copilot uses AI. Check for mistakes.

modifier = Modifier.draggableHandle(interactionSource = interactionSource),
onClick = {},
tooltip = stringResource(R.string.delete),
onClick = { }
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty onClick handler should be replaced with a meaningful implementation or removed if not needed.

Suggested change
onClick = { }
onClick = {
if (!deleteMode) {
deletionTargets.add(item.key)
deleteMode = true
} else {
if (item.key in deletionTargets) {
deletionTargets.remove(item.key)
deleteMode = deletionTargets.isNotEmpty()
} else {
deletionTargets.add(item.key)
}
}
}

Copilot uses AI. Check for mistakes.

Comment on lines +225 to +233
TooltipIconButton(
onClick = onSettingsClick,
tooltip = stringResource(R.string.settings),
) {
BadgedBox(
badge = {
Badge(modifier = Modifier.size(6.dp))
}
) {
Copy link

Copilot AI Aug 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The settings icon shows a badge without any conditional logic. This will always display a badge even when there are no settings notifications, which is likely unintended behavior.

Suggested change
TooltipIconButton(
onClick = onSettingsClick,
tooltip = stringResource(R.string.settings),
) {
BadgedBox(
badge = {
Badge(modifier = Modifier.size(6.dp))
}
) {
// TODO: Replace with actual logic to determine if a settings notification exists
val hasSettingsNotification = false
TooltipIconButton(
onClick = onSettingsClick,
tooltip = stringResource(R.string.settings),
) {
if (hasSettingsNotification) {
BadgedBox(
badge = {
Badge(modifier = Modifier.size(6.dp))
}
) {
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
}
} else {

Copilot uses AI. Check for mistakes.

visible = !visible
}) {
TooltipIconButton(
modifier = Modifier,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unnecessary to add empty Modifiers, since that is already the default. There are several of these across the codebase that need to be removed as well.

},
supportingContent = { Text(stringResource(if (patchBundle != null) R.string.file_field_set else R.string.file_field_not_set)) },
trailingContent = {
// TODO: Determine if this button should be [TooltipWrap]'ped
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be adressed.

import app.revanced.manager.util.withHapticFeedback

@Composable
fun HapticSmallFloatingActionButton (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fun HapticSmallFloatingActionButton (
fun HapticSmallFloatingActionButton(

TooltipIconButton(
modifier = Modifier.draggableHandle(interactionSource = interactionSource),
onClick = {},
tooltip = stringResource(R.string.delete),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using R.string.delete doesn't seem right here. This is just a drag handle.

import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton

/**
* [HapticFloatingActionButton] with tooltip-specific params.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe [HapticComponent] with a tooltip or something.

Comment on lines +72 to +96
fun TooltipWrap(
modifier: Modifier = Modifier,
@StringRes tooltip: Int,
positionProvider: PopupPositionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
haptic: Boolean = true,
hapticFeedbackType: HapticFeedbackType = HapticFeedbackType.LongPress,
content: @Composable () -> Unit
) {
val tooltipState = rememberTooltipState()
val localHaptic = LocalHapticFeedback.current

LaunchedEffect(tooltipState.isVisible) {
if (tooltipState.isVisible && haptic) {
localHaptic.performHapticFeedback(hapticFeedbackType)
}
}

TooltipBox(
modifier = modifier,
positionProvider = positionProvider,
tooltip = { PlainTooltip { Text(stringResource(tooltip)) } },
state = tooltipState,
content = content,
)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string resource variants seem unused, so you can get rid of them.

supportingContent = patch.description?.let { { Text(it) } },
trailingContent = {
if (patch.options?.isNotEmpty() == true) {
// TODO: Determine if this button should be [TooltipWrap]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

@Ushie Ushie changed the base branch from compose-dev to dev October 3, 2025 13:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.