Skip to content

Commit

Permalink
feat(structure): add sheet list table view. (#6647)
Browse files Browse the repository at this point in the history
* feat(structure): add virtualised documentSheetList and sheetListStore

* feat(core): add useEditStateList hook

* feat(sheet-list): add table view

* feat(sheet-list): add paginated sheet list view

* feat(structure): clean files and implement paginated sheet list with filter

* fix(core): remove useEditStateList hook

* chore(core): refactor search elements for export and reusability

* fix(structure): update documentSheetList test

* chore(structure): rename useDocumentSheetListStore properties

* chore(structure): rename documentSheet* to documentSheetList*
  • Loading branch information
pedrobonamin authored May 16, 2024
1 parent 77785ff commit c5916d4
Show file tree
Hide file tree
Showing 15 changed files with 765 additions and 38 deletions.
1 change: 1 addition & 0 deletions packages/sanity/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"@sanity/ui": "^2.1.10",
"@sanity/util": "3.42.1",
"@sanity/uuid": "^3.0.1",
"@tanstack/react-table": "^8.16.0",
"@tanstack/react-virtual": "3.0.0-beta.54",
"@types/react-copy-to-clipboard": "^5.0.2",
"@types/react-is": "^18.2.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,7 @@ export function SearchDialog({onClose, onOpen, open}: SearchDialogProps) {
<FocusLock autoFocus={!supportsTouch} returnFocus>
<SearchDialogBox>
<InnerCard display="flex" height="fill" scheme={scheme} tone="default">
<SearchHeader
ariaInputLabel={
hasValidTerms
? t('search.search-results-aria-label')
: t('search.recent-searches-aria-label')
}
onClose={onClose}
ref={setInputElement}
/>
<SearchHeader onClose={onClose} ref={setInputElement} />
{filtersVisible && (
<Card borderTop flex="none">
<Filters />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {Button} from '../../../../../../ui-components'
import {StatusButton} from '../../../../../components'
import {useTranslation} from '../../../../../i18n'
import {useSearchState} from '../contexts/search/useSearchState'
import {hasSearchableTerms} from '../utils/hasSearchableTerms'
import {CustomTextInput} from './common/CustomTextInput'

const rotate = keyframes`
Expand All @@ -28,27 +29,37 @@ const FilterDiv = styled.div`
`

interface SearchHeaderProps {
ariaInputLabel: string
ariaInputLabel?: string
onClose?: () => void
}

/**
* @internal
*/
export const SearchHeader = forwardRef<HTMLInputElement, SearchHeaderProps>(function SearchHeader(
{ariaInputLabel, onClose},
ref,
) {
const isMountedRef = useRef(false)

const {t} = useTranslation()
const {
dispatch,
state: {
filters,
filtersVisible,
fullscreen,
result: {loading},
terms: {types, query},
terms,
},
} = useSearchState()
const {t} = useTranslation()
const {types, query} = terms

const hasValidTerms = hasSearchableTerms({terms})
const ariaLabel =
ariaInputLabel || hasValidTerms
? t('search.search-results-aria-label')
: t('search.recent-searches-aria-label')

const handleFiltersToggle = useCallback(
() => dispatch({type: 'FILTERS_VISIBLE_SET', visible: !filtersVisible}),
Expand Down Expand Up @@ -99,7 +110,7 @@ export const SearchHeader = forwardRef<HTMLInputElement, SearchHeaderProps>(func
__unstable_disableFocusRing
$background={fullscreen}
$smallClearButton={fullscreen}
aria-label={ariaInputLabel}
aria-label={ariaLabel}
autoComplete="off"
border={false}
clearButton={!!query}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,7 @@ export function SearchPopover({
transition={ANIMATION_TRANSITION}
variants={CARD_VARIANTS}
>
<SearchHeader
ariaInputLabel={
hasValidTerms
? t('search.search-results-aria-label')
: t('search.recent-searches-aria-label')
}
onClose={onClose}
ref={setInputElement}
/>
<SearchHeader onClose={onClose} ref={setInputElement} />
{filtersVisible && (
<Card borderTop flex="none">
<Filters />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {DebugFilterQuery} from './debug/_DebugFilterQuery'
import {DocumentTypesButton} from './documentTypes/DocumentTypesButton'
import {FilterButton} from './filter/FilterButton'

export function Filters() {
/**
* @internal
*/
export function Filters({showTypeFilter = true}: {showTypeFilter?: boolean}) {
const {
dispatch,
state: {
Expand All @@ -27,11 +30,11 @@ export function Filters() {
const isMounted = useRef(false)

const handleClear = useCallback(() => {
if (showTypeFilter) dispatch({type: 'TERMS_TYPES_CLEAR'})
dispatch({type: 'TERMS_FILTERS_CLEAR'})
dispatch({type: 'TERMS_TYPES_CLEAR'})
}, [dispatch])
}, [dispatch, showTypeFilter])

const clearFiltersButtonVisible = filters.length > 0 || types.length > 0
const clearFiltersButtonVisible = filters.length > 0 || (showTypeFilter && types.length > 0)

useEffect(() => {
isMounted.current = true
Expand All @@ -53,7 +56,7 @@ export function Filters() {
<>
<Flex align="flex-start" gap={3} justify="space-between" padding={2}>
<Flex flex={1} gap={2} wrap="wrap">
<DocumentTypesButton />
{showTypeFilter && <DocumentTypesButton />}
{filters?.map((filter) => {
const key = getFilterKey(filter)
return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './filters/Filters'
export * from './SearchHeader'
export * from './SearchPopover'
export * from './searchResults'
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {Flex} from '@sanity/ui'
import {Filters, SearchHeader, useSearchState} from 'sanity'
import {styled} from 'styled-components'

const SearchContainer = styled(Flex)`
flex-shrink: 0;
`

export function DocumentSheetListFilter() {
const {
state: {filtersVisible},
} = useSearchState()

return (
<SearchContainer>
<SearchHeader />
{filtersVisible && <Filters showTypeFilter={false} />}
</SearchContainer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* eslint-disable i18next/no-literal-string */
/* eslint-disable @sanity/i18n/no-attribute-string-literals */
/* eslint-disable react/jsx-no-bind */
import {
ChevronLeftIcon,
ChevronRightIcon,
DoubleChevronLeftIcon,
DoubleChevronRightIcon,
} from '@sanity/icons'
import {Flex, Text} from '@sanity/ui'
import {type Table} from '@tanstack/react-table'
import {type SanityDocument} from 'sanity'

import {Button, TooltipDelayGroupProvider} from '../../../ui-components'

export function DocumentSheetListPaginator({table}: {table: Table<SanityDocument>}) {
return (
<TooltipDelayGroupProvider>
<Flex gap={3} align={'center'}>
<Button
onClick={() => table.setPageIndex(0)}
disabled={!table.getCanPreviousPage()}
icon={DoubleChevronLeftIcon}
tooltipProps={{
content: 'Go to first page',
}}
/>
<Button
onClick={() => table.previousPage()}
disabled={!table.getCanPreviousPage()}
icon={ChevronLeftIcon}
tooltipProps={{
content: 'Go to previous page',
}}
/>
<Text style={{whiteSpace: 'nowrap'}}>
{table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
</Text>

<Button
onClick={() => table.nextPage()}
disabled={!table.getCanNextPage()}
icon={ChevronRightIcon}
tooltipProps={{
content: 'Go to next page',
}}
/>
<Button
onClick={() => table.setPageIndex(table.getPageCount() - 1)}
disabled={!table.getCanNextPage()}
icon={DoubleChevronRightIcon}
tooltipProps={{
content: 'Go to last page',
}}
/>
<select
value={table.getState().pagination.pageSize}
onChange={(e) => {
table.setPageSize(Number(e.target.value))
}}
>
{[25, 50, 100].map((pageSize) => (
<option key={pageSize} value={pageSize}>
{pageSize}
</option>
))}
</select>
</Flex>
</TooltipDelayGroupProvider>
)
}
Loading

0 comments on commit c5916d4

Please sign in to comment.