Skip to content

Commit f621d23

Browse files
committed
refactor: Image migration
1 parent db3cc20 commit f621d23

File tree

7 files changed

+147
-106
lines changed

7 files changed

+147
-106
lines changed

packages/notion-to-jsx/src/components/Renderer/components/Block/BlockRenderer.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import {
77
} from '../MemoizedComponents';
88
import { CodeBlock } from '../Code';
99
import { Heading1, Heading2, Heading3, Paragraph } from '../Typography';
10-
import { BookmarkCard, BookmarkLink, ImageWrapper } from '../Media';
1110

1211
export interface Props {
1312
block: any;
@@ -78,20 +77,16 @@ const BlockRenderer: React.FC<Props> = ({ block, onFocus, index }) => {
7877
</div>
7978
);
8079

81-
// case 'image':
82-
// return (
83-
// <ImageWrapper {...blockProps}>
84-
// <MemoizedImage
85-
// src={block.image.file?.url || block.image.external?.url}
86-
// alt={block.image.caption?.[0]?.plain_text || ''}
87-
// />
88-
// {block.image.caption && (
89-
// <figcaption>
90-
// <MemoizedRichText richTexts={block.image.caption} />
91-
// </figcaption>
92-
// )}
93-
// </ImageWrapper>
94-
// );
80+
case 'image':
81+
return (
82+
<figure {...blockProps}>
83+
<MemoizedImage
84+
src={block.image.file?.url || block.image.external?.url}
85+
alt={block.image.caption?.[0]?.plain_text || ''}
86+
caption={block.image.caption}
87+
/>
88+
</figure>
89+
);
9590

9691
// case 'bookmark':
9792
// return (

packages/notion-to-jsx/src/components/Renderer/components/Image/Image.tsx

Lines changed: 19 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import React, { useState, useEffect } from 'react';
2-
import styled from 'styled-components';
32
import { RichTextItem } from '../../../../types';
4-
import RichTexts from '../RichText/RichTexts';
3+
import { MemoizedRichText } from '../MemoizedComponents';
4+
import {
5+
imageContainer,
6+
styledImage,
7+
placeholder,
8+
caption,
9+
} from './styles.css';
510

611
export interface ImageProps {
712
src: string;
@@ -10,46 +15,10 @@ export interface ImageProps {
1015
priority?: boolean;
1116
}
1217

13-
const ImageContainer = styled.div`
14-
position: relative;
15-
width: 100%;
16-
background: ${({ theme }) => theme.colors.code.background};
17-
border-radius: ${({ theme }) => theme.borderRadius.md};
18-
overflow: hidden;
19-
`;
20-
21-
const StyledImage = styled.img<{ $isLoaded: boolean }>`
22-
width: 100%;
23-
height: auto;
24-
display: block;
25-
opacity: ${({ $isLoaded }) => ($isLoaded ? 1 : 0)};
26-
transition: opacity 0.3s ease;
27-
`;
28-
29-
const Placeholder = styled.div`
30-
position: absolute;
31-
top: 0;
32-
left: 0;
33-
right: 0;
34-
bottom: 0;
35-
display: flex;
36-
align-items: center;
37-
justify-content: center;
38-
background: ${({ theme }) => theme.colors.code.background};
39-
color: ${({ theme }) => theme.colors.secondary};
40-
`;
41-
42-
const Caption = styled.figcaption`
43-
text-align: center;
44-
color: ${({ theme }) => theme.colors.secondary};
45-
margin-top: ${({ theme }) => theme.spacing.sm};
46-
font-size: ${({ theme }) => theme.typography.fontSize.small};
47-
`;
48-
4918
const Image: React.FC<ImageProps> = ({
5019
src,
5120
alt,
52-
caption,
21+
caption: imageCaption,
5322
priority = false,
5423
}) => {
5524
const [isLoaded, setIsLoaded] = useState(false);
@@ -61,23 +30,23 @@ const Image: React.FC<ImageProps> = ({
6130
}, [src]);
6231

6332
return (
64-
<figure>
65-
<ImageContainer>
66-
{!isLoaded && !error && <Placeholder>Loading...</Placeholder>}
67-
{error && <Placeholder>Failed to load image</Placeholder>}
68-
<StyledImage
33+
<figure className={imageContainer}>
34+
<div>
35+
{!isLoaded && !error && <div className={placeholder}>Loading...</div>}
36+
{error && <div className={placeholder}>Failed to load image</div>}
37+
<img
38+
className={styledImage({ loaded: isLoaded })}
6939
src={src}
7040
alt={alt}
71-
$isLoaded={isLoaded}
7241
loading={priority ? 'eager' : 'lazy'}
7342
onLoad={() => setIsLoaded(true)}
7443
onError={() => setError(true)}
7544
/>
76-
</ImageContainer>
77-
{caption && caption.length > 0 && (
78-
<Caption>
79-
<RichTexts richTexts={caption} />
80-
</Caption>
45+
</div>
46+
{imageCaption && imageCaption.length > 0 && (
47+
<figcaption className={caption}>
48+
<MemoizedRichText richTexts={imageCaption} />
49+
</figcaption>
8150
)}
8251
</figure>
8352
);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { style } from '@vanilla-extract/css';
2+
import { recipe } from '@vanilla-extract/recipes';
3+
import { vars } from '../../../../styles/theme.css';
4+
5+
export const imageContainer = style({
6+
position: 'relative',
7+
width: '100%',
8+
background: vars.colors.code.background,
9+
borderRadius: vars.borderRadius.md,
10+
overflow: 'hidden',
11+
});
12+
13+
export const styledImage = recipe({
14+
base: {
15+
width: '100%',
16+
height: 'auto',
17+
display: 'block',
18+
transition: 'opacity 0.3s ease',
19+
},
20+
variants: {
21+
loaded: {
22+
true: {
23+
opacity: 1,
24+
},
25+
false: {
26+
opacity: 0,
27+
},
28+
},
29+
},
30+
defaultVariants: {
31+
loaded: false,
32+
},
33+
});
34+
35+
export const placeholder = style({
36+
position: 'absolute',
37+
top: 0,
38+
left: 0,
39+
right: 0,
40+
bottom: 0,
41+
display: 'flex',
42+
alignItems: 'center',
43+
justifyContent: 'center',
44+
background: vars.colors.code.background,
45+
color: vars.colors.secondary,
46+
});
47+
48+
export const caption = style({
49+
textAlign: 'center',
50+
color: vars.colors.secondary,
51+
marginTop: vars.spacing.sm,
52+
fontSize: vars.typography.fontSize.small,
53+
});
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from 'react';
2+
import { RichTextItem } from '../../../../types';
3+
import { MemoizedRichText } from '../MemoizedComponents';
4+
import { caption, bookmarkCard, bookmarkLink } from './styles.css';
5+
6+
interface BookmarkProps {
7+
url: string;
8+
title: string;
9+
description?: string;
10+
caption?: RichTextItem[];
11+
}
12+
13+
export const Bookmark: React.FC<BookmarkProps> = ({
14+
url,
15+
title,
16+
description,
17+
caption: bookmarkCaption,
18+
}) => {
19+
return (
20+
<div className={bookmarkCard}>
21+
<a
22+
href={url}
23+
target="_blank"
24+
rel="noopener noreferrer"
25+
className={bookmarkLink}
26+
>
27+
<h4>{title}</h4>
28+
{description && <p>{description}</p>}
29+
</a>
30+
{bookmarkCaption && (
31+
<figcaption className={caption}>
32+
<MemoizedRichText richTexts={bookmarkCaption} />
33+
</figcaption>
34+
)}
35+
</div>
36+
);
37+
};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './styles';
1+
export { Bookmark } from './Media';
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { style } from '@vanilla-extract/css';
2+
import { vars } from '../../../../styles/theme.css';
3+
4+
export const caption = style({
5+
marginTop: vars.spacing.sm,
6+
fontSize: vars.typography.fontSize.small,
7+
color: vars.colors.secondary,
8+
});
9+
10+
export const bookmarkCard = style({
11+
margin: `${vars.spacing.md} 0`,
12+
padding: vars.spacing.md,
13+
border: `1px solid ${vars.colors.border}`,
14+
borderRadius: vars.borderRadius.md,
15+
transition: 'box-shadow 0.2s ease',
16+
':hover': {
17+
boxShadow: vars.shadows.sm,
18+
},
19+
});
20+
21+
export const bookmarkLink = style({
22+
color: vars.colors.primary,
23+
textDecoration: 'none',
24+
':hover': {
25+
textDecoration: 'underline',
26+
},
27+
});

packages/notion-to-jsx/src/components/Renderer/components/Media/styles.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)