Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support clickable citation card with link #444

Merged
merged 4 commits into from
Jun 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/search-ui-react.citationprops.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ interface CitationProps

| Property | Modifiers | Type | Description |
| --- | --- | --- | --- |
| [citation](./search-ui-react.citationprops.citation.md) | | string | |
| [cssClasses](./search-ui-react.citationprops.cssclasses.md) | | [GenerativeDirectAnswerCssClasses](./search-ui-react.generativedirectanswercssclasses.md) | |
| [searchResults](./search-ui-react.citationprops.searchresults.md) | | Result\[\] | |
| [searchResult](./search-ui-react.citationprops.searchresult.md) | | Result | |

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [CitationProps](./search-ui-react.citationprops.md) &gt; [citation](./search-ui-react.citationprops.citation.md)
[Home](./index.md) &gt; [@yext/search-ui-react](./search-ui-react.md) &gt; [CitationProps](./search-ui-react.citationprops.md) &gt; [searchResult](./search-ui-react.citationprops.searchresult.md)

## CitationProps.citation property
## CitationProps.searchResult property

**Signature:**

```typescript
citation: string;
searchResult: Result;
```
11 changes: 0 additions & 11 deletions docs/search-ui-react.citationprops.searchresults.md

This file was deleted.

4 changes: 2 additions & 2 deletions docs/search-ui-react.generativedirectanswer.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ Displays the AI generated answer of a generative direct answer.
**Signature:**

```typescript
declare function GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard }: GenerativeDirectAnswerProps): JSX.Element | null;
declare function GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard, }: GenerativeDirectAnswerProps): JSX.Element | null;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| { customCssClasses, answerHeader, citationsHeader, CitationCard } | [GenerativeDirectAnswerProps](./search-ui-react.generativedirectanswerprops.md) | |
| { customCssClasses, answerHeader, citationsHeader, CitationCard, } | [GenerativeDirectAnswerProps](./search-ui-react.generativedirectanswerprops.md) | |

**Returns:**

Expand Down
2 changes: 1 addition & 1 deletion docs/search-ui-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
| [Facets(props)](./search-ui-react.facets.md) | A component that displays all facets applicable to the current vertical search. |
| [FilterDivider({ className })](./search-ui-react.filterdivider.md) | A divider component used to separate NumericalFacets, HierarchicalFacets, StandardFacets, and StaticFilters. |
| [FilterSearch({ searchFields, label, placeholder, searchOnSelect, onSelect, onDropdownInputChange, afterDropdownInputFocus, sectioned, customCssClasses })](./search-ui-react.filtersearch.md) | A component which allows a user to search for filters associated with specific entities and fields. |
| [GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard })](./search-ui-react.generativedirectanswer.md) | Displays the AI generated answer of a generative direct answer. |
| [GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard, })](./search-ui-react.generativedirectanswer.md) | Displays the AI generated answer of a generative direct answer. |
| [Geolocation\_2({ geolocationOptions, radius, label, GeolocationIcon, handleClick, customCssClasses, })](./search-ui-react.geolocation_2.md) | A React Component which collects location information to create a location filter and perform a new search. |
| [getSearchIntents(searchActions)](./search-ui-react.getsearchintents.md) | Get search intents of the current query stored in headless using autocomplete request. |
| [getUserLocation(geolocationOptions)](./search-ui-react.getuserlocation.md) | Retrieves user's location using navigator.geolocation API. |
Expand Down
6 changes: 2 additions & 4 deletions etc/search-ui-react.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,12 +138,10 @@ export interface CardProps<T = DefaultRawDataType> {

// @public
export interface CitationProps {
// (undocumented)
citation: string;
// (undocumented)
cssClasses: GenerativeDirectAnswerCssClasses;
// (undocumented)
searchResults: Result[];
searchResult: Result;
}

// @public
Expand Down Expand Up @@ -323,7 +321,7 @@ export interface FilterSearchProps {
export type FocusedItemData = Record<string, unknown>;

// @public
export function GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard }: GenerativeDirectAnswerProps): JSX.Element | null;
export function GenerativeDirectAnswer({ customCssClasses, answerHeader, citationsHeader, CitationCard, }: GenerativeDirectAnswerProps): JSX.Element | null;

// @public
export interface GenerativeDirectAnswerCssClasses {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yext/search-ui-react",
"version": "1.7.0-beta.3",
"version": "1.7.0-beta.4",
"description": "A library of React Components for powering Yext Search integrations",
"author": "slapshot@yext.com",
"license": "BSD-3-Clause",
Expand Down
55 changes: 35 additions & 20 deletions src/components/GenerativeDirectAnswer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const builtInCssClasses: Readonly<GenerativeDirectAnswerCssClasses> = {
answerText: 'mt-4',
divider: 'border-b border-gray-200 w-full pb-6 mb-6',
citationsContainer: 'mt-4 flex overflow-x-auto gap-4',
citation: 'p-4 border border-gray-200 rounded-lg shadow-sm bg-slate-100 flex flex-col grow-0 shrink-0 basis-64 text-sm text-neutral overflow-x-auto',
citation: 'p-4 border border-gray-200 rounded-lg shadow-sm bg-slate-100 flex flex-col grow-0 shrink-0 basis-64 text-sm text-neutral overflow-x-auto cursor-pointer hover:border-indigo-500',
citationTitle: 'font-bold',
citationSnippet: 'line-clamp-2 text-ellipsis break-words'
};
Expand Down Expand Up @@ -65,7 +65,7 @@ export function GenerativeDirectAnswer({
customCssClasses,
answerHeader,
citationsHeader,
CitationCard
CitationCard,
}: GenerativeDirectAnswerProps): JSX.Element | null {
const cssClasses = useComposedCssClasses(builtInCssClasses, customCssClasses);

Expand Down Expand Up @@ -100,7 +100,13 @@ export function GenerativeDirectAnswer({
<div className={cssClasses.container}>
<Answer gdaResponse={gdaResponse} cssClasses={cssClasses} answerHeader={answerHeader}/>
<div className={cssClasses.divider} />
<Citations gdaResponse={gdaResponse} cssClasses={cssClasses} citationsHeader={citationsHeader} searchResults={searchResults} CitationCard={CitationCard}/>
<Citations
gdaResponse={gdaResponse}
cssClasses={cssClasses}
searchResults={searchResults}
citationsHeader={citationsHeader}
CitationCard={CitationCard}
/>
</div>
);
}
Expand Down Expand Up @@ -131,8 +137,8 @@ function Answer(props: AnswerProps) {
interface CitationsProps {
gdaResponse: GenerativeDirectAnswerResponse,
cssClasses: GenerativeDirectAnswerCssClasses,
citationsHeader?: string | JSX.Element,
searchResults: Result[],
citationsHeader?: string | JSX.Element,
CitationCard?: (props: CitationProps) => JSX.Element | null
}

Expand All @@ -143,20 +149,34 @@ function Citations(props: CitationsProps) {
const {
gdaResponse,
cssClasses,
citationsHeader = `Sources (${gdaResponse.citations.length})`,
searchResults,
citationsHeader = `Sources (${gdaResponse.citations.length})`,
CitationCard = Citation
} = props;
if (!gdaResponse.citations.length) {
return null;
}
const citationCards: JSX.Element[] = [];
gdaResponse.citations.forEach(
citation => {
const result: Result | undefined = searchResults.find(r => r.rawData.uid === citation);
if (result) {
citationCards.push(
<CitationCard
key={citation}
searchResult={result}
cssClasses={cssClasses}
/>
)
}
});

return <>
<div className={cssClasses.header}>
{citationsHeader}
</div>
<div className={cssClasses.citationsContainer}>
{gdaResponse.citations.map(
citation => <CitationCard key={citation} searchResults={searchResults} citation={citation} cssClasses={cssClasses} />)}
{citationCards}
</div>
</>;
}
Expand All @@ -167,24 +187,19 @@ function Citations(props: CitationsProps) {
* @public
*/
export interface CitationProps {
searchResults: Result[],
citation: string,
searchResult: Result,
cssClasses: GenerativeDirectAnswerCssClasses
}

function Citation(props: CitationProps) {
const {
searchResults,
citation,
searchResult,
cssClasses
} = props;
const rawResult: Result | undefined = searchResults.find(r => r.rawData.uid === citation);
if (!rawResult) {
return null;
}

return <div className={cssClasses.citation}>
<div className={cssClasses.citationTitle}>{rawResult.rawData.name}</div>
<div className={cssClasses.citationSnippet}>{rawResult.rawData.description}</div>
</div>;
return (
<a className={cssClasses.citation} href={typeof searchResult.rawData.link === 'string' ? searchResult.rawData.link : undefined}>
<div className={cssClasses.citationTitle}>{searchResult.rawData.name}</div>
<div className={cssClasses.citationSnippet}>{searchResult.rawData.description}</div>
</a>
);
}
25 changes: 11 additions & 14 deletions test-site/src/pages/UniversalPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,14 @@ const customSearchBarCss = {

function CustomCitationCard(props: CitationProps): JSX.Element | null {
const {
searchResults,
citation,
cssClasses
searchResult,
cssClasses,
} = props;
const rawResult: Result | undefined = searchResults.find((r: Result) => r.rawData.uid === citation);

if (!rawResult) {
return null;
}

return <div key={citation} className={cssClasses.citation}>
{typeof rawResult.rawData.id === 'string' && <div className={cssClasses.citationTitle}>{rawResult.rawData.id}</div>}
{typeof rawResult.rawData.type === 'string' && <div className={cssClasses.citationSnippet}>{rawResult.rawData.type}</div>}
</div>;
const citationLink = typeof searchResult.rawData.link === 'string' ? searchResult.rawData.link : undefined;
return <a className={cssClasses.citation} href={citationLink}>
{typeof searchResult.rawData.id === 'string' && <div className={cssClasses.citationTitle}>{searchResult.rawData.id}</div>}
{typeof searchResult.rawData.s_snippet === 'string' && <div className={cssClasses.citationSnippet}>{searchResult.rawData.s_snippet}</div>}
</a>;
}

export default function UniversalPage(): JSX.Element {
Expand All @@ -92,7 +86,10 @@ export default function UniversalPage(): JSX.Element {
customCssClasses={customSearchBarCss}
/>
<SpellCheck />
<GenerativeDirectAnswer answerHeader='A custom answer header' CitationCard={CustomCitationCard}/>
<GenerativeDirectAnswer
answerHeader='A custom answer header'
CitationCard={CustomCitationCard}
/>
<DirectAnswer />
<ResultsCount />
<UniversalResults
Expand Down
Loading