Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Commit

Permalink
feat(image-edit): add edit alt text button and modal
Browse files Browse the repository at this point in the history
re #845
  • Loading branch information
wanlingt committed Nov 23, 2021
1 parent dca24b6 commit 427f445
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 3 deletions.
112 changes: 110 additions & 2 deletions client/src/components/RichText/ImageBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@ import {
SelectionState,
Modifier,
} from 'draft-js'
import { useRef, useState, useContext } from 'react'
import { useRef, useState, useContext, ChangeEvent, MouseEvent } from 'react'
import {
useMultiStyleConfig,
Button,
ButtonGroup,
Divider,
HStack,
Box,
Flex,
Image,
Modal,
ModalOverlay,
ModalContent,
ModalBody,
ModalFooter,
useDisclosure,
VStack,
Text,
Input,
} from '@chakra-ui/react'

import { EditorContext } from './RichTextEditor.component'
Expand All @@ -38,7 +48,16 @@ export const ImageBlock = ({
const [currentImageSize, setCurrentImageSize] = useState(
width ? convertWidthToInt(width) : 100,
)
const [altText, setAltText] = useState(alt)

const styles = useMultiStyleConfig('ImageBlock', {})
const editImageStyles = useMultiStyleConfig('ImageControl', {})

const {
onOpen: onEditModalOpen,
onClose: onEditModalClose,
isOpen: isEditModalOpen,
} = useDisclosure()

function convertWidthToInt(widthString: string) {
const width = parseInt(widthString.substring(0, widthString.length - 1))
Expand Down Expand Up @@ -123,12 +142,97 @@ export const ImageBlock = ({
}
}

function getUpdateAlt(altText: string) {
return () => {
// Preserve selection to prevent jumping to start of editor after setting width
const currentSelection = editorState.getSelection()
const entityKey = block.getEntityAt(0)
contentState.mergeEntityData(entityKey, {
alt: altText,
})
const updated = EditorState.push(
EditorState.forceSelection(editorState, currentSelection),
contentState,
'change-block-data',
)

setEditorState(updated)
onEditModalClose()
}
}

function handleCancelAlt() {
onEditModalClose()
setAltText(alt)
}

function renderPreviewImage() {
return (
<img ref={imageRef} src={src} width={width} height={height} alt={alt} />
)
}

const stopPropagation = (e: MouseEvent<HTMLElement>) => {
e.stopPropagation()
}

const renderModal = () => (
<div onClick={stopPropagation}>
<Modal isOpen={isEditModalOpen} onClose={onEditModalClose} isCentered>
<ModalOverlay />
<ModalContent maxW="680px">
<ModalBody>
<VStack align="stretch">
<Text sx={editImageStyles.titleText}>Edit Alt Text</Text>
<Flex sx={editImageStyles.uploadedImageFlexBox}>
<Image src={src} alt={alt} />
</Flex>
<Box>
<Box sx={editImageStyles.altTextBox}>
<Text textStyle="subhead-1">Alt text</Text>
<Text textStyle="body-2">
Alt text (text that describes this media) improves
accessibility for people who can’t see images on web pages,
including users who use screen readers. This text will not
appear on your page.
</Text>
</Box>
<Box px="16px">
<Input
value={altText}
isRequired
placeholder="e.g. Table of the different quarantine types"
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setAltText(e.target.value)
}
/>
</Box>
</Box>
</VStack>
<Divider sx={editImageStyles.divider} />
</ModalBody>
<ModalFooter>
<Flex sx={editImageStyles.buttonsFlexBox}>
<Button
sx={editImageStyles.cancelButton}
onClick={handleCancelAlt}
>
Cancel
</Button>
<Box w="8px"></Box>
<Button
sx={editImageStyles.submitButton}
onClick={getUpdateAlt(altText)}
>
Save
</Button>
</Flex>
</ModalFooter>
</ModalContent>
</Modal>
</div>
)

return readOnly ? (
renderPreviewImage()
) : (
Expand All @@ -139,7 +243,7 @@ export const ImageBlock = ({
src={src}
width={width}
height={height}
alt={alt}
alt={altText}
/>
{showPopover && (
<HStack sx={styles.popover}>
Expand All @@ -158,12 +262,16 @@ export const ImageBlock = ({
</ButtonGroup>
<Divider orientation="vertical" h="28px" />
<ButtonGroup sx={styles.buttonGroup}>
<Button sx={styles.editButton} onClick={onEditModalOpen}>
Edit Alt Text
</Button>
<Button sx={styles.removeButton} onClick={handleRemove}>
Remove
</Button>
</ButtonGroup>
</HStack>
)}
{renderModal()}
</Box>
)
}
12 changes: 11 additions & 1 deletion client/src/components/RichText/RichTextEditor.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ const defaultValue = {
}
export const EditorContext = createContext(defaultValue)

// const readOnlyValue = {
// readOnlyState: true,
// setReadOnlyState: {} as Dispatch<SetStateAction<boolean>>,
// }
// export const ReadOnlyContext = createContext(readOnlyValue)

export const RichTextEditor: FC<{
onChange: (outputHTML: string) => void
placeholder?: string
Expand Down Expand Up @@ -110,6 +116,8 @@ export const RichTextEditor: FC<{
onChange(html)
}, [editorState, onChange, value])

// const [readOnlyState, setReadOnlyState] = useState(false)

function renderBlock(block: ContentBlock): unknown | void {
if (block.getType() === 'atomic') {
const contentState = editorState.getCurrentContent()
Expand All @@ -120,7 +128,7 @@ export const RichTextEditor: FC<{
if (entity?.getType() === 'IMAGE') {
return {
component: ImageBlock,
editable: false,
editable: true,
}
}
}
Expand All @@ -146,6 +154,7 @@ export const RichTextEditor: FC<{

return (
<EditorContext.Provider value={{ editorState, setEditorState }}>
{/* <ReadOnlyContext.Provider value={{ readOnlyState, setReadOnlyState }}> */}
<ExtendedEditor
placeholder={placeholder}
editorState={editorState}
Expand All @@ -162,6 +171,7 @@ export const RichTextEditor: FC<{
stripPastedStyles
editorRef={editorRef}
/>
{/* </ReadOnlyContext.Provider> */}
</EditorContext.Provider>
)
}
Expand Down

0 comments on commit 427f445

Please sign in to comment.