From 3b132490c9544b7b4e40e067f6f0be38003d8a0f Mon Sep 17 00:00:00 2001 From: Jackson Harper Date: Fri, 3 Mar 2023 10:21:06 +0800 Subject: [PATCH] Start adding a search modal thingy --- .../patterns/LibraryCards/SearchModal.tsx | 62 +++++++++ .../templates/homeFeed/HomeFeedContainer.tsx | 10 ++ .../templates/homeFeed/LibraryHeader.tsx | 126 +++++++++++++----- 3 files changed, 163 insertions(+), 35 deletions(-) create mode 100644 packages/web/components/patterns/LibraryCards/SearchModal.tsx diff --git a/packages/web/components/patterns/LibraryCards/SearchModal.tsx b/packages/web/components/patterns/LibraryCards/SearchModal.tsx new file mode 100644 index 000000000..167c2e10c --- /dev/null +++ b/packages/web/components/patterns/LibraryCards/SearchModal.tsx @@ -0,0 +1,62 @@ +import { ReactNode, useMemo, useRef, useState } from 'react' +import { StyledText } from '../../elements/StyledText' +import { Box, HStack, SpanBox, VStack } from '../../elements/LayoutPrimitives' +import { Dropdown, DropdownOption } from '../../elements/DropdownElements' +import { Button, IconButton } from '../../elements/Button' +import { + CaretRight, + Circle, + DotsThree, + MagnifyingGlass, + Plus, + X, +} from 'phosphor-react' +import { useGetSubscriptionsQuery } from '../../../lib/networking/queries/useGetSubscriptionsQuery' +import { useGetLabelsQuery } from '../../../lib/networking/queries/useGetLabelsQuery' +import { Label } from '../../../lib/networking/fragments/labelFragment' +import { + ModalContent, + ModalOverlay, + ModalRoot, +} from '../../elements/ModalPrimitives' +import { theme } from '../../tokens/stitches.config' +import { FormInput } from '../../elements/FormElements' +import { SearchBox } from '../../templates/homeFeed/LibraryHeader' + +type SearchModalProps = { + searchTerm: string | undefined + applySearchQuery: (searchTerm: string) => void + + onOpenChange: (open: boolean) => void +} + +export function SearchModal(props: SearchModalProps): JSX.Element { + return ( + + e.preventDefault()} /> + { + // remove focus from modal + ;(document.activeElement as HTMLElement).blur() + }} + > + + + props.onOpenChange(false)} + /> + + + + + ) +} diff --git a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx index 4c732b4e1..d34a4186e 100644 --- a/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx +++ b/packages/web/components/templates/homeFeed/HomeFeedContainer.tsx @@ -52,6 +52,7 @@ import { uploadFileRequestMutation } from '../../../lib/networking/mutations/upl import { setLabelsMutation } from '../../../lib/networking/mutations/setLabelsMutation' import { LibraryHeader } from './LibraryHeader' import { LibraryFilterMenu } from './LibraryFilterMenu' +import { SearchModal } from '../../patterns/LibraryCards/SearchModal' export type LayoutType = 'LIST_LAYOUT' | 'GRID_LAYOUT' @@ -733,6 +734,7 @@ function HomeFeedGrid(props: HomeFeedContentProps): JSX.Element { } const [showFilterMenu, setShowFilterMenu] = useState(false) + const [showSearchModal, setShowSearchModal] = useState(false) return ( @@ -746,6 +748,7 @@ function HomeFeedGrid(props: HomeFeedContentProps): JSX.Element { }} showFilterMenu={showFilterMenu} setShowFilterMenu={setShowFilterMenu} + setShowSearchModal={setShowSearchModal} /> )} + {showSearchModal && ( + setShowSearchModal(open)} + /> + )} ) diff --git a/packages/web/components/templates/homeFeed/LibraryHeader.tsx b/packages/web/components/templates/homeFeed/LibraryHeader.tsx index d91ad8d64..4dfc3fbfa 100644 --- a/packages/web/components/templates/homeFeed/LibraryHeader.tsx +++ b/packages/web/components/templates/homeFeed/LibraryHeader.tsx @@ -12,6 +12,7 @@ import { LayoutType } from './HomeFeedContainer' import { PrimaryDropdown } from '../PrimaryDropdown' import { LogoBox } from '../../elements/LogoBox' import { OmnivoreSmallLogo } from '../../elements/images/OmnivoreNameLogo' +import { SearchModal } from '../../patterns/LibraryCards/SearchModal' type LibraryHeaderProps = { layout: LayoutType @@ -22,9 +23,9 @@ type LibraryHeaderProps = { showFilterMenu: boolean setShowFilterMenu: (show: boolean) => void -} -const FOCUSED_BOXSHADOW = '0px 0px 2px 2px rgba(255, 234, 159, 0.56)' + setShowSearchModal: (show: boolean) => void +} const HEADER_HEIGHT = '105px' const MOBILE_HEIGHT = '48px' @@ -89,6 +90,7 @@ function LargeHeaderLayout(props: LibraryHeaderProps): JSX.Element { ) @@ -111,6 +113,7 @@ function SmallHeaderLayout(props: LibraryHeaderProps): JSX.Element { ) @@ -147,12 +150,15 @@ export function MenuHeaderButton(props: MenuHeaderButtonProps): JSX.Element { ) } -type SearchBoxProps = { +export type SearchBoxProps = { searchTerm: string | undefined applySearchQuery: (searchQuery: string) => void + + compact?: boolean + onClose?: () => void } -function SearchBox(props: SearchBoxProps): JSX.Element { +export function SearchBox(props: SearchBoxProps): JSX.Element { const inputRef = useRef(null) const [focused, setFocused] = useState(false) const [searchTerm, setSearchTerm] = useState(props.searchTerm ?? '') @@ -174,7 +180,7 @@ function SearchBox(props: SearchBoxProps): JSX.Element { mr: '15px', bg: '#F3F3F3', borderRadius: '6px', - boxShadow: focused ? FOCUSED_BOXSHADOW : 'unset', + border: focused ? '1px solid $omnivoreCtaYellow' : '1px solid #D9D9D9', }} > { inputRef.current?.focus() e.preventDefault() }} > @@ -201,6 +211,9 @@ function SearchBox(props: SearchBoxProps): JSX.Element { event.preventDefault() props.applySearchQuery(searchTerm || '') inputRef.current?.blur() + if (props.onClose) { + props.onClose() + } }} style={{ width: '100%' }} > @@ -221,7 +234,7 @@ function SearchBox(props: SearchBoxProps): JSX.Element { }} /> - {searchTerm && searchTerm.length > 0 ? ( + {searchTerm && searchTerm.length && props.compact && ( + )} + {focused || props.compact ? ( + // + + { + // In compact mode this closes the search, in fullscreen mode it clears the search + if (props.compact) { + props.onClose && props.onClose() + } else { + event.preventDefault() + setSearchTerm('') + props.applySearchQuery('') + inputRef.current?.blur() + } + }} + tabIndex={-1} + > + + + ) : ( - requestAnimationFrame(() => inputRef?.current?.focus()) - } + // onClick={() => + // requestAnimationFrame(() => inputRef?.current?.focus()) + // } // we can make it unreachable via keyboard as we have the same message for the SR label tabIndex={-1} > @@ -276,6 +346,7 @@ function SearchBox(props: SearchBoxProps): JSX.Element { type ControlButtonBoxProps = { layout: LayoutType updateLayout: (layout: LayoutType) => void + setShowSearchModal: (show: boolean) => void } function ControlButtonBox(props: ControlButtonBoxProps): JSX.Element { @@ -340,26 +411,11 @@ function ControlButtonBox(props: ControlButtonBoxProps): JSX.Element { }, }} > - {showInlineSearch && ( - setShowInlineSearch(false)} - > - {/* */} - - )}