AI Search feedback fixes round 3 (#54669)
This commit is contained in:
@@ -26,7 +26,9 @@ release_notes:
|
|||||||
search:
|
search:
|
||||||
input:
|
input:
|
||||||
aria_label: Open search overlay
|
aria_label: Open search overlay
|
||||||
placeholder: Search or ask Copilot
|
placeholder: Search or ask {{icon}} Copilot
|
||||||
|
placeholder_no_icon: Search or ask Copilot
|
||||||
|
shortcut: Type {{icon}} to search
|
||||||
overlay:
|
overlay:
|
||||||
input_aria_label: Search or ask Copilot
|
input_aria_label: Search or ask Copilot
|
||||||
suggestions_list_aria_label: Search suggestions
|
suggestions_list_aria_label: Search suggestions
|
||||||
@@ -38,7 +40,7 @@ search:
|
|||||||
beta_tag: Beta
|
beta_tag: Beta
|
||||||
return_to_search: Return to search
|
return_to_search: Return to search
|
||||||
clear_search_query: Clear
|
clear_search_query: Clear
|
||||||
view_all_search_results: View all {{length}} results
|
view_all_search_results: View more results
|
||||||
no_results_found: No results found
|
no_results_found: No results found
|
||||||
ai:
|
ai:
|
||||||
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ release_notes:
|
|||||||
search:
|
search:
|
||||||
input:
|
input:
|
||||||
aria_label: Open search overlay
|
aria_label: Open search overlay
|
||||||
placeholder: Search or ask Copilot
|
placeholder: Search or ask {{icon}} Copilot
|
||||||
|
placeholder_no_icon: Search or ask Copilot
|
||||||
|
shortcut: Type {{icon}} to search
|
||||||
overlay:
|
overlay:
|
||||||
input_aria_label: Search or ask Copilot
|
input_aria_label: Search or ask Copilot
|
||||||
suggestions_list_aria_label: Search suggestions
|
suggestions_list_aria_label: Search suggestions
|
||||||
@@ -38,7 +40,7 @@ search:
|
|||||||
beta_tag: Beta
|
beta_tag: Beta
|
||||||
return_to_search: Return to search
|
return_to_search: Return to search
|
||||||
clear_search_query: Clear
|
clear_search_query: Clear
|
||||||
view_all_search_results: View all {{length}} results
|
view_all_search_results: View more results
|
||||||
no_results_found: No results found
|
no_results_found: No results found
|
||||||
ai:
|
ai:
|
||||||
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export type MarkdownContentPropsT = {
|
|||||||
children: string
|
children: string
|
||||||
className?: string
|
className?: string
|
||||||
openLinksInNewTab?: boolean
|
openLinksInNewTab?: boolean
|
||||||
|
includeQueryParams?: boolean
|
||||||
eventGroupKey?: string
|
eventGroupKey?: string
|
||||||
eventGroupId?: string
|
eventGroupId?: string
|
||||||
as?: keyof JSX.IntrinsicElements
|
as?: keyof JSX.IntrinsicElements
|
||||||
@@ -20,16 +21,48 @@ export const UnrenderedMarkdownContent = ({
|
|||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
openLinksInNewTab = true,
|
openLinksInNewTab = true,
|
||||||
|
includeQueryParams = true,
|
||||||
eventGroupKey = '',
|
eventGroupKey = '',
|
||||||
eventGroupId = '',
|
eventGroupId = '',
|
||||||
...restProps
|
...restProps
|
||||||
}: MarkdownContentPropsT) => {
|
}: MarkdownContentPropsT) => {
|
||||||
// Overrides for ReactMarkdown components
|
// Overrides for ReactMarkdown components
|
||||||
const components = {} as Components
|
const components = {} as Components
|
||||||
if (openLinksInNewTab) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
components.a = ({ node, ...props }) => (
|
components.a = ({ node, ...props }) => {
|
||||||
<a {...props} target="_blank" data-group-key={eventGroupKey} data-group-id={eventGroupId}>
|
let href = props.href || ''
|
||||||
|
let existingAnchorParams = ''
|
||||||
|
// When we want to include specific query parameters in the URL
|
||||||
|
if (includeQueryParams) {
|
||||||
|
if (href.includes('?')) {
|
||||||
|
href = href.split('?')[0]
|
||||||
|
existingAnchorParams = href.split('?')[1]
|
||||||
|
}
|
||||||
|
// Include feature, search-overlay-ask-ai, and search-overlay-input query parameters if they exist in the current URL
|
||||||
|
const existingURLParams = new URLSearchParams(window.location.search)
|
||||||
|
const newParams = new URLSearchParams()
|
||||||
|
if (existingURLParams.get('feature')) {
|
||||||
|
newParams.set('feature', existingURLParams.get('feature') || '')
|
||||||
|
}
|
||||||
|
if (existingURLParams.get('search-overlay-ask-ai')) {
|
||||||
|
newParams.set('search-overlay-ask-ai', existingURLParams.get('search-overlay-ask-ai') || '')
|
||||||
|
}
|
||||||
|
if (existingURLParams.get('search-overlay-input')) {
|
||||||
|
newParams.set('search-overlay-input', existingURLParams.get('search-overlay-input') || '')
|
||||||
|
}
|
||||||
|
// Combine new and existing query parameters
|
||||||
|
if (newParams.toString()) {
|
||||||
|
href = `${href}?${existingAnchorParams}&${newParams.toString()}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
{...props}
|
||||||
|
href={href}
|
||||||
|
target={openLinksInNewTab ? '_blank' : undefined}
|
||||||
|
data-group-key={eventGroupKey}
|
||||||
|
data-group-id={eventGroupId}
|
||||||
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type UseCombinedSearchReturn = {
|
|||||||
clearAutocompleteResults: () => void
|
clearAutocompleteResults: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEBOUNCE_TIME = 300 // In milliseconds
|
const DEBOUNCE_TIME = 1 // In milliseconds
|
||||||
|
|
||||||
// Results are only cached for the current session
|
// Results are only cached for the current session
|
||||||
// We cache results so if a user presses backspace, we can show the results immediately without burdening the API
|
// We cache results so if a user presses backspace, we can show the results immediately without burdening the API
|
||||||
@@ -65,7 +65,7 @@ export function useCombinedSearchResults({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
debouncedFetchRef.current = debounce((value: string) => {
|
debouncedFetchRef.current = debounce((value: string) => {
|
||||||
fetchAutocompleteResults(value)
|
fetchAutocompleteResults(value)
|
||||||
}, DEBOUNCE_TIME) // 300ms debounce
|
}, DEBOUNCE_TIME) // 1ms debounce
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
debouncedFetchRef.current?.cancel()
|
debouncedFetchRef.current?.cancel()
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ export function AskAIResults({
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<article aria-busy={responseLoading} aria-live="polite">
|
<article aria-busy={responseLoading} aria-live="polite">
|
||||||
{!aiCouldNotAnswer && message === '' ? (
|
{!aiCouldNotAnswer && message !== '' ? (
|
||||||
<span ref={disclaimerRef} className={styles.disclaimerText}>
|
<span ref={disclaimerRef} className={styles.disclaimerText}>
|
||||||
{t('search.ai.disclaimer')}
|
{t('search.ai.disclaimer')}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -117,6 +117,34 @@
|
|||||||
font-weight: var(--base-text-weight-normal, 400) !important;
|
font-weight: var(--base-text-weight-normal, 400) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.placeholderShortcutContainer {
|
||||||
|
float: right;
|
||||||
|
color: var(--fgColor-disabled);
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forwardSlashIcon {
|
||||||
|
display: inline-grid;
|
||||||
|
width: var(--base-size-16, 16px);
|
||||||
|
height: var(--base-size-16, 16px);
|
||||||
|
color: var(--color-fg-default);
|
||||||
|
|
||||||
|
margin-right: 4px;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding-left: 6px;
|
||||||
|
padding-right: 6px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
|
||||||
|
border-radius: var(--borderRadius-small);
|
||||||
|
|
||||||
|
border: 0.0625rem solid var(--color-fg-muted);
|
||||||
|
border-radius: 0.1875rem;
|
||||||
|
box-shadow: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.searchIconContainer {
|
.searchIconContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -40,6 +40,18 @@ export function SearchBarButton({ isSearchOpen, setIsSearchOpen }: Props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shortcutElements = t('search.input.shortcut')
|
||||||
|
.split(/({{[^}]+}})/)
|
||||||
|
.filter((item) => item.trim() !== '')
|
||||||
|
.map((item) => <>{item.trim()}</>)
|
||||||
|
shortcutElements[1] = <kbd className={styles.forwardSlashIcon}>/</kbd>
|
||||||
|
|
||||||
|
const placeHolderElements = t('search.input.placeholder')
|
||||||
|
.split(/({{[^}]+}})/)
|
||||||
|
.filter((item) => item.trim() !== '')
|
||||||
|
.map((item) => <>{item.trim()}</>)
|
||||||
|
placeHolderElements[1] = <CopilotIcon aria-hidden className="mr-1 ml-1" />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* We don't want to show the input when overlay is open */}
|
{/* We don't want to show the input when overlay is open */}
|
||||||
@@ -78,8 +90,8 @@ export function SearchBarButton({ isSearchOpen, setIsSearchOpen }: Props) {
|
|||||||
urlSearchInputQuery
|
urlSearchInputQuery
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{t('search.input.placeholder')}
|
<span className={styles.placeholderText}>{placeHolderElements}</span>
|
||||||
<CopilotIcon aria-hidden className="mr-1 ml-1" />
|
<span className={styles.placeholderShortcutContainer}>{shortcutElements}</span>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -133,10 +133,7 @@ export function SearchOverlay({
|
|||||||
|
|
||||||
if (generalSearchResults.length > 0) {
|
if (generalSearchResults.length > 0) {
|
||||||
generalOptionsWithViewStatus.push({
|
generalOptionsWithViewStatus.push({
|
||||||
title: t('search.overlay.view_all_search_results').replace(
|
title: t('search.overlay.view_all_search_results'),
|
||||||
'{{length}}',
|
|
||||||
totalGeneralSearchResults.toLocaleString('en-US'),
|
|
||||||
),
|
|
||||||
isViewAllResults: true,
|
isViewAllResults: true,
|
||||||
} as any)
|
} as any)
|
||||||
} else if (urlSearchInputQuery.trim() !== '' && !searchLoading) {
|
} else if (urlSearchInputQuery.trim() !== '' && !searchLoading) {
|
||||||
@@ -468,7 +465,7 @@ export function SearchOverlay({
|
|||||||
{/* Always show the AI Search UI error message when it is needed */}
|
{/* Always show the AI Search UI error message when it is needed */}
|
||||||
{aiSearchError && (
|
{aiSearchError && (
|
||||||
<>
|
<>
|
||||||
<ActionList.Divider key="general-divider" />
|
<ActionList.Divider key="error-top-divider" />
|
||||||
<ActionList.GroupHeading
|
<ActionList.GroupHeading
|
||||||
as="h3"
|
as="h3"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
@@ -492,7 +489,7 @@ export function SearchOverlay({
|
|||||||
role="alert"
|
role="alert"
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<ActionList.Divider key="general-divider" />
|
<ActionList.Divider key="error-bottom-divider" />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* Only show the autocomplete search UI error message in Dev */}
|
{/* Only show the autocomplete search UI error message in Dev */}
|
||||||
@@ -581,7 +578,7 @@ export function SearchOverlay({
|
|||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
leadingVisual={<SearchIcon />}
|
leadingVisual={<SearchIcon />}
|
||||||
aria-labelledby={overlayHeadingId}
|
aria-labelledby={overlayHeadingId}
|
||||||
placeholder={t('search.input.placeholder')}
|
placeholder={t('search.input.placeholder_no_icon')}
|
||||||
trailingAction={
|
trailingAction={
|
||||||
<Stack
|
<Stack
|
||||||
justify="center"
|
justify="center"
|
||||||
@@ -697,6 +694,7 @@ function renderSearchGroups(
|
|||||||
|
|
||||||
const askAIGroupHeading = (
|
const askAIGroupHeading = (
|
||||||
<ActionList.GroupHeading
|
<ActionList.GroupHeading
|
||||||
|
key="ai-heading"
|
||||||
as="h3"
|
as="h3"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
aria-label={t('search.overlay.ai_suggestions_list_aria_label')}
|
aria-label={t('search.overlay.ai_suggestions_list_aria_label')}
|
||||||
@@ -732,12 +730,13 @@ function renderSearchGroups(
|
|||||||
let isInAskAIStateButNoAnswer = isInAskAIState && askAIState.aiCouldNotAnswer
|
let isInAskAIStateButNoAnswer = isInAskAIState && askAIState.aiCouldNotAnswer
|
||||||
|
|
||||||
if (isInAskAIStateButNoAnswer) {
|
if (isInAskAIStateButNoAnswer) {
|
||||||
groups.push(<ActionList.Divider key="general-divider" />)
|
groups.push(<ActionList.Divider key="no-answer-divider" />)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchLoading) {
|
if (searchLoading) {
|
||||||
groups.push(
|
groups.push(
|
||||||
<Box
|
<Box
|
||||||
|
key="loading"
|
||||||
role="status"
|
role="status"
|
||||||
className={styles.loadingContainer}
|
className={styles.loadingContainer}
|
||||||
sx={{
|
sx={{
|
||||||
@@ -831,13 +830,13 @@ function renderSearchGroups(
|
|||||||
(option) => !option.isViewAllResults && !option.isNoResultsFound,
|
(option) => !option.isViewAllResults && !option.isNoResultsFound,
|
||||||
).length)
|
).length)
|
||||||
) {
|
) {
|
||||||
groups.push(<ActionList.Divider key="general-divider" />)
|
groups.push(<ActionList.Divider key="bottom-divider" />)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aiOptionsWithUserInput.length && !isInAskAIState) {
|
if (aiOptionsWithUserInput.length && !isInAskAIState) {
|
||||||
groups.push(
|
groups.push(
|
||||||
<ActionList.Group key="ai" data-testid="ai-autocomplete-suggestions">
|
<ActionList.Group key="ai-suggestions" data-testid="ai-autocomplete-suggestions">
|
||||||
<ActionList.GroupHeading
|
<ActionList.GroupHeading
|
||||||
as="h3"
|
as="h3"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
|||||||
Reference in New Issue
Block a user