AI Search feedback fixes round 3 (#54669)
This commit is contained in:
@@ -26,7 +26,9 @@ release_notes:
|
||||
search:
|
||||
input:
|
||||
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:
|
||||
input_aria_label: Search or ask Copilot
|
||||
suggestions_list_aria_label: Search suggestions
|
||||
@@ -38,7 +40,7 @@ search:
|
||||
beta_tag: Beta
|
||||
return_to_search: Return to search
|
||||
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
|
||||
ai:
|
||||
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
||||
|
||||
@@ -26,7 +26,9 @@ release_notes:
|
||||
search:
|
||||
input:
|
||||
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:
|
||||
input_aria_label: Search or ask Copilot
|
||||
suggestions_list_aria_label: Search suggestions
|
||||
@@ -38,7 +40,7 @@ search:
|
||||
beta_tag: Beta
|
||||
return_to_search: Return to search
|
||||
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
|
||||
ai:
|
||||
disclaimer: Copilot uses AI. Check for mistakes by reviewing the links in the response.
|
||||
|
||||
@@ -7,6 +7,7 @@ export type MarkdownContentPropsT = {
|
||||
children: string
|
||||
className?: string
|
||||
openLinksInNewTab?: boolean
|
||||
includeQueryParams?: boolean
|
||||
eventGroupKey?: string
|
||||
eventGroupId?: string
|
||||
as?: keyof JSX.IntrinsicElements
|
||||
@@ -20,16 +21,48 @@ export const UnrenderedMarkdownContent = ({
|
||||
children,
|
||||
className,
|
||||
openLinksInNewTab = true,
|
||||
includeQueryParams = true,
|
||||
eventGroupKey = '',
|
||||
eventGroupId = '',
|
||||
...restProps
|
||||
}: MarkdownContentPropsT) => {
|
||||
// Overrides for ReactMarkdown components
|
||||
const components = {} as Components
|
||||
if (openLinksInNewTab) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
components.a = ({ node, ...props }) => (
|
||||
<a {...props} target="_blank" data-group-key={eventGroupKey} data-group-id={eventGroupId}>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
components.a = ({ node, ...props }) => {
|
||||
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}
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ type UseCombinedSearchReturn = {
|
||||
clearAutocompleteResults: () => void
|
||||
}
|
||||
|
||||
const DEBOUNCE_TIME = 300 // In milliseconds
|
||||
const DEBOUNCE_TIME = 1 // In milliseconds
|
||||
|
||||
// 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
|
||||
@@ -65,7 +65,7 @@ export function useCombinedSearchResults({
|
||||
useEffect(() => {
|
||||
debouncedFetchRef.current = debounce((value: string) => {
|
||||
fetchAutocompleteResults(value)
|
||||
}, DEBOUNCE_TIME) // 300ms debounce
|
||||
}, DEBOUNCE_TIME) // 1ms debounce
|
||||
|
||||
return () => {
|
||||
debouncedFetchRef.current?.cancel()
|
||||
|
||||
@@ -223,7 +223,7 @@ export function AskAIResults({
|
||||
</div>
|
||||
) : (
|
||||
<article aria-busy={responseLoading} aria-live="polite">
|
||||
{!aiCouldNotAnswer && message === '' ? (
|
||||
{!aiCouldNotAnswer && message !== '' ? (
|
||||
<span ref={disclaimerRef} className={styles.disclaimerText}>
|
||||
{t('search.ai.disclaimer')}
|
||||
</span>
|
||||
|
||||
@@ -117,6 +117,34 @@
|
||||
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 {
|
||||
display: flex;
|
||||
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 (
|
||||
<>
|
||||
{/* We don't want to show the input when overlay is open */}
|
||||
@@ -78,8 +90,8 @@ export function SearchBarButton({ isSearchOpen, setIsSearchOpen }: Props) {
|
||||
urlSearchInputQuery
|
||||
) : (
|
||||
<>
|
||||
{t('search.input.placeholder')}
|
||||
<CopilotIcon aria-hidden className="mr-1 ml-1" />
|
||||
<span className={styles.placeholderText}>{placeHolderElements}</span>
|
||||
<span className={styles.placeholderShortcutContainer}>{shortcutElements}</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
|
||||
@@ -133,10 +133,7 @@ export function SearchOverlay({
|
||||
|
||||
if (generalSearchResults.length > 0) {
|
||||
generalOptionsWithViewStatus.push({
|
||||
title: t('search.overlay.view_all_search_results').replace(
|
||||
'{{length}}',
|
||||
totalGeneralSearchResults.toLocaleString('en-US'),
|
||||
),
|
||||
title: t('search.overlay.view_all_search_results'),
|
||||
isViewAllResults: true,
|
||||
} as any)
|
||||
} else if (urlSearchInputQuery.trim() !== '' && !searchLoading) {
|
||||
@@ -468,7 +465,7 @@ export function SearchOverlay({
|
||||
{/* Always show the AI Search UI error message when it is needed */}
|
||||
{aiSearchError && (
|
||||
<>
|
||||
<ActionList.Divider key="general-divider" />
|
||||
<ActionList.Divider key="error-top-divider" />
|
||||
<ActionList.GroupHeading
|
||||
as="h3"
|
||||
tabIndex={-1}
|
||||
@@ -492,7 +489,7 @@ export function SearchOverlay({
|
||||
role="alert"
|
||||
/>
|
||||
</Box>
|
||||
<ActionList.Divider key="general-divider" />
|
||||
<ActionList.Divider key="error-bottom-divider" />
|
||||
</>
|
||||
)}
|
||||
{/* Only show the autocomplete search UI error message in Dev */}
|
||||
@@ -581,7 +578,7 @@ export function SearchOverlay({
|
||||
onKeyDown={handleKeyDown}
|
||||
leadingVisual={<SearchIcon />}
|
||||
aria-labelledby={overlayHeadingId}
|
||||
placeholder={t('search.input.placeholder')}
|
||||
placeholder={t('search.input.placeholder_no_icon')}
|
||||
trailingAction={
|
||||
<Stack
|
||||
justify="center"
|
||||
@@ -697,6 +694,7 @@ function renderSearchGroups(
|
||||
|
||||
const askAIGroupHeading = (
|
||||
<ActionList.GroupHeading
|
||||
key="ai-heading"
|
||||
as="h3"
|
||||
tabIndex={-1}
|
||||
aria-label={t('search.overlay.ai_suggestions_list_aria_label')}
|
||||
@@ -732,12 +730,13 @@ function renderSearchGroups(
|
||||
let isInAskAIStateButNoAnswer = isInAskAIState && askAIState.aiCouldNotAnswer
|
||||
|
||||
if (isInAskAIStateButNoAnswer) {
|
||||
groups.push(<ActionList.Divider key="general-divider" />)
|
||||
groups.push(<ActionList.Divider key="no-answer-divider" />)
|
||||
}
|
||||
|
||||
if (searchLoading) {
|
||||
groups.push(
|
||||
<Box
|
||||
key="loading"
|
||||
role="status"
|
||||
className={styles.loadingContainer}
|
||||
sx={{
|
||||
@@ -831,13 +830,13 @@ function renderSearchGroups(
|
||||
(option) => !option.isViewAllResults && !option.isNoResultsFound,
|
||||
).length)
|
||||
) {
|
||||
groups.push(<ActionList.Divider key="general-divider" />)
|
||||
groups.push(<ActionList.Divider key="bottom-divider" />)
|
||||
}
|
||||
}
|
||||
|
||||
if (aiOptionsWithUserInput.length && !isInAskAIState) {
|
||||
groups.push(
|
||||
<ActionList.Group key="ai" data-testid="ai-autocomplete-suggestions">
|
||||
<ActionList.Group key="ai-suggestions" data-testid="ai-autocomplete-suggestions">
|
||||
<ActionList.GroupHeading
|
||||
as="h3"
|
||||
tabIndex={-1}
|
||||
|
||||
Reference in New Issue
Block a user