Add multi select file

This commit is contained in:
Jackson Harper 2024-02-29 12:46:02 +08:00
parent c67bd364ae
commit 9739d58fdf

View file

@ -0,0 +1,300 @@
import { useState } from 'react'
import { theme } from '../../tokens/stitches.config'
import { Box, HStack, SpanBox } from '../../elements/LayoutPrimitives'
import { Button } from '../../elements/Button'
import { BulkAction } from '../../../lib/networking/mutations/bulkActionMutation'
import { ArchiveIcon } from '../../elements/icons/ArchiveIcon'
import { LabelIcon } from '../../elements/icons/LabelIcon'
import { TrashIcon } from '../../elements/icons/TrashIcon'
import { ConfirmationModal } from '../../patterns/ConfirmationModal'
import { AddBulkLabelsModal } from '../article/AddBulkLabelsModal'
import { X } from 'phosphor-react'
import { LibraryHeaderProps } from './LibraryHeader'
import { HeaderCheckboxIcon } from '../../elements/icons/HeaderCheckboxIcon'
export const MultiSelectControls = (props: LibraryHeaderProps): JSX.Element => {
const [showConfirmDelete, setShowConfirmDelete] = useState(false)
const [showLabelsModal, setShowLabelsModal] = useState(false)
// Don't change on immediate hover, the button has to be blurred at least once
const [hoveredOut, setHoveredOut] = useState(false)
const [hoverColor, setHoverColor] = useState<string>(
theme.colors.thTextContrast2.toString()
)
const compact = false
return (
<Box
css={{
height: '38px',
width: '100%',
maxWidth: '521px',
bg: '$thLibrarySearchbox',
borderRadius: '6px',
boxShadow:
'0 1px 3px 0 rgba(0, 0, 0, 0.1),0 1px 2px 0 rgba(0, 0, 0, 0.06);',
}}
onMouseLeave={(event) => {
setHoveredOut(true)
event.preventDefault()
}}
>
<HStack
alignment="center"
distribution="end"
css={{
width: '100%',
height: '100%',
pr: compact ? '5px' : '10px',
}}
onClick={(e) => {
e.preventDefault()
}}
>
<HStack
alignment="center"
distribution="center"
css={{
width: '53px',
height: '100%',
display: 'flex',
bg: props.multiSelectMode !== 'off' ? '$ctaBlue' : 'transparent',
borderTopLeftRadius: '6px',
borderBottomLeftRadius: '6px',
'--checkbox-color': 'white',
'&:hover': {
bg: hoveredOut ? '$thLibraryMultiselectHover' : '$ctaBlue',
'--checkbox-color': hoveredOut
? 'var(--colors-thLibraryMultiselectCheckboxHover)'
: 'white',
},
}}
>
<CheckBoxButton {...props} />
</HStack>
<HStack
alignment="center"
distribution="start"
css={{
gap: '15px',
pl: '15px',
border: '2px solid transparent',
width: '100%',
height: '100%',
}}
>
<SpanBox
css={{
fontSize: '14px',
fontFamily: '$display',
marginRight: 'auto',
}}
>
{props.numItemsSelected} items selected
</SpanBox>
<ArchiveButton {...props} />
<AddLabelsButton setShowLabelsModal={setShowLabelsModal} />
<RemoveItemsButton setShowConfirmDelete={setShowConfirmDelete} />
{showConfirmDelete && (
<ConfirmationModal
message={`You are about to delete ${props.numItemsSelected} items. All associated notes and highlights will be deleted.`}
acceptButtonLabel={'Delete'}
onAccept={() => {
props.performMultiSelectAction(BulkAction.DELETE)
}}
onOpenChange={(open: boolean) => {
setShowConfirmDelete(false)
}}
/>
)}
{showLabelsModal && (
<AddBulkLabelsModal
bulkSetLabels={(labels: Label[]) => {
const labelIds = labels.map((l) => l.id)
props.performMultiSelectAction(BulkAction.ADD_LABELS, labelIds)
}}
onOpenChange={(open: boolean) => {
setShowLabelsModal(false)
}}
/>
)}
<CancelButton {...props} />
</HStack>
</HStack>
</Box>
)
}
export const CheckBoxButton = (props: LibraryHeaderProps): JSX.Element => {
return (
<Button
title="Select multiple"
style="plainIcon"
css={{ display: 'flex', '&:hover': { opacity: '1.0' } }}
onClick={(e) => {
switch (props.multiSelectMode) {
case 'off':
case 'none':
case 'some':
props.setMultiSelectMode('visible')
break
default:
props.setMultiSelectMode('off')
break
}
e.preventDefault()
}}
>
<HeaderCheckboxIcon multiSelectMode={props.multiSelectMode} />
</Button>
)
}
export const ArchiveButton = (props: LibraryHeaderProps): JSX.Element => {
const [color, setColor] = useState<string>(
theme.colors.thTextContrast2.toString()
)
return (
<Button
title="Archive"
css={{
p: '5px',
display: 'flex',
'&:hover': {
bg: '$ctaBlue',
borderRadius: '100px',
opacity: 1.0,
},
}}
onMouseEnter={(event) => {
setColor('white')
event.preventDefault()
}}
onMouseLeave={(event) => {
setColor(theme.colors.thTextContrast2.toString())
event.preventDefault()
}}
style="plainIcon"
onClick={(e) => {
props.performMultiSelectAction(BulkAction.ARCHIVE)
e.preventDefault()
}}
>
<ArchiveIcon size={20} color={color} />
</Button>
)
}
type AddLabelsButtonProps = {
setShowLabelsModal: (set: boolean) => void
}
export const AddLabelsButton = (props: AddLabelsButtonProps): JSX.Element => {
const [color, setColor] = useState<string>(
theme.colors.thTextContrast2.toString()
)
return (
<Button
title="Archive"
css={{
p: '5px',
display: 'flex',
'&:hover': {
bg: '$ctaBlue',
borderRadius: '100px',
opacity: 1.0,
},
}}
onMouseEnter={(event) => {
setColor('white')
event.preventDefault()
}}
onMouseLeave={(event) => {
setColor(theme.colors.thTextContrast2.toString())
event.preventDefault()
}}
style="plainIcon"
onClick={(e) => {
props.setShowLabelsModal(true)
e.preventDefault()
}}
>
<LabelIcon size={20} color={color} />
</Button>
)
}
type RemoveItemsButtonProps = {
setShowConfirmDelete: (set: boolean) => void
}
export const RemoveItemsButton = (
props: RemoveItemsButtonProps
): JSX.Element => {
const [color, setColor] = useState<string>(
theme.colors.thTextContrast2.toString()
)
return (
<Button
title="Archive"
css={{
p: '5px',
display: 'flex',
'&:hover': {
bg: '$ctaBlue',
borderRadius: '100px',
opacity: 1.0,
},
}}
onMouseEnter={(event) => {
setColor('white')
event.preventDefault()
}}
onMouseLeave={(event) => {
setColor(theme.colors.thTextContrast2.toString())
event.preventDefault()
}}
style="plainIcon"
onClick={(e) => {
props.setShowConfirmDelete(true)
e.preventDefault()
}}
>
<TrashIcon size={20} color={color} />
</Button>
)
}
export const CancelButton = (props: LibraryHeaderProps): JSX.Element => {
const [color, setColor] = useState<string>(
theme.colors.thTextContrast2.toString()
)
return (
<Button
title="Archive"
css={{
p: '5px',
display: 'flex',
'&:hover': {
bg: '$ctaBlue',
borderRadius: '100px',
opacity: 1.0,
},
}}
onMouseEnter={(event) => {
setColor('white')
event.preventDefault()
}}
onMouseLeave={(event) => {
setColor(theme.colors.thTextContrast2.toString())
event.preventDefault()
}}
style="plainIcon"
onClick={(e) => {
props.setMultiSelectMode('off')
e.preventDefault()
}}
>
<X width={19} height={19} color={color} />
</Button>
)
}