New CSS-only overlay border glow component
Replaces the overlay shimmer canvas.
Guarded by the flag `LensOverlayVisualSelectionUpdates`
When on, the shimmer is disabled and the initial gradient (upper scrim) does not display.
Change-Id: I4214b8f3e7e2c093012b38c3f99ddf325a27977a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6547186
Reviewed-by: Juan Mojica <juanmojica@google.com>
Reviewed-by: Duncan Mercer <mercerd@google.com>
Commit-Queue: Shez Daredia <helloshez@google.com>
Cr-Commit-Position: refs/heads/main@{#1461682}
diff --git a/chrome/browser/resources/lens/overlay/BUILD.gn b/chrome/browser/resources/lens/overlay/BUILD.gn
index 34314cd..2f1edf0 100644
--- a/chrome/browser/resources/lens/overlay/BUILD.gn
+++ b/chrome/browser/resources/lens/overlay/BUILD.gn
@@ -75,6 +75,8 @@
"screenshot_utils.ts",
"searchbox_utils.ts",
"selection_utils.ts",
+ "overlay_border_glow.ts",
+ "overlay_border_glow.html.ts",
"side_panel/side_panel_browser_proxy.ts",
"side_panel/side_panel_error_page.ts",
"side_panel/feedback_toast.ts",
@@ -94,6 +96,7 @@
"simplified_text_layer.css",
"side_panel/side_panel_error_page.css",
"side_panel/feedback_toast.css",
+ "overlay_border_glow.css",
]
ts_deps = [
diff --git a/chrome/browser/resources/lens/overlay/lens_overlay_app.ts b/chrome/browser/resources/lens/overlay/lens_overlay_app.ts
index 9431d931..bcd6c9e8 100644
--- a/chrome/browser/resources/lens/overlay/lens_overlay_app.ts
+++ b/chrome/browser/resources/lens/overlay/lens_overlay_app.ts
@@ -79,6 +79,10 @@
type: Boolean,
value: false,
},
+ enableBorderGlow: {
+ type: Boolean,
+ value: () => loadTimeData.getBoolean('enableBorderGlow'),
+ },
forceHideSearchBox: {
type: Boolean,
value: false,
@@ -202,6 +206,8 @@
};
}
+ // Whether the border glow is enabled via feature flag.
+ declare enableBorderGlow: boolean;
// Whether the user is currently focused into the searchbox.
declare isSearchboxFocused: boolean;
// Whether to purposely suppress the ghost loader. Done when escaping from
@@ -610,7 +616,9 @@
// The user finished making their selection on the selection overlay.
private handleSelectionFinished() {
- this.$.initialGradient.triggerHideScrimAnimation();
+ if (!this.enableBorderGlow) {
+ this.$.initialGradient.triggerHideScrimAnimation();
+ }
this.$.cursorTooltip.setPauseTooltipChanges(false);
this.isPointerDown = false;
}
@@ -621,7 +629,9 @@
private onInitialFlashAnimationEnd() {
this.initialFlashAnimationHasEnded = true;
- this.$.initialGradient.setScrimVisible();
+ if (!this.enableBorderGlow) {
+ this.$.initialGradient.setScrimVisible();
+ }
// The searchbox is not focusable until the animation has ended.
if (this.autoFocusSearchbox &&
this.isLensOverlayContextualSearchboxVisible) {
diff --git a/chrome/browser/resources/lens/overlay/overlay_border_glow.css b/chrome/browser/resources/lens/overlay/overlay_border_glow.css
new file mode 100644
index 0000000..3e127ee
--- /dev/null
+++ b/chrome/browser/resources/lens/overlay/overlay_border_glow.css
@@ -0,0 +1,97 @@
+/* Copyright 2025 The Chromium Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* #css_wrapper_metadata_start
+ * #type=style-lit
+ * #scheme=relative
+ * #css_wrapper_metadata_end */
+
+:host {
+ --gradient-blue: #3186ff;
+ --gradient-green: #34a853;
+ --gradient-red: #ff4641;
+ --gradient-rotation-angle: 0deg;
+ --gradient-yellow: #ffd314;
+ height: 100%;
+ width: 100%;
+}
+
+@property --gradient-rotation-angle {
+ inherits: false;
+ initial-value: 0deg;
+ syntax: '<angle>';
+}
+
+@property --gradient-blue {
+ inherits: false;
+ initial-value: #3186ff;
+ syntax: '<color>';
+}
+
+@property --gradient-green {
+ inherits: false;
+ initial-value: #34a853;
+ syntax: '<color>';
+}
+
+@property --gradient-yellow {
+ inherits: false;
+ initial-value: #ffd314;
+ syntax: '<color>';
+}
+
+@property --gradient-red {
+ inherits: false;
+ initial-value: #ff4641;
+ syntax: '<color>';
+}
+
+@keyframes rotateGradient {
+ 0% {
+ --gradient-rotation-angle: 0deg;
+ }
+ 100% {
+ --gradient-rotation-angle: 360deg;
+ }
+}
+
+@keyframes shaderOpacityIn {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 0.6;
+ }
+}
+
+@keyframes shaderOpacityToResting {
+ 0% {
+ opacity: 0.5;
+ }
+ 100% {
+ opacity: 0.3;
+ }
+}
+
+#borderGlowContainer {
+ animation: 117ms cubic-bezier(0, 0, 0, 1) 0s 1 normal forwards running shaderOpacityIn,
+ 1016ms cubic-bezier(0.2, 0, 0, 1) 117ms 1 normal forwards running shaderOpacityToResting,
+ 20s linear 0s infinite normal forwards running rotateGradient;
+ background: conic-gradient(from var(--gradient-rotation-angle, 0deg) at center,
+ var(--gradient-blue) 0deg, var(--gradient-blue) 10deg,
+ var(--gradient-red) 80deg, var(--gradient-yellow) 120deg,
+ var(--gradient-green) 160deg, var(--gradient-blue) 200deg,
+ var(--gradient-blue) 360deg);
+ content: '';
+ filter: blur(20px);
+ height: 100%;
+ left: 0;
+ -webkit-mask: url(#roundedFrameMask);
+ mask: url(#roundedFrameMask);
+ opacity: 0;
+ position: absolute;
+ top: 0;
+ transform: scale(140%);
+ width: 100%;
+}
\ No newline at end of file
diff --git a/chrome/browser/resources/lens/overlay/overlay_border_glow.html.ts b/chrome/browser/resources/lens/overlay/overlay_border_glow.html.ts
new file mode 100644
index 0000000..cd8667c3
--- /dev/null
+++ b/chrome/browser/resources/lens/overlay/overlay_border_glow.html.ts
@@ -0,0 +1,63 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html} from '//resources/lit/v3_0/lit.rollup.js';
+
+import type {OverlayBorderGlowElement} from './overlay_border_glow.js';
+
+export function getHtml(this: OverlayBorderGlowElement) {
+ return html`<div id="borderGlowContainer">
+ <svg style="position: absolute; width: 0; height: 0; overflow: hidden">
+ <defs>
+ <filter id="blur-filter">
+ <feGaussianBlur id="blur" in="SourceGraphic" stdDeviation="0.02">
+ <animate
+ id="blur-animation"
+ attributeName="stdDeviation"
+ attributeType="XML"
+ from="0.02"
+ to="0.05"
+ dur="117ms"
+ begin="0s"
+ fill="freeze"
+ calcMode="spline"
+ keyTimes="0;1"
+ keySplines="0 0 0 0.1"
+ />
+
+ <animate
+ id="blur-animationToResting"
+ attributeName="stdDeviation"
+ attributeType="XML"
+ from="0.05"
+ to="0.1"
+ dur="1016ms"
+ begin="117ms"
+ fill="freeze"
+ calcMode="spline"
+ keyTimes="0;1"
+ keySplines="0.2 0 0 1"
+ />
+ </feGaussianBlur>
+ </filter>
+
+ <mask id="roundedFrameMask" maskContentUnits="objectBoundingBox">
+ <rect width="1" height="1" fill="white" />
+
+ <rect
+ id="mask-hole-rect"
+ x=".18"
+ y=".18"
+ width=".64"
+ height="0.64"
+ rx="0.25"
+ ry="0.25"
+ fill="black"
+ filter="url(#blur-filter)"
+ />
+ </mask>
+ </defs>
+ </svg>
+</div>`;
+}
diff --git a/chrome/browser/resources/lens/overlay/overlay_border_glow.ts b/chrome/browser/resources/lens/overlay/overlay_border_glow.ts
new file mode 100644
index 0000000..f2b15f9
--- /dev/null
+++ b/chrome/browser/resources/lens/overlay/overlay_border_glow.ts
@@ -0,0 +1,38 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
+
+import {getCss} from './overlay_border_glow.css.js';
+import {getHtml} from './overlay_border_glow.html.js';
+
+/*
+ * Element responsible for rendering the border glow as a replacement for the
+ * shimmer.
+ */
+export class OverlayBorderGlowElement extends CrLitElement {
+ static get is() {
+ return 'overlay-border-glow';
+ }
+
+ static override get properties() {
+ return {};
+ }
+
+ static override get styles() {
+ return getCss();
+ }
+
+ override render() {
+ return getHtml.bind(this)();
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ 'overlay-border-glow': OverlayBorderGlowElement;
+ }
+}
+
+customElements.define(OverlayBorderGlowElement.is, OverlayBorderGlowElement);
diff --git a/chrome/browser/resources/lens/overlay/selection_overlay.html b/chrome/browser/resources/lens/overlay/selection_overlay.html
index b9b7322b1..9a229a59 100644
--- a/chrome/browser/resources/lens/overlay/selection_overlay.html
+++ b/chrome/browser/resources/lens/overlay/selection_overlay.html
@@ -1,4 +1,4 @@
-<link rel="stylesheet" href="//resources/css/text_defaults_md.css">
+<link rel="stylesheet" href="//resources/css/text_defaults_md.css" />
<style>
:host {
--cursor-img-url: url("lens.svg");
@@ -29,9 +29,10 @@
}
:host([is-initial-size]) #backgroundImageCanvas {
- animation: initial-blur-animation 700ms cubic-bezier(0.2, 0.0, 0, 1.0),
- initial-inset-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1.0),
- initial-scale-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1.0);
+ animation:
+ initial-blur-animation 700ms cubic-bezier(0.2, 0, 0, 1),
+ initial-inset-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1),
+ initial-scale-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1);
position: relative;
}
@@ -59,8 +60,7 @@
:host([suppress-copy-and-save-as-image]) .save-as-image-context-menu-item,
:host(:not([enable-copy-as-image])) .copy-as-image-context-menu-item,
:host(:not([enable-save-as-image])) .save-as-image-context-menu-item,
- :host(:not([show-detected-text-context-menu-options]))
- .detected-text-context-menu-option,
+ :host(:not([show-detected-text-context-menu-options])) .detected-text-context-menu-option,
:host(:not([show-translate-context-menu-item])) .translate-context-menu-item,
:host([disable-shimmer]) #overlayShimmerCanvas,
:host([disable-shimmer]) #overlayShimmer {
@@ -69,9 +69,8 @@
:host([shimmer-on-segmentation]) #objectSelectionLayer,
:host([shimmer-on-segmentation]) #overlayShimmer,
- :host([shimmer-on-segmentation][shimmer-fade-out-complete])
- #overlayShimmerCanvas {
- z-index: 4; /* Position above words but below selection corners. */
+ :host([shimmer-on-segmentation][shimmer-fade-out-complete]) #overlayShimmerCanvas {
+ z-index: 4; /* Position above words but below selection corners. */
}
:host([translate-mode-enabled]) #objectSelectionLayer {
@@ -100,7 +99,7 @@
}
#selectionElements {
- background-color: rgba(var(--color-scrim-rgb), .05);
+ background-color: rgba(var(--color-scrim-rgb), 0.05);
}
:host([translate-mode-enabled]) #selectionElements {
@@ -116,9 +115,10 @@
}
:host([is-initial-size]) #initialFlashScrim {
- animation: initial-inset-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1.0),
- initial-scale-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1.0),
- initial-flash-animation 700ms cubic-bezier(0.2, 0.0, 0, 1.0);
+ animation:
+ initial-inset-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1),
+ initial-scale-animation 400ms cubic-bezier(0.05, 0.7, 0.1, 1),
+ initial-flash-animation 700ms cubic-bezier(0.2, 0, 0, 1);
background-color: rgb(255, 255, 255);
height: 100%;
max-height: 100vh;
@@ -190,7 +190,7 @@
.context-menu {
align-items: flex-start;
- animation: scale-out 150ms cubic-bezier(0.2, 0.0, 0, 1.0);
+ animation: scale-out 150ms cubic-bezier(0.2, 0, 0, 1);
background: var(--color-selection-element);
border-radius: 8px;
box-shadow: 0px 2px 6px 0px rgba(60, 64, 67, 0.16);
@@ -203,7 +203,9 @@
pointer-events: auto;
position: absolute;
visibility: hidden;
- transition: opacity 150ms, visibility 150ms;
+ transition:
+ opacity 150ms,
+ visibility 150ms;
z-index: 6;
}
@@ -213,7 +215,7 @@
:host([show-selected-text-context-menu]) #selectedTextContextMenu,
:host([show-selected-region-context-menu]) #selectedRegionContextMenu {
- animation: scale-in 250ms cubic-bezier(0.2, 0.0, 0, 1.0);
+ animation: scale-in 250ms cubic-bezier(0.2, 0, 0, 1);
opacity: 1;
visibility: visible;
}
@@ -232,7 +234,7 @@
}
.context-menu-item:active {
- background-color: rgba(var(--color-scrim-rgb), 0.10);
+ background-color: rgba(var(--color-scrim-rgb), 0.1);
}
.menu-item-icon {
@@ -246,23 +248,23 @@
}
.menu-item-icon.copy {
- mask-image: url('copy.svg');
+ mask-image: url("copy.svg");
}
.menu-item-icon.copy-image {
- mask-image: url('copy_image.svg');
+ mask-image: url("copy_image.svg");
}
.menu-item-icon.download {
- mask-image: url('download.svg');
+ mask-image: url("download.svg");
}
.menu-item-icon.translate {
- mask-image: url('translate.svg');
+ mask-image: url("translate.svg");
}
.menu-item-icon.text {
- mask-image: url('text.svg');
+ mask-image: url("text.svg");
}
.menu-item-label {
@@ -293,7 +295,7 @@
@keyframes initial-inset-animation {
50% {
- animation-timing-function: cubic-bezier(0.2, 0.0, 0, 1.0);
+ animation-timing-function: cubic-bezier(0.2, 0, 0, 1);
border-radius: 8px;
}
@@ -305,7 +307,7 @@
@keyframes initial-blur-animation {
/* 2/7 of the way through the animation. */
28.6% {
- filter: blur(2.5px)
+ filter: blur(2.5px);
}
to {
@@ -353,90 +355,134 @@
}
}
</style>
-<div id="selectionOverlay" on-pointerenter="handlePointerEnter"
- on-pointerleave="handlePointerLeave">
- <canvas id="backgroundImageCanvas"
- style$="height: [[canvasHeight]]px; width: [[canvasWidth]]px;"></canvas>
+<div
+ id="selectionOverlay"
+ on-pointerenter="handlePointerEnter"
+ on-pointerleave="handlePointerLeave"
+>
+ <canvas
+ id="backgroundImageCanvas"
+ style$="height: [[canvasHeight]]px; width: [[canvasWidth]]px;"
+ ></canvas>
<!-- Wrapper div is needed to stack the selection elements on top of
background image. -->
<div id="selectionElements">
<!-- Other elements that need to be bounded to the image go here -->
<div id="extraScrim"></div>
- <overlay-shimmer-canvas hidden$="[[disableShimmer]]" theme="[[theme]]"
- id="overlayShimmerCanvas"></overlay-shimmer-canvas>
- <post-selection-renderer id="postSelectionRenderer"
- selection-overlay-rect="[[selectionOverlayRect]]">
+ <overlay-shimmer-canvas
+ hidden$="[[disableShimmer || enableBorderGlow]]"
+ theme="[[theme]]"
+ id="overlayShimmerCanvas"
+ ></overlay-shimmer-canvas>
+ <template is="dom-if" if="[[enableBorderGlow]]">
+ <overlay-border-glow id="overlayBorderGlowCanvas"></overlay-border-glow>
+ </template>
+ <post-selection-renderer
+ id="postSelectionRenderer"
+ selection-overlay-rect="[[selectionOverlayRect]]"
+ >
</post-selection-renderer>
- <lens-object-layer id="objectSelectionLayer"
- screenshot-data-uri="[[screenshotDataUri]]" theme="[[theme]]">
+ <lens-object-layer
+ id="objectSelectionLayer"
+ screenshot-data-uri="[[screenshotDataUri]]"
+ theme="[[theme]]"
+ >
</lens-object-layer>
- <region-selection id="regionSelectionLayer" theme="[[theme]]"
- screenshot-data-uri="[[screenshotDataUri]]"
- selection-overlay-rect="[[selectionOverlayRect]]"></region-selection>
+ <region-selection
+ id="regionSelectionLayer"
+ theme="[[theme]]"
+ screenshot-data-uri="[[screenshotDataUri]]"
+ selection-overlay-rect="[[selectionOverlayRect]]"
+ ></region-selection>
<template is="dom-if" if="[[!simplifiedSelectionEnabled]]">
- <lens-text-layer id="textSelectionLayer"
- selection-overlay-rect="[[selectionOverlayRect]]"></lens-text-layer>
+ <lens-text-layer
+ id="textSelectionLayer"
+ selection-overlay-rect="[[selectionOverlayRect]]"
+ ></lens-text-layer>
</template>
<template is="dom-if" if="[[simplifiedSelectionEnabled]]">
- <lens-simplified-text-layer
- selection-overlay-rect="[[selectionOverlayRect]]">
+ <lens-simplified-text-layer selection-overlay-rect="[[selectionOverlayRect]]">
</lens-simplified-text-layer>
</template>
</div>
<div id="initialFlashScrim"></div>
<div id="contextMenuOverlay">
- <div id="selectedTextContextMenu" class="context-menu" role="menu"
- style$="[[getContextMenuStyle(selectedTextContextMenuX,
+ <div
+ id="selectedTextContextMenu"
+ class="context-menu"
+ role="menu"
+ style$="[[getContextMenuStyle(selectedTextContextMenuX,
selectedTextContextMenuY)]]"
- on-pointerenter="handlePointerEnterContextMenu"
- on-pointerleave="handlePointerLeaveContextMenu">
+ on-pointerenter="handlePointerEnterContextMenu"
+ on-pointerleave="handlePointerLeaveContextMenu"
+ >
<div class="context-menu-item" role="menuitem" on-pointerup="handleCopy">
<span class="menu-item-icon copy"></span>
<span class="menu-item-label">$i18n{copy}</span>
</div>
- <div class="context-menu-item translate-context-menu-item" role="menuitem"
- on-pointerup="handleTranslate">
+ <div
+ class="context-menu-item translate-context-menu-item"
+ role="menuitem"
+ on-pointerup="handleTranslate"
+ >
<span class="menu-item-icon translate"></span>
<span class="menu-item-label">$i18n{translate}</span>
</div>
</div>
- <div id="selectedRegionContextMenu" class="context-menu" role="menu"
- style$="[[selectedRegionContextMenuHorizontalStyle]]
+ <div
+ id="selectedRegionContextMenu"
+ class="context-menu"
+ role="menu"
+ style$="[[selectedRegionContextMenuHorizontalStyle]]
[[selectedRegionContextMenuVerticalStyle]]"
- on-pointerenter="handlePointerEnterContextMenu"
- on-pointerleave="handlePointerLeaveContextMenu">
- <div id="copyDetectedTextContextMenuItem"
- class="context-menu-item detected-text-context-menu-option"
- role="menuitem" on-pointerup="handleCopyDetectedText">
+ on-pointerenter="handlePointerEnterContextMenu"
+ on-pointerleave="handlePointerLeaveContextMenu"
+ >
+ <div
+ id="copyDetectedTextContextMenuItem"
+ class="context-menu-item detected-text-context-menu-option"
+ role="menuitem"
+ on-pointerup="handleCopyDetectedText"
+ >
<span class="menu-item-icon copy"></span>
<span class="menu-item-label">$i18n{copyText}</span>
</div>
- <div id="selectTextContextMenuItem"
- class="context-menu-item detected-text-context-menu-option"
- role="menuitem" on-pointerup="handleSelectText">
+ <div
+ id="selectTextContextMenuItem"
+ class="context-menu-item detected-text-context-menu-option"
+ role="menuitem"
+ on-pointerup="handleSelectText"
+ >
<span class="menu-item-icon text"></span>
<span class="menu-item-label">$i18n{selectText}</span>
</div>
- <div class="context-menu-item translate-context-menu-item
- detected-text-context-menu-option" role="menuitem"
- on-pointerup="handleTranslateDetectedText">
+ <div
+ class="context-menu-item translate-context-menu-item detected-text-context-menu-option"
+ role="menuitem"
+ on-pointerup="handleTranslateDetectedText"
+ >
<span class="menu-item-icon translate"></span>
<span class="menu-item-label">$i18n{translate}</span>
</div>
- <div class="context-menu-item copy-as-image-context-menu-item"
- role="menuitem" on-pointerup="handleCopyAsImage">
+ <div
+ class="context-menu-item copy-as-image-context-menu-item"
+ role="menuitem"
+ on-pointerup="handleCopyAsImage"
+ >
<span class="menu-item-icon copy-image"></span>
<span class="menu-item-label">$i18n{copyAsImage}</span>
</div>
- <div class="context-menu-item save-as-image-context-menu-item"
- role="menuitem" on-pointerup="handleSaveAsImage">
+ <div
+ class="context-menu-item save-as-image-context-menu-item"
+ role="menuitem"
+ on-pointerup="handleSaveAsImage"
+ >
<span class="menu-item-icon download"></span>
<span class="menu-item-label">$i18n{saveAsImage}</span>
</div>
</div>
</div>
</div>
-<div id="cursor"
- class$="[[getHiddenCursorClass(isPointerInside, currentGesture.state)]]">
+<div id="cursor" class$="[[getHiddenCursorClass(isPointerInside, currentGesture.state)]]">
<div id="cursorImg"></div>
</div>
diff --git a/chrome/browser/resources/lens/overlay/selection_overlay.ts b/chrome/browser/resources/lens/overlay/selection_overlay.ts
index c104574..c84c9eb 100644
--- a/chrome/browser/resources/lens/overlay/selection_overlay.ts
+++ b/chrome/browser/resources/lens/overlay/selection_overlay.ts
@@ -7,6 +7,7 @@
import './text_layer.js';
import './region_selection.js';
import './post_selection_renderer.js';
+import './overlay_border_glow.js';
import './overlay_shimmer_canvas.js';
import '/strings.m.js';
import '//resources/cr_elements/cr_button/cr_button.js';
@@ -178,6 +179,10 @@
readOnly: true,
value: !loadTimeData.getBoolean('enableShimmer'),
},
+ enableBorderGlow: {
+ type: Boolean,
+ value: () => loadTimeData.getBoolean('enableBorderGlow'),
+ },
enableCopyAsImage: {
type: Boolean,
reflectToAttribute: true,
@@ -282,6 +287,7 @@
// gesture has started.
declare private currentGesture: GestureEvent;
declare private disableShimmer: boolean;
+ declare private enableBorderGlow: boolean;
declare private enableCopyAsImage: boolean;
declare private enableSaveAsImage: boolean;
declare private suppressCopyAndSaveAsImage: boolean;
@@ -1242,7 +1248,7 @@
// Don't start the shimmer animation until the initial flash animation is
// finished.
- if (!this.disableShimmer) {
+ if (!this.disableShimmer && !this.enableBorderGlow) {
this.$.overlayShimmerCanvas.startAnimation();
}
}
diff --git a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
index af9ce9f..df54fa6 100644
--- a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
+++ b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
@@ -240,6 +240,9 @@
lens::features::GetLensOverlayTranslateRecentLanguagesAmount());
html_source->AddBoolean("simplifiedSelectionEnabled",
lens::features::IsSimplifiedSelectionEnabled());
+ html_source->AddBoolean(
+ "enableBorderGlow",
+ lens::features::GetVisualSelectionUpdatesEnableBorderGlow());
html_source->AddBoolean("autoFocusSearchbox",
lens::features::ShouldAutoFocusSearchbox());
html_source->AddBoolean("cornerSlidersEnabled",
diff --git a/components/lens/lens_features.cc b/components/lens/lens_features.cc
index 4ec318ea..bdaab00 100644
--- a/components/lens/lens_features.cc
+++ b/components/lens/lens_features.cc
@@ -63,6 +63,10 @@
"LensOverlaySimplifiedSelection",
base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kLensOverlayVisualSelectionUpdates,
+ "LensOverlayVisualSelectionUpdates",
+ base::FEATURE_DISABLED_BY_DEFAULT);
+
BASE_FEATURE(kLensOverlayUpdatedClientContext,
"LensOverlayUpdatedClientContext",
base::FEATURE_DISABLED_BY_DEFAULT);
@@ -466,6 +470,10 @@
&kLensOverlaySimplifiedSelection, "copy-command-copies-as-image",
false};
+constexpr base::FeatureParam<bool>
+ kLensOverlayVisualSelectionUpdatesEnableBorderGlow{
+ &kLensOverlayVisualSelectionUpdates, "enable-border-glow", true};
+
constexpr base::FeatureParam<std::string> kHomepageURLForLens{
&kLensStandalone, "lens-homepage-url", "https://lens.google.com/v3/"};
@@ -982,6 +990,15 @@
return kLensOverlaySimplifiedSelectionShouldCopyAsImage.Get();
}
+bool IsLensOverlayVisualSelectionUpdatesEnabled() {
+ return base::FeatureList::IsEnabled(kLensOverlayVisualSelectionUpdates);
+}
+
+bool GetVisualSelectionUpdatesEnableBorderGlow() {
+ return base::FeatureList::IsEnabled(kLensOverlayVisualSelectionUpdates) &&
+ kLensOverlayVisualSelectionUpdatesEnableBorderGlow.Get();
+}
+
bool PageContentUploadRequestIdFixEnabled() {
return kPageContentUploadRequestIdFix.Get();
}
diff --git a/components/lens/lens_features.h b/components/lens/lens_features.h
index 2e665bd5..d1933ab 100644
--- a/components/lens/lens_features.h
+++ b/components/lens/lens_features.h
@@ -57,6 +57,10 @@
COMPONENT_EXPORT(LENS_FEATURES)
BASE_DECLARE_FEATURE(kLensOverlaySimplifiedSelection);
+// Enables the Lens overlay visual selection updates.
+COMPONENT_EXPORT(LENS_FEATURES)
+BASE_DECLARE_FEATURE(kLensOverlayVisualSelectionUpdates);
+
// Enables the Lens overlay updated client context.
COMPONENT_EXPORT(LENS_FEATURES)
BASE_DECLARE_FEATURE(kLensOverlayUpdatedClientContext);
@@ -755,6 +759,11 @@
COMPONENT_EXPORT(LENS_FEATURES)
extern bool GetShouldCopyAsImage();
+// Whether to enable the border glow for the visual selection updates. Enabling
+// this will disable the shimmer animation.
+COMPONENT_EXPORT(LENS_FEATURES)
+extern bool GetVisualSelectionUpdatesEnableBorderGlow();
+
// Whether to fix the request id for page content upload requests. When enabled,
// this will not increment the image upload request ID when the page content
// upload request is sent.