a tool for shared writing and social publishing
0

Configure Feed

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

some formatting WIP

celine (May 20, 2026, 2:33 PM EDT) c3fa74f4 802ce6ac

+110 -22
+10 -7
components/Blocks/Block.tsx
··· 126 126 const bindSwipe = useDrag( 127 127 ({ last, movement: [mx], event }) => { 128 128 if (!last) return; 129 - if ( 130 - event && 131 - "pointerType" in event && 132 - event.pointerType !== "touch" 133 - ) 129 + if (event && "pointerType" in event && event.pointerType !== "touch") 134 130 return; 135 131 if (!rep || !props.listData || !entity_set.permissions.write) return; 136 132 if (Math.abs(mx) < SWIPE_THRESHOLD) return; ··· 504 500 <Separator classname="border-bg-page! h-4! mx-0.5" /> 505 501 </> 506 502 )} 507 - {props.extraOptions} 503 + {props.extraOptions && ( 504 + <> 505 + {props.extraOptions}{" "} 506 + <Separator classname="border-bg-page! h-4! mx-0.5" /> 507 + </> 508 + )} 508 509 <button 509 510 onClick={async (e) => { 510 511 e.stopPropagation(); ··· 648 649 onClick={(e) => { 649 650 e.stopPropagation(); 650 651 if (permissions.write && listStyle?.data.value === "ordered") { 651 - setNumberInputValue(String(props.listData?.displayNumber || 1)); 652 + setNumberInputValue( 653 + String(props.listData?.displayNumber || 1), 654 + ); 652 655 setEditingNumber(true); 653 656 } 654 657 }}
+100 -15
components/Blocks/StandardSitePostBlock/index.tsx
··· 2 2 import { useEntity, useReplicache } from "src/replicache"; 3 3 import { useUIState } from "src/useUIState"; 4 4 import { Popover } from "components/Popover"; 5 - import { ToggleGroup } from "components/ToggleGroup"; 5 + import { Radio } from "components/Checkbox"; 6 6 import { SettingsTriggerButton } from "../SettingsTriggerButton"; 7 7 import { 8 8 StandardSitePostItem, ··· 47 47 side="top" 48 48 align="end" 49 49 sideOffset={6} 50 + className="flex flex-col gap-1 w-md" 50 51 trigger={ 51 52 <SettingsTriggerButton aria-label="Standard Site Post Settings" /> 52 53 } 53 54 > 54 - <div className="flex flex-col gap-3 text-primary py-1 min-w-[220px]"> 55 - <div className="flex flex-col gap-1"> 56 - <div className="font-bold text-sm">Post Size</div> 57 - <ToggleGroup<StandardSitePostSize> 58 - fullWidth 59 - value={size} 60 - onChange={(value) => { 55 + <h4>Post Size</h4> 56 + 57 + <div className="flex flex-row gap-1 w-full"> 58 + <div className="flex flex-col gap-1 flex-1"> 59 + {( 60 + [ 61 + { value: "small", label: "Small" }, 62 + { value: "medium", label: "Medium" }, 63 + ] as { value: StandardSitePostSize; label: string }[] 64 + ).map((option) => ( 65 + <Radio 66 + key={option.value} 67 + id={`standard-site-post-size-${props.entityID}-${option.value}`} 68 + name={`standard-site-post-size-${props.entityID}`} 69 + value={option.value} 70 + checked={size === option.value} 71 + onChange={(e) => { 72 + if (!e.currentTarget.checked) return; 73 + if (!rep) return; 74 + rep.mutate.assertFact({ 75 + entity: props.entityID, 76 + attribute: "standard-site-post/size", 77 + data: { 78 + type: "standard-site-post-size-union", 79 + value: option.value, 80 + }, 81 + }); 82 + }} 83 + > 84 + {option.label === "Small" ? <SmallIcon /> : <MedIcon />} 85 + </Radio> 86 + ))} 87 + </div> 88 + <div className="flex-1"> 89 + <Radio 90 + id={`standard-site-post-size-${props.entityID}-large`} 91 + name={`standard-site-post-size-${props.entityID}`} 92 + value="large" 93 + checked={size === "large"} 94 + onChange={(e) => { 95 + if (!e.currentTarget.checked) return; 61 96 if (!rep) return; 62 97 rep.mutate.assertFact({ 63 98 entity: props.entityID, 64 99 attribute: "standard-site-post/size", 65 - data: { type: "standard-site-post-size-union", value }, 100 + data: { 101 + type: "standard-site-post-size-union", 102 + value: "large", 103 + }, 66 104 }); 67 105 }} 68 - options={[ 69 - { value: "small", label: "Small" }, 70 - { value: "medium", label: "Medium" }, 71 - { value: "large", label: "Large" }, 72 - ]} 73 - /> 106 + > 107 + <LargeIcon /> 108 + </Radio> 74 109 </div> 75 110 </div> 76 111 </Popover> 77 112 ); 78 113 } 114 + 115 + const SmallIcon = () => { 116 + return ( 117 + <div className="flex gap-2 p-2 w-full light-container"> 118 + <div className="flex flex-col gap-1 grow min-w-0"> 119 + <div className="w-full h-5 bg-tertiary rounded-[2px]" /> 120 + 121 + <div className="flex justify-between mt-1 w-full"> 122 + <div className="w-[60%] h-2 bg-border rounded-[2px]" /> 123 + <div className="w-6 h-2 bg-border rounded-[2px]" /> 124 + </div> 125 + </div> 126 + </div> 127 + ); 128 + }; 129 + 130 + const MedIcon = () => { 131 + return ( 132 + <div className="flex gap-2 p-2 w-full light-container"> 133 + <div className="flex flex-col gap-1 grow min-w-0"> 134 + <div className="w-full h-5 bg-tertiary rounded-[2px]" /> 135 + <div className="w-full h-3 bg-tertiary mt-1 rounded-[2px]" /> 136 + <div className="w-full h-3 bg-tertiary rounded-[2px]" /> 137 + <div className="flex justify-between mt-2 w-full"> 138 + <div className="w-[60%] h-2 bg-border rounded-[2px]" /> 139 + <div className="w-6 h-2 bg-border rounded-[2px]" /> 140 + </div> 141 + </div> 142 + <div className="aspect-square h-full bg-test shrink-0" /> 143 + </div> 144 + ); 145 + }; 146 + 147 + const LargeIcon = () => { 148 + return ( 149 + <div className="flex flex-col gap-2 w-full light-container"> 150 + <div className="w-full aspect-video bg-test rounded-t[2px]" /> 151 + 152 + <div className="flex flex-col gap-1 p-2 pt-0.5!"> 153 + <div className="w-full h-5 bg-tertiary rounded-[2px]" /> 154 + <div className="w-full h-3 bg-tertiary mt-1 rounded-[2px]" /> 155 + <div className="w-full h-3 bg-tertiary rounded-[2px]" /> 156 + <div className="flex justify-between mt-2 w-full"> 157 + <div className="w-[60%] h-2 bg-border rounded-[2px]" /> 158 + <div className="w-6 h-2 bg-border rounded-[2px]" /> 159 + </div> 160 + </div> 161 + </div> 162 + ); 163 + };