Skip to content

Commit

Permalink
Add fallback component for offline images
Browse files Browse the repository at this point in the history
  • Loading branch information
microbit-robert committed Apr 25, 2024
1 parent b74b33c commit fcf4d63
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 16 deletions.
33 changes: 33 additions & 0 deletions src/documentation/OfflineImageFallback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BoxProps, Image, Text, VStack } from "@chakra-ui/react";
import offlinePlaceholder from "./offline.svg";

interface OfflineImageFallbackProps extends BoxProps {
useIcon?: boolean;
}

const OfflineImageFallback = ({
useIcon = false,
width,
...props
}: OfflineImageFallbackProps) => {
return (
<>
{useIcon ? (
<Image
fallbackSrc={offlinePlaceholder}
{...props}
p={2}
alt="Image unavailable offline"
/>
) : (
<VStack justifyContent="center" {...props} maxWidth={width}>
<Text textAlign="center" wordBreak="break-word">
Image unavailable offline
</Text>
</VStack>
)}
</>
);
};

export default OfflineImageFallback;
19 changes: 12 additions & 7 deletions src/documentation/common/DocumentationContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from "../reference/model";
import CodeEmbed from "./CodeEmbed";
import { decorateWithCollapseNodes } from "./collapse-util";
import OfflineImageFallback from "../OfflineImageFallback";

export const enum DocumentationCollapseMode {
ShowAll,
Expand Down Expand Up @@ -202,21 +203,25 @@ const serializers = {
<ContextualCodeEmbed code={main} />
),
simpleImage: (props: SerializerNodeProps<SimpleImage>) => {
const imageProps = {
width: 300,
borderRadius: "lg",
border: "solid 1px",
borderColor: "gray.300",
sx: {
aspectRatio: getAspectRatio(props.node.asset._ref),
},
};
return (
<Image
src={imageUrlBuilder
.image(props.node.asset)
.width(300)
.fit("max")
.url()}
fallback={<OfflineImageFallback {...imageProps} />}
alt={props.node.alt}
width={300}
borderRadius="lg"
border="solid 1px"
borderColor="gray.300"
sx={{
aspectRatio: getAspectRatio(props.node.asset._ref),
}}
{...imageProps}
/>
);
},
Expand Down
19 changes: 16 additions & 3 deletions src/documentation/common/DocumentationIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { Image, ImageProps } from "@chakra-ui/react";
import { imageUrlBuilder } from "../../common/imageUrlBuilder";
import { SimpleImage } from "../../common/sanity";
import OfflineImageFallback from "../OfflineImageFallback";

interface DocumentationIconProps extends ImageProps {
icon: SimpleImage;
Expand All @@ -18,14 +19,26 @@ const DocumentationIcon = ({
...props
}: DocumentationIconProps) => {
const size = reduced ? "50px" : "80px";
const imageProps = {
transition: "all .2s",
width: size,
height: size,
};
return (
<Image
{...props}
src={imageUrlBuilder.image(icon.asset).url()}
fallback={
<OfflineImageFallback
useIcon
{...props}
{...imageProps}
width={size}
height={size}
/>
}
alt=""
transition="all .2s"
width={size}
height={size}
{...imageProps}
/>
);
};
Expand Down
8 changes: 7 additions & 1 deletion src/documentation/ideas/IdeaCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Image } from "@chakra-ui/react";
import { imageUrlBuilder } from "../../common/imageUrlBuilder";
import { SimpleImage } from "../../common/sanity";
import DocumentationHeading from "../common/DocumentationHeading";
import OfflineImageFallback from "../OfflineImageFallback";

interface IdeaCardProps {
name: string;
Expand All @@ -21,6 +22,10 @@ const IdeaCard = ({ name, image, isV2Only, onClick }: IdeaCardProps) => {
outline: "none",
boxShadow: "var(--chakra-shadows-outline)",
};
const imageProps = {
borderTopRadius: "lg",
width: 500,
};
return (
<VStack
as="button"
Expand All @@ -35,9 +40,10 @@ const IdeaCard = ({ name, image, isV2Only, onClick }: IdeaCardProps) => {
_focus={focusStyles}
>
<Image
borderTopRadius="lg"
src={imageUrlBuilder.image(image.asset).width(550).url()}
fallback={<OfflineImageFallback useIcon {...imageProps} />}
alt=""
{...imageProps}
/>
<DocumentationHeading
alignSelf="flex-start"
Expand Down
15 changes: 10 additions & 5 deletions src/documentation/ideas/IdeasDocumentation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import DocumentationContent, {
import { isV2Only } from "../common/model";
import IdeaCard from "./IdeaCard";
import { Idea } from "./model";
import OfflineImageFallback from "../OfflineImageFallback";

interface IdeasDocumentationProps {
ideas: Idea[];
Expand Down Expand Up @@ -70,6 +71,13 @@ const ActiveLevel = ({
const numCols =
!contentWidth || contentWidth > 1100 ? 3 : contentWidth > 550 ? 2 : 1;
if (activeIdea) {
const imageProps = {
borderTopRadius: "lg",
width: 600,
sx: {
aspectRatio: getAspectRatio(activeIdea.image.asset._ref),
},
};
return (
<HeadedScrollablePanel
key={activeIdea.slug.current}
Expand Down Expand Up @@ -97,16 +105,13 @@ const ActiveLevel = ({
>
{activeIdea.image && (
<Image
borderRadius="lg"
src={imageUrlBuilder
.image(activeIdea.image.asset)
.fit("max")
.url()}
fallback={<OfflineImageFallback {...imageProps} />}
alt=""
width={600}
sx={{
aspectRatio: getAspectRatio(activeIdea.image.asset._ref),
}}
{...imageProps}
/>
)}

Expand Down
1 change: 1 addition & 0 deletions src/documentation/offline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit fcf4d63

Please sign in to comment.