@@ -10,6 +10,7 @@ import * as Common from '../../core/common/common.js';
1010import * as i18n from '../../core/i18n/i18n.js' ;
1111import * as Platform from '../../core/platform/platform.js' ;
1212import * as Geometry from '../../models/geometry/geometry.js' ;
13+ import * as Annotations from '../../ui/components/annotations/annotations.js' ;
1314import * as Buttons from '../../ui/components/buttons/buttons.js' ;
1415import * as VisualLogging from '../../ui/visual_logging/visual_logging.js' ;
1516import * as IconButton from '../components/icon_button/icon_button.js' ;
@@ -53,6 +54,10 @@ const UIStrings = {
5354 * @description Indicates that a tab contains a preview feature (i.e., a beta / experimental feature).
5455 */
5556 previewFeature : 'Preview feature' ,
57+ /**
58+ * @description Indicates that a tab contains annotation(s).
59+ */
60+ panelContainsAnnotation : 'This panel has one or more annotations' ,
5661 /**
5762 * @description Text to move a tab forwar.
5863 */
@@ -121,6 +126,11 @@ export class TabbedPane extends Common.ObjectWrapper.eventMixin<EventTypes, type
121126 this . currentDevicePixelRatio = window . devicePixelRatio ;
122127 ZoomManager . instance ( ) . addEventListener ( ZoomManagerEvents . ZOOM_CHANGED , this . zoomChanged , this ) ;
123128 this . makeTabSlider ( ) ;
129+
130+ if ( Annotations . AnnotationRepository . annotationsEnabled ( ) ) {
131+ Annotations . AnnotationRepository . instance ( ) . addEventListener (
132+ Annotations . Events . ANNOTATION_ADDED , this . #onAnnotationAdded, this ) ;
133+ }
124134 }
125135
126136 setAccessibleName ( name : string ) : void {
@@ -555,6 +565,36 @@ export class TabbedPane extends Common.ObjectWrapper.eventMixin<EventTypes, type
555565 this . performUpdate ( ) ;
556566 }
557567
568+ updateTabAnnotationIcons ( ) : void {
569+ if ( ! Annotations . AnnotationRepository . annotationsEnabled ( ) ) {
570+ return ;
571+ }
572+
573+ const annotations = Annotations . AnnotationRepository . instance ( ) ;
574+ if ( ! annotations ) {
575+ return ;
576+ }
577+
578+ for ( const tab of this . tabs ) {
579+ let primaryType = - 1 ;
580+ let secondaryType = - 1 ;
581+ switch ( tab . id ) {
582+ case 'elements' :
583+ primaryType = Annotations . AnnotationType . ELEMENT_NODE ;
584+ secondaryType = Annotations . AnnotationType . STYLE_RULE ;
585+ break ;
586+ case 'network' :
587+ primaryType = Annotations . AnnotationType . NETWORK_REQUEST ;
588+ secondaryType = Annotations . AnnotationType . NETWORK_REQUEST_SUBPANEL_HEADERS ;
589+ break ;
590+ }
591+
592+ const showTabAnnotationIcon = annotations . getAnnotationsByType ( primaryType ) . length > 0 ||
593+ annotations . getAnnotationsByType ( secondaryType ) . length > 0 ;
594+ this . setTabAnnotationIcon ( tab . id , showTabAnnotationIcon ) ;
595+ }
596+ }
597+
558598 override performUpdate ( ) : void {
559599 if ( ! this . isShowing ( ) ) {
560600 return ;
@@ -583,6 +623,7 @@ export class TabbedPane extends Common.ObjectWrapper.eventMixin<EventTypes, type
583623 this . updateWidths ( ) ;
584624 this . updateTabsDropDown ( ) ;
585625 this . updateTabSlider ( ) ;
626+ this . updateTabAnnotationIcons ( ) ;
586627 }
587628
588629 private adjustToolbarWidth ( ) : void {
@@ -939,6 +980,17 @@ export class TabbedPane extends Common.ObjectWrapper.eventMixin<EventTypes, type
939980 this . automaticReorder = automatic ;
940981 }
941982
983+ setTabAnnotationIcon ( id : string , iconVisible : boolean ) : void {
984+ const tab = this . tabsById . get ( id ) ;
985+ if ( tab ) {
986+ tab . tabAnnotationIcon = iconVisible ;
987+ }
988+ }
989+
990+ #onAnnotationAdded( ) : void {
991+ this . updateTabAnnotationIcons ( ) ;
992+ }
993+
942994 private keyDown ( event : KeyboardEvent ) : void {
943995 if ( ! this . currentTab ) {
944996 return ;
@@ -1009,6 +1061,7 @@ export interface EventTypes {
10091061export class TabbedPaneTab {
10101062 closeable : boolean ;
10111063 previewFeature = false ;
1064+ #tabAnnotationIcon = false ;
10121065 private readonly tabbedPane : TabbedPane ;
10131066 #id: string ;
10141067 #title: string ;
@@ -1064,6 +1117,32 @@ export class TabbedPaneTab {
10641117 return this . #jslogContext ?? ( this . #id === 'console-view' ? 'console' : this . #id) ;
10651118 }
10661119
1120+ get tabAnnotationIcon ( ) : boolean {
1121+ return this . #tabAnnotationIcon;
1122+ }
1123+
1124+ set tabAnnotationIcon ( iconVisible : boolean ) {
1125+ if ( this . #tabAnnotationIcon === iconVisible ) {
1126+ return ;
1127+ }
1128+ this . #tabAnnotationIcon = iconVisible ;
1129+ if ( ! this . #tabElement) {
1130+ return ;
1131+ }
1132+ const iconElement = this . #tabElement. querySelector ( '.ai-icon' ) ;
1133+ if ( iconVisible ) {
1134+ if ( ! iconElement ) {
1135+ const closeButton = this . #tabElement. querySelector ( '.close-button' ) ;
1136+ this . #tabElement. insertBefore ( this . createTabAnnotationIcon ( ) , closeButton ) ;
1137+ }
1138+ } else {
1139+ iconElement ?. remove ( ) ;
1140+ }
1141+ this . #tabElement. classList . toggle ( 'ai' , iconVisible ) ;
1142+ delete this . measuredWidth ;
1143+ this . tabbedPane . requestUpdate ( ) ;
1144+ }
1145+
10671146 isCloseable ( ) : boolean {
10681147 return this . closeable ;
10691148 }
@@ -1204,6 +1283,12 @@ export class TabbedPaneTab {
12041283 tabElement . classList . add ( 'preview' ) ;
12051284 }
12061285
1286+ if ( this . tabAnnotationIcon ) {
1287+ const tabAnnotationIcon = this . createTabAnnotationIcon ( ) ;
1288+ tabElement . appendChild ( tabAnnotationIcon ) ;
1289+ tabElement . classList . add ( 'ai' ) ;
1290+ }
1291+
12071292 if ( this . closeable ) {
12081293 const closeIcon = this . createCloseIconButton ( ) ;
12091294 tabElement . appendChild ( closeIcon ) ;
@@ -1230,6 +1315,19 @@ export class TabbedPaneTab {
12301315 return tabElement as HTMLElement ;
12311316 }
12321317
1318+ private createTabAnnotationIcon ( ) : HTMLDivElement {
1319+ // TODO(finnur): Replace the ai-icon with the squiggly svg once it becomes available.
1320+ const iconContainer = document . createElement ( 'div' ) ;
1321+ iconContainer . classList . add ( 'ai-icon' ) ;
1322+ const tabAnnotationIcon = new IconButton . Icon . Icon ( ) ;
1323+ tabAnnotationIcon . name = 'smart-assistant' ;
1324+ tabAnnotationIcon . classList . add ( 'small' ) ;
1325+ iconContainer . appendChild ( tabAnnotationIcon ) ;
1326+ iconContainer . setAttribute ( 'title' , i18nString ( UIStrings . panelContainsAnnotation ) ) ;
1327+ iconContainer . setAttribute ( 'aria-label' , i18nString ( UIStrings . panelContainsAnnotation ) ) ;
1328+ return iconContainer ;
1329+ }
1330+
12331331 private createCloseIconButton ( ) : Buttons . Button . Button {
12341332 const closeButton = new Buttons . Button . Button ( ) ;
12351333 closeButton . data = {
0 commit comments