a tool for shared writing and social publishing

adjustments to the invite contributor flow

+49 -162
+1 -1
app/lish/[did]/[publication]/dashboard/Actions.tsx
··· 1 1 "use client"; 2 2 3 3 import { NewDraftActionButton } from "./NewDraftButton"; 4 - import { PublicationSettingsButton } from "./PublicationSettings"; 4 + import { PublicationSettingsButton } from "./publicationSettings/PublicationSettings"; 5 5 import { ActionButton } from "components/ActionBar/ActionButton"; 6 6 import { ShareSmall } from "components/Icons/ShareSmall"; 7 7 import { Menu } from "components/Layout";
-132
app/lish/[did]/[publication]/dashboard/PublicationSettings.tsx
··· 1 - "use client"; 2 - 3 - import { ActionButton } from "components/ActionBar/ActionButton"; 4 - import { Popover } from "components/Popover"; 5 - import { SettingsSmall } from "components/Icons/SettingsSmall"; 6 - import { EditPubForm } from "app/lish/createPub/UpdatePubForm"; 7 - import { PubThemeSetter } from "components/ThemeManager/PubThemeSetter"; 8 - import { useIsMobile } from "src/hooks/isMobile"; 9 - import { useState } from "react"; 10 - import { GoBackSmall } from "components/Icons/GoBackSmall"; 11 - import { theme } from "tailwind.config"; 12 - import { ButtonPrimary } from "components/Buttons"; 13 - import { DotLoader } from "components/utils/DotLoader"; 14 - import { ArrowRightTiny } from "components/Icons/ArrowRightTiny"; 15 - 16 - export function PublicationSettingsButton(props: { publication: string }) { 17 - let isMobile = useIsMobile(); 18 - let [state, setState] = useState<"menu" | "general" | "theme">("menu"); 19 - let [loading, setLoading] = useState(false); 20 - 21 - return ( 22 - <Popover 23 - asChild 24 - onOpenChange={() => setState("menu")} 25 - side={isMobile ? "top" : "right"} 26 - align={isMobile ? "center" : "start"} 27 - className={`max-w-xs w-[1000px] ${state === "theme" && "bg-white!"}`} 28 - arrowFill={theme.colors["border-light"]} 29 - trigger={ 30 - <ActionButton 31 - id="pub-settings-button" 32 - icon=<SettingsSmall /> 33 - label="Settings" 34 - /> 35 - } 36 - > 37 - {state === "general" ? ( 38 - <EditPubForm 39 - backToMenuAction={() => setState("menu")} 40 - loading={loading} 41 - setLoadingAction={setLoading} 42 - /> 43 - ) : state === "theme" ? ( 44 - <PubThemeSetter 45 - backToMenu={() => setState("menu")} 46 - loading={loading} 47 - setLoading={setLoading} 48 - /> 49 - ) : ( 50 - <PubSettingsMenu 51 - state={state} 52 - setState={setState} 53 - loading={loading} 54 - setLoading={setLoading} 55 - /> 56 - )} 57 - </Popover> 58 - ); 59 - } 60 - 61 - const PubSettingsMenu = (props: { 62 - state: "menu" | "general" | "theme"; 63 - setState: (s: typeof props.state) => void; 64 - loading: boolean; 65 - setLoading: (l: boolean) => void; 66 - }) => { 67 - let menuItemClassName = 68 - "menuItem -mx-[8px] text-left flex items-center justify-between hover:no-underline!"; 69 - 70 - return ( 71 - <div className="flex flex-col gap-0.5"> 72 - <PubSettingsHeader 73 - loading={props.loading} 74 - setLoadingAction={props.setLoading} 75 - state={"menu"} 76 - /> 77 - <button 78 - className={menuItemClassName} 79 - type="button" 80 - onClick={() => { 81 - props.setState("general"); 82 - }} 83 - > 84 - Publication Settings 85 - <ArrowRightTiny /> 86 - </button> 87 - <button 88 - className={menuItemClassName} 89 - type="button" 90 - onClick={() => props.setState("theme")} 91 - > 92 - Publication Theme 93 - <ArrowRightTiny /> 94 - </button> 95 - </div> 96 - ); 97 - }; 98 - 99 - export const PubSettingsHeader = (props: { 100 - state: "menu" | "general" | "theme"; 101 - backToMenuAction?: () => void; 102 - loading: boolean; 103 - setLoadingAction: (l: boolean) => void; 104 - }) => { 105 - return ( 106 - <div className="flex justify-between font-bold text-secondary bg-border-light -mx-3 -mt-2 px-3 py-2 mb-1"> 107 - {props.state === "menu" 108 - ? "Settings" 109 - : props.state === "general" 110 - ? "General" 111 - : props.state === "theme" 112 - ? "Publication Theme" 113 - : ""} 114 - {props.state !== "menu" && ( 115 - <div className="flex gap-2"> 116 - <button 117 - type="button" 118 - onClick={() => { 119 - props.backToMenuAction && props.backToMenuAction(); 120 - }} 121 - > 122 - <GoBackSmall className="text-accent-contrast" /> 123 - </button> 124 - 125 - <ButtonPrimary compact type="submit"> 126 - {props.loading ? <DotLoader /> : "Update"} 127 - </ButtonPrimary> 128 - </div> 129 - )} 130 - </div> 131 - ); 132 - };
+38 -20
app/lish/[did]/[publication]/dashboard/publicationSettings/PublicationContributors.tsx
··· 7 7 import { useState } from "react"; 8 8 import { Input } from "components/Input"; 9 9 import { ButtonPrimary } from "components/Buttons"; 10 + import { PopoverArrow } from "components/Icons/PopoverArrow"; 11 + import { useSmoker } from "components/Toast"; 10 12 11 13 export const PubContributorManager = (props: { 12 14 backToMenuAction: () => void; ··· 54 56 }) => { 55 57 let [inputValue, setInputValue] = useState(""); 56 58 return ( 57 - <div className="flex flex-col gap-1 "> 58 - <div className="flex flex-col gap-1 py-2"> 59 - <div className="flex flex-col gap-0.5 text-sm text-tertiary "> 60 - <ButtonPrimary fullWidth compact className=" "> 61 - Get Contributor Invite Link 62 - </ButtonPrimary> 63 - Only added contributors can access 64 - </div> 65 - </div> 66 - <hr className="border-border-light" /> 67 - <div className="flex flex-col gap-0.5 my-2"> 59 + <div className="flex flex-col gap-1 pt-2"> 60 + <div className="flex flex-col gap-0.5"> 68 61 <div className="font-bold text-tertiary text-sm"> 69 62 Add a New Contributor 70 63 </div> ··· 72 65 <div className="text-tertiary">@</div> 73 66 <Input 74 67 placeholder="search bluesky handles" 75 - className="w-full outline-none!" 68 + className="w-full outline-none! text-primary" 76 69 value={inputValue} 77 70 onChange={(e) => setInputValue(e.currentTarget.value)} 78 71 /> 79 72 </div> 80 73 </div> 74 + 75 + <div className="flex flex-col gap-1 text-sm text-secondary text-center mb-2 mt-1 p-2 accent-container"> 76 + <ButtonPrimary fullWidth compact onClick={(e) => getContributorLink(e)}> 77 + Copy Accept Invite Link 78 + </ButtonPrimary> 79 + Send this link to contributors so they can access this publication 80 + </div> 81 + <hr className="border-border-light" /> 82 + 81 83 {props.contributors.map((contributor) => { 82 84 return ( 83 85 <div className="flex justify-between items-center"> 84 - <div className="flex gap-2 items-baseline"> 85 - <div className="font-bold text-secondary">{contributor.name}</div> 86 + <div className="font-bold text-secondary truncate grow"> 87 + {contributor.name} 88 + </div> 89 + 90 + <div className="flex gap-2 items-center"> 86 91 {contributor.status === "pending" && ( 87 - <div className="text-sm text-tertiary italic">Invited</div> 92 + <button 93 + className="text-sm text-accent-contrast italic w-max shrink-0" 94 + onClick={(e) => getContributorLink(e)} 95 + > 96 + Resend Invite 97 + </button> 88 98 )} 99 + 100 + <PubContributorOptions /> 89 101 </div> 90 - 91 - <PubContributorOptions /> 92 102 </div> 93 103 ); 94 104 })} ··· 96 106 ); 97 107 }; 98 108 99 - const PubContibutor = () => { 100 - return <div></div>; 101 - }; 109 + function getContributorLink(e: React.MouseEvent) { 110 + let smoker = useSmoker(); 111 + 112 + smoker({ 113 + text: "Copied Invite Link!", 114 + position: { 115 + y: e.clientY, 116 + x: e.clientX, 117 + }, 118 + }); 119 + } 102 120 103 121 const PubContributorOptions = () => { 104 122 return (
+1 -2
app/lish/[did]/[publication]/dashboard/publicationSettings/PublicationSettings.tsx
··· 1 1 "use client"; 2 - 3 2 import { ActionButton } from "components/ActionBar/ActionButton"; 4 3 import { Popover } from "components/Popover"; 5 4 import { SettingsSmall } from "components/Icons/SettingsSmall"; ··· 27 26 onOpenChange={() => setState("menu")} 28 27 side={isMobile ? "top" : "right"} 29 28 align={isMobile ? "center" : "start"} 30 - className={`max-w-xs w-[1000px] ${state === "theme" && "bg-white!"}`} 29 + className={`text-secondary max-w-xs w-[1000px] ${state === "theme" && "bg-white!"}`} 31 30 arrowFill={theme.colors["border-light"]} 32 31 trigger={ 33 32 <ActionButton
+4 -3
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/PublicationSettings"; 23 + import { PubSettingsHeader } from "../[did]/[publication]/dashboard/publicationSettings/PublicationSettings"; 24 24 25 25 export const EditPubForm = (props: { 26 26 backToMenuAction: () => void; ··· 84 84 > 85 85 <PubSettingsHeader 86 86 loading={props.loading} 87 - setLoadingAction={props.setLoadingAction} 88 87 backToMenuAction={props.backToMenuAction} 89 88 state={"theme"} 90 - /> 89 + > 90 + Publication Settings 91 + </PubSettingsHeader> 91 92 <div className="flex flex-col gap-3 w-[1000px] max-w-full pb-2"> 92 93 <div className="flex items-center justify-between gap-2 "> 93 94 <p className="pl-0.5 pb-0.5 text-tertiary italic text-sm font-bold">
+1 -1
components/Icons/PopoverArrow.tsx
··· 11 11 height="8" 12 12 viewBox="0 0 16 8" 13 13 fill="none" 14 - className="-mt-px" 14 + className={`-mt-px ${props.className}`} 15 15 xmlns="http://www.w3.org/2000/svg" 16 16 > 17 17 <path
+4 -3
components/ThemeManager/PubThemeSetter.tsx
··· 15 15 import { BackgroundPicker } from "./PubPickers/PubBackgroundPickers"; 16 16 import { PubAccentPickers } from "./PubPickers/PubAcccentPickers"; 17 17 import { Separator } from "components/Layout"; 18 - import { PubSettingsHeader } from "app/lish/[did]/[publication]/dashboard/PublicationSettings"; 18 + import { PubSettingsHeader } from "app/lish/[did]/[publication]/dashboard/publicationSettings/PublicationSettings"; 19 19 20 20 export type ImageState = { 21 21 src: string; ··· 92 92 > 93 93 <PubSettingsHeader 94 94 loading={props.loading} 95 - setLoadingAction={props.setLoading} 96 95 backToMenuAction={props.backToMenu} 97 96 state={"theme"} 98 - /> 97 + > 98 + Publication Theme 99 + </PubSettingsHeader> 99 100 </form> 100 101 101 102 <div className="themeSetterContent flex flex-col w-full overflow-y-scroll -mb-2 ">