Use SelectionArea instead of SelectableText (#9333)

diff --git a/packages/devtools_app/lib/src/framework/scaffold/about_dialog.dart b/packages/devtools_app/lib/src/framework/scaffold/about_dialog.dart
index cc0fb5a..2a31c09 100644
--- a/packages/devtools_app/lib/src/framework/scaffold/about_dialog.dart
+++ b/packages/devtools_app/lib/src/framework/scaffold/about_dialog.dart
@@ -24,42 +24,50 @@
     final theme = Theme.of(context);
     return DevToolsDialog(
       title: const DialogTitleText('About DevTools'),
-      content: Column(
-        mainAxisSize: MainAxisSize.min,
-        crossAxisAlignment: CrossAxisAlignment.start,
-        children: [
-          Wrap(
-            children: [
-              SelectableText('DevTools version $devToolsVersion'),
-              const Text(' - '),
-              InkWell(
-                child: Text('release notes', style: theme.linkTextStyle),
-                onTap: () =>
-                    unawaited(releaseNotesController.openLatestReleaseNotes()),
-              ),
-            ],
-          ),
-          const SizedBox(height: denseSpacing),
-          const Wrap(
-            children: [
-              Text('Encountered an issue? Let us know at '),
-              _FeedbackLink(),
-              Text('.'),
-            ],
-          ),
-          const SizedBox(height: defaultSpacing),
-          ...dialogSubHeader(theme, 'Contributing'),
-          const Wrap(
-            children: [
-              Text('Want to contribute to DevTools? Please see our '),
-              _ContributingLink(),
-              Text(' guide, or '),
-            ],
-          ),
-          const Wrap(
-            children: [Text('connect with us on '), _DiscordLink(), Text('.')],
-          ),
-        ],
+      content: SelectionArea(
+        child: Column(
+          mainAxisSize: MainAxisSize.min,
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            Wrap(
+              children: [
+                Text('DevTools version $devToolsVersion'),
+                const Text(' - '),
+                InkWell(
+                  child: Text('release notes', style: theme.linkTextStyle),
+                  onTap: () => unawaited(
+                    releaseNotesController.openLatestReleaseNotes(),
+                  ),
+                ),
+              ],
+            ),
+            const SizedBox(height: denseSpacing),
+            const Wrap(
+              children: [
+                Text('Encountered an issue? Let us know at '),
+                _FeedbackLink(),
+                Text('.'),
+              ],
+            ),
+            const SizedBox(height: defaultSpacing),
+            ...dialogSubHeader(theme, 'Contributing'),
+            const Wrap(
+              children: [
+                Text('Want to contribute to DevTools? Please see our '),
+                _ContributingLink(),
+                Text(' guide, or '),
+              ],
+            ),
+
+            const Wrap(
+              children: [
+                Text('connect with us on '),
+                _DiscordLink(),
+                Text('.'),
+              ],
+            ),
+          ],
+        ),
       ),
       actions: const [DialogLicenseButton(), DialogCloseButton()],
     );
diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart
index 0a2d4d5..feaed09 100644
--- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart
+++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart
@@ -586,7 +586,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return dataObject.domain == null
         ? Text('missing domain', style: Theme.of(context).errorTextStyle)
@@ -648,7 +647,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return _ErrorAwareText(
       isError: dataObject.pathErrors.isNotEmpty,
@@ -730,7 +728,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return dataObject.scheme.isEmpty
         ? Text(missingScheme, style: Theme.of(context).errorTextStyle)
@@ -782,7 +779,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return Text(getValue(dataObject));
   }
@@ -855,7 +851,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     if (dataObject.domainErrors.isNotEmpty ||
         dataObject.pathErrors.isNotEmpty) {
@@ -890,7 +885,6 @@
     LinkData dataObject, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return isRowHovered
         ? const Icon(Icons.arrow_forward)
diff --git a/packages/devtools_app/lib/src/screens/logging/_log_details.dart b/packages/devtools_app/lib/src/screens/logging/_log_details.dart
index e32a901..977af41 100644
--- a/packages/devtools_app/lib/src/screens/logging/_log_details.dart
+++ b/packages/devtools_app/lib/src/screens/logging/_log_details.dart
@@ -92,9 +92,11 @@
                   (log?.encodedDetails ?? '').isEmpty
               ? Padding(
                   padding: const EdgeInsets.all(denseSpacing),
-                  child: SelectableText(
-                    log?.prettyPrinted() ?? '',
-                    textAlign: TextAlign.left,
+                  child: SelectionArea(
+                    child: Text(
+                      log?.prettyPrinted() ?? '',
+                      textAlign: TextAlign.left,
+                    ),
                   ),
                 )
               : JsonViewer(encodedJson: log!.encodedDetails),
diff --git a/packages/devtools_app/lib/src/screens/logging/_message_column.dart b/packages/devtools_app/lib/src/screens/logging/_message_column.dart
index 6e806e9..96a6c91 100644
--- a/packages/devtools_app/lib/src/screens/logging/_message_column.dart
+++ b/packages/devtools_app/lib/src/screens/logging/_message_column.dart
@@ -48,7 +48,6 @@
     LogData data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     final theme = Theme.of(context);
     final hasSummary = !data.summary.isNullOrEmpty;
diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart
index c6a6f59..a40c9eb 100644
--- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart
+++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_diff.dart
@@ -48,7 +48,6 @@
     DiffClassData data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return HeapClassView(
       theClass: data.className,
@@ -132,7 +131,6 @@
     DiffClassData data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     final objects = _instances(data);
 
diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart
index 59b299f..24b9ceb 100644
--- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart
+++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/classes_table_single.dart
@@ -45,7 +45,6 @@
     SingleClassData data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return HeapClassView(
       theClass: data.className,
@@ -94,7 +93,6 @@
     SingleClassData data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return HeapInstanceTableCell(
       data.objects,
diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart
index d424f87..16c3827 100644
--- a/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart
+++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/profile_view.dart
@@ -54,7 +54,6 @@
     ProfileRecord data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     if (data.isTotal) return null;
 
@@ -134,7 +133,6 @@
     ProfileRecord data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return ProfileInstanceTableCell(
       data.heapClass,
diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart
index e28a9f2..2d342d1 100644
--- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart
+++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/class_table.dart
@@ -42,7 +42,6 @@
     TracedClass item, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return Checkbox(
       value: item.traceAllocations,
@@ -86,7 +85,6 @@
     TracedClass data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return HeapClassView(
       theClass: data.name,
diff --git a/packages/devtools_app/lib/src/screens/network/network_screen.dart b/packages/devtools_app/lib/src/screens/network/network_screen.dart
index 4d830d2..90fecb0 100644
--- a/packages/devtools_app/lib/src/screens/network/network_screen.dart
+++ b/packages/devtools_app/lib/src/screens/network/network_screen.dart
@@ -379,18 +379,12 @@
     NetworkRequest data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     final value = getDisplayValue(data);
-
-    return SelectableText(
+    return Text(
       value,
       maxLines: 1,
       style: const TextStyle(overflow: TextOverflow.ellipsis),
-      // [onPressed] needs to be passed along to [SelectableText] so that a
-      // click on the text will still trigger the [onPressed] action for the
-      // row.
-      onTap: onPressed,
     );
   }
 }
@@ -426,7 +420,6 @@
     NetworkRequest data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     // Only show the actions button when there are options and the row is
     // currently selected.
@@ -489,7 +482,6 @@
     NetworkRequest data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     final theme = Theme.of(context);
     return Text(
diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart
index 4696bed..b2a9720 100644
--- a/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart
+++ b/packages/devtools_app/lib/src/screens/profiler/panes/cpu_profile_columns.dart
@@ -58,7 +58,6 @@
     CpuStackFrame data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return MethodAndSourceDisplay(
       methodName: data.name,
diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart
index 55ddcee..589e36d 100644
--- a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart
+++ b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table.dart
@@ -256,7 +256,6 @@
     MethodTableGraphNode data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return MethodAndSourceDisplay(
       methodName: data.name,
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store.dart
index 73f3b57..fe42a31 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/object_store.dart
@@ -49,7 +49,6 @@
     dynamic data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return VmServiceObjectLink(
       // TODO(srawlins): What type is `data` at runtime? If cast to `int`, no
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart
index 4a5938f..0e24710 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_code_display.dart
@@ -62,7 +62,6 @@
     InliningEntry data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     return Row(
       children: [
@@ -165,7 +164,6 @@
     Instruction data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     final theme = Theme.of(context);
     return Text.rich(
@@ -253,7 +251,6 @@
     Instruction data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     if (data.object == null) return Container();
     return VmServiceObjectLink(
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart
index 492ad9f..8bd7e66 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_instance_display.dart
@@ -163,57 +163,67 @@
   Widget build(BuildContext context) {
     final theme = Theme.of(context);
     if (variable.text != null) {
-      return SelectableText.rich(
-        TextSpan(
-          children: textSpansFromAnsi(
-            variable.text ?? '',
-            theme.subtleFixedFontStyle,
+      return SelectionArea(
+        child: GestureDetector(
+          onTap: onTap,
+          child: Text.rich(
+            TextSpan(
+              children: textSpansFromAnsi(
+                variable.text ?? '',
+                theme.subtleFixedFontStyle,
+              ),
+            ),
           ),
         ),
-        onTap: onTap,
       );
     }
 
     final hasName = variable.name?.isNotEmpty ?? false;
-    return Row(
-      children: [
-        SelectableText.rich(
-          TextSpan(
-            text: hasName ? variable.name : null,
-            style: variable.artificialName
-                ? theme.subtleFixedFontStyle
-                : theme.fixedFontStyle.apply(
-                    color: theme.colorScheme.controlFlowSyntaxColor,
-                  ),
-            children: [
-              if (hasName) TextSpan(text: ': ', style: theme.fixedFontStyle),
-              if (variable.ref!.value is Sentinel)
-                TextSpan(
-                  text: 'Sentinel ${variable.displayValue.toString()}',
-                  style: theme.subtleFixedFontStyle,
-                ),
-            ],
+    return SelectionArea(
+      child: Row(
+        children: [
+          GestureDetector(
+            onTap: onTap,
+            child: Text.rich(
+              TextSpan(
+                text: hasName ? variable.name : null,
+                style: variable.artificialName
+                    ? theme.subtleFixedFontStyle
+                    : theme.fixedFontStyle.apply(
+                        color: theme.colorScheme.controlFlowSyntaxColor,
+                      ),
+                children: [
+                  if (hasName)
+                    TextSpan(text: ': ', style: theme.fixedFontStyle),
+                  if (variable.ref!.value is Sentinel)
+                    TextSpan(
+                      text: 'Sentinel ${variable.displayValue.toString()}',
+                      style: theme.subtleFixedFontStyle,
+                    ),
+                ],
+              ),
+            ),
           ),
-          onTap: onTap,
-        ),
-        if (variable.ref!.value is! Sentinel && variable.ref!.value is ObjRef?)
-          VmServiceObjectLink(
-            object: variable.ref!.value as ObjRef?,
-            textBuilder: (object) {
-              if (object is InstanceRef &&
-                  object.kind == InstanceKind.kString) {
-                return "'${object.valueAsString}'";
-              }
-              return null;
-            },
-            onTap: controller.findAndSelectNodeForObject,
-          )
-        else
-          Text(
-            variable.ref!.value.toString(),
-            style: Theme.of(context).subtleFixedFontStyle,
-          ),
-      ],
+          if (variable.ref!.value is! Sentinel &&
+              variable.ref!.value is ObjRef?)
+            VmServiceObjectLink(
+              object: variable.ref!.value as ObjRef?,
+              textBuilder: (object) {
+                if (object is InstanceRef &&
+                    object.kind == InstanceKind.kString) {
+                  return "'${object.valueAsString}'";
+                }
+                return null;
+              },
+              onTap: controller.findAndSelectNodeForObject,
+            )
+          else
+            Text(
+              variable.ref!.value.toString(),
+              style: Theme.of(context).subtleFixedFontStyle,
+            ),
+        ],
+      ),
     );
   }
 }
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart
index 71529a9..faa3d3e 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_library_display.dart
@@ -69,22 +69,21 @@
 
   List<Row> dependencyRows(BuildContext context) {
     final textStyle = Theme.of(context).fixedFontStyle;
-
     return <Row>[
       for (final dep in dependencies)
         Row(
-          children: [
-            Flexible(child: SelectableText(dep.description, style: textStyle)),
-          ],
+          children: [Flexible(child: Text(dep.description, style: textStyle))],
         ),
     ];
   }
 
   @override
   Widget build(BuildContext context) {
-    return VmExpansionTile(
-      title: 'Dependencies (${dependencies.length})',
-      children: prettyRows(context, dependencyRows(context)),
+    return SelectionArea(
+      child: VmExpansionTile(
+        title: 'Dependencies (${dependencies.length})',
+        children: prettyRows(context, dependencyRows(context)),
+      ),
     );
   }
 }
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart
index f1f7994..0f10967 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/vm_object_pool_display.dart
@@ -52,7 +52,6 @@
     ObjectPoolEntry data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   }) {
     if (data.value is int) return Text(data.value.toString());
     return VmServiceObjectLink(
diff --git a/packages/devtools_app/lib/src/screens/vm_developer/queued_microtasks/queued_microtasks_view.dart b/packages/devtools_app/lib/src/screens/vm_developer/queued_microtasks/queued_microtasks_view.dart
index f658b9a..692c48e 100644
--- a/packages/devtools_app/lib/src/screens/vm_developer/queued_microtasks/queued_microtasks_view.dart
+++ b/packages/devtools_app/lib/src/screens/vm_developer/queued_microtasks/queued_microtasks_view.dart
@@ -139,14 +139,16 @@
         Row(
           children: [
             Expanded(
-              child: Padding(
-                padding: const EdgeInsets.symmetric(
-                  vertical: denseRowSpacing,
-                  horizontal: defaultSpacing,
-                ),
-                child: SelectableText(
-                  style: theme.fixedFontStyle,
-                  _selectedMicrotask!.stackTrace.toString(),
+              child: SelectionArea(
+                child: Padding(
+                  padding: const EdgeInsets.symmetric(
+                    vertical: denseRowSpacing,
+                    horizontal: defaultSpacing,
+                  ),
+                  child: Text(
+                    style: theme.fixedFontStyle,
+                    _selectedMicrotask!.stackTrace.toString(),
+                  ),
                 ),
               ),
             ),
diff --git a/packages/devtools_app/lib/src/service/connected_app/connection_info.dart b/packages/devtools_app/lib/src/service/connected_app/connection_info.dart
index fd5a26e..c651fe0 100644
--- a/packages/devtools_app/lib/src/service/connected_app/connection_info.dart
+++ b/packages/devtools_app/lib/src/service/connected_app/connection_info.dart
@@ -76,13 +76,15 @@
             padding: EdgeInsets.only(
               bottom: entry == entries.last ? 0.0 : denseRowSpacing,
             ),
-            child: Row(
-              mainAxisSize: MainAxisSize.min,
-              children: [
-                Text('${entry.title}: ', style: boldText),
-                SelectableText(entry.description, style: theme.subtleTextStyle),
-                if (entry.actions.isNotEmpty) ...entry.actions,
-              ],
+            child: SelectionArea(
+              child: Row(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  Text('${entry.title}: ', style: boldText),
+                  Text(entry.description, style: theme.subtleTextStyle),
+                  if (entry.actions.isNotEmpty) ...entry.actions,
+                ],
+              ),
             ),
           ),
       ],
diff --git a/packages/devtools_app/lib/src/shared/analytics/prompt.dart b/packages/devtools_app/lib/src/shared/analytics/prompt.dart
index 0d26ecc..9b4aca2 100644
--- a/packages/devtools_app/lib/src/shared/analytics/prompt.dart
+++ b/packages/devtools_app/lib/src/shared/analytics/prompt.dart
@@ -96,38 +96,42 @@
     // When failing to parse the consent message, fallback to displaying the
     // consent message in its regular form.
     if (consentMessageRegExpResults == null) {
-      return SelectableText.rich(
-        TextSpan(
-          children: [
-            TextSpan(
-              text: adjustLineBreaks(controller.consentMessage),
-              style: theme.regularTextStyle,
-            ),
-          ],
+      return SelectionArea(
+        child: Text.rich(
+          TextSpan(
+            children: [
+              TextSpan(
+                text: adjustLineBreaks(controller.consentMessage),
+                style: theme.regularTextStyle,
+              ),
+            ],
+          ),
         ),
       );
     }
 
-    return SelectableText.rich(
-      TextSpan(
-        children: [
-          TextSpan(
-            text: consentMessageRegExpResults[0],
-            style: theme.regularTextStyle,
-          ),
-          LinkTextSpan(
-            link: GaLink(
-              display: consentMessageRegExpResults[1],
-              url: consentMessageRegExpResults[1],
+    return SelectionArea(
+      child: Text.rich(
+        TextSpan(
+          children: [
+            TextSpan(
+              text: consentMessageRegExpResults[0],
+              style: theme.regularTextStyle,
             ),
-            context: context,
-            style: theme.linkTextStyle,
-          ),
-          TextSpan(
-            text: consentMessageRegExpResults[2],
-            style: theme.regularTextStyle,
-          ),
-        ],
+            LinkTextSpan(
+              link: GaLink(
+                display: consentMessageRegExpResults[1],
+                url: consentMessageRegExpResults[1],
+              ),
+              context: context,
+              style: theme.linkTextStyle,
+            ),
+            TextSpan(
+              text: consentMessageRegExpResults[2],
+              style: theme.regularTextStyle,
+            ),
+          ],
+        ),
       ),
     );
   }
diff --git a/packages/devtools_app/lib/src/shared/console/widgets/description.dart b/packages/devtools_app/lib/src/shared/console/widgets/description.dart
index 7b667b3..7ea8389 100644
--- a/packages/devtools_app/lib/src/shared/console/widgets/description.dart
+++ b/packages/devtools_app/lib/src/shared/console/widgets/description.dart
@@ -571,7 +571,7 @@
   @override
   Widget build(BuildContext context) {
     if (multiline) {
-      return SelectableText.rich(text);
+      return SelectionArea(child: Text.rich(text));
     }
 
     if (actionLabel != null) {
diff --git a/packages/devtools_app/lib/src/shared/table/_table_column.dart b/packages/devtools_app/lib/src/shared/table/_table_column.dart
index 4506902..521d212 100644
--- a/packages/devtools_app/lib/src/shared/table/_table_column.dart
+++ b/packages/devtools_app/lib/src/shared/table/_table_column.dart
@@ -18,7 +18,6 @@
     T data, {
     bool isRowSelected = false,
     bool isRowHovered = false,
-    VoidCallback? onPressed,
   });
 }
 
diff --git a/packages/devtools_app/lib/src/shared/table/_table_row.dart b/packages/devtools_app/lib/src/shared/table/_table_row.dart
index 293cf84..7634388 100644
--- a/packages/devtools_app/lib/src/shared/table/_table_row.dart
+++ b/packages/devtools_app/lib/src/shared/table/_table_row.dart
@@ -272,7 +272,7 @@
       onPressed = () => widgetOnPressed(node);
     }
 
-    final row = tableRowFor(context, onPressed: onPressed);
+    final row = tableRowFor(context);
 
     final box = SizedBox(
       height: widget._rowType == _TableRowType.data
@@ -401,7 +401,7 @@
   }
 
   /// Presents the content of this row.
-  Widget tableRowFor(BuildContext context, {VoidCallback? onPressed}) {
+  Widget tableRowFor(BuildContext context) {
     Widget columnFor(ColumnData<T> column, double columnWidth) {
       Widget? content;
       final theme = Theme.of(context);
@@ -439,7 +439,6 @@
             node,
             isRowSelected: widget.isSelected,
             isRowHovered: isHovering,
-            onPressed: onPressed,
           );
         }
         // If ColumnRenderer.build returns null, fall back to the default
diff --git a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart
index 566538c..8e7467d 100644
--- a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart
+++ b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart
@@ -1080,7 +1080,7 @@
     } else {
       displayText = text;
     }
-    return SelectableText(displayText, style: style);
+    return SelectionArea(child: Text(displayText, style: style));
   }
 }
 
@@ -1768,24 +1768,29 @@
         serviceConnection.serviceManager.connectedApp!.isFlutterAppNow == true;
     final sdkName = isFlutterApp ? 'Flutter' : 'Dart';
     final minSdkVersion = isFlutterApp ? '2.8.0' : '2.15.0';
-    return SelectableText.rich(
-      TextSpan(
-        text:
-            'Warning: you should no longer be launching DevTools from'
-            ' pub.\n\n',
-        style: theme.subtleTextStyle.copyWith(color: theme.colorScheme.error),
-        children: [
-          TextSpan(
-            text:
-                'DevTools version 2.8.0 will be the last version to '
-                'be shipped on pub. As of $sdkName\nversion >= '
-                '$minSdkVersion, DevTools should be launched by running '
-                'the ',
-            style: theme.subtleTextStyle,
-          ),
-          TextSpan(text: '`dart devtools`', style: theme.subtleFixedFontStyle),
-          TextSpan(text: '\ncommand.', style: theme.subtleTextStyle),
-        ],
+    return SelectionArea(
+      child: Text.rich(
+        TextSpan(
+          text:
+              'Warning: you should no longer be launching DevTools from'
+              ' pub.\n\n',
+          style: theme.subtleTextStyle.copyWith(color: theme.colorScheme.error),
+          children: [
+            TextSpan(
+              text:
+                  'DevTools version 2.8.0 will be the last version to '
+                  'be shipped on pub. As of $sdkName\nversion >= '
+                  '$minSdkVersion, DevTools should be launched by running '
+                  'the ',
+              style: theme.subtleTextStyle,
+            ),
+            TextSpan(
+              text: '`dart devtools`',
+              style: theme.subtleFixedFontStyle,
+            ),
+            TextSpan(text: '\ncommand.', style: theme.subtleTextStyle),
+          ],
+        ),
       ),
     );
   }
diff --git a/packages/devtools_app/test/framework/scaffold/about_dialog_test.dart b/packages/devtools_app/test/framework/scaffold/about_dialog_test.dart
index 25bf81a..2b32b4c 100644
--- a/packages/devtools_app/test/framework/scaffold/about_dialog_test.dart
+++ b/packages/devtools_app/test/framework/scaffold/about_dialog_test.dart
@@ -53,7 +53,7 @@
     testWidgets('content renders correctly', (WidgetTester tester) async {
       await tester.pumpWidget(wrap(aboutDialog));
       expect(find.text('About DevTools'), findsOneWidget);
-      expect(findSubstring(devtools.version), findsOneWidget);
+      expect(find.textContaining(devtools.version), findsOneWidget);
       expect(find.text('release notes'), findsOneWidget);
       expect(find.textContaining('Encountered an issue?'), findsOneWidget);
       expect(
diff --git a/packages/devtools_app/test/screens/logging/logging_screen_data_test.dart b/packages/devtools_app/test/screens/logging/logging_screen_data_test.dart
index 968ef19..8852ab0 100644
--- a/packages/devtools_app/test/screens/logging/logging_screen_data_test.dart
+++ b/packages/devtools_app/test/screens/logging/logging_screen_data_test.dart
@@ -88,7 +88,7 @@
     expect(
       find.descendant(
         of: find.byType(LogDetails),
-        matching: find.selectableText('log event 6'),
+        matching: find.text('log event 6'),
       ),
       findsOneWidget,
       reason: 'The log details should now be visible in the details section.',
@@ -175,7 +175,7 @@
       await tester.tap(find.byKey(ValueKey(log)));
       await tester.pump();
       expect(
-        find.selectableText(nonJsonOutput),
+        find.text(nonJsonOutput),
         findsNothing,
         reason:
             "The details of the log haven't computed yet, so they shouldn't "
@@ -183,7 +183,7 @@
       );
 
       await tester.pumpAndSettle();
-      expect(find.selectableText(nonJsonOutput), findsOneWidget);
+      expect(find.text(nonJsonOutput), findsOneWidget);
       expect(find.byType(JsonViewer), findsNothing);
 
       // Toggle the log details view format to view as JSON.
@@ -198,7 +198,7 @@
       await tester.tap(find.byType(LogDetailsFormatButton));
       await tester.pumpAndSettle();
 
-      expect(find.selectableText(nonJsonOutput), findsNothing);
+      expect(find.text(nonJsonOutput), findsNothing);
       expect(find.byType(JsonViewer), findsOneWidget);
       expect(
         find.byTooltip(LogDetailsFormatButton.viewAsJsonTooltip),
@@ -216,9 +216,11 @@
   ) async {
     const index = 9;
     bool containsJson(Widget widget) {
-      if (widget is! SelectableText) return false;
-      final content = widget.data!.trim();
-      return content.startsWith('{') && content.endsWith('}');
+      if (widget is! Text) return false;
+      final content = (widget.data ?? '').trim();
+      return content.startsWith('{') &&
+          content.endsWith('}') &&
+          content != '{ }';
     }
 
     final findJson = find.descendant(
diff --git a/packages/devtools_app/test/screens/network/network_profiler_test.dart b/packages/devtools_app/test/screens/network/network_profiler_test.dart
index 15253ee..bee1cad 100644
--- a/packages/devtools_app/test/screens/network/network_profiler_test.dart
+++ b/packages/devtools_app/test/screens/network/network_profiler_test.dart
@@ -307,16 +307,10 @@
 
       expectNoSelection();
 
-      final textElement = tester.element(
-        find
-            .text(
-              'https://jsonplaceholder.typicode.com/albums/1?userId=1&title=myalbum',
-            )
-            .first,
+      final textWidget = find.text(
+        'https://jsonplaceholder.typicode.com/albums/1?userId=1&title=myalbum',
       );
-      final selectableTextWidget = textElement
-          .findAncestorWidgetOfExactType<SelectableText>()!;
-      await tester.tap(find.byWidget(selectableTextWidget));
+      await tester.tap(textWidget);
       await tester.pumpAndSettle();
 
       expect(controller.selectedRequest.value, isNotNull);
diff --git a/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_library_display_test.dart b/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_library_display_test.dart
index ff3d1ec..21cc476 100644
--- a/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_library_display_test.dart
+++ b/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_library_display_test.dart
@@ -195,7 +195,7 @@
 
       await tester.pumpAndSettle();
 
-      expect(find.byType(SelectableText), findsNWidgets(3));
+      expect(find.byType(Text), findsNWidgets(4));
     });
   });
 }
diff --git a/packages/devtools_app_shared/lib/src/ui/common.dart b/packages/devtools_app_shared/lib/src/ui/common.dart
index f201d4a..90b196e 100644
--- a/packages/devtools_app_shared/lib/src/ui/common.dart
+++ b/packages/devtools_app_shared/lib/src/ui/common.dart
@@ -517,9 +517,12 @@
   @override
   Widget build(BuildContext context) {
     final theme = Theme.of(context);
-    return SelectableText(
-      json != null ? encoder.convert(json) : formattedString!,
-      style: useSubtleStyle ? theme.subtleFixedFontStyle : theme.fixedFontStyle,
+    return SelectionArea(
+      child: Text(
+        json != null ? encoder.convert(json) : formattedString!,
+        style:
+            useSubtleStyle ? theme.subtleFixedFontStyle : theme.fixedFontStyle,
+      ),
     );
   }
 }