11import { css , html , LitElement , nothing } from 'lit' ;
2- import { customElement , property } from 'lit/decorators.js' ;
2+ import { customElement , property , query } from 'lit/decorators.js' ;
33import { ifDefined } from 'lit/directives/if-defined.js' ;
44import { unsafeHTML } from 'lit/directives/unsafe-html.js' ;
55import { until } from 'lit/directives/until.js' ;
66import type { GlCommands } from '../../../../constants.commands' ;
77import type { Source } from '../../../../constants.telemetry' ;
88import type { Promo } from '../../../../plus/gk/models/promo' ;
99import { createCommandLink } from '../../../../system/commands' ;
10+ import { focusOutline } from './styles/lit/a11y.css' ;
1011
1112@customElement ( 'gl-promo' )
1213export class GlPromo extends LitElement {
14+ static override shadowRootOptions : ShadowRootInit = {
15+ ...LitElement . shadowRootOptions ,
16+ delegatesFocus : true ,
17+ } ;
18+
1319 static override styles = [
1420 css `
1521 :host {
@@ -45,13 +51,20 @@ export class GlPromo extends LitElement {
4551 white-space: nowrap;
4652 }
4753
54+ .link:focus-visible {
55+ ${ focusOutline }
56+ }
57+
4858 .link:hover {
4959 color: inherit;
5060 text-decoration: underline;
5161 }
5262 ` ,
5363 ] ;
5464
65+ @query ( 'a,button,[tabindex="0"]' )
66+ private _focusable ?: HTMLElement ;
67+
5568 @property ( { type : Object } )
5669 promoPromise ! : Promise < Promo | undefined > ;
5770
@@ -61,6 +74,15 @@ export class GlPromo extends LitElement {
6174 @property ( { reflect : true , type : String } )
6275 type : 'link' | 'info' = 'info' ;
6376
77+ private _hasPromo = false ;
78+ @property ( { type : Boolean , reflect : true , attribute : 'has-promo' } )
79+ get hasPromo ( ) {
80+ return this . _hasPromo ;
81+ }
82+ private set hasPromo ( value : boolean ) {
83+ this . _hasPromo = value ;
84+ }
85+
6486 override render ( ) : unknown {
6587 return html `${ until (
6688 this . promoPromise . then ( promo => this . renderPromo ( promo ) ) ,
@@ -69,20 +91,23 @@ export class GlPromo extends LitElement {
6991 }
7092
7193 private renderPromo ( promo : Promo | undefined ) {
72- if ( ! promo ?. content ?. webview ) return ;
94+ if ( ! promo ?. content ?. webview ) {
95+ this . hasPromo = false ;
96+ return ;
97+ }
7398
7499 const content = promo . content . webview ;
75100 switch ( this . type ) {
76101 case 'info' :
77102 if ( content . info ) {
78- this . setAttribute ( 'has-promo' , '' ) ;
103+ this . hasPromo = true ;
79104 return html `< p class ="promo "> ${ unsafeHTML ( content . info . html ) } </ p > ` ;
80105 }
81106 break ;
82107
83108 case 'link' :
84109 if ( content . link ) {
85- this . setAttribute ( 'has-promo' , '' ) ;
110+ this . hasPromo = true ;
86111 return html `< a
87112 class ="link "
88113 href ="${ this . getCommandUrl ( promo ) } "
@@ -93,7 +118,7 @@ export class GlPromo extends LitElement {
93118 break ;
94119 }
95120
96- this . removeAttribute ( 'has-promo' ) ;
121+ this . hasPromo = false ;
97122 return nothing ;
98123 }
99124
@@ -105,4 +130,8 @@ export class GlPromo extends LitElement {
105130
106131 return createCommandLink < Source > ( command ?? 'gitlens.plus.upgrade' , this . source ) ;
107132 }
133+
134+ override focus ( ) : void {
135+ this . _focusable ?. focus ( ) ;
136+ }
108137}
0 commit comments