Skip to content

Commit dbf3243

Browse files
authored
Merge pull request #36910 from github/repo-sync
Repo sync
2 parents 7b08470 + bb47f55 commit dbf3243

File tree

3 files changed

+61
-18
lines changed

3 files changed

+61
-18
lines changed

content/copilot/managing-copilot/configuring-and-auditing-content-exclusion/excluding-content-from-github-copilot.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ Repository administrators{% ifversion ghec %}, organization owners, and enterpri
4545
| JetBrains IDEs | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} |
4646
| Vim/Neovim | {% octicon "check" aria-label="Supported" %} | Not applicable |
4747
| Xcode | {% octicon "check" aria-label="Supported" %} | Not applicable |
48+
| Eclipse | {% octicon "check" aria-label="Supported" %} | {% octicon "x" aria-label="Not supported" %} |
4849
| Azure Data Studio | {% octicon "x" aria-label="Not supported" %} | Not applicable |
4950
| The {% data variables.product.github %} website | Not applicable | {% octicon "check" aria-label="Supported" %} |
5051
| {% data variables.product.prodname_mobile %} | Not applicable | {% octicon "check" aria-label="Supported" %} |

src/search/components/input/AskAIResults.tsx

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export function AskAIResults({
5858
const [message, setMessage] = useState('')
5959
const [initialLoading, setInitialLoading] = useState(true)
6060
const [responseLoading, setResponseLoading] = useState(false)
61+
const [announcement, setAnnouncement] = useState<string>('')
6162
const disclaimerRef = useRef<HTMLDivElement>(null)
6263
// We cache up to 1000 queries, and expire them after 30 days
6364
const { getItem, setItem } = useAISearchLocalStorageCache<{
@@ -83,6 +84,7 @@ export function AskAIResults({
8384
status: 400,
8485
})
8586
setMessage(cannedResponse)
87+
setAnnouncement(cannedResponse)
8688
setReferences([])
8789
setItem(
8890
query,
@@ -105,6 +107,7 @@ export function AskAIResults({
105107
}
106108
let isCancelled = false
107109
setMessage('')
110+
setAnnouncement('')
108111
setReferences([])
109112
setAICouldNotAnswer(false)
110113
setInitialLoading(true)
@@ -118,13 +121,18 @@ export function AskAIResults({
118121
setAICouldNotAnswer(cachedData.aiCouldNotAnswer || false)
119122
setInitialLoading(false)
120123
setResponseLoading(false)
124+
121125
sendAISearchResultEvent({
122126
sources: cachedData.sources,
123127
message: cachedData.message,
124128
eventGroupId: askAIEventGroupId.current,
125129
couldNotAnswer: cachedData.aiCouldNotAnswer,
126130
status: cachedData.aiCouldNotAnswer ? 400 : 200,
127131
})
132+
133+
setTimeout(() => {
134+
setAnnouncement(cachedData.message)
135+
}, 1500)
128136
return
129137
}
130138

@@ -203,6 +211,9 @@ export function AskAIResults({
203211
setMessage(messageBuffer)
204212
}
205213
}
214+
if (!isCancelled) {
215+
setAnnouncement('Copilot Response Loading...')
216+
}
206217
}
207218
}
208219
}
@@ -246,18 +257,12 @@ export function AskAIResults({
246257

247258
return (
248259
<div className={styles.container}>
249-
{/* Hidden status message for screen readers */}
250-
<span role="status" aria-live="polite" className={styles.displayForScreenReader}>
251-
{initialLoading || responseLoading
252-
? t('search.ai.loading_status_message')
253-
: t('search.ai.done_loading_status_message')}
254-
</span>
255260
{initialLoading ? (
256261
<div className={styles.loadingContainer} role="status">
257262
<Spinner />
258263
</div>
259264
) : (
260-
<article aria-busy={responseLoading} aria-live="polite">
265+
<article aria-busy={responseLoading} aria-live="assertive">
261266
{!aiCouldNotAnswer && message !== '' ? (
262267
<span ref={disclaimerRef} className={styles.disclaimerText}>
263268
{t('search.ai.disclaimer')}
@@ -358,6 +363,8 @@ export function AskAIResults({
358363
paddingLeft: '0px',
359364
}}
360365
key={`reference-${index}`}
366+
id={`search-option-reference-${index + referencesIndexOffset}`}
367+
role="option"
361368
tabIndex={-1}
362369
onSelect={() => {
363370
referenceOnSelect(source.url)
@@ -374,6 +381,22 @@ export function AskAIResults({
374381
</ActionList>
375382
</>
376383
) : null}
384+
<div
385+
aria-live="assertive"
386+
style={{
387+
position: 'absolute',
388+
width: '1px',
389+
height: '1px',
390+
padding: '0',
391+
margin: '-1px',
392+
overflow: 'hidden',
393+
clip: 'rect(0, 0, 0, 0)',
394+
whiteSpace: 'nowrap',
395+
border: '0',
396+
}}
397+
>
398+
{announcement}
399+
</div>
377400
</div>
378401
)
379402
}

src/search/components/input/SearchOverlay.tsx

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { EventType } from '@/events/types'
3939
import { ASK_AI_EVENT_GROUP, SEARCH_OVERLAY_EVENT_GROUP } from '@/events/components/event-groups'
4040
import type { AIReference } from '../types'
4141
import type { AutocompleteSearchHit, GeneralSearchHit } from '@/search/types'
42+
import { focusTrap } from '@primer/behaviors'
4243

4344
type Props = {
4445
searchOverlayOpen: boolean
@@ -88,6 +89,14 @@ export function SearchOverlay({
8889

8990
// Group all events between open / close of the overlay together
9091
const searchEventGroupId = useRef<string>('')
92+
const overlayRef = useRef<HTMLDivElement>(null)
93+
94+
useEffect(() => {
95+
if (searchOverlayOpen && overlayRef.current) {
96+
focusTrap(overlayRef.current, inputRef.current || undefined)
97+
}
98+
}, [searchOverlayOpen])
99+
91100
useEffect(() => {
92101
searchEventGroupId.current = uuidv4()
93102
}, [searchOverlayOpen])
@@ -486,6 +495,7 @@ export function SearchOverlay({
486495
<>
487496
<ActionList
488497
aria-label={t('search.overlay.suggestions_list_aria_label')}
498+
id="search-suggestions-list"
489499
showDividers
490500
className={styles.suggestionsList}
491501
ref={suggestionsListHeightRef}
@@ -601,6 +611,7 @@ export function SearchOverlay({
601611
role="dialog"
602612
aria-modal="true"
603613
aria-labelledby={overlayHeadingId}
614+
ref={overlayRef}
604615
>
605616
<Header className={styles.header}>
606617
<TextInput
@@ -609,9 +620,17 @@ export function SearchOverlay({
609620
ref={inputRef}
610621
value={urlSearchInputQuery}
611622
onChange={handleSearchQueryChange}
612-
onKeyDown={handleKeyDown}
613623
leadingVisual={<SearchIcon />}
614624
aria-labelledby={overlayHeadingId}
625+
role="combobox"
626+
aria-controls="search-suggestions-list"
627+
aria-expanded={combinedOptions.length > 0}
628+
aria-activedescendant={
629+
selectedIndex >= 0
630+
? `search-option-${combinedOptions[selectedIndex].group}-${selectedIndex}`
631+
: undefined
632+
}
633+
onKeyDown={handleKeyDown}
615634
placeholder={t('search.input.placeholder_no_icon')}
616635
trailingAction={
617636
<Stack
@@ -793,6 +812,8 @@ function renderSearchGroups(
793812
items.push(
794813
<ActionList.Item
795814
key={`general-${index}`}
815+
id={`search-option-general-${index}`}
816+
role="option"
796817
className={styles.noResultsFound}
797818
tabIndex={-1}
798819
aria-label={t('search.overlay.no_results_found')}
@@ -808,6 +829,9 @@ function renderSearchGroups(
808829
items.push(
809830
<ActionList.Item
810831
key={`general-${index}`}
832+
id={`search-option-general-${index}`}
833+
role="option"
834+
aria-describedby="search-suggestions-list"
811835
onSelect={() =>
812836
option.isViewAllResults ? performGeneralSearch() : generalSearchResultOnSelect(option)
813837
}
@@ -843,11 +867,7 @@ function renderSearchGroups(
843867

844868
groups.push(
845869
<ActionList.Group key="general" data-testid="general-autocomplete-suggestions">
846-
<ActionList.GroupHeading
847-
as="h3"
848-
tabIndex={-1}
849-
aria-label={t('search.overlay.general_suggestions_list_aria_label')}
850-
>
870+
<ActionList.GroupHeading as="h3" tabIndex={-1} id="search-suggestions-list">
851871
{t('search.overlay.general_suggestions_list_heading')}
852872
</ActionList.GroupHeading>
853873
{items}
@@ -872,11 +892,7 @@ function renderSearchGroups(
872892
if (aiOptionsWithUserInput.length && !isInAskAIState) {
873893
groups.push(
874894
<ActionList.Group key="ai-suggestions" data-testid="ai-autocomplete-suggestions">
875-
<ActionList.GroupHeading
876-
as="h3"
877-
tabIndex={-1}
878-
aria-label={t('search.overlay.ai_suggestions_list_aria_label')}
879-
>
895+
<ActionList.GroupHeading as="h3" id="copilot-suggestions" tabIndex={-1}>
880896
<CopilotIcon className="mr-1" />
881897
{t('search.overlay.ai_autocomplete_list_heading')}
882898
</ActionList.GroupHeading>
@@ -887,6 +903,9 @@ function renderSearchGroups(
887903
const item = (
888904
<ActionList.Item
889905
key={`ai-${indexWithOffset}`}
906+
id={`search-option-ai-${indexWithOffset}`}
907+
role="option"
908+
aria-describedby="copilot-suggestions"
890909
onSelect={() => aiAutocompleteOnSelect(option)}
891910
active={isActive}
892911
tabIndex={-1}

0 commit comments

Comments
 (0)