• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yext / search-ui-react / 17986846418

24 Sep 2025 07:05PM UTC coverage: 87.704% (-0.6%) from 88.287%
17986846418

Pull #508

github

web-flow
Merge d9b1f2121 into f4c07d723
Pull Request #508: ksearch: upgrade to Events API

817 of 1029 branches covered (79.4%)

Branch coverage included in aggregate %.

40 of 67 new or added lines in 8 files covered. (59.7%)

3 existing lines in 3 files now uncovered.

2086 of 2281 relevant lines covered (91.45%)

134.74 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.0
/src/components/sections/SectionHeader.tsx
1
import { useTranslation } from 'react-i18next';
6✔
2
import { AppliedFiltersCssClasses } from '../AppliedFilters';
3
import { AppliedFiltersDisplay } from '../AppliedFiltersDisplay';
6✔
4
import { CollectionIcon } from '../../icons/CollectionIcon';
6✔
5
import { AppliedQueryFilter, useSearchState } from '@yext/search-headless-react';
6✔
6
import classNames from 'classnames';
6✔
7
import { useAnalytics } from '../../hooks';
6✔
8
import { VerticalLink } from '../../models';
9
import React, { useCallback } from 'react';
6✔
10

11
const FALLBACK_CSS_CLASSES: SectionHeaderCssClasses = {};
71✔
12

13
/**
14
 * The CSS class interface used for the SectionHeader component.
15
 *
16
 * @public
17
 */
18
export interface SectionHeaderCssClasses extends AppliedFiltersCssClasses {
19
  sectionHeaderContainer?: string,
20
  sectionHeaderIconContainer?: string,
21
  sectionHeaderLabel?: string,
22
  viewMoreContainer?: string,
23
  viewMoreLink?: string
24
}
25

26
export const builtInCssClasses: Readonly<SectionHeaderCssClasses> = {
71✔
27
  sectionHeaderContainer: 'flex items-center w-full pl-1 mb-4',
28
  sectionHeaderIconContainer: 'w-5 h-5',
29
  sectionHeaderLabel: 'font-bold text-neutral-dark text-base pl-3',
30
  viewMoreContainer: 'flex justify-end flex-grow ml-auto font-medium text-neutral-dark',
31
  viewMoreLink: 'text-primary pr-1 pl-3',
32
  appliedFiltersContainer: 'ml-3 flex flex-wrap',
33
  nlpFilter: 'border border-gray-200 rounded-3xl px-3 py-1.5 text-sm font-medium text-neutral-dark mr-2',
34
  removableFilter: 'flex items-center border border-gray-200 rounded-3xl px-3 py-1.5 text-sm font-medium text-neutral-dark mr-2'
35
};
36

37
/**
38
 * The props for a {@link SectionHeader}.
39
 */
40
export interface SectionHeaderProps {
41
  /** The display label for the section header. */
42
  label: string,
43
  /** An array of AppliedQueryFilters which are displayed in the section header. */
44
  appliedQueryFilters?: AppliedQueryFilter[],
45
  /** CSS classes for customizing the component styling. */
46
  cssClasses?: SectionHeaderCssClasses,
47
  /** The verticalKey associated with the section. */
48
  verticalKey: string,
49
  /** Display a button to view all results for that section, if true. */
50
  viewAllButton?: boolean,
51
  /** A function which returns the viewAll link based on the vertical and query. */
52
  getViewAllUrl?: (data: VerticalLink) => string
53
}
54

55
/**
56
 * The header of a section which includes an icon, the section title, applied query filters, and optionally
57
 * a view all button.
58
 *
59
 * @param props - {@link SectionHeaderProps}
60
 * @returns A React element for a Section Header
61
 */
62
export function SectionHeader(props: SectionHeaderProps): JSX.Element {
6✔
63
  const { t } = useTranslation();
16✔
64
  const {
65
    label,
66
    verticalKey,
67
    viewAllButton = false,
10✔
68
    appliedQueryFilters,
69
    cssClasses = FALLBACK_CSS_CLASSES,
×
70
    getViewAllUrl
71
  } = props;
16✔
72
  const latestQuery = useSearchState(state => state.query.mostRecentSearch);
16✔
73
  const nlpFilterDisplayNames = appliedQueryFilters?.map(f => f.displayValue);
16✔
74

75
  const analytics = useAnalytics();
16✔
76
  const queryId = useSearchState(state => state.query.queryId);
16✔
77
  const searchId = useSearchState(state => state.meta.uuid);
16✔
78
  const locale = useSearchState(state => state.meta.locale);
16✔
79
  const experienceKey = useSearchState(state => state.meta.experienceKey);
16✔
80

81
  const isLoading = useSearchState(state => state.searchStatus.isLoading);
16✔
82
  cssClasses.appliedFiltersContainer = classNames(cssClasses.appliedFiltersContainer, {
16✔
83
    [cssClasses.appliedFiltersLoading ?? '']: isLoading
32✔
84
  });
85

86
  const href = getViewAllUrl
16✔
87
    ? getViewAllUrl({ verticalKey, query: latestQuery })
88
    : `/${verticalKey}?query=${latestQuery}`;
89

90
  const handleClickViewAllButton = useCallback(() => {
16✔
91
    if (!analytics) {
×
92
      return;
×
93
    }
94
    if (!queryId) {
×
95
      console.error('Unable to report a vertical view all event. Missing field: queryId.');
×
96
      return;
×
97
    }
NEW
98
    if (!searchId) {
×
NEW
99
      console.error('Unable to report a vertical view all event. Missing field: searchId.');
×
NEW
100
      return;
×
101
    }
NEW
102
    if (!experienceKey) {
×
NEW
103
      console.error('Unable to report a vertical view all event. Missing field: experienceKey.');
×
NEW
104
      return;
×
105
    }
UNCOV
106
    analytics?.report({
×
107
      action: 'VERTICAL_VIEW_ALL',
108
      locale,
109
      searchId,
110
      queryId,
111
      verticalKey,
112
      experienceKey,
113
    });
114
  }, [analytics, queryId, verticalKey]);
115

116
  return (
16✔
117
    <div className={cssClasses.sectionHeaderContainer}>
118
      <div className={cssClasses.sectionHeaderIconContainer}>
119
        <CollectionIcon></CollectionIcon>
120
      </div>
121
      <h2 className={cssClasses.sectionHeaderLabel}>{label}</h2>
122
      {appliedQueryFilters &&
24✔
123
        <AppliedFiltersDisplay nlpFilterDisplayNames={nlpFilterDisplayNames} cssClasses={cssClasses} />
124
      }
125
      {viewAllButton &&
22✔
126
        <div className={cssClasses.viewMoreContainer}>
127
          <a className={cssClasses.viewMoreLink} href={href} onClick={handleClickViewAllButton}>
128
            {t('viewAll')}
129
          </a>
130
        </div>}
131
    </div>
132
  );
133
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc