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

feat: added no results placeholders for search areas #185

Merged
merged 1 commit into from
Aug 6, 2022
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
37 changes: 37 additions & 0 deletions apps/extension/src/components/no-results-placeholder/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react'
import { Text, Flex, Box } from 'ui/src/components/atoms'
import { MagnifyingGlassIcon } from '@radix-ui/react-icons'

interface IProps {
title?: string
subTitle?: string
}

const defaultProps = {
title: 'No results found',
subTitle: 'please refine search',
}

export const NoResultsPlaceholder: React.FC<IProps> = ({ title, subTitle }) => (
<Flex
direction="column"
align="center"
justify="center"
css={{
position: 'relative',
height: '100%',
}}
>
<Flex align="center" css={{ position: 'relative' }}>
<Text size="5" bold css={{ pr: '6px' }}>
{title}
</Text>
<Box css={{ transform: 'translateY(3px)' }}>
<MagnifyingGlassIcon />
</Box>
</Flex>
<Text css={{ pt: '$2' }}>{subTitle}</Text>
</Flex>
)

NoResultsPlaceholder.defaultProps = defaultProps
32 changes: 19 additions & 13 deletions apps/extension/src/components/token-selector/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useEventListener } from 'usehooks-ts'
import { CircleAvatar } from '@src/components/circle-avatar'
import { useKnownTokens } from '@src/hooks/react-query/queries/radixscan'
import { Box, Text, Flex } from 'ui/src/components/atoms'
import { NoResultsPlaceholder } from '@src/components/no-results-placeholder'
import Button from 'ui/src/components/button'
import { Dialog, DialogTrigger, DialogContent } from 'ui/src/components/dialog'
import { parseResourceIdentifier } from '@src/services/radix/serializer'
Expand Down Expand Up @@ -47,6 +48,15 @@ export const TokenSelector: React.FC<IProps> = ({ triggerType, token, tokens, on
filteredTokens: [],
})

const searchedTokens = state.filteredTokens.filter((_token: VisibleToken) => {
const search = state.search.toLowerCase()
return (
(search !== '' && _token.name?.toLowerCase().includes(search)) || _token.symbol?.toLowerCase().includes(search)
)
})

const hasSearchResults = searchedTokens?.length > 0

const handleCloseModal = () => {
setState(draft => {
draft.isModalOpen = false
Expand Down Expand Up @@ -210,21 +220,17 @@ export const TokenSelector: React.FC<IProps> = ({ triggerType, token, tokens, on
</Box>
</Box>
<Box css={{ height: '295px', position: 'relative' }}>
<ScrollArea>
<Box css={{ px: '$5', pb: '$5', pt: '$2' }}>
{state.filteredTokens
.filter((_token: VisibleToken) => {
const search = state.search.toLowerCase()
return (
(search !== '' && _token.name?.toLowerCase().includes(search)) ||
_token.symbol?.toLowerCase().includes(search)
)
})
.map(({ rri }: VisibleToken) => (
{hasSearchResults ? (
<ScrollArea>
<Box css={{ px: '$5', pb: '$5', pt: '$2' }}>
{searchedTokens.map(({ rri }: VisibleToken) => (
<TokenItem rri={rri} onClick={handleValueChange} />
))}
</Box>
</ScrollArea>
</Box>
</ScrollArea>
) : (
<NoResultsPlaceholder />
)}
</Box>
<Flex justify="end" gap="2" css={{ py: '$4', px: '$5', borderTop: '1px solid $borderPanel' }}>
<Button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { RowsIcon, MagnifyingGlassIcon } from '@radix-ui/react-icons'
import { Virtuoso } from 'react-virtuoso'
import { ScrollArea } from 'ui/src/components/scroll-area'
import { SearchBox } from '@src/components/search-box'
import { NoResultsPlaceholder } from '@src/components/no-results-placeholder'
import Button from 'ui/src/components/button'
import { SLIDE_PANEL_HEIGHT, SLIDE_PANEL_EXPAND_HEIGHT, SLIDE_PANEL_HEADER_HEIGHT } from '@src/config'
import { Box, Text, Flex } from 'ui/src/components/atoms'
Expand Down Expand Up @@ -103,33 +104,40 @@ const AllBalances: React.FC = () => {
const tokenSymbol = _token?.symbol?.toLowerCase() || ''
return tokenName?.includes(searchTerm) || tokenSymbol?.includes(searchTerm)
})
const hasSearchResults = searchedTokens?.length > 0

const list = hasLiquidBalances ? (
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={searchedTokens.length}
data={searchedTokens}
itemContent={(i, { rri, amount, symbol }) => (
<TokenRow
i={i}
key={rri}
rri={rri}
amount={amount}
staked={symbol === 'xrd' && staked ? staked : null}
symbol={symbol}
disableClick
/>
)}
/>
</ScrollArea>
) : (
let list = (
<Box css={{ p: '$5' }}>
<Text size="4">All accounts are empty.</Text>
</Box>
)

return <Box>{list}</Box>
if (hasLiquidBalances && hasSearchResults) {
list = (
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={searchedTokens.length}
data={searchedTokens}
itemContent={(i, { rri, amount, symbol }) => (
<TokenRow
i={i}
key={rri}
rri={rri}
amount={amount}
staked={symbol === 'xrd' && staked ? staked : null}
symbol={symbol}
disableClick
/>
)}
/>
</ScrollArea>
)
} else if (hasLiquidBalances) {
list = <NoResultsPlaceholder title="No tokens found" />
}

return list
}

const AccountBalances: React.FC = () => {
Expand Down Expand Up @@ -164,32 +172,39 @@ const AccountBalances: React.FC = () => {
const tokenSymbol = _token?.symbol?.toLowerCase() || ''
return tokenName?.includes(searchTerm) || tokenSymbol?.includes(searchTerm)
})
const hasSearchResults = searchedTokens?.length > 0

const list = hasLiquidBalances ? (
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={searchedTokens.length}
data={searchedTokens}
itemContent={(i, { rri, amount, symbol }) => (
<TokenRow
i={i}
key={rri}
rri={rri}
amount={amount || 0}
staked={symbol === 'xrd' && staked ? staked : null}
symbol={symbol}
loading={isLoading}
/>
)}
/>
</ScrollArea>
) : (
let list = (
<Box css={{ p: '$5' }}>
<Text size="4">Account has no token balances.</Text>
</Box>
)

if (hasLiquidBalances && hasSearchResults) {
list = (
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={searchedTokens.length}
data={searchedTokens}
itemContent={(i, { rri, amount, symbol }) => (
<TokenRow
i={i}
key={rri}
rri={rri}
amount={amount || 0}
staked={symbol === 'xrd' && staked ? staked : null}
symbol={symbol}
loading={isLoading}
/>
)}
/>
</ScrollArea>
)
} else if (hasLiquidBalances) {
list = <NoResultsPlaceholder title="No tokens found" />
}

return isLoading ? <TokenLoadingRows /> : list
}

Expand Down Expand Up @@ -249,7 +264,13 @@ export const TokenList: React.FC = () => {
return (
<>
<AccountSwitcher />
<VisibleFadeAnimation isVisible={isSlideUpPanelVisible}>
<Box
css={{
pe: isSlideUpPanelVisible ? 'auto' : 'none',
opacity: isSlideUpPanelVisible ? '1' : '0',
transition: !isSlideUpPanelVisible ? '$default' : 'unset',
}}
>
<SlideUpPanel
headerComponent={
<SlideUpHeader
Expand All @@ -262,7 +283,7 @@ export const TokenList: React.FC = () => {
>
<Balances />
</SlideUpPanel>
</VisibleFadeAnimation>
</Box>
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,15 @@ export const StakeItem: React.FC<IProps> = ({
}

return (
<Box css={{ px: '$4', pb: '$4', pt: '$3', borderTop: `1px solid ${border ? '$borderPanel' : 'transparent'}` }}>
<Box
css={{
px: '$4',
pb: '$4',
pt: '$3',
bg: '$bgPanel',
borderTop: `1px solid ${border ? '$borderPanel' : 'transparent'}`,
}}
>
<Flex css={{ position: 'relative' }}>
<Box css={{ flex: '1', pt: '6px' }}>
<Text bold truncate css={{ pb: '$3', maxWidth: '250px' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import React, { useEffect } from 'react'
import { Box, Flex, Text, StyledLink } from 'ui/src/components/atoms'
import { useStakedPositions, useUnstakePositions } from '@src/hooks/react-query/queries/radix'
import { NoResultsPlaceholder } from '@src/components/no-results-placeholder'
import { useImmer } from 'use-immer'
import { SearchBox } from '@src/components/search-box'
import { ScrollArea } from 'ui/src/components/scroll-area'
Expand Down Expand Up @@ -110,6 +111,9 @@ export const StakesList: React.FC<IProps> = ({ totalStakes }) => {
borderRadius: ' 0px 0px 5px 5px',
}}
>
<Box css={{ position: 'absolute', top: '70px', width: '100%', pe: 'none' }}>
<NoResultsPlaceholder />
</Box>
<ScrollArea>
{Object.keys(state.filteredList)
.filter(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from 'react'
import { useValidators } from '@src/hooks/react-query/queries/radix'
import { Validator } from '@src/types'
import { NoResultsPlaceholder } from '@src/components/no-results-placeholder'
import { Flex, Box } from 'ui/src/components/atoms'
import { useImmer } from 'use-immer'
import { SearchBox } from '@src/components/search-box'
Expand Down Expand Up @@ -36,6 +37,7 @@ export const ValidatorList: React.FC<IProps> = ({ totalStakes }) => {
})
const { data = [] } = useValidators()
const hasValidations = data.length > 0
const hasSearchResults = state.filteredList.length > 0

const handleSearchValidatorList = (search: string) => {
setState(draft => {
Expand Down Expand Up @@ -69,17 +71,21 @@ export const ValidatorList: React.FC<IProps> = ({ totalStakes }) => {
borderRadius: ' 0px 0px 5px 5px',
}}
>
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={state.filteredList.length}
// eslint-disable-next-line react/no-unstable-nested-components
itemContent={i => {
const validator = state.filteredList[i]
return <ValidatorItem i={i} validator={validator} totalStakes={totalStakes} />
}}
/>
</ScrollArea>
{hasSearchResults ? (
<ScrollArea scrollableNodeProps={{ ref: setCustomScrollParent }}>
<Virtuoso
customScrollParent={customScrollParent}
totalCount={state.filteredList.length}
// eslint-disable-next-line react/no-unstable-nested-components
itemContent={i => {
const validator = state.filteredList[i]
return <ValidatorItem i={i} validator={validator} totalStakes={totalStakes} />
}}
/>
</ScrollArea>
) : (
<NoResultsPlaceholder />
)}
</Box>
</Box>
) : (
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/button-tip-feedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ const ButtonTipFeedback: React.FC<IProps> = ({
const timeoutEnterRef = useRef(null)
const timeoutLeaveRef = useRef(null)
const timeoutFeedbackRef = useRef(null)
const [isOpen, setIsOpen] = useState(false)
const [isShowFeedback, setIsShowFeedback] = useState(false)
const [isOpen, setIsOpen] = useState<boolean>(false)
const [isShowFeedback, setIsShowFeedback] = useState<boolean>(false)
let clonedButton = null

const handleShowFeedback = () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const Button = React.forwardRef<HTMLButtonElement, React.PropsWithChildren<Butto
css,
...rest
} = props
const [buttonWidth, setButtonWidth] = useState(0)
const [buttonWidth, setButtonWidth] = useState<number>(0)
const rippleRef = useRef<HTMLElement>(null)
const buttonRef = useRef<HTMLButtonElement>(null)
useImperativeHandle(ref, () => buttonRef.current)
Expand Down
7 changes: 6 additions & 1 deletion packages/ui/src/components/scroll-area/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ import SimpleBar from 'simplebar-react'
import { useImmer } from 'use-immer'
import { Box } from '../atoms/box'

interface ImmerT {
isTopShadowVisible: boolean
isBottmShadowVisible: boolean
}

interface IProps {
children: React.ReactNode
scrollableNodeProps?: any
Expand All @@ -17,7 +22,7 @@ export const ScrollArea: React.FC<IProps> = ({ children, scrollableNodeProps })
const observer = useRef<ResizeObserver | null>(null)
const scrollObserver = useRef<ResizeObserver | null>(null)

const [state, setState] = useImmer({
const [state, setState] = useImmer<ImmerT>({
isTopShadowVisible: false,
isBottmShadowVisible: false,
})
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/components/toasts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const Toast = React.forwardRef<HTMLDivElement, ToastProps>(({ uniqueId, config,
const toastRef = useRef<HTMLDivElement>(null)
useImperativeHandle(ref, () => toastRef.current)

const [isMounted, setIsMounted] = useState(false)
const [isMounted, setIsMounted] = useState<boolean>(false)
const { duration = 3500, type } = config

const { toastList, close } = useToastStore(
Expand Down
2 changes: 1 addition & 1 deletion packages/ui/src/theme/dark-colors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const darkColors = {
bgToggleActive: '#aca7d3',
bgSlider: '#000000',
bgSliderRange: '#aca7d3',
bgTransparentDialog: 'rgba(0,0,0, 0.4)',
bgTransparentDialog: 'rgba(0,0,0, 0.6)',
bgSliderTrack: '$buttonBgPrimary',
bgInput: '#111111',
bgLink: 'rgba(192,125,219,0.1)',
Expand Down