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

fix: fixed search bar layout and ux: can now click to preview search results #27015

Merged
merged 5 commits into from
Dec 19, 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
Binary file modified frontend/__snapshots__/components-command-bar--search--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/lemon-ui-lemon-input--search--dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified frontend/__snapshots__/lemon-ui-lemon-input--search--light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/lib/components/CommandBar/CommandBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const CommandBarOverlay = forwardRef<HTMLDivElement, CommandBarOverlayProps>(fun
data-attr="command-bar"
className={`w-full ${
barStatus === BarStatus.SHOW_SEARCH && 'h-full'
} bg-bg-3000 rounded overflow-hidden border border-border-bold`}
} w-full bg-bg-3000 rounded overflow-hidden border border-border-bold`}
ref={ref}
>
{children}
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/lib/components/CommandBar/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ export const SearchBar = (): JSX.Element => {
const inputRef = useRef<HTMLInputElement>(null)

return (
<div className="flex w-full h-full">
<div className="grid grid-cols-[8.5rem_1fr] lg:grid-cols-[12.5rem_1fr] h-full">
<SearchTabs inputRef={inputRef} />
<div className="grow flex flex-col overscroll-contain overflow-hidden">
{/* 49px = height of search input, 40rem = height of search results */}
<div className="grid grid-rows-[49px_calc(40rem-49px)] overflow-hidden overscroll-contain">
<SearchInput ref={inputRef} />
<SearchResults />
</div>
Expand Down
52 changes: 31 additions & 21 deletions frontend/src/lib/components/CommandBar/SearchResult.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { LemonSkeleton } from '@posthog/lemon-ui'
import clsx from 'clsx'
import { useActions, useValues } from 'kea'
import { TAILWIND_BREAKPOINTS } from 'lib/constants'
import { useWindowSize } from 'lib/hooks/useWindowSize'
import { capitalizeFirstLetter } from 'lib/utils'
import { useLayoutEffect, useRef } from 'react'
import { useSummarizeInsight } from 'scenes/insights/summarizeInsight'
Expand All @@ -22,10 +24,12 @@ type SearchResultProps = {

export const SearchResult = ({ result, resultIndex, focused }: SearchResultProps): JSX.Element => {
const { aggregationLabel } = useValues(searchBarLogic)
const { openResult } = useActions(searchBarLogic)
const { setActiveResultIndex, openResult } = useActions(searchBarLogic)

const ref = useRef<HTMLDivElement | null>(null)

const { width } = useWindowSize()

useLayoutEffect(() => {
if (focused) {
// :HACKY: This uses the non-standard scrollIntoViewIfNeeded api
Expand All @@ -40,27 +44,33 @@ export const SearchResult = ({ result, resultIndex, focused }: SearchResultProps
}, [focused])

return (
<div
className={clsx(
'w-full px-2 hover:bg-bg-3000 border-l-4 border-r border-b cursor-pointer',
focused ? 'bg-bg-3000 border-l-primary-3000' : 'bg-bg-light'
)}
onClick={() => {
openResult(resultIndex)
}}
ref={ref}
>
<div className="px-2 py-3 w-full space-y-0.5 flex flex-col items-start">
<span className="text-muted-3000 text-xs">
{result.type !== 'group'
? tabToName[result.type]
: `${capitalizeFirstLetter(aggregationLabel(result.extra_fields.group_type_index).plural)}`}
</span>
<span className="text-text-3000 font-bold">
<ResultName result={result} />
</span>
<>
<div
className={clsx(
'w-full px-2 hover:bg-bg-3000 border-l-4 border-b cursor-pointer',
focused ? 'bg-bg-3000 border-l-primary-3000' : 'bg-bg-light'
)}
onClick={() => {
if (width && width <= TAILWIND_BREAKPOINTS.md) {
openResult(resultIndex)
} else {
setActiveResultIndex(resultIndex)
}
}}
ref={ref}
>
<div className="px-2 py-3 w-full space-y-0.5 flex flex-col items-start">
<span className="text-muted-3000 text-xs">
{result.type !== 'group'
? tabToName[result.type]
: `${capitalizeFirstLetter(aggregationLabel(result.extra_fields.group_type_index).plural)}`}
</span>
<span className="text-text-3000 font-bold">
<ResultName result={result} />
</span>
</div>
</div>
</div>
</>
)
}

Expand Down
52 changes: 40 additions & 12 deletions frontend/src/lib/components/CommandBar/SearchResultPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useValues } from 'kea'
import { useActions, useValues } from 'kea'
import { ResultDescription, ResultName } from 'lib/components/CommandBar/SearchResult'
import { LemonButton } from 'lib/lemon-ui/LemonButton'

import { KeyboardShortcut } from '~/layout/navigation-3000/components/KeyboardShortcut'

import { tabToName } from './constants'
import { searchBarLogic, urlForResult } from './searchBarLogic'

export const SearchResultPreview = (): JSX.Element | null => {
const { activeResultIndex, combinedSearchResults } = useValues(searchBarLogic)
const { openResult } = useActions(searchBarLogic)

if (!combinedSearchResults || combinedSearchResults.length === 0) {
return null
Expand All @@ -14,17 +18,41 @@ export const SearchResultPreview = (): JSX.Element | null => {
const result = combinedSearchResults[activeResultIndex]

return (
<div className="border bg-bg-light rounded p-6">
<div>{tabToName[result.type]}</div>
<div className="text-text-3000 font-bold text-lg">
<ResultName result={result} />
</div>
<span className="text-[var(--trace-3000)] text-xs">
{location.host}
<span className="text-muted-3000">{urlForResult(result)}</span>
</span>
<div className="mt-2 text-muted">
<ResultDescription result={result} />
<div className="border bg-bg-light rounded p-4 md:p-6">
<div className="space-y-4">
<div>
<div>{tabToName[result.type as keyof typeof tabToName]}</div>
<div className="text-text-3000 font-bold text-lg">
<ResultName result={result} />
</div>
<span className="text-[var(--trace-3000)] text-xs break-all">
{location.host}
<span className="text-muted-3000">{urlForResult(result)}</span>
</span>
<div className="mt-2 text-muted">
<ResultDescription result={result} />
</div>
</div>
<div className="grid grid-cols-[auto_1fr] items-center gap-2">
<LemonButton
type="secondary"
size="small"
onClick={() => {
openResult(activeResultIndex)
}}
tooltip={
<>
Open <KeyboardShortcut enter />
</>
}
aria-label="Open search result"
>
Open
</LemonButton>
<div>
<KeyboardShortcut enter /> Open
</div>
</div>
</div>
</div>
)
Expand Down
30 changes: 8 additions & 22 deletions frontend/src/lib/components/CommandBar/SearchResults.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import clsx from 'clsx'
import { useValues } from 'kea'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'

import { DetectiveHog } from '../hedgehogs'
import { searchBarLogic } from './searchBarLogic'
Expand All @@ -10,27 +8,17 @@ import { SearchResultPreview } from './SearchResultPreview'
export const SearchResults = (): JSX.Element => {
const { combinedSearchResults, combinedSearchLoading, activeResultIndex } = useValues(searchBarLogic)

const { ref, size } = useResizeBreakpoints({
0: 'small',
550: 'normal',
})

return (
<div className="SearchResults grow" ref={ref}>
<>
{!combinedSearchLoading && combinedSearchResults?.length === 0 ? (
<div className="w-full h-full flex flex-col items-center justify-center p-3">
<div className="w-full h-full flex flex-col items-center justify-center p-3 text-center">
<h3 className="mb-0 text-xl">No results</h3>
<p className="opacity-75 mb-0">This doesn't happen often, but we're stumped!</p>
<DetectiveHog height={150} width={150} />
</div>
) : (
<div className="overflow-hidden overscroll-contain flex h-full">
<div
className={clsx(
'border-r bg-bg-3000 overscroll-contain overflow-y-scroll grow-0 shrink-0 w-full',
size !== 'small' && 'max-w-80'
)}
>
<div className="md:grid md:grid-cols-[320px_1fr]">
<div className="border-r border-b md:border-b-0 bg-bg-3000 overscroll-contain overflow-y-auto">
{combinedSearchLoading && (
<>
<SearchResultSkeleton />
Expand All @@ -48,13 +36,11 @@ export const SearchResults = (): JSX.Element => {
/>
))}
</div>
{size !== 'small' ? (
<div className="p-2 grow">
<SearchResultPreview />
</div>
) : null}
<div className="p-2 grow hidden md:block overflow-auto">
<SearchResultPreview />
</div>
</div>
)}
</div>
</>
)
}
6 changes: 4 additions & 2 deletions frontend/src/lib/components/CommandBar/SearchTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ type SearchTabsProps = {
export const SearchTabs = ({ inputRef }: SearchTabsProps): JSX.Element | null => {
const { tabsGrouped } = useValues(searchBarLogic)
return (
<div className="flex flex-col border-r bg-bg-light min-w-30 w-1/3 max-w-50 flex-0 overflow-y-auto">
<div className="flex flex-col border-r bg-bg-light overflow-y-auto">
{Object.entries(tabsGrouped).map(([group, tabs]) => (
<div key={group} className={group !== 'all' ? 'pt-1.5' : ''}>
{group !== 'all' && (
<span className="ml-4 text-xxs text-muted uppercase">{groupToName[group]}</span>
<span className="ml-4 text-xxs text-muted uppercase">
{groupToName[group as keyof typeof groupToName]}
</span>
)}
{tabs.map((tab) => (
<SearchBarTab key={tab} tab={tab} inputRef={inputRef} />
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/lib/components/CommandBar/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
}
}

.SearchResults {
// offset container height by input
height: calc(100% - 2.875rem);
}

.CommandBar__overlay {
position: fixed;
top: 0;
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib/components/CommandBar/searchBarLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export const searchBarLogic = kea<searchBarLogicType>([
onArrowUp: (activeIndex: number, maxIndex: number) => ({ activeIndex, maxIndex }),
onArrowDown: (activeIndex: number, maxIndex: number) => ({ activeIndex, maxIndex }),
openResult: (index: number) => ({ index }),
setActiveResultIndex: (index: number) => ({ index }),
}),
loaders(({ values, actions }) => ({
rawSearchResponse: [
Expand Down Expand Up @@ -208,6 +209,7 @@ export const searchBarLogic = kea<searchBarLogicType>([
openResult: () => 0,
onArrowUp: (_, { activeIndex, maxIndex }) => (activeIndex > 0 ? activeIndex - 1 : maxIndex),
onArrowDown: (_, { activeIndex, maxIndex }) => (activeIndex < maxIndex ? activeIndex + 1 : 0),
setActiveResultIndex: (_, { index }) => index,
},
],
activeTab: [
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/lib/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,11 @@ export const SESSION_REPLAY_MINIMUM_DURATION_OPTIONS: LemonSelectOptions<number
]

export const UNSUBSCRIBE_SURVEY_ID = '018b6e13-590c-0000-decb-c727a2b3f462'

export const TAILWIND_BREAKPOINTS = {
sm: 526,
md: 768,
lg: 992,
xl: 1200,
'2xl': 1600,
}
6 changes: 6 additions & 0 deletions frontend/src/lib/lemon-ui/LemonInput/LemonInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@
&.LemonInput--type-search {
// NOTE Design: Search inputs are given a specific small width
max-width: 240px;
border-radius: 0;

// Add a focus ring to the element (not the input) when focused
&:has(:focus-visible) {
outline: -webkit-focus-ring-color auto 1px;
adamleithp marked this conversation as resolved.
Show resolved Hide resolved
}
}

&.LemonInput--type-number {
Expand Down
Loading