a tool for shared writing and social publishing

move pub theme into the settings button

+323 -253
-30
app/about/page.tsx
··· 1 - import { LegalContent } from "app/legal/content"; 2 - import Link from "next/link"; 3 - 4 - export default function AboutPage() { 5 - return ( 6 - <div className="flex flex-col gap-2"> 7 - <div className="flex flex-col h-[80vh] mx-auto sm:px-4 px-3 sm:py-6 py-4 max-w-prose gap-4 text-lg"> 8 - <p> 9 - Leaflet.pub is a web app for instantly creating and collaborating on 10 - documents.{" "} 11 - <Link href="/" prefetch={false}> 12 - Click here 13 - </Link>{" "} 14 - to create one and get started! 15 - </p> 16 - 17 - <p> 18 - Leaflet is made by Learning Futures Inc. Previously we built{" "} 19 - <a href="https://hyperlink.academy">hyperlink.academy</a> 20 - </p> 21 - <p> 22 - You can find us on{" "} 23 - <a href="https://bsky.app/profile/leaflet.pub">Bluesky</a> or email as 24 - at <a href="mailto:contact@leaflet.pub">contact@leaflet.pub</a> 25 - </p> 26 - </div> 27 - <LegalContent /> 28 - </div> 29 - ); 30 - }
+109 -17
app/lish/[did]/[publication]/dashboard/Actions.tsx
··· 18 18 import { PubThemeSetter } from "components/ThemeManager/PubThemeSetter"; 19 19 import { useIsMobile } from "src/hooks/isMobile"; 20 20 import { SpeedyLink } from "components/SpeedyLink"; 21 + import { FormEvent, useState } from "react"; 22 + import { GoBackSmall } from "components/Icons/GoBackSmall"; 23 + import { theme } from "tailwind.config"; 24 + import { ButtonPrimary } from "components/Buttons"; 25 + import { DotLoader } from "components/utils/DotLoader"; 26 + import { GoToArrow } from "components/Icons/GoToArrow"; 27 + import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; 21 28 22 29 export const Actions = (props: { publication: string }) => { 23 30 return ( 24 31 <> 25 32 <NewDraftActionButton publication={props.publication} /> 26 33 <PublicationShareButton /> 27 - <PublicationThemeButton /> 28 34 <PublicationSettingsButton publication={props.publication} /> 29 35 </> 30 36 ); ··· 88 94 89 95 function PublicationSettingsButton(props: { publication: string }) { 90 96 let isMobile = useIsMobile(); 97 + let [state, setState] = useState<"menu" | "general" | "theme">("menu"); 98 + let [loading, setLoading] = useState(false); 99 + 91 100 return ( 92 101 <Popover 93 102 asChild 94 103 side={isMobile ? "top" : "right"} 95 104 align={isMobile ? "center" : "start"} 96 - className="max-w-xs" 105 + className={`max-w-xs w-[1000px] ${state === "theme" && "bg-white!"}`} 106 + arrowFill={theme.colors["border-light"]} 97 107 trigger={ 98 108 <ActionButton 99 109 id="pub-settings-button" ··· 102 112 /> 103 113 } 104 114 > 105 - <EditPubForm /> 115 + {state === "general" ? ( 116 + <EditPubForm 117 + goBack={() => setState("menu")} 118 + loading={loading} 119 + setLoading={setLoading} 120 + /> 121 + ) : state === "theme" ? ( 122 + <PubThemeSetter 123 + goBack={() => setState("menu")} 124 + loading={loading} 125 + setLoading={setLoading} 126 + /> 127 + ) : ( 128 + <SettingsMenu 129 + state={state} 130 + setState={setState} 131 + loading={loading} 132 + setLoading={setLoading} 133 + /> 134 + )} 106 135 </Popover> 107 136 ); 108 137 } 109 138 110 - function PublicationThemeButton() { 111 - let isMobile = useIsMobile(); 139 + const SettingsMenu = (props: { 140 + state: "menu" | "general" | "theme"; 141 + setState: (s: typeof props.state) => void; 142 + loading: boolean; 143 + setLoading: (l: boolean) => void; 144 + }) => { 145 + let menuItemClassName = 146 + "hover:bg-[var(--accent-light)] text-secondary hover:no-underline! rounded-md px-2 py-0.5 -mx-[8px] font-bold text-left flex items-center justify-between"; 112 147 113 148 return ( 114 - <Popover 115 - asChild 116 - className="max-w-xs pb-0 bg-white!" 117 - side={isMobile ? "top" : "right"} 118 - align={isMobile ? "center" : "start"} 119 - trigger={ 120 - <ActionButton id="pub-theme-button" icon=<PaintSmall /> label="Theme" /> 121 - } 122 - > 123 - <PubThemeSetter /> 124 - </Popover> 149 + <div className="flex flex-col gap-0.5"> 150 + <PubSettingsHeader 151 + loading={props.loading} 152 + setLoadingAction={props.setLoading} 153 + state={"menu"} 154 + /> 155 + <button 156 + className={menuItemClassName} 157 + type="button" 158 + onClick={() => { 159 + props.setState("general"); 160 + }} 161 + > 162 + Settings 163 + <ArrowRightTiny /> 164 + </button> 165 + <button 166 + className={menuItemClassName} 167 + type="button" 168 + onClick={() => props.setState("theme")} 169 + > 170 + Publication Theme 171 + <ArrowRightTiny /> 172 + </button> 173 + <SpeedyLink 174 + className={menuItemClassName} 175 + href="https://about.leaflet.pub/ 176 + " 177 + > 178 + About Leaflet 179 + <ArrowRightTiny /> 180 + </SpeedyLink> 181 + </div> 125 182 ); 126 - } 183 + }; 184 + 185 + export const PubSettingsHeader = (props: { 186 + state: "menu" | "general" | "theme"; 187 + goBackAction?: () => void; 188 + loading: boolean; 189 + setLoadingAction: (l: boolean) => void; 190 + }) => { 191 + return ( 192 + <div className="flex justify-between font-bold text-secondary bg-border-light -mx-3 -mt-2 px-3 pt-2 pb-1 mb-1"> 193 + {props.state === "menu" 194 + ? "Settings" 195 + : props.state === "general" 196 + ? "General" 197 + : props.state === "theme" 198 + ? "Publication Theme" 199 + : ""} 200 + {props.state !== "menu" && ( 201 + <div className="flex gap-2"> 202 + <button 203 + type="button" 204 + onClick={() => { 205 + props.goBackAction && props.goBackAction(); 206 + }} 207 + > 208 + <GoBackSmall className="text-accent-contrast" /> 209 + </button> 210 + 211 + <ButtonPrimary compact type="submit"> 212 + {props.loading ? <DotLoader /> : "Update"} 213 + </ButtonPrimary> 214 + </div> 215 + )} 216 + </div> 217 + ); 218 + };
+106 -98
app/lish/createPub/UpdatePubForm.tsx
··· 20 20 import Link from "next/link"; 21 21 import { Checkbox } from "components/Checkbox"; 22 22 import type { GetDomainConfigResponseBody } from "@vercel/sdk/esm/models/getdomainconfigop"; 23 + import { PubSettingsHeader } from "../[did]/[publication]/dashboard/Actions"; 23 24 24 - export const EditPubForm = () => { 25 + export const EditPubForm = (props: { 26 + goBack: () => void; 27 + loading: boolean; 28 + setLoading: (l: boolean) => void; 29 + }) => { 25 30 let { data } = usePublicationData(); 26 31 let { publication: pubData } = data || {}; 27 32 let record = pubData?.record as PubLeafletPublication.Record; ··· 57 62 58 63 return ( 59 64 <form 60 - className="flex flex-col gap-3 w-[1000px] max-w-full py-1" 61 65 onSubmit={async (e) => { 62 66 if (!pubData) return; 63 67 e.preventDefault(); 64 - setFormState("loading"); 68 + props.setLoading(true); 69 + console.log("step 1:update"); 65 70 let data = await updatePublication({ 66 71 uri: pubData.uri, 67 72 name: nameValue, ··· 73 78 }, 74 79 }); 75 80 toast({ type: "success", content: "Updated!" }); 76 - setFormState("normal"); 81 + props.setLoading(false); 77 82 mutate("publication-data"); 78 83 }} 79 84 > 80 - <div className="flex items-center justify-between gap-2 "> 81 - <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold"> 82 - Logo <span className="font-normal">(optional)</span> 83 - </p> 84 - <div 85 - className={`w-8 h-8 rounded-full flex items-center justify-center cursor-pointer ${iconPreview ? "border border-border-light hover:outline-border" : "border border-dotted border-accent-contrast hover:outline-accent-contrast"} selected-outline`} 86 - onClick={() => fileInputRef.current?.click()} 87 - > 88 - {iconPreview ? ( 89 - <img 90 - src={iconPreview} 91 - alt="Logo preview" 92 - className="w-full h-full rounded-full object-cover" 93 - /> 94 - ) : ( 95 - <AddTiny className="text-accent-1" /> 96 - )} 85 + <PubSettingsHeader 86 + loading={props.loading} 87 + setLoadingAction={props.setLoading} 88 + goBackAction={props.goBack} 89 + state={"theme"} 90 + /> 91 + <div className="flex flex-col gap-3 w-[1000px] max-w-full pb-2"> 92 + <div className="flex items-center justify-between gap-2 "> 93 + <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold"> 94 + Logo <span className="font-normal">(optional)</span> 95 + </p> 96 + <div 97 + className={`w-8 h-8 rounded-full flex items-center justify-center cursor-pointer ${iconPreview ? "border border-border-light hover:outline-border" : "border border-dotted border-accent-contrast hover:outline-accent-contrast"} selected-outline`} 98 + onClick={() => fileInputRef.current?.click()} 99 + > 100 + {iconPreview ? ( 101 + <img 102 + src={iconPreview} 103 + alt="Logo preview" 104 + className="w-full h-full rounded-full object-cover" 105 + /> 106 + ) : ( 107 + <AddTiny className="text-accent-1" /> 108 + )} 109 + </div> 110 + <input 111 + type="file" 112 + accept="image/*" 113 + className="hidden" 114 + ref={fileInputRef} 115 + onChange={(e) => { 116 + const file = e.target.files?.[0]; 117 + if (file) { 118 + setIconFile(file); 119 + const reader = new FileReader(); 120 + reader.onload = (e) => { 121 + setIconPreview(e.target?.result as string); 122 + }; 123 + reader.readAsDataURL(file); 124 + } 125 + }} 126 + /> 97 127 </div> 98 - <input 99 - type="file" 100 - accept="image/*" 101 - className="hidden" 102 - ref={fileInputRef} 103 - onChange={(e) => { 104 - const file = e.target.files?.[0]; 105 - if (file) { 106 - setIconFile(file); 107 - const reader = new FileReader(); 108 - reader.onload = (e) => { 109 - setIconPreview(e.target?.result as string); 110 - }; 111 - reader.readAsDataURL(file); 112 - } 113 - }} 114 - /> 115 - </div> 116 128 117 - <label> 118 - <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold"> 119 - Publication Name 120 - </p> 121 - <Input 122 - className="input-with-border w-full text-primary" 123 - type="text" 124 - id="pubName" 125 - value={nameValue} 126 - onChange={(e) => { 127 - setNameValue(e.currentTarget.value); 128 - }} 129 - /> 130 - </label> 131 - <label> 132 - <p className="text-tertiary italic text-sm font-bold pl-0.5 pb-0.5"> 133 - Description <span className="font-normal">(optional)</span> 134 - </p> 135 - <Input 136 - textarea 137 - className="input-with-border w-full text-primary" 138 - rows={3} 139 - id="pubDescription" 140 - value={descriptionValue} 141 - onChange={(e) => { 142 - setDescriptionValue(e.currentTarget.value); 143 - }} 144 - /> 145 - </label> 146 - 147 - <CustomDomainForm /> 148 - <hr className="border-border-light" /> 149 - 150 - <Checkbox 151 - checked={showInDiscover} 152 - onChange={(e) => setShowInDiscover(e.target.checked)} 153 - > 154 - <div className=" pt-0.5 flex flex-col text-sm italic text-tertiary "> 155 - <p className="font-bold"> 156 - Show In{" "} 157 - <a href="/discover" target="_blank"> 158 - Discover 159 - </a> 129 + <label> 130 + <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold"> 131 + Publication Name 160 132 </p> 161 - <p className="text-xs text-tertiary font-normal"> 162 - This publication will appear on our public Discover page 133 + <Input 134 + className="input-with-border w-full text-primary" 135 + type="text" 136 + id="pubName" 137 + value={nameValue} 138 + onChange={(e) => { 139 + setNameValue(e.currentTarget.value); 140 + }} 141 + /> 142 + </label> 143 + <label> 144 + <p className="text-tertiary italic text-sm font-bold pl-0.5 pb-0.5"> 145 + Description <span className="font-normal">(optional)</span> 163 146 </p> 164 - </div> 165 - </Checkbox> 147 + <Input 148 + textarea 149 + className="input-with-border w-full text-primary" 150 + rows={3} 151 + id="pubDescription" 152 + value={descriptionValue} 153 + onChange={(e) => { 154 + setDescriptionValue(e.currentTarget.value); 155 + }} 156 + /> 157 + </label> 166 158 167 - <Checkbox 168 - checked={showComments} 169 - onChange={(e) => setShowComments(e.target.checked)} 170 - > 171 - <div className=" pt-0.5 flex flex-col text-sm italic text-tertiary "> 172 - <p className="font-bold">Show comments on posts</p> 173 - </div> 174 - </Checkbox> 175 - <hr className="border-border-light" /> 159 + <CustomDomainForm /> 160 + <hr className="border-border-light" /> 161 + 162 + <Checkbox 163 + checked={showInDiscover} 164 + onChange={(e) => setShowInDiscover(e.target.checked)} 165 + > 166 + <div className=" pt-0.5 flex flex-col text-sm italic text-tertiary "> 167 + <p className="font-bold"> 168 + Show In{" "} 169 + <a href="/discover" target="_blank"> 170 + Discover 171 + </a> 172 + </p> 173 + <p className="text-xs text-tertiary font-normal"> 174 + This publication will appear on our public Discover page 175 + </p> 176 + </div> 177 + </Checkbox> 176 178 177 - <ButtonPrimary className="place-self-end" type="submit"> 178 - {formState === "loading" ? <DotLoader /> : "Update!"} 179 - </ButtonPrimary> 179 + <Checkbox 180 + checked={showComments} 181 + onChange={(e) => setShowComments(e.target.checked)} 182 + > 183 + <div className=" pt-0.5 flex flex-col text-sm italic text-tertiary "> 184 + <p className="font-bold">Show comments on posts</p> 185 + </div> 186 + </Checkbox> 187 + </div> 180 188 </form> 181 189 ); 182 190 };
+2 -2
components/ActionBar/Navigation.tsx
··· 19 19 import { hydrateNotifications } from "src/notifications"; 20 20 import { supabaseServerClient } from "supabase/serverClient"; 21 21 import { CommentNotification } from "app/(home-pages)/notifications/CommentNotication"; 22 + import { Separator } from "components/Layout"; 22 23 23 24 export type navPages = "home" | "reader" | "pub" | "discover" | "notifications"; 24 25 ··· 51 52 ); 52 53 return ( 53 54 <div className="flex gap-1 pr-2"> 54 - <NotificationButton /> 55 - 56 55 <Popover 57 56 onOpenAutoFocus={(e) => e.preventDefault()} 58 57 asChild ··· 82 81 isMobile 83 82 /> 84 83 </Popover> 84 + <NotificationButton /> 85 85 </div> 86 86 ); 87 87 };
+1
components/Icons/GoBackSmall.tsx
··· 8 8 viewBox="0 0 24 24" 9 9 fill="none" 10 10 xmlns="http://www.w3.org/2000/svg" 11 + {...props} 11 12 > 12 13 <path 13 14 d="M12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2ZM12.6826 5.96582C12.2921 5.57556 11.659 5.57557 11.2686 5.96582L5.94141 11.293C5.55114 11.6834 5.55114 12.3166 5.94141 12.707L11.2686 18.0332L11.3438 18.1025C11.7365 18.4229 12.3165 18.3993 12.6826 18.0332C13.0484 17.6671 13.0712 17.088 12.751 16.6953L12.6826 16.6191L9.06348 13H17.9473L18.0498 12.9951C18.5538 12.9438 18.9471 12.5175 18.9473 12C18.9472 11.4824 18.5538 11.0563 18.0498 11.0049L17.9473 11H9.06152L12.6826 7.37988C13.0729 6.98941 13.0729 6.35629 12.6826 5.96582Z"
+103 -100
components/ThemeManager/PubThemeSetter.tsx
··· 17 17 import { BackgroundPicker } from "./PubPickers/PubBackgroundPickers"; 18 18 import { PubAccentPickers } from "./PubPickers/PubAcccentPickers"; 19 19 import { Separator } from "components/Layout"; 20 + import { PubSettingsHeader } from "app/lish/[did]/[publication]/dashboard/Actions"; 20 21 21 22 export type ImageState = { 22 23 src: string; 23 24 file?: File; 24 25 repeat: number | null; 25 26 }; 26 - export const PubThemeSetter = () => { 27 - let [loading, setLoading] = useState(false); 27 + export const PubThemeSetter = (props: { 28 + goBack: () => void; 29 + loading: boolean; 30 + setLoading: (l: boolean) => void; 31 + }) => { 28 32 let [sample, setSample] = useState<"pub" | "post">("pub"); 29 33 let [openPicker, setOpenPicker] = useState<pickers>("null"); 30 34 let { data, mutate } = usePublicationData(); ··· 58 62 return ( 59 63 <BaseThemeProvider local {...localPubTheme}> 60 64 <form 61 - className="bg-accent-1 -mx-3 -mt-2 px-3 py-1 mb-1 flex justify-between items-center" 62 65 onSubmit={async (e) => { 63 66 e.preventDefault(); 64 67 if (!pub) return; 65 - setLoading(true); 68 + props.setLoading(true); 66 69 let result = await updatePublicationTheme({ 67 70 uri: pub.uri, 68 71 theme: { ··· 86 89 }; 87 90 return pub; 88 91 }, false); 89 - setLoading(false); 92 + props.setLoading(false); 90 93 }} 91 94 > 92 - <h4 className="text-accent-2">Publication Theme</h4> 93 - <ButtonSecondary compact> 94 - {loading ? <DotLoader /> : "Update"} 95 - </ButtonSecondary> 95 + <PubSettingsHeader 96 + loading={props.loading} 97 + setLoadingAction={props.setLoading} 98 + goBackAction={props.goBack} 99 + state={"theme"} 100 + /> 96 101 </form> 97 102 98 - <div> 99 - <div className="themeSetterContent flex flex-col w-full overflow-y-scroll no-scrollbar"> 100 - <div className="themeBGLeaflet flex"> 101 - <div 102 - className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `} 103 - > 104 - <div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md text-[#595959] bg-white"> 105 - <BackgroundPicker 106 - bgImage={image} 107 - setBgImage={setImage} 108 - backgroundColor={localPubTheme.bgLeaflet} 109 - pageBackground={localPubTheme.bgPage} 110 - setPageBackground={(color) => { 111 - setTheme((t) => ({ ...t, bgPage: color })); 112 - }} 113 - setBackgroundColor={(color) => { 114 - setTheme((t) => ({ ...t, bgLeaflet: color })); 115 - }} 116 - openPicker={openPicker} 117 - setOpenPicker={setOpenPicker} 118 - hasPageBackground={!!showPageBackground} 119 - setHasPageBackground={setShowPageBackground} 120 - /> 121 - </div> 122 - 123 - <SectionArrow 124 - fill="white" 125 - stroke="#CCCCCC" 126 - className="ml-2 -mt-px" 127 - /> 128 - </div> 129 - </div> 130 - 103 + <div className="themeSetterContent flex flex-col w-full overflow-y-scroll -mb-2 "> 104 + <div className="themeBGLeaflet flex"> 131 105 <div 132 - style={{ 133 - backgroundImage: pubBGImage ? `url(${pubBGImage})` : undefined, 134 - backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat", 135 - backgroundPosition: "center", 136 - backgroundSize: !leafletBGRepeat 137 - ? "cover" 138 - : `calc(${leafletBGRepeat}px / 2 )`, 139 - }} 140 - className={` relative bg-bg-leaflet px-3 py-4 flex flex-col rounded-md border border-border `} 106 + className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full `} 141 107 > 142 - <div className={`flex flex-col gap-3 z-10`}> 143 - <PagePickers 108 + <div className="bgPickerBody w-full flex flex-col gap-2 p-2 mt-1 border border-[#CCCCCC] rounded-md text-[#595959] bg-white"> 109 + <BackgroundPicker 110 + bgImage={image} 111 + setBgImage={setImage} 112 + backgroundColor={localPubTheme.bgLeaflet} 144 113 pageBackground={localPubTheme.bgPage} 145 - primary={localPubTheme.primary} 146 114 setPageBackground={(color) => { 147 115 setTheme((t) => ({ ...t, bgPage: color })); 148 116 }} 149 - setPrimary={(color) => { 150 - setTheme((t) => ({ ...t, primary: color })); 117 + setBackgroundColor={(color) => { 118 + setTheme((t) => ({ ...t, bgLeaflet: color })); 151 119 }} 152 120 openPicker={openPicker} 153 - setOpenPicker={(pickers) => setOpenPicker(pickers)} 154 - hasPageBackground={showPageBackground} 155 - /> 156 - <PubAccentPickers 157 - accent1={localPubTheme.accent1} 158 - setAccent1={(color) => { 159 - setTheme((t) => ({ ...t, accent1: color })); 160 - }} 161 - accent2={localPubTheme.accent2} 162 - setAccent2={(color) => { 163 - setTheme((t) => ({ ...t, accent2: color })); 164 - }} 165 - openPicker={openPicker} 166 - setOpenPicker={(pickers) => setOpenPicker(pickers)} 121 + setOpenPicker={setOpenPicker} 122 + hasPageBackground={!!showPageBackground} 123 + setHasPageBackground={setShowPageBackground} 167 124 /> 168 125 </div> 126 + 127 + <SectionArrow 128 + fill="white" 129 + stroke="#CCCCCC" 130 + className="ml-2 -mt-[1px]" 131 + /> 169 132 </div> 170 - <div className="flex flex-col mt-4 "> 171 - <div className="flex gap-2 items-center text-sm text-[#8C8C8C]"> 172 - <div className="text-sm">Preview</div> 173 - <Separator classname="h-4!" />{" "} 174 - <button 175 - className={`${sample === "pub" ? "font-bold text-[#595959]" : ""}`} 176 - onClick={() => setSample("pub")} 177 - > 178 - Pub 179 - </button> 180 - <button 181 - className={`${sample === "post" ? "font-bold text-[#595959]" : ""}`} 182 - onClick={() => setSample("post")} 183 - > 184 - Post 185 - </button> 186 - </div> 187 - {sample === "pub" ? ( 188 - <SamplePub 189 - pubBGImage={pubBGImage} 190 - pubBGRepeat={leafletBGRepeat} 191 - showPageBackground={showPageBackground} 192 - /> 193 - ) : ( 194 - <SamplePost 195 - pubBGImage={pubBGImage} 196 - pubBGRepeat={leafletBGRepeat} 197 - showPageBackground={showPageBackground} 198 - /> 199 - )} 133 + </div> 134 + 135 + <div 136 + style={{ 137 + backgroundImage: pubBGImage ? `url(${pubBGImage})` : undefined, 138 + backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat", 139 + backgroundPosition: "center", 140 + backgroundSize: !leafletBGRepeat 141 + ? "cover" 142 + : `calc(${leafletBGRepeat}px / 2 )`, 143 + }} 144 + className={` relative bg-bg-leaflet px-3 py-4 flex flex-col rounded-md border border-border `} 145 + > 146 + <div className={`flex flex-col gap-3 z-10`}> 147 + <PagePickers 148 + pageBackground={localPubTheme.bgPage} 149 + primary={localPubTheme.primary} 150 + setPageBackground={(color) => { 151 + setTheme((t) => ({ ...t, bgPage: color })); 152 + }} 153 + setPrimary={(color) => { 154 + setTheme((t) => ({ ...t, primary: color })); 155 + }} 156 + openPicker={openPicker} 157 + setOpenPicker={(pickers) => setOpenPicker(pickers)} 158 + hasPageBackground={showPageBackground} 159 + /> 160 + <PubAccentPickers 161 + accent1={localPubTheme.accent1} 162 + setAccent1={(color) => { 163 + setTheme((t) => ({ ...t, accent1: color })); 164 + }} 165 + accent2={localPubTheme.accent2} 166 + setAccent2={(color) => { 167 + setTheme((t) => ({ ...t, accent2: color })); 168 + }} 169 + openPicker={openPicker} 170 + setOpenPicker={(pickers) => setOpenPicker(pickers)} 171 + /> 172 + </div> 173 + </div> 174 + <div className="flex flex-col mt-4 "> 175 + <div className="flex gap-2 items-center text-sm text-[#8C8C8C]"> 176 + <div className="text-sm">Preview</div> 177 + <Separator classname="h-4!" />{" "} 178 + <button 179 + className={`${sample === "pub" ? "font-bold text-[#595959]" : ""}`} 180 + onClick={() => setSample("pub")} 181 + > 182 + Pub 183 + </button> 184 + <button 185 + className={`${sample === "post" ? "font-bold text-[#595959]" : ""}`} 186 + onClick={() => setSample("post")} 187 + > 188 + Post 189 + </button> 200 190 </div> 191 + {sample === "pub" ? ( 192 + <SamplePub 193 + pubBGImage={pubBGImage} 194 + pubBGRepeat={leafletBGRepeat} 195 + showPageBackground={showPageBackground} 196 + /> 197 + ) : ( 198 + <SamplePost 199 + pubBGImage={pubBGImage} 200 + pubBGRepeat={leafletBGRepeat} 201 + showPageBackground={showPageBackground} 202 + /> 203 + )} 201 204 </div> 202 205 </div> 203 206 </BaseThemeProvider>
+2 -6
components/Toast.tsx
··· 95 95 from: { top: -40 }, 96 96 enter: { top: 8 }, 97 97 leave: { top: -40 }, 98 - config: { 99 - mass: 8, 100 - friction: 150, 101 - tension: 2000, 102 - }, 98 + config: {}, 103 99 }); 104 100 105 101 return transitions((style, item) => { 106 102 return item ? ( 107 103 <animated.div 108 104 style={style} 109 - className={`toastAnimationWrapper fixed bottom-0 right-0 left-0 z-50 h-fit`} 105 + className={`toastAnimationWrapper fixed top-0 bottom-0 right-0 left-0 z-50 h-fit`} 110 106 > 111 107 <div 112 108 className={`toast absolute right-2 w-max shadow-md px-3 py-1 flex flex-row gap-2 rounded-full border text-center ${