a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

force sidebar open when button has popover

+195 -176
+15 -5
components/ActionBar/ActionButton.tsx
··· 1 - import { useContext } from "react"; 2 - import { SidebarOpenContext } from "./Sidebar"; 1 + import { useContext, useEffect } from "react"; 2 + import { SidebarContext } from "./Sidebar"; 3 3 import React, { forwardRef, type JSX } from "react"; 4 + import { PopoverOpenContext } from "components/Popover"; 4 5 5 6 type ButtonProps = Omit<JSX.IntrinsicElements["button"], "content">; 6 7 ··· 15 16 } 16 17 >((props, ref) => { 17 18 let { id, icon, label, primary, secondary, ...buttonProps } = props; 18 - 19 - let sidebarExpanded = useContext(SidebarOpenContext); 19 + let sidebar = useContext(SidebarContext); 20 + let inOpenPopover = useContext(PopoverOpenContext); 21 + useEffect(() => { 22 + if (inOpenPopover) { 23 + console.log("inOpenPopover"); 24 + sidebar.setChildForceOpen(true); 25 + return () => { 26 + sidebar.setChildForceOpen(false); 27 + }; 28 + } 29 + }, [sidebar, inOpenPopover]); 20 30 return ( 21 31 <button 22 32 {...buttonProps} ··· 38 48 > 39 49 <div className="shrink-0">{props.icon}</div> 40 50 <div 41 - className={`pr-1 w-max ${sidebarExpanded ? "block" : props.primary || props.secondary ? "sm:hidden block" : "hidden"}`} 51 + className={`pr-1 w-max ${sidebar.open ? "block" : props.primary || props.secondary ? "sm:hidden block" : "hidden"}`} 42 52 > 43 53 {props.label} 44 54 </div>
+15 -4
components/ActionBar/Sidebar.tsx
··· 1 1 "use client"; 2 + import { uv } from "colorjs.io/fn"; 2 3 import { Media } from "components/Media"; 3 4 import { createContext, useState } from "react"; 4 5 5 - export const SidebarOpenContext = createContext(false); 6 + export const SidebarContext = createContext({ 7 + open: false, 8 + setChildForceOpen: (b: boolean) => {}, 9 + }); 6 10 7 11 export function Sidebar(props: { 8 12 children?: React.ReactNode; ··· 10 14 className?: string; 11 15 }) { 12 16 let [sidebarExpanded, setSidebarExpanded] = useState(false); 17 + let [childForceOpen, setChildForceOpen] = useState(false); 18 + let open = sidebarExpanded || childForceOpen; 13 19 return ( 14 20 <Media mobile={false}> 15 - <SidebarOpenContext value={props.alwaysOpen ? true : sidebarExpanded}> 21 + <SidebarContext 22 + value={{ 23 + open: props.alwaysOpen ? true : open, 24 + setChildForceOpen, 25 + }} 26 + > 16 27 <div 17 28 className={` 18 29 actionSidebar 19 30 ${!props.alwaysOpen && "absolute top-0 left-0 z-10"} 20 31 h-fit w-max p-[6px] 21 32 flex flex-col gap-2 justify-start border 22 - rounded-md bg-bg-page ${sidebarExpanded && !props.alwaysOpen ? "border-border-light" : "container"} 33 + rounded-md bg-bg-page ${open && !props.alwaysOpen ? "border-border-light" : "container"} 23 34 ${props.className} 24 35 `} 25 36 onMouseOver={() => { ··· 31 42 > 32 43 {props.children} 33 44 </div> 34 - </SidebarOpenContext> 45 + </SidebarContext> 35 46 </Media> 36 47 ); 37 48 }
+43 -30
components/Popover.tsx
··· 2 2 import { PopoverArrow } from "./Icons"; 3 3 import { theme } from "tailwind.config"; 4 4 import { NestedCardThemeProvider } from "./ThemeManager/ThemeProvider"; 5 + import { createContext, useState } from "react"; 5 6 7 + export const PopoverOpenContext = createContext(false); 6 8 export const Popover = (props: { 7 9 trigger: React.ReactNode; 8 10 disabled?: boolean; ··· 15 17 onOpenChange?: (open: boolean) => void; 16 18 asChild?: boolean; 17 19 }) => { 20 + let [open, setOpen] = useState(props.open || false); 18 21 return ( 19 - <RadixPopover.Root open={props.open} onOpenChange={props.onOpenChange}> 20 - <RadixPopover.Trigger disabled={props.disabled} asChild={props.asChild}> 21 - {props.trigger} 22 - </RadixPopover.Trigger> 23 - <RadixPopover.Portal> 24 - <NestedCardThemeProvider> 25 - <RadixPopover.Content 26 - className={` 22 + <RadixPopover.Root 23 + open={props.open} 24 + onOpenChange={(o) => { 25 + setOpen(o); 26 + props.onOpenChange?.(open); 27 + }} 28 + > 29 + <PopoverOpenContext value={open}> 30 + <RadixPopover.Trigger disabled={props.disabled} asChild={props.asChild}> 31 + {props.trigger} 32 + </RadixPopover.Trigger> 33 + <RadixPopover.Portal> 34 + <NestedCardThemeProvider> 35 + <RadixPopover.Content 36 + className={` 27 37 z-20 bg-bg-page 28 38 px-3 py-2 29 39 max-w-[var(--radix-popover-content-available-width)] ··· 32 42 overflow-y-scroll no-scrollbar 33 43 ${props.className} 34 44 `} 35 - align={props.align ? props.align : "center"} 36 - sideOffset={4} 37 - collisionPadding={16} 38 - > 39 - {props.children} 40 - <RadixPopover.Arrow 41 - asChild 42 - width={16} 43 - height={8} 44 - viewBox="0 0 16 8" 45 + align={props.align ? props.align : "center"} 46 + sideOffset={4} 47 + collisionPadding={16} 45 48 > 46 - <PopoverArrow 47 - arrowFill={ 48 - props.background ? props.background : theme.colors["bg-page"] 49 - } 50 - arrowStroke={ 51 - props.border ? props.border : theme.colors["border"] 52 - } 53 - /> 54 - </RadixPopover.Arrow> 55 - </RadixPopover.Content> 56 - </NestedCardThemeProvider> 57 - </RadixPopover.Portal> 49 + {props.children} 50 + <RadixPopover.Arrow 51 + asChild 52 + width={16} 53 + height={8} 54 + viewBox="0 0 16 8" 55 + > 56 + <PopoverArrow 57 + arrowFill={ 58 + props.background 59 + ? props.background 60 + : theme.colors["bg-page"] 61 + } 62 + arrowStroke={ 63 + props.border ? props.border : theme.colors["border"] 64 + } 65 + /> 66 + </RadixPopover.Arrow> 67 + </RadixPopover.Content> 68 + </NestedCardThemeProvider> 69 + </RadixPopover.Portal> 70 + </PopoverOpenContext> 58 71 </RadixPopover.Root> 59 72 ); 60 73 };
+122 -137
components/ThemeManager/ThemeSetter.tsx
··· 1 1 "use client"; 2 - import * as Popover from "@radix-ui/react-popover"; 2 + import { Popover } from "components/Popover"; 3 3 import * as Slider from "@radix-ui/react-slider"; 4 4 import { theme } from "../../tailwind.config"; 5 5 ··· 118 118 119 119 return ( 120 120 <> 121 - <Popover.Root> 122 - <Popover.Trigger asChild> 123 - <ActionButton icon={<PaintSmall />} label="Theme" /> 124 - </Popover.Trigger> 125 - <Popover.Portal> 126 - <Popover.Content 127 - className="z-20 themeSetterWrapper w-80 h-fit bg-white rounded-md border border-border flex max-w-[var(--radix-popover-content-available-width)] 128 - max-h-[var(--radix-popover-content-available-height)]" 129 - align="center" 130 - sideOffset={4} 131 - collisionPadding={16} 132 - > 133 - <div className="themeSetterContent flex flex-col w-full overflow-y-scroll no-scrollbar"> 134 - <div className="themeBGLeaflet flex"> 135 - <div 136 - className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full px-2 pt-3`} 137 - > 138 - <div className="bgPickerBody w-full flex flex-col gap-2 p-2 border border-[#CCCCCC] rounded-md"> 139 - <LeafletBGPicker 140 - entityID={props.entityID} 141 - thisPicker={"leaflet"} 142 - openPicker={openPicker} 143 - setOpenPicker={setOpenPicker} 144 - closePicker={() => setOpenPicker("null")} 145 - setValue={set("theme/page-background")} 146 - /> 147 - </div> 148 - 149 - <SectionArrow 150 - fill="white" 151 - stroke="#CCCCCC" 152 - className="ml-2 -mt-[1px]" 153 - /> 154 - </div> 121 + <Popover 122 + className="w-80" 123 + asChild 124 + trigger={<ActionButton icon={<PaintSmall />} label="Theme" />} 125 + > 126 + <div className="themeSetterContent flex flex-col w-full overflow-y-scroll no-scrollbar"> 127 + <div className="themeBGLeaflet flex"> 128 + <div 129 + className={`bgPicker flex flex-col gap-0 -mb-[6px] z-10 w-full px-2 pt-3`} 130 + > 131 + <div className="bgPickerBody w-full flex flex-col gap-2 p-2 border border-[#CCCCCC] rounded-md"> 132 + <LeafletBGPicker 133 + entityID={props.entityID} 134 + thisPicker={"leaflet"} 135 + openPicker={openPicker} 136 + setOpenPicker={setOpenPicker} 137 + closePicker={() => setOpenPicker("null")} 138 + setValue={set("theme/page-background")} 139 + /> 155 140 </div> 156 141 142 + <SectionArrow 143 + fill="white" 144 + stroke="#CCCCCC" 145 + className="ml-2 -mt-[1px]" 146 + /> 147 + </div> 148 + </div> 149 + 150 + <div 151 + onClick={(e) => { 152 + e.currentTarget === e.target && setOpenPicker("leaflet"); 153 + }} 154 + style={{ 155 + backgroundImage: leafletBGImage 156 + ? `url(${leafletBGImage.data.src})` 157 + : undefined, 158 + backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat", 159 + backgroundPosition: "center", 160 + backgroundSize: !leafletBGRepeat 161 + ? "cover" 162 + : `calc(${leafletBGRepeat.data.value}px / 2 )`, 163 + }} 164 + className={`bg-bg-leaflet mx-2 p-3 mb-2 flex flex-col rounded-md border border-border pb-0`} 165 + > 166 + <div className={`flex flex-col z-10 mt-4 -mb-[6px] `}> 157 167 <div 158 - onClick={(e) => { 159 - e.currentTarget === e.target && setOpenPicker("leaflet"); 160 - }} 168 + className="themeLeafletControls text-accent-2 flex flex-col gap-2 h-full bg-bg-leaflet p-2 rounded-md border border-accent-2 shadow-[0_0_0_1px_rgb(var(--accent-1))]" 161 169 style={{ 162 - backgroundImage: leafletBGImage 163 - ? `url(${leafletBGImage.data.src})` 164 - : undefined, 165 - backgroundRepeat: leafletBGRepeat ? "repeat" : "no-repeat", 166 - backgroundPosition: "center", 167 - backgroundSize: !leafletBGRepeat 168 - ? "cover" 169 - : `calc(${leafletBGRepeat.data.value}px / 2 )`, 170 + backgroundColor: "rgba(var(--accent-1), 0.6)", 170 171 }} 171 - className={`bg-bg-leaflet mx-2 p-3 mb-2 flex flex-col rounded-md border border-border pb-0`} 172 172 > 173 - <div className={`flex flex-col z-10 mt-4 -mb-[6px] `}> 174 - <div 175 - className="themeLeafletControls text-accent-2 flex flex-col gap-2 h-full bg-bg-leaflet p-2 rounded-md border border-accent-2 shadow-[0_0_0_1px_rgb(var(--accent-1))]" 176 - style={{ 177 - backgroundColor: "rgba(var(--accent-1), 0.6)", 178 - }} 179 - > 180 - <ColorPicker 181 - label="Accent" 182 - value={accent1Value} 183 - setValue={set("theme/accent-background")} 184 - thisPicker={"accent-1"} 185 - openPicker={openPicker} 186 - setOpenPicker={setOpenPicker} 187 - closePicker={() => setOpenPicker("null")} 188 - /> 189 - <ColorPicker 190 - label="Text on Accent" 191 - value={accent2Value} 192 - setValue={set("theme/accent-text")} 193 - thisPicker={"accent-2"} 194 - openPicker={openPicker} 195 - setOpenPicker={setOpenPicker} 196 - closePicker={() => setOpenPicker("null")} 197 - /> 198 - </div> 199 - <SectionArrow 200 - fill={theme.colors["accent-2"]} 201 - stroke={theme.colors["accent-1"]} 202 - className="ml-2" 203 - /> 204 - </div> 173 + <ColorPicker 174 + label="Accent" 175 + value={accent1Value} 176 + setValue={set("theme/accent-background")} 177 + thisPicker={"accent-1"} 178 + openPicker={openPicker} 179 + setOpenPicker={setOpenPicker} 180 + closePicker={() => setOpenPicker("null")} 181 + /> 182 + <ColorPicker 183 + label="Text on Accent" 184 + value={accent2Value} 185 + setValue={set("theme/accent-text")} 186 + thisPicker={"accent-2"} 187 + openPicker={openPicker} 188 + setOpenPicker={setOpenPicker} 189 + closePicker={() => setOpenPicker("null")} 190 + /> 191 + </div> 192 + <SectionArrow 193 + fill={theme.colors["accent-2"]} 194 + stroke={theme.colors["accent-1"]} 195 + className="ml-2" 196 + /> 197 + </div> 205 198 206 - <div 207 - onClick={(e) => { 208 - e.target === e.currentTarget && setOpenPicker("accent-1"); 209 - }} 210 - className="pointer-cursor font-bold relative text-center text-lg py-2 rounded-md bg-accent-1 text-accent-2 shadow-md flex items-center justify-center" 211 - > 212 - <div 213 - className="cursor-pointer w-fit" 214 - onClick={() => { 215 - setOpenPicker("accent-2"); 216 - }} 217 - > 218 - Example Button 219 - </div> 220 - </div> 199 + <div 200 + onClick={(e) => { 201 + e.target === e.currentTarget && setOpenPicker("accent-1"); 202 + }} 203 + className="pointer-cursor font-bold relative text-center text-lg py-2 rounded-md bg-accent-1 text-accent-2 shadow-md flex items-center justify-center" 204 + > 205 + <div 206 + className="cursor-pointer w-fit" 207 + onClick={() => { 208 + setOpenPicker("accent-2"); 209 + }} 210 + > 211 + Example Button 212 + </div> 213 + </div> 221 214 222 - <div className="flex flex-col mt-8 -mb-[6px] z-10"> 223 - <div 224 - className="themeLeafletControls flex flex-col gap-2 h-full text-primary bg-bg-leaflet p-2 rounded-md border border-primary shadow-[0_0_0_1px_rgb(var(--bg-page))]" 225 - style={{ backgroundColor: "rgba(var(--bg-page, 0.6)" }} 226 - > 227 - <ColorPicker 228 - label={props.home ? "Menu" : "Page"} 229 - alpha 230 - value={pageValue} 231 - setValue={set("theme/card-background")} 232 - thisPicker={"page"} 233 - openPicker={openPicker} 234 - setOpenPicker={setOpenPicker} 235 - closePicker={() => setOpenPicker("null")} 236 - /> 237 - <ColorPicker 238 - label={props.home ? "Menu Text" : "Text"} 239 - value={primaryValue} 240 - setValue={set("theme/primary")} 241 - thisPicker={"text"} 242 - openPicker={openPicker} 243 - setOpenPicker={setOpenPicker} 244 - closePicker={() => setOpenPicker("null")} 245 - /> 246 - </div> 247 - <SectionArrow 248 - fill={theme.colors["primary"]} 249 - stroke={theme.colors["bg-page"]} 250 - className=" ml-2" 251 - /> 252 - </div> 253 - 254 - <SamplePage setOpenPicker={setOpenPicker} home={props.home} /> 215 + <div className="flex flex-col mt-8 -mb-[6px] z-10"> 216 + <div 217 + className="themeLeafletControls flex flex-col gap-2 h-full text-primary bg-bg-leaflet p-2 rounded-md border border-primary shadow-[0_0_0_1px_rgb(var(--bg-page))]" 218 + style={{ backgroundColor: "rgba(var(--bg-page, 0.6)" }} 219 + > 220 + <ColorPicker 221 + label={props.home ? "Menu" : "Page"} 222 + alpha 223 + value={pageValue} 224 + setValue={set("theme/card-background")} 225 + thisPicker={"page"} 226 + openPicker={openPicker} 227 + setOpenPicker={setOpenPicker} 228 + closePicker={() => setOpenPicker("null")} 229 + /> 230 + <ColorPicker 231 + label={props.home ? "Menu Text" : "Text"} 232 + value={primaryValue} 233 + setValue={set("theme/primary")} 234 + thisPicker={"text"} 235 + openPicker={openPicker} 236 + setOpenPicker={setOpenPicker} 237 + closePicker={() => setOpenPicker("null")} 238 + /> 255 239 </div> 256 - {!props.home && <WatermarkSetter entityID={props.entityID} />} 257 - </div> 258 - <Popover.Arrow asChild width={16} height={8} viewBox="0 0 16 8"> 259 - <PopoverArrow 260 - arrowFill={theme.colors["white"]} 261 - arrowStroke={theme.colors["border"]} 240 + <SectionArrow 241 + fill={theme.colors["primary"]} 242 + stroke={theme.colors["bg-page"]} 243 + className=" ml-2" 262 244 /> 263 - </Popover.Arrow> 264 - </Popover.Content> 265 - </Popover.Portal> 266 - </Popover.Root> 245 + </div> 246 + 247 + <SamplePage setOpenPicker={setOpenPicker} home={props.home} /> 248 + </div> 249 + {!props.home && <WatermarkSetter entityID={props.entityID} />} 250 + </div> 251 + </Popover> 267 252 </> 268 253 ); 269 254 };