tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
27
pulls
pipelines
use server safe popover for image alt text in blog
awarm.space
8 months ago
8cba7191
18f00c77
+66
-49
5 changed files
expand all
collapse all
unified
split
app
lish
[did]
[publication]
[rkey]
PostContent.tsx
ServerSafePopover.tsx
components
Blocks
ImageBlock.tsx
Icons
ImageAlt.tsx
Toolbar
ImageToolbar.tsx
+4
-3
app/lish/[did]/[publication]/[rkey]/PostContent.tsx
···
10
10
import { blobRefToSrc } from "src/utils/blobRefToSrc";
11
11
import { TextBlock } from "./TextBlock";
12
12
import { Popover } from "components/Popover";
13
13
-
import { ImageAltSmall } from "components/Toolbar/ImageToolbar";
14
13
import { theme } from "tailwind.config";
14
14
+
import { ServerSafePopover } from "./ServerSafePopover";
15
15
+
import { ImageAltSmall } from "components/Icons/ImageAlt";
15
16
16
17
export function PostContent({
17
18
blocks,
···
125
126
/>
126
127
{b.block.alt && (
127
128
<div className="absolute bottom-1.5 right-2 h-max">
128
128
-
<Popover
129
129
+
<ServerSafePopover
129
130
className="text-sm max-w-xs min-w-0"
130
131
side="left"
131
132
trigger={<ImageAltSmall fillColor={theme.colors["bg-page"]} />}
···
133
134
<div className="text-sm text-secondary w-full">
134
135
{b.block.alt}
135
136
</div>
136
136
-
</Popover>
137
137
+
</ServerSafePopover>
137
138
</div>
138
139
)}
139
140
</div>
+19
app/lish/[did]/[publication]/[rkey]/ServerSafePopover.tsx
···
1
1
+
import { Popover } from "components/Popover";
2
2
+
3
3
+
export const ServerSafePopover = (props: {
4
4
+
trigger: React.ReactNode;
5
5
+
disabled?: boolean;
6
6
+
children: React.ReactNode;
7
7
+
align?: "start" | "end" | "center";
8
8
+
side?: "top" | "bottom" | "left" | "right";
9
9
+
background?: string;
10
10
+
border?: string;
11
11
+
className?: string;
12
12
+
open?: boolean;
13
13
+
onOpenChange?: (open: boolean) => void;
14
14
+
asChild?: boolean;
15
15
+
arrowFill?: string;
16
16
+
}) => {
17
17
+
if (typeof window === "undefined") return props.trigger;
18
18
+
return <Popover {...props} />;
19
19
+
};
+1
-1
components/Blocks/ImageBlock.tsx
···
12
12
import { createContext, useContext, useEffect, useState } from "react";
13
13
import { BlockImageSmall } from "components/Icons/BlockImageSmall";
14
14
import { Popover } from "components/Popover";
15
15
-
import { ImageAltSmall } from "components/Toolbar/ImageToolbar";
16
15
import { theme } from "tailwind.config";
17
16
import { EditTiny } from "components/Icons/EditTiny";
18
17
import { AsyncValueAutosizeTextarea } from "components/utils/AutosizeTextarea";
19
18
import { set } from "colorjs.io/fn";
19
19
+
import { ImageAltSmall } from "components/Icons/ImageAlt";
20
20
21
21
export function ImageBlock(props: BlockProps & { preview?: boolean }) {
22
22
let { rep } = useReplicache();
+41
components/Icons/ImageAlt.tsx
···
1
1
+
export const ImageAltSmall = (props: { fillColor: string }) => {
2
2
+
return (
3
3
+
<svg
4
4
+
width="24"
5
5
+
height="24"
6
6
+
viewBox="0 0 24 24"
7
7
+
fill="none"
8
8
+
xmlns="http://www.w3.org/2000/svg"
9
9
+
>
10
10
+
<rect
11
11
+
x="1.07886"
12
12
+
y="5.237"
13
13
+
width="21.8423"
14
14
+
height="13.4703"
15
15
+
rx="2.5"
16
16
+
fill={props.fillColor}
17
17
+
/>
18
18
+
<path
19
19
+
d="M21.0718 5C22.3323 5.12817 23.3159 6.19299 23.3159 7.4873V16.4443L23.3032 16.7002C23.1837 17.8766 22.2482 18.812 21.0718 18.9316L20.8159 18.9443H3.89014L2.92822 18.9316C1.752 18.8118 0.816287 17.8765 0.696777 16.7002L0.684082 7.4873C0.684082 6.19312 1.66793 5.12835 2.92822 5H21.0718ZM3.18408 6.2373C2.49395 6.23756 1.93408 6.7971 1.93408 7.4873V16.4443C1.93408 17.1345 2.49395 17.6941 3.18408 17.6943H20.8159C21.5062 17.6943 22.0659 17.1347 22.0659 16.4443V7.4873C22.0659 6.79698 21.5062 6.23736 20.8159 6.2373H3.18408ZM6.7876 8.3291C7.10561 8.32913 7.38885 8.53018 7.49463 8.83008L9.57275 14.7236C9.7236 15.1525 9.40533 15.6023 8.95068 15.6025C8.66735 15.6025 8.41495 15.4209 8.32471 15.1523L7.87354 13.8086H5.13916L4.68896 15.1523C4.5988 15.4211 4.34649 15.6025 4.06299 15.6025C3.6083 15.6023 3.29009 15.1526 3.44092 14.7236L5.51514 8.83008C5.62084 8.53004 5.90502 8.32913 6.22314 8.3291H6.7876ZM11.3452 8.3291C11.7089 8.32928 12.0034 8.62458 12.0034 8.98828V14.1777C12.0035 14.2329 12.0489 14.2773 12.104 14.2773H14.5444C14.9101 14.2774 15.2063 14.5739 15.2065 14.9395C15.2065 15.3052 14.9102 15.6025 14.5444 15.6025H11.686C11.1339 15.6025 10.6862 15.1546 10.686 14.6025V8.98828C10.686 8.62449 10.9814 8.32912 11.3452 8.3291ZM19.7026 8.3291C20.0076 8.3291 20.2554 8.57686 20.2554 8.88184C20.2553 9.18673 20.0076 9.43359 19.7026 9.43359H18.1079C18.0527 9.4336 18.0073 9.47895 18.0073 9.53418V14.9492C18.0071 15.3099 17.7147 15.6025 17.354 15.6025C16.9933 15.6025 16.7009 15.3099 16.7007 14.9492V9.53418C16.7007 9.4791 16.6561 9.43384 16.6011 9.43359H15.0054C14.7005 9.43358 14.4527 9.18672 14.4526 8.88184C14.4526 8.57687 14.7004 8.32911 15.0054 8.3291H19.7026ZM6.50537 9.82129C6.48845 9.82132 6.4727 9.83163 6.46729 9.84766L5.49365 12.751H7.51807L6.54248 9.84766C6.53703 9.83177 6.52217 9.82138 6.50537 9.82129Z"
20
20
+
fill="currentColor"
21
21
+
/>
22
22
+
</svg>
23
23
+
);
24
24
+
};
25
25
+
26
26
+
export const ImageRemoveAltSmall = () => {
27
27
+
return (
28
28
+
<svg
29
29
+
width="24"
30
30
+
height="24"
31
31
+
viewBox="0 0 24 24"
32
32
+
fill="none"
33
33
+
xmlns="http://www.w3.org/2000/svg"
34
34
+
>
35
35
+
<path
36
36
+
d="M19.7529 3.18659C20.0459 2.89419 20.5207 2.89386 20.8135 3.18659C21.1061 3.47932 21.1058 3.95423 20.8135 4.24713L4.24805 20.8126C3.95517 21.1054 3.48038 21.1053 3.1875 20.8126C2.89463 20.5197 2.89467 20.0449 3.1875 19.752L19.7529 3.18659ZM21.6631 5.1651C22.6263 5.51251 23.3164 6.43272 23.3164 7.51568V16.4727L23.3037 16.7286C23.184 17.9046 22.2483 18.8402 21.0723 18.96L20.8164 18.9727H7.85645L9.10645 17.7227H20.8164C21.5063 17.7224 22.0661 17.1626 22.0664 16.4727V7.51568C22.0664 6.82552 21.5065 6.266 20.8164 6.26569H20.5635L21.6631 5.1651ZM14.9072 6.26569H3.18457C2.49444 6.26594 1.93457 6.82548 1.93457 7.51568V16.4727C1.93488 17.1626 2.49463 17.7225 3.18457 17.7227H3.4502L2.3457 18.8262C1.45485 18.5088 0.796417 17.7021 0.697266 16.7286L0.683594 7.51568C0.683594 6.2215 1.66842 5.15576 2.92871 5.0274H16.1455L14.9072 6.26569ZM6.78809 8.35748C7.1059 8.35772 7.38939 8.55871 7.49512 8.85846L8.75098 12.421L7.33594 13.837H5.13965L4.68945 15.1807C4.59924 15.4491 4.34665 15.6307 4.06348 15.6309C3.60892 15.6307 3.29088 15.1809 3.44141 14.752L5.51562 8.85846C5.62133 8.55842 5.90551 8.35751 6.22363 8.35748H6.78809ZM14.5449 14.3057C14.9103 14.306 15.2068 14.6024 15.207 14.9678C15.2067 15.3332 14.9103 15.6306 14.5449 15.6309H11.6865C11.5431 15.6309 11.4065 15.5994 11.2832 15.545L12.5234 14.3057H14.5449ZM19.7031 8.35748C20.0079 8.35775 20.2559 8.60541 20.2559 8.91022C20.2555 9.21468 20.0076 9.46171 19.7031 9.46197H18.1084C18.0532 9.46198 18.0078 9.50733 18.0078 9.56256V14.9776C18.0073 15.3378 17.7148 15.6307 17.3545 15.6309C16.994 15.6309 16.7017 15.338 16.7012 14.9776V10.128L18.4717 8.35748H19.7031ZM6.50586 9.84967C6.48894 9.84969 6.47319 9.86 6.46777 9.87603L5.49414 12.7794H7.51855L6.54297 9.87603C6.53757 9.86031 6.52245 9.84996 6.50586 9.84967ZM11.3457 8.35748C11.7091 8.35793 12.0039 8.65313 12.0039 9.01666V9.169L10.6865 10.4864V9.01666C10.6865 8.65286 10.9819 8.3575 11.3457 8.35748Z"
37
37
+
fill="currentColor"
38
38
+
/>
39
39
+
</svg>
40
40
+
);
41
41
+
};
+1
-45
components/Toolbar/ImageToolbar.tsx
···
3
3
import { useEntity, useReplicache } from "src/replicache";
4
4
import { useUIState } from "src/useUIState";
5
5
import { Props } from "components/Icons/Props";
6
6
-
import { useContext, useEffect } from "react";
7
7
-
import { ImageBlockContext } from "components/Blocks/ImageBlock";
8
8
-
import { set } from "colorjs.io/fn";
6
6
+
import { ImageAltSmall, ImageRemoveAltSmall } from "components/Icons/ImageAlt";
9
7
10
8
export const ImageFullBleedButton = (props: {}) => {
11
9
let { rep } = useReplicache();
···
120
118
</svg>
121
119
);
122
120
};
123
123
-
124
124
-
export const ImageAltSmall = (props: { fillColor: string }) => {
125
125
-
return (
126
126
-
<svg
127
127
-
width="24"
128
128
-
height="24"
129
129
-
viewBox="0 0 24 24"
130
130
-
fill="none"
131
131
-
xmlns="http://www.w3.org/2000/svg"
132
132
-
>
133
133
-
<rect
134
134
-
x="1.07886"
135
135
-
y="5.237"
136
136
-
width="21.8423"
137
137
-
height="13.4703"
138
138
-
rx="2.5"
139
139
-
fill={props.fillColor}
140
140
-
/>
141
141
-
<path
142
142
-
d="M21.0718 5C22.3323 5.12817 23.3159 6.19299 23.3159 7.4873V16.4443L23.3032 16.7002C23.1837 17.8766 22.2482 18.812 21.0718 18.9316L20.8159 18.9443H3.89014L2.92822 18.9316C1.752 18.8118 0.816287 17.8765 0.696777 16.7002L0.684082 7.4873C0.684082 6.19312 1.66793 5.12835 2.92822 5H21.0718ZM3.18408 6.2373C2.49395 6.23756 1.93408 6.7971 1.93408 7.4873V16.4443C1.93408 17.1345 2.49395 17.6941 3.18408 17.6943H20.8159C21.5062 17.6943 22.0659 17.1347 22.0659 16.4443V7.4873C22.0659 6.79698 21.5062 6.23736 20.8159 6.2373H3.18408ZM6.7876 8.3291C7.10561 8.32913 7.38885 8.53018 7.49463 8.83008L9.57275 14.7236C9.7236 15.1525 9.40533 15.6023 8.95068 15.6025C8.66735 15.6025 8.41495 15.4209 8.32471 15.1523L7.87354 13.8086H5.13916L4.68896 15.1523C4.5988 15.4211 4.34649 15.6025 4.06299 15.6025C3.6083 15.6023 3.29009 15.1526 3.44092 14.7236L5.51514 8.83008C5.62084 8.53004 5.90502 8.32913 6.22314 8.3291H6.7876ZM11.3452 8.3291C11.7089 8.32928 12.0034 8.62458 12.0034 8.98828V14.1777C12.0035 14.2329 12.0489 14.2773 12.104 14.2773H14.5444C14.9101 14.2774 15.2063 14.5739 15.2065 14.9395C15.2065 15.3052 14.9102 15.6025 14.5444 15.6025H11.686C11.1339 15.6025 10.6862 15.1546 10.686 14.6025V8.98828C10.686 8.62449 10.9814 8.32912 11.3452 8.3291ZM19.7026 8.3291C20.0076 8.3291 20.2554 8.57686 20.2554 8.88184C20.2553 9.18673 20.0076 9.43359 19.7026 9.43359H18.1079C18.0527 9.4336 18.0073 9.47895 18.0073 9.53418V14.9492C18.0071 15.3099 17.7147 15.6025 17.354 15.6025C16.9933 15.6025 16.7009 15.3099 16.7007 14.9492V9.53418C16.7007 9.4791 16.6561 9.43384 16.6011 9.43359H15.0054C14.7005 9.43358 14.4527 9.18672 14.4526 8.88184C14.4526 8.57687 14.7004 8.32911 15.0054 8.3291H19.7026ZM6.50537 9.82129C6.48845 9.82132 6.4727 9.83163 6.46729 9.84766L5.49365 12.751H7.51807L6.54248 9.84766C6.53703 9.83177 6.52217 9.82138 6.50537 9.82129Z"
143
143
-
fill="currentColor"
144
144
-
/>
145
145
-
</svg>
146
146
-
);
147
147
-
};
148
148
-
149
149
-
const ImageRemoveAltSmall = () => {
150
150
-
return (
151
151
-
<svg
152
152
-
width="24"
153
153
-
height="24"
154
154
-
viewBox="0 0 24 24"
155
155
-
fill="none"
156
156
-
xmlns="http://www.w3.org/2000/svg"
157
157
-
>
158
158
-
<path
159
159
-
d="M19.7529 3.18659C20.0459 2.89419 20.5207 2.89386 20.8135 3.18659C21.1061 3.47932 21.1058 3.95423 20.8135 4.24713L4.24805 20.8126C3.95517 21.1054 3.48038 21.1053 3.1875 20.8126C2.89463 20.5197 2.89467 20.0449 3.1875 19.752L19.7529 3.18659ZM21.6631 5.1651C22.6263 5.51251 23.3164 6.43272 23.3164 7.51568V16.4727L23.3037 16.7286C23.184 17.9046 22.2483 18.8402 21.0723 18.96L20.8164 18.9727H7.85645L9.10645 17.7227H20.8164C21.5063 17.7224 22.0661 17.1626 22.0664 16.4727V7.51568C22.0664 6.82552 21.5065 6.266 20.8164 6.26569H20.5635L21.6631 5.1651ZM14.9072 6.26569H3.18457C2.49444 6.26594 1.93457 6.82548 1.93457 7.51568V16.4727C1.93488 17.1626 2.49463 17.7225 3.18457 17.7227H3.4502L2.3457 18.8262C1.45485 18.5088 0.796417 17.7021 0.697266 16.7286L0.683594 7.51568C0.683594 6.2215 1.66842 5.15576 2.92871 5.0274H16.1455L14.9072 6.26569ZM6.78809 8.35748C7.1059 8.35772 7.38939 8.55871 7.49512 8.85846L8.75098 12.421L7.33594 13.837H5.13965L4.68945 15.1807C4.59924 15.4491 4.34665 15.6307 4.06348 15.6309C3.60892 15.6307 3.29088 15.1809 3.44141 14.752L5.51562 8.85846C5.62133 8.55842 5.90551 8.35751 6.22363 8.35748H6.78809ZM14.5449 14.3057C14.9103 14.306 15.2068 14.6024 15.207 14.9678C15.2067 15.3332 14.9103 15.6306 14.5449 15.6309H11.6865C11.5431 15.6309 11.4065 15.5994 11.2832 15.545L12.5234 14.3057H14.5449ZM19.7031 8.35748C20.0079 8.35775 20.2559 8.60541 20.2559 8.91022C20.2555 9.21468 20.0076 9.46171 19.7031 9.46197H18.1084C18.0532 9.46198 18.0078 9.50733 18.0078 9.56256V14.9776C18.0073 15.3378 17.7148 15.6307 17.3545 15.6309C16.994 15.6309 16.7017 15.338 16.7012 14.9776V10.128L18.4717 8.35748H19.7031ZM6.50586 9.84967C6.48894 9.84969 6.47319 9.86 6.46777 9.87603L5.49414 12.7794H7.51855L6.54297 9.87603C6.53757 9.86031 6.52245 9.84996 6.50586 9.84967ZM11.3457 8.35748C11.7091 8.35793 12.0039 8.65313 12.0039 9.01666V9.169L10.6865 10.4864V9.01666C10.6865 8.65286 10.9819 8.3575 11.3457 8.35748Z"
160
160
-
fill="currentColor"
161
161
-
/>
162
162
-
</svg>
163
163
-
);
164
164
-
};