@@ -12,7 +12,6 @@ import type { SettingsActions } from '../actions.js';
1212import type { SettingsState } from '../state.js' ;
1313import { settingsStateContext } from '../state.js' ;
1414import '../../shared/components/button.js' ;
15- import '../../shared/components/checkbox/checkbox.js' ;
1615import '../../shared/components/code-icon.js' ;
1716
1817export const tagName = 'gl-settings-autolinks' ;
@@ -86,20 +85,67 @@ export class GlSettingsAutolinks extends SignalWatcher(LitElement) {
8685 ${ focusOutline }
8786 }
8887
89- .rule__prefix {
88+ /* The prefix field embeds its match-option toggles, so the prefix + its
89+ options read as one control (mirrors gl-search-input's field pattern) */
90+ .rule__prefix-field {
91+ --toggle-size: 2rem;
92+
93+ position: relative;
9094 flex: none;
91- width: 10rem;
95+ width: 16rem;
96+ }
97+
98+ .rule__prefix {
99+ width: 100%;
100+
101+ /* Reserve room so typed text never runs under the toggles */
102+ padding-inline-end: calc(2 * var(--toggle-size) + var(--gl-space-2) + 2 * var(--gl-space-4));
92103 }
93104
94105 .rule__url {
95106 flex: 1;
96107 min-width: 24rem;
97108 }
98109
99- .rule__options {
100- display: flex;
101- gap: var(--gl-space-12);
110+ .rule__toggles {
111+ position: absolute;
112+ inset-block: var(--gl-space-2);
113+ inset-inline-end: var(--gl-space-4);
114+ z-index: 1;
115+ display: inline-flex;
116+ gap: var(--gl-space-2);
117+ align-items: stretch;
118+ }
119+
120+ .rule__toggle {
121+ display: inline-flex;
102122 align-items: center;
123+ justify-content: center;
124+ min-width: var(--toggle-size);
125+ padding-inline: var(--gl-space-2);
126+ font-family: var(--vscode-editor-font-family);
127+ font-size: 1.1rem;
128+ line-height: 1;
129+ color: var(--color-foreground--65);
130+ cursor: pointer;
131+ background: transparent;
132+ border: var(--gl-border-width) solid transparent;
133+ border-radius: var(--gl-radius-sm);
134+ }
135+
136+ .rule__toggle:hover {
137+ color: var(--color-foreground);
138+ background-color: var(--vscode-inputOption-hoverBackground);
139+ }
140+
141+ .rule__toggle[aria-pressed='true'] {
142+ color: var(--vscode-inputOption-activeForeground);
143+ background-color: var(--vscode-inputOption-activeBackground);
144+ border-color: var(--vscode-inputOption-activeBorder);
145+ }
146+
147+ .rule__toggle:focus-visible {
148+ ${ focusOutline }
103149 }
104150
105151 .rule__delete {
@@ -304,18 +350,48 @@ export class GlSettingsAutolinks extends SignalWatcher(LitElement) {
304350 // position, so deleting an earlier rule doesn't silently rename the rest
305351 const name = autolink . prefix ?. trim ( ) || 'New' ;
306352
353+ // `ignoreCase: false` IS case-sensitive (the config semantics are inverted
354+ // from the label), so the Case-sensitive toggle is pressed when ignoreCase
355+ // is false and toggling simply flips the flag.
356+ const caseSensitive = ! ( autolink . ignoreCase ?? false ) ;
357+ const alphanumeric = autolink . alphanumeric ?? false ;
358+
307359 return html `< div class ="rule " data-index =${ index } >
308- < input
309- class ="rule__prefix ${ invalid . prefix ? 'rule__prefix--invalid' : '' } "
310- type ="text "
311- placeholder ="TICKET- "
312- spellcheck ="false "
313- aria-label ="${ name } autolink prefix "
314- aria-invalid =${ invalid . prefix ? 'true' : 'false' }
315- aria-describedby =${ invalid . prefix ? prefixErrorId : nothing }
316- .value=${ autolink . prefix ?? '' }
317- @blur=${ ( e : FocusEvent ) => this . commitRule ( index , 'prefix' , ( e . target as HTMLInputElement ) . value ) }
318- />
360+ < span class ="rule__prefix-field ">
361+ < input
362+ class ="rule__prefix ${ invalid . prefix ? 'rule__prefix--invalid' : '' } "
363+ type ="text "
364+ placeholder ="TICKET- "
365+ spellcheck ="false "
366+ aria-label ="${ name } autolink prefix "
367+ aria-invalid =${ invalid . prefix ? 'true' : 'false' }
368+ aria-describedby =${ invalid . prefix ? prefixErrorId : nothing }
369+ .value=${ autolink . prefix ?? '' }
370+ @blur=${ ( e : FocusEvent ) => this . commitRule ( index , 'prefix' , ( e . target as HTMLInputElement ) . value ) }
371+ />
372+ < span class ="rule__toggles ">
373+ < button
374+ type ="button "
375+ class ="rule__toggle "
376+ aria-pressed =${ caseSensitive ? 'true' : 'false' }
377+ aria-label ="Case-sensitive"
378+ title="Case-sensitive matching"
379+ @click=${ ( ) => this . commitRule ( index , 'ignoreCase' , caseSensitive ) }
380+ >
381+ Aa
382+ </ button >
383+ < button
384+ type ="button "
385+ class ="rule__toggle "
386+ aria-pressed =${ alphanumeric ? 'true' : 'false' }
387+ aria-label ="Alphanumeric"
388+ title="Match alphanumeric references"
389+ @click=${ ( ) => this . commitRule ( index , 'alphanumeric' , ! alphanumeric ) }
390+ >
391+ a1
392+ </ button >
393+ </ span >
394+ </ span >
319395 < input
320396 class ="rule__url ${ invalid . url ? 'rule__url--invalid' : '' } "
321397 type ="text "
@@ -327,32 +403,6 @@ export class GlSettingsAutolinks extends SignalWatcher(LitElement) {
327403 .value=${ autolink . url ?? '' }
328404 @blur=${ ( e : FocusEvent ) => this . commitRule ( index , 'url' , ( e . target as HTMLInputElement ) . value ) }
329405 />
330- < span class ="rule__options ">
331- < gl-checkbox
332- .checked =${ ! ( autolink . ignoreCase ?? false ) }
333- @gl-change-value =${ ( e : Event ) =>
334- this . commitRule (
335- index ,
336- 'ignoreCase' ,
337- // The config semantics are inverted from the label: `ignoreCase: false`
338- // IS case-sensitive. The legacy view bound these directly — a
339- // long-standing bug hidden behind an icon-only toggle — so bind
340- // inverted to make the labeled checkbox tell the truth.
341- ! ( e . target as HTMLElement & { checked : boolean } ) . checked ,
342- ) }
343- > Case-sensitive</ gl-checkbox
344- >
345- < gl-checkbox
346- .checked =${ autolink . alphanumeric ?? false }
347- @gl-change-value =${ ( e : Event ) =>
348- this . commitRule (
349- index ,
350- 'alphanumeric' ,
351- ( e . target as HTMLElement & { checked : boolean } ) . checked ,
352- ) }
353- > Alphanumeric</ gl-checkbox
354- >
355- </ span >
356406 < button
357407 type ="button "
358408 class ="rule__delete "
0 commit comments