a tool for shared writing and social publishing
0
fork

Configure Feed

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

changed select style to be a background color rather than a border on the side, added a focused style for link block

celine 604c294f 36d07595

+59 -25
+13 -2
components/Blocks/ExternalLinkBlock.tsx
··· 1 1 import { useEntity, useReplicache } from "src/replicache"; 2 2 import { CloseTiny } from "components/Icons"; 3 3 import { useEntitySetContext } from "components/EntitySetProvider"; 4 + import { useUIState } from "src/useUIState"; 4 5 5 6 export const ExternalLinkBlock = (props: { entityID: string }) => { 6 7 let previewImage = useEntity(props.entityID, "link/preview"); ··· 8 9 let description = useEntity(props.entityID, "link/description"); 9 10 let url = useEntity(props.entityID, "link/url"); 10 11 12 + let selected = useUIState((s) => 13 + s.selectedBlock.find((b) => b.value === props.entityID), 14 + ); 11 15 let permission = useEntitySetContext().permissions.write; 12 16 let { rep } = useReplicache(); 13 17 ··· 15 19 <a 16 20 href={url?.data.value} 17 21 target="_blank" 18 - className="externalLinkBlock relative group/linkBlock h-[104px] bg-bg-card shadow-sm flex border border-border-light hover:border-accent outline outline-1 outline-transparent hover:outline-accent rounded-lg overflow-hidden text-primary no-underline" 22 + className={` 23 + externalLinkBlock flex relative group/linkBlock 24 + h-[104px] bg-bg-card overflow-hidden text-primary no-underline 25 + border hover:border-accent outline outline-1 hover:outline-accent rounded-lg shadow-sm 26 + ${selected ? "outline-accent border-accent" : "outline-transparent border-border-light"} 27 + `} 19 28 > 20 29 <div className="pt-2 pb-2 px-2 grow min-w-0"> 21 30 <div className="flex flex-col w-full min-w-0 h-full grow "> ··· 30 39 > 31 40 {description?.data.value} 32 41 </div> 33 - <div className="inline-block place-self-end w-full text-xs text-tertiary italic line-clamp-1 truncate group-hover/linkBlock:text-accent"> 42 + <div 43 + className={`inline-block place-self-end w-full text-xs italic line-clamp-1 truncate group-hover/linkBlock:text-accent ${selected ? "text-accent" : "text-tertiary"}`} 44 + > 34 45 {url?.data.value} 35 46 </div> 36 47 </div>
+21 -19
components/Blocks/TextBlock/index.tsx
··· 123 123 return ( 124 124 <pre 125 125 className={` 126 - w-full whitespace-pre-wrap outline-none break-words ${props.className} ${ 127 - props.preview 128 - ? "p-0" 129 - : `px-2 sm:px-3 ${ 130 - props.type === "heading" ? "pb-0 " : "pb-2" 131 - } ${props.first ? "pt-2 sm:pt-3" : "pt-1"}` 132 - }`} 126 + w-full whitespace-pre-wrap outline-none break-words ${props.className} ${ 127 + props.preview 128 + ? "p-0 min-h-1" 129 + : `px-3 sm:px-4 min-h-9 ${ 130 + props.type === "heading" ? "pb-0 " : "pb-2" 131 + } ${props.first ? "pt-2 sm:pt-3" : "pt-1"}` 132 + }`} 133 133 > 134 134 {nodes.map((node, index) => ( 135 135 <RenderYJSFragment key={index} node={node} /> ··· 139 139 } 140 140 export function BaseTextBlock(props: BlockProps & { className: string }) { 141 141 const [mount, setMount] = useState<HTMLElement | null>(null); 142 - let selected = useUIState((s) => 143 - s.selectedBlock.find((b) => b.value === props.entityID), 144 - ); 145 - let first = props.previousBlock === null; 146 - let headingLevel = useEntity(props.entityID, "block/heading-level"); 147 142 148 - let [value, factID] = useYJSValue(props.entityID); 149 143 let repRef = useRef<null | Replicache<ReplicacheMutators>>(null); 150 144 let entity_set = useEntitySetContext(); 151 145 let propsRef = useRef({ ...props, entity_set }); ··· 156 150 useEffect(() => { 157 151 repRef.current = rep.rep; 158 152 }, [rep?.rep]); 153 + 154 + let selected = useUIState((s) => 155 + s.selectedBlock.find((b) => b.value === props.entityID), 156 + ); 157 + let first = props.previousBlock === null; 158 + let headingLevel = useEntity(props.entityID, "block/heading-level"); 159 + 160 + let [value, factID] = useYJSValue(props.entityID); 159 161 160 162 let editorState = useEditorStates( 161 163 (s) => s.editorStates[props.entityID], ··· 240 242 }} 241 243 id={elementId.block(props.entityID).text} 242 244 className={` 243 - textBlock 244 - w-full pl-1 pr-2 sm:pl-2 sm:pr-3 245 - border-l-4 outline-none 246 - resize-none align-top whitespace-pre-wrap bg-transparent ${ 247 - selected ? " border-tertiary" : "border-transparent" 248 - } ${first ? "pt-2 sm:pt-3" : "pt-1"} ${props.type === "heading" ? "pb-0" : "pb-2"} ${props.className}`} 245 + textContent 246 + w-full pl-3 pr-3 sm:pl-4 sm:pr-4 247 + relative 248 + outline-none 249 + resize-none align-top whitespace-pre-wrap bg-transparent ${first ? "pt-2 sm:pt-3" : "pt-1"} ${props.type === "heading" ? "pb-0" : "pb-2"} ${props.className}`} 249 250 ref={setMount} 250 251 /> 252 + 251 253 {editorState.doc.textContent.length === 0 && 252 254 props.position === "a0" && 253 255 props.nextBlock === null && (
+25 -3
components/Blocks/index.tsx
··· 169 169 }; 170 170 171 171 function Block(props: BlockProps) { 172 + let { rep } = useReplicache(); 173 + 174 + let selectedBlocks = useUIState((s) => s.selectedBlock); 175 + 172 176 let selected = useUIState( 173 177 (s) => 174 178 (!textBlocks[props.type] || s.selectedBlock.length > 1) && 175 179 s.selectedBlock.find((b) => b.value === props.entityID), 176 180 ); 177 - let { rep } = useReplicache(); 181 + 182 + let nextBlockSelected = useUIState((s) => 183 + s.selectedBlock.find((b) => b.value === props.nextBlock?.value), 184 + ); 185 + let prevBlockSelected = useUIState((s) => 186 + s.selectedBlock.find((b) => b.value === props.previousBlock?.value), 187 + ); 178 188 179 189 let entity_set = useEntitySetContext(); 180 190 useEffect(() => { ··· 284 294 }} 285 295 // text and heading blocks handle thier own padding so that 286 296 // clicking anywhere on them (even the padding between blocks) will focus the textarea 287 - className={`${ 297 + className={` relative ${ 288 298 props.type !== "heading" && 289 299 props.type !== "text" && 290 - `border-l-4 first:pt-2 sm:first:pt-3 pl-1 sm:pl-2 pr-2 sm:pr-3 pt-1 pb-2 ${selected ? "border-tertiary" : "border-transparent"}` 300 + `first:pt-0 sm:first:pt-0 pl-3 pr-3 sm:pl-4 sm:pr-4 pt-1 pb-2` 291 301 }`} 292 302 id={elementId.block(props.entityID).container} 293 303 > 304 + {selected && selectedBlocks.length > 1 && ( 305 + <div 306 + className={` 307 + textSelection pointer-events-none 308 + absolute right-2 left-2 bg-border-light 309 + ${!props.previousBlock ? "top-2" : "top-0"} 310 + ${props.type !== "heading" && !nextBlockSelected ? "bottom-1" : "bottom-0"} 311 + ${!prevBlockSelected && "rounded-t-md"} 312 + ${!nextBlockSelected && "rounded-b-md"} 313 + `} 314 + /> 315 + )} 294 316 {props.type === "card" ? ( 295 317 <CardBlock {...props} /> 296 318 ) : props.type === "text" ? (
-1
components/Cards.tsx
··· 101 101 }} 102 102 className={` 103 103 card w-[calc(100vw-12px)] sm:w-[calc(100vw-128px)] lg:w-[calc(50vw-32px)] max-w-prose 104 - sm:pt-0 pt-2 105 104 grow flex flex-col 106 105 overscroll-y-none 107 106 overflow-y-scroll no-scrollbar