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
adjusting some issues in popover
cozylittle.house
1 week ago
52258dbc
40e42a84
+177
-164
7 changed files
expand all
collapse all
unified
split
app
[leaflet_id]
actions
HelpButton.tsx
lish
[did]
[publication]
dashboard
settings
PublicationSettings.tsx
createPub
UpdatePubForm.tsx
components
Icons
PopoverArrow.tsx
Popover
index.tsx
ThemeManager
PubThemeSetter.tsx
ThemeProvider.tsx
+4
-2
app/[leaflet_id]/actions/HelpButton.tsx
···
19
side={isMobile ? "top" : "right"}
20
align={isMobile ? "center" : "start"}
21
asChild
22
-
className="max-w-xs w-full"
23
trigger={<ActionButton icon={<HelpSmall />} label="About" />}
24
>
25
-
<div className="flex flex-col text-sm gap-2 text-secondary">
0
0
26
{/* about links */}
27
<HelpLink text="📖 Leaflet Manual" url="https://about.leaflet.pub" />
28
<HelpLink text="💡 Make with Leaflet" url="https://make.leaflet.pub" />
···
19
side={isMobile ? "top" : "right"}
20
align={isMobile ? "center" : "start"}
21
asChild
22
+
className="max-w-xs w-full p-0!"
23
trigger={<ActionButton icon={<HelpSmall />} label="About" />}
24
>
25
+
<div
26
+
className={`flex flex-col text-sm gap-2 p-3 text-secondary max-h-[70vh] overflow-y-auto p-2" : ""}`}
27
+
>
28
{/* about links */}
29
<HelpLink text="📖 Leaflet Manual" url="https://about.leaflet.pub" />
30
<HelpLink text="💡 Make with Leaflet" url="https://make.leaflet.pub" />
+8
-7
app/lish/[did]/[publication]/dashboard/settings/PublicationSettings.tsx
···
27
onOpenChange={() => setState("menu")}
28
side={isMobile ? "top" : "right"}
29
align={isMobile ? "center" : "start"}
30
-
className={`max-w-xs w-[1000px] ${state === "theme" && "bg-white!"}`}
31
arrowFill={theme.colors["border-light"]}
32
trigger={
33
<ActionButton
···
64
setLoading={setLoading}
65
/>
66
)}
0
67
</Popover>
68
);
69
}
···
93
props.setState("general");
94
}}
95
>
96
-
General Settings
97
<ArrowRightTiny />
98
</button>
99
<button
100
className={menuItemClassName}
101
type="button"
102
-
onClick={() => props.setState("theme")}
103
>
104
-
Theme and Layout
105
<ArrowRightTiny />
106
</button>
107
<button
108
className={menuItemClassName}
109
type="button"
110
-
onClick={() => props.setState("post-options")}
111
>
112
-
Post Options
113
<ArrowRightTiny />
114
</button>
115
</div>
···
124
children: React.ReactNode;
125
}) => {
126
return (
127
-
<div className="flex justify-between font-bold text-secondary bg-border-light -mx-3 -mt-2 px-3 py-2 mb-1">
128
{props.children}
129
{props.state !== "menu" && (
130
<div className="flex gap-2">
···
27
onOpenChange={() => setState("menu")}
28
side={isMobile ? "top" : "right"}
29
align={isMobile ? "center" : "start"}
30
+
className={`flex flex-col max-w-xs w-[1000px] ${state === "theme" && "bg-white!"} pb-0!`}
31
arrowFill={theme.colors["border-light"]}
32
trigger={
33
<ActionButton
···
64
setLoading={setLoading}
65
/>
66
)}
67
+
<div className="spacer h-2 w-full" aria-hidden />
68
</Popover>
69
);
70
}
···
94
props.setState("general");
95
}}
96
>
97
+
Publication Settings
98
<ArrowRightTiny />
99
</button>
100
<button
101
className={menuItemClassName}
102
type="button"
103
+
onClick={() => props.setState("post-options")}
104
>
105
+
Post Settings
106
<ArrowRightTiny />
107
</button>
108
<button
109
className={menuItemClassName}
110
type="button"
111
+
onClick={() => props.setState("theme")}
112
>
113
+
Theme and Layout
114
<ArrowRightTiny />
115
</button>
116
</div>
···
125
children: React.ReactNode;
126
}) => {
127
return (
128
+
<div className="flex justify-between font-bold text-secondary bg-border-light -mx-3 -mt-2 px-3 py-2 mb-1 flex-shrink-0">
129
{props.children}
130
{props.state !== "menu" && (
131
<div className="flex gap-2">
+2
-1
app/lish/createPub/UpdatePubForm.tsx
···
74
75
return (
76
<form
0
77
onSubmit={async (e) => {
78
if (!pubData) return;
79
e.preventDefault();
···
104
>
105
General Settings
106
</PubSettingsHeader>
107
-
<div className="flex flex-col gap-3 w-[1000px] max-w-full pb-2">
108
<div className="flex items-center justify-between gap-2 mt-2 ">
109
<p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold">
110
Logo <span className="font-normal">(optional)</span>
···
74
75
return (
76
<form
77
+
className="min-h-0 flex-1 flex flex-col pb-2"
78
onSubmit={async (e) => {
79
if (!pubData) return;
80
e.preventDefault();
···
105
>
106
General Settings
107
</PubSettingsHeader>
108
+
<div className="flex flex-col gap-3 w-[1000px] max-w-full pb-2 overflow-y-auto min-h-0">
109
<div className="flex items-center justify-between gap-2 mt-2 ">
110
<p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold">
111
Logo <span className="font-normal">(optional)</span>
+1
-1
components/Icons/PopoverArrow.tsx
···
11
height="8"
12
viewBox="0 0 16 8"
13
fill="none"
14
-
className="-mt-px"
15
xmlns="http://www.w3.org/2000/svg"
16
>
17
<path
···
11
height="8"
12
viewBox="0 0 16 8"
13
fill="none"
14
+
className=""
15
xmlns="http://www.w3.org/2000/svg"
16
>
17
<path
-1
components/Popover/index.tsx
···
47
max-w-(--radix-popover-content-available-width)
48
max-h-(--radix-popover-content-available-height)
49
border border-border rounded-md shadow-md
50
-
overflow-y-scroll
51
${props.className}
52
`}
53
side={props.side}
···
47
max-w-(--radix-popover-content-available-width)
48
max-h-(--radix-popover-content-available-height)
49
border border-border rounded-md shadow-md
0
50
${props.className}
51
`}
52
side={props.side}
+159
-151
components/ThemeManager/PubThemeSetter.tsx
···
65
let toaster = useToaster();
66
67
return (
68
-
<BaseThemeProvider local {...localPubTheme} hasBackgroundImage={!!image}>
69
-
<form
70
-
onSubmit={async (e) => {
71
-
e.preventDefault();
72
-
if (!pub) return;
73
-
props.setLoading(true);
74
-
let result = await updatePublicationTheme({
75
-
uri: pub.uri,
76
-
theme: {
77
-
pageBackground: ColorToRGBA(localPubTheme.bgPage),
78
-
showPageBackground: showPageBackground,
79
-
backgroundColor: image
80
-
? ColorToRGBA(localPubTheme.bgLeaflet)
81
-
: ColorToRGB(localPubTheme.bgLeaflet),
82
-
backgroundRepeat: image?.repeat,
83
-
backgroundImage: image ? image.file : null,
84
-
pageWidth: pageWidth,
85
-
primary: ColorToRGB(localPubTheme.primary),
86
-
accentBackground: ColorToRGB(localPubTheme.accent1),
87
-
accentText: ColorToRGB(localPubTheme.accent2),
88
-
},
89
-
});
0
0
0
0
0
0
0
90
91
-
if (!result.success) {
92
-
props.setLoading(false);
93
-
if (result.error && isOAuthSessionError(result.error)) {
94
-
toaster({
95
-
content: <OAuthErrorMessage error={result.error} />,
96
-
type: "error",
97
-
});
98
-
} else {
99
-
toaster({
100
-
content: "Failed to update theme",
101
-
type: "error",
102
-
});
0
0
103
}
104
-
return;
105
-
}
106
107
-
mutate((pub) => {
108
-
if (result.publication && pub?.publication)
109
-
return {
110
-
...pub,
111
-
publication: { ...pub.publication, ...result.publication },
112
-
};
113
-
return pub;
114
-
}, false);
115
-
props.setLoading(false);
116
-
}}
117
-
>
118
-
<PubSettingsHeader
119
-
loading={props.loading}
120
-
setLoadingAction={props.setLoading}
121
-
backToMenuAction={props.backToMenu}
122
-
state={"theme"}
123
>
124
-
Theme and Layout
125
-
</PubSettingsHeader>
126
-
</form>
0
0
0
0
0
0
127
128
-
<div className="themeSetterContent flex flex-col w-full overflow-y-scroll -mb-2 mt-2 ">
129
-
<PubPageWidthSetter
130
-
pageWidth={pageWidth}
131
-
setPageWidth={setPageWidth}
132
-
thisPicker="page-width"
133
-
openPicker={openPicker}
134
-
setOpenPicker={setOpenPicker}
135
-
/>
136
-
<div className="themeBGLeaflet flex flex-col">
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
137
<div
138
-
className={`themeBgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `}
0
0
0
0
0
0
0
0
139
>
140
-
<div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md text-[#595959] bg-white">
141
-
<BackgroundPicker
142
-
bgImage={image}
143
-
setBgImage={setImage}
144
-
backgroundColor={localPubTheme.bgLeaflet}
145
pageBackground={localPubTheme.bgPage}
0
146
setPageBackground={(color) => {
147
setTheme((t) => ({ ...t, bgPage: color }));
148
}}
149
-
setBackgroundColor={(color) => {
150
-
setTheme((t) => ({ ...t, bgLeaflet: color }));
151
}}
152
openPicker={openPicker}
153
-
setOpenPicker={setOpenPicker}
154
-
hasPageBackground={!!showPageBackground}
155
-
setHasPageBackground={setShowPageBackground}
0
0
0
0
0
0
0
0
0
0
0
156
/>
157
</div>
158
-
159
-
<SectionArrow
160
-
fill="white"
161
-
stroke="#CCCCCC"
162
-
className="ml-2 -mt-[1px]"
163
-
/>
164
</div>
165
-
</div>
166
-
167
-
<div
168
-
style={{
169
-
backgroundImage: pubBGImage ? `url(${pubBGImage})` : undefined,
170
-
backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat",
171
-
backgroundPosition: "center",
172
-
backgroundSize: !leafletBGRepeat
173
-
? "cover"
174
-
: `calc(${leafletBGRepeat}px / 2 )`,
175
-
}}
176
-
className={` relative bg-bg-leaflet px-3 py-4 flex flex-col rounded-md border border-border `}
177
-
>
178
-
<div className={`flex flex-col gap-3 z-10`}>
179
-
<PagePickers
180
-
pageBackground={localPubTheme.bgPage}
181
-
primary={localPubTheme.primary}
182
-
setPageBackground={(color) => {
183
-
setTheme((t) => ({ ...t, bgPage: color }));
184
-
}}
185
-
setPrimary={(color) => {
186
-
setTheme((t) => ({ ...t, primary: color }));
187
-
}}
188
-
openPicker={openPicker}
189
-
setOpenPicker={(pickers) => setOpenPicker(pickers)}
190
-
hasPageBackground={showPageBackground}
191
-
/>
192
-
<PubAccentPickers
193
-
accent1={localPubTheme.accent1}
194
-
setAccent1={(color) => {
195
-
setTheme((t) => ({ ...t, accent1: color }));
196
-
}}
197
-
accent2={localPubTheme.accent2}
198
-
setAccent2={(color) => {
199
-
setTheme((t) => ({ ...t, accent2: color }));
200
-
}}
201
-
openPicker={openPicker}
202
-
setOpenPicker={(pickers) => setOpenPicker(pickers)}
203
-
/>
204
</div>
205
-
</div>
206
-
<div className="flex flex-col mt-4 ">
207
-
<div className="flex gap-2 items-center text-sm text-[#8C8C8C]">
208
-
<div className="text-sm">Preview</div>
209
-
<Separator classname="h-4!" />{" "}
210
-
<button
211
-
className={`${sample === "pub" ? "font-bold text-[#595959]" : ""}`}
212
-
onClick={() => setSample("pub")}
213
-
>
214
-
Pub
215
-
</button>
216
-
<button
217
-
className={`${sample === "post" ? "font-bold text-[#595959]" : ""}`}
218
-
onClick={() => setSample("post")}
219
-
>
220
-
Post
221
-
</button>
222
-
</div>
223
-
{sample === "pub" ? (
224
-
<SamplePub
225
-
pubBGImage={pubBGImage}
226
-
pubBGRepeat={leafletBGRepeat}
227
-
showPageBackground={showPageBackground}
228
-
/>
229
-
) : (
230
-
<SamplePost
231
-
pubBGImage={pubBGImage}
232
-
pubBGRepeat={leafletBGRepeat}
233
-
showPageBackground={showPageBackground}
234
-
/>
235
-
)}
236
</div>
237
</div>
238
</BaseThemeProvider>
···
65
let toaster = useToaster();
66
67
return (
68
+
<BaseThemeProvider
69
+
local
70
+
{...localPubTheme}
71
+
hasBackgroundImage={!!image}
72
+
className="min-h-0!"
73
+
>
74
+
<div className="min-h-0 flex-1 flex flex-col pb-0.5">
75
+
<form
76
+
className="flex-shrink-0"
77
+
onSubmit={async (e) => {
78
+
e.preventDefault();
79
+
if (!pub) return;
80
+
props.setLoading(true);
81
+
let result = await updatePublicationTheme({
82
+
uri: pub.uri,
83
+
theme: {
84
+
pageBackground: ColorToRGBA(localPubTheme.bgPage),
85
+
showPageBackground: showPageBackground,
86
+
backgroundColor: image
87
+
? ColorToRGBA(localPubTheme.bgLeaflet)
88
+
: ColorToRGB(localPubTheme.bgLeaflet),
89
+
backgroundRepeat: image?.repeat,
90
+
backgroundImage: image ? image.file : null,
91
+
pageWidth: pageWidth,
92
+
primary: ColorToRGB(localPubTheme.primary),
93
+
accentBackground: ColorToRGB(localPubTheme.accent1),
94
+
accentText: ColorToRGB(localPubTheme.accent2),
95
+
},
96
+
});
97
98
+
if (!result.success) {
99
+
props.setLoading(false);
100
+
if (result.error && isOAuthSessionError(result.error)) {
101
+
toaster({
102
+
content: <OAuthErrorMessage error={result.error} />,
103
+
type: "error",
104
+
});
105
+
} else {
106
+
toaster({
107
+
content: "Failed to update theme",
108
+
type: "error",
109
+
});
110
+
}
111
+
return;
112
}
0
0
113
114
+
mutate((pub) => {
115
+
if (result.publication && pub?.publication)
116
+
return {
117
+
...pub,
118
+
publication: { ...pub.publication, ...result.publication },
119
+
};
120
+
return pub;
121
+
}, false);
122
+
props.setLoading(false);
123
+
}}
0
0
0
0
0
0
124
>
125
+
<PubSettingsHeader
126
+
loading={props.loading}
127
+
setLoadingAction={props.setLoading}
128
+
backToMenuAction={props.backToMenu}
129
+
state={"theme"}
130
+
>
131
+
Theme and Layout
132
+
</PubSettingsHeader>
133
+
</form>
134
135
+
<div className="themeSetterContent flex flex-col w-full overflow-y-scroll min-h-0 -mb-2 pt-2 ">
136
+
<PubPageWidthSetter
137
+
pageWidth={pageWidth}
138
+
setPageWidth={setPageWidth}
139
+
thisPicker="page-width"
140
+
openPicker={openPicker}
141
+
setOpenPicker={setOpenPicker}
142
+
/>
143
+
<div className="themeBGLeaflet flex flex-col">
144
+
<div
145
+
className={`themeBgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `}
146
+
>
147
+
<div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md text-[#595959] bg-white">
148
+
<BackgroundPicker
149
+
bgImage={image}
150
+
setBgImage={setImage}
151
+
backgroundColor={localPubTheme.bgLeaflet}
152
+
pageBackground={localPubTheme.bgPage}
153
+
setPageBackground={(color) => {
154
+
setTheme((t) => ({ ...t, bgPage: color }));
155
+
}}
156
+
setBackgroundColor={(color) => {
157
+
setTheme((t) => ({ ...t, bgLeaflet: color }));
158
+
}}
159
+
openPicker={openPicker}
160
+
setOpenPicker={setOpenPicker}
161
+
hasPageBackground={!!showPageBackground}
162
+
setHasPageBackground={setShowPageBackground}
163
+
/>
164
+
</div>
165
+
166
+
<SectionArrow
167
+
fill="white"
168
+
stroke="#CCCCCC"
169
+
className="ml-2 -mt-[1px]"
170
+
/>
171
+
</div>
172
+
</div>
173
+
174
<div
175
+
style={{
176
+
backgroundImage: pubBGImage ? `url(${pubBGImage})` : undefined,
177
+
backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat",
178
+
backgroundPosition: "center",
179
+
backgroundSize: !leafletBGRepeat
180
+
? "cover"
181
+
: `calc(${leafletBGRepeat}px / 2 )`,
182
+
}}
183
+
className={` relative bg-bg-leaflet px-3 py-4 flex flex-col rounded-md border border-border `}
184
>
185
+
<div className={`flex flex-col gap-3 z-10`}>
186
+
<PagePickers
0
0
0
187
pageBackground={localPubTheme.bgPage}
188
+
primary={localPubTheme.primary}
189
setPageBackground={(color) => {
190
setTheme((t) => ({ ...t, bgPage: color }));
191
}}
192
+
setPrimary={(color) => {
193
+
setTheme((t) => ({ ...t, primary: color }));
194
}}
195
openPicker={openPicker}
196
+
setOpenPicker={(pickers) => setOpenPicker(pickers)}
197
+
hasPageBackground={showPageBackground}
198
+
/>
199
+
<PubAccentPickers
200
+
accent1={localPubTheme.accent1}
201
+
setAccent1={(color) => {
202
+
setTheme((t) => ({ ...t, accent1: color }));
203
+
}}
204
+
accent2={localPubTheme.accent2}
205
+
setAccent2={(color) => {
206
+
setTheme((t) => ({ ...t, accent2: color }));
207
+
}}
208
+
openPicker={openPicker}
209
+
setOpenPicker={(pickers) => setOpenPicker(pickers)}
210
/>
211
</div>
0
0
0
0
0
0
212
</div>
213
+
<div className="flex flex-col mt-4 ">
214
+
<div className="flex gap-2 items-center text-sm text-[#8C8C8C]">
215
+
<div className="text-sm">Preview</div>
216
+
<Separator classname="h-4!" />{" "}
217
+
<button
218
+
className={`${sample === "pub" ? "font-bold text-[#595959]" : ""}`}
219
+
onClick={() => setSample("pub")}
220
+
>
221
+
Pub
222
+
</button>
223
+
<button
224
+
className={`${sample === "post" ? "font-bold text-[#595959]" : ""}`}
225
+
onClick={() => setSample("post")}
226
+
>
227
+
Post
228
+
</button>
229
+
</div>
230
+
{sample === "pub" ? (
231
+
<SamplePub
232
+
pubBGImage={pubBGImage}
233
+
pubBGRepeat={leafletBGRepeat}
234
+
showPageBackground={showPageBackground}
235
+
/>
236
+
) : (
237
+
<SamplePost
238
+
pubBGImage={pubBGImage}
239
+
pubBGRepeat={leafletBGRepeat}
240
+
showPageBackground={showPageBackground}
241
+
/>
242
+
)}
0
0
0
0
0
0
0
0
0
243
</div>
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
244
</div>
245
</div>
246
</BaseThemeProvider>
+3
-1
components/ThemeManager/ThemeProvider.tsx
···
122
showPageBackground,
123
pageWidth,
124
hasBackgroundImage,
0
125
children,
126
}: {
127
local?: boolean;
···
136
highlight2: AriaColor;
137
highlight3: AriaColor;
138
pageWidth?: number;
0
139
children: React.ReactNode;
140
}) => {
141
// When showPageBackground is false and there's no background image,
···
239
]);
240
return (
241
<div
242
-
className="leafletWrapper w-full text-primary h-full min-h-fit flex flex-col bg-center items-stretch "
243
style={
244
{
245
"--bg-leaflet": colorToString(bgLeaflet, "rgb"),
···
122
showPageBackground,
123
pageWidth,
124
hasBackgroundImage,
125
+
className,
126
children,
127
}: {
128
local?: boolean;
···
137
highlight2: AriaColor;
138
highlight3: AriaColor;
139
pageWidth?: number;
140
+
className?: string;
141
children: React.ReactNode;
142
}) => {
143
// When showPageBackground is false and there's no background image,
···
241
]);
242
return (
243
<div
244
+
className={`leafletWrapper w-full text-primary h-full min-h-fit flex flex-col bg-center items-stretch ${className || ""}`}
245
style={
246
{
247
"--bg-leaflet": colorToString(bgLeaflet, "rgb"),