-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Image + RichTextWithImage components with placement
1. Renames RichTextParagraph to just RichText 2. Creates an Image component that uses GatsbyImage to render gatsbyImageData 3. Does some fun with typing so that gatsbyImageData isn't undefined (see the bug at cometkim/gatsby-plugin-typegen#146) 4. Loads images for projects & sections' paragraphs & displays them
- Loading branch information
Showing
6 changed files
with
153 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { GatsbyImage, IGatsbyImageData } from 'gatsby-plugin-image' | ||
import * as React from 'react' | ||
|
||
/** | ||
* Shared type to describe what image data looks like coming from Contentful. Note that because Scalars[JSON] | ||
* is defined as `never`, the type of Pick<... 'gatsbyImageData'> is undefined and I need a separate type | ||
*/ | ||
export type RawImageData = GatsbyTypes.Maybe< | ||
Pick< | ||
GatsbyTypes.ContentfulAsset, | ||
'id' | 'title' | 'gatsbyImageData' | 'description' | ||
> | ||
> | ||
|
||
/** | ||
* Internal type to describe what image data looks like coming from Contentful with a transformation applied | ||
* manually. Note that because Scalars[JSON] is defined as `never`, this separate type is necessary. | ||
*/ | ||
type ImageData = GatsbyTypes.Maybe< | ||
Pick<GatsbyTypes.ContentfulAsset, 'id' | 'title' | 'description'> & { | ||
gatsbyImageData: IGatsbyImageData | ||
} | ||
> | ||
|
||
/** | ||
* Just image data + alt text that we need | ||
*/ | ||
type PropTypes = { | ||
image: RawImageData | ||
} | ||
|
||
/** | ||
* A simple image using the gatsby image data passed to it | ||
* @param props An object containing `PropTypes` | ||
* @returns An element for the image and all associated content | ||
*/ | ||
const Image = ({ image }: PropTypes): JSX.Element => { | ||
const typedImageData = (image as ImageData)?.gatsbyImageData | ||
if (!image || !typedImageData?.images.sources) { | ||
throw TypeError('Malformed image data') | ||
} | ||
return ( | ||
<GatsbyImage | ||
image={typedImageData} | ||
alt={image.description ?? image.title ?? image.id} | ||
/> | ||
) | ||
} | ||
|
||
export default Image |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import * as React from 'react' | ||
import Image, { RawImageData } from './Image' | ||
import RichText, { RawRichText } from './RichText' | ||
|
||
/** | ||
* Shared type for raw image type without yet being an enum | ||
*/ | ||
type ImageTypeData = GatsbyTypes.Maybe<string> | ||
|
||
/** | ||
* Describes the supported values for image placement. If not one of these, either | ||
* we need to support a new value or the existing data is incorrect. | ||
*/ | ||
enum ImagePlacement { | ||
None = 'none', | ||
Left = 'left', | ||
Right = 'right', | ||
} | ||
|
||
/** | ||
* Rich text, image data, and information about how to position that image | ||
*/ | ||
type PropTypes = { | ||
richText: RawRichText | ||
imageType: ImageTypeData | ||
image: RawImageData | ||
} | ||
|
||
/** | ||
* A rich text paragraph using the default settings to render the elements because it's | ||
* really tough to set up elements that work right for custom elements. | ||
* See https://www.contentful.com/developers/docs/concepts/rich-text/ | ||
* @param props An object containing `PropTypes` | ||
* @returns An element for the rich text, composed of other items inside it | ||
*/ | ||
const RichTextWithImage = ({ | ||
richText, | ||
image, | ||
imageType, | ||
}: PropTypes): JSX.Element => { | ||
const placement = imageType as ImagePlacement | ||
if (!richText || !imageType || !placement) { | ||
throw TypeError('Malformed rich text with image data') | ||
} | ||
const textElement = () => <RichText richText={richText} /> | ||
const imageElement = () => <Image image={image} /> | ||
switch (placement) { | ||
case ImagePlacement.None: | ||
return <>{textElement()}</> | ||
case ImagePlacement.Left: | ||
return ( | ||
<> | ||
{imageElement()} | ||
{textElement()} | ||
</> | ||
) | ||
case ImagePlacement.Right: | ||
return ( | ||
<> | ||
{textElement()} | ||
{imageElement()} | ||
</> | ||
) | ||
} | ||
} | ||
|
||
export default RichTextWithImage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters