a tool for shared writing and social publishing
0
fork

Configure Feed

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

added styling for card blocks

- initial styping for cards that begin with h1, h2, h3, p, or image blocks
- added a tiny close icon
- minor adjustments to image block

celine 07a4230a 8b02c972

+161 -54
+91 -13
app/test/blocks.tsx
··· 1 1 import { useState } from "react"; 2 - import { CardSmall, ImageSmall, LinkSmall } from "../../components/Icons"; 2 + import { 3 + CardSmall, 4 + CloseTiny, 5 + ImageSmall, 6 + LinkSmall, 7 + } from "../../components/Icons"; 8 + import { theme } from "../../tailwind.config"; 9 + import useMeasure from "react-use-measure"; 3 10 4 11 export const TextBlock = (props: { defaultValue: string; lines: number }) => { 5 12 let [value, setValue] = useState(props.defaultValue); 6 13 let [focus, setFocus] = useState(false); 7 14 8 15 return ( 9 - <div className="textBlockWrapper relative group pt-3"> 16 + <div className="textBlockWrapper relative group/text pt-3"> 10 17 <textarea 11 18 className={`textBlock w-full p-0 border-none outline-none resize-none align-top`} 12 19 style={{ ··· 30 37 <div 31 38 className={`blockTypeSelector 32 39 ${props.focus && props.empty ? "block" : "hidden"} 33 - ${props.empty && "group-hover:block"}`} 40 + ${props.empty && "group-hover/text:block"}`} 34 41 > 35 42 <div className="flex gap-1 "> 36 43 <button className="opacity-30 hover:opacity-100 hover:text-accent"> ··· 48 55 </div> 49 56 ); 50 57 }; 51 - export const ImageBlock = (props: { children: React.ReactNode }) => { 58 + export const ImageBlock = (props: { src: string; cardHeight: number }) => { 52 59 return ( 53 - <div className=" pt-6 relative"> 54 - <div className="absolute right-2 top-2 h-6 w-6 rounded-full bg-bg-card flex place-items-center justify-center"> 55 - x 60 + <div className="pt-4 pb-2 relative group/image flex w-fit place-self-center justify-center"> 61 + <div className="absolute right-2 top-6 z-10 hidden group-hover/image:block"> 62 + <ImageRemoveButton /> 56 63 </div> 57 - {props.children} 64 + <img 65 + src={props.src} 66 + alt="image" 67 + className={`w-max relative`} 68 + style={{ maxHeight: `calc(${props.cardHeight}px - 48px)` }} 69 + /> 58 70 </div> 59 - // add close button 60 - // add drag handle 61 - // add rotate 62 71 ); 63 72 }; 64 73 65 - export const CardBlock = (props: { children: React.ReactNode }) => { 66 - return <div>{props.children}</div>; 74 + const ImageRemoveButton = () => { 75 + return ( 76 + <svg 77 + width="24" 78 + height="24" 79 + viewBox="0 0 24 24" 80 + fill="none" 81 + xmlns="http://www.w3.org/2000/svg" 82 + > 83 + <path 84 + fillRule="evenodd" 85 + clipRule="evenodd" 86 + d="M19.5314 17.2686C20.1562 17.8935 20.1562 18.9065 19.5314 19.5314C18.9065 20.1562 17.8935 20.1562 17.2686 19.5314L12 14.2627L6.73137 19.5314C6.10653 20.1562 5.09347 20.1562 4.46863 19.5314C3.84379 18.9065 3.84379 17.8935 4.46863 17.2686L9.73726 12L4.46863 6.73137C3.84379 6.10653 3.84379 5.09347 4.46863 4.46863C5.09347 3.84379 6.10653 3.84379 6.73137 4.46863L12 9.73726L17.2686 4.46863C17.8935 3.84379 18.9065 3.84379 19.5314 4.46863C20.1562 5.09347 20.1562 6.10653 19.5314 6.73137L14.2627 12L19.5314 17.2686Z" 87 + fill={theme.colors.primary} 88 + /> 89 + <path 90 + fillRule="evenodd" 91 + clipRule="evenodd" 92 + d="M17.2686 4.46863C17.8935 3.84379 18.9065 3.84379 19.5314 4.46863C20.1562 5.09347 20.1562 6.10653 19.5314 6.73137L14.2627 12L19.5314 17.2686C20.1562 17.8935 20.1562 18.9065 19.5314 19.5314C18.9065 20.1562 17.8935 20.1562 17.2686 19.5314L12 14.2627L6.73137 19.5314C6.10653 20.1562 5.09347 20.1562 4.46863 19.5314C3.84379 18.9065 3.84379 17.8935 4.46863 17.2686L9.73726 12L4.46863 6.73137C3.84379 6.10653 3.84379 5.09347 4.46863 4.46863C5.09347 3.84379 6.10653 3.84379 6.73137 4.46863L12 9.73726L17.2686 4.46863ZM12 7.61594L16.208 3.40797C17.4186 2.19734 19.3814 2.19734 20.592 3.40797C21.8027 4.61859 21.8027 6.58141 20.592 7.79203L16.3841 12L20.592 16.208C21.8027 17.4186 21.8027 19.3814 20.592 20.592C19.3814 21.8027 17.4186 21.8027 16.208 20.592L12 16.3841L7.79203 20.592C6.58141 21.8027 4.61859 21.8027 3.40797 20.592C2.19734 19.3814 2.19734 17.4186 3.40797 16.208L7.61594 12L3.40797 7.79203C2.19734 6.5814 2.19734 4.6186 3.40797 3.40797C4.61859 2.19734 6.58141 2.19734 7.79203 3.40797L12 7.61594Z" 93 + fill={theme.colors["bg-card"]} 94 + /> 95 + </svg> 96 + ); 97 + }; 98 + 99 + export const CardBlock = (props: { 100 + children: React.ReactNode; 101 + fontSize: string; 102 + imgSrc?: string; 103 + cardHeight?: number; 104 + }) => { 105 + let [blockRef, { width: blockWidth }] = useMeasure(); 106 + 107 + return ( 108 + <div 109 + ref={blockRef} 110 + className="cardBlockWrapper w-full mt-3 border bg-bg-card border-border hover:border-accent outline outline-1 outline-transparent hover:outline-accent rounded-lg flex flex-col overflow-hidden" 111 + style={{ maxHeight: blockWidth }} 112 + > 113 + {props.imgSrc && ( 114 + <div className="w-full h-fit max-h-full flex overflow-hidden"> 115 + <img 116 + src={props.imgSrc} 117 + className={`w-max relative place-self-center`} 118 + /> 119 + </div> 120 + )} 121 + 122 + <div className="flex items-center p-2"> 123 + <div 124 + className={`w-full grow ${ 125 + props.fontSize === "h1" 126 + ? "text-lg font-bold line-clamp-1" 127 + : props.fontSize === "h2" 128 + ? "text-base font-bold line-clamp-1" 129 + : props.fontSize === "h3" 130 + ? "text-sm font-bold italic line-clamp-2" 131 + : props.fontSize === "p" 132 + ? "text-sm line-clamp-2" 133 + : "" 134 + }`} 135 + > 136 + {props.children} 137 + </div> 138 + 139 + <div className="shrink-0 opacity-30 hover:text-accent hover:opacity-100"> 140 + <CloseTiny /> 141 + </div> 142 + </div> 143 + </div> 144 + ); 67 145 }; 68 146 69 147 export const ExternalLinkBlock = (props: { children: React.ReactNode }) => {
+48 -40
app/test/card.tsx
··· 1 1 import React from "react"; 2 2 import { ButtonPrimary } from "../../components/Buttons"; 3 - import { TextBlock, ImageBlock } from "./Blocks"; 3 + import { TextBlock, ImageBlock, CardBlock } from "./Blocks"; 4 4 5 5 export const Card = (props: { 6 6 children: React.ReactNode; ··· 13 13 cards: number[]; 14 14 card: number; 15 15 cardWidth: number; 16 + cardHeight: number; 16 17 }) => { 17 18 return ( 18 19 <> ··· 21 22 <div 22 23 id={props.id} 23 24 className={` 24 - cardWrapper w-[calc(100vw-12px)] md:w-[calc(50vw-24px)] max-w-prose 25 + cardWrapper w-[calc(100vw-12px)] md:w-[calc(50vw-32px)] max-w-prose 25 26 relative 26 27 grow flex flex-col 27 28 overflow-y-scroll no-scrollbar ··· 31 32 32 33 `} 33 34 > 34 - <CardContent /> 35 + <CardContent cardHeight={props.cardHeight} /> 35 36 </div> 36 37 {/* <AddCardButton 37 38 setCards={props.setCards} ··· 150 151 ); 151 152 }; 152 153 153 - const CardContent = () => { 154 + const CardContent = (props: { cardHeight: number }) => { 154 155 return ( 155 - <div className=" p-3 sm:p-4 flex flex-col gap-1 z-10"> 156 - <h3>Card Title</h3> 156 + <div className=" p-3 sm:p-4 flex flex-col"> 157 + <h2>Chapter 1</h2> 158 + 159 + <TextBlock 160 + lines={6} 161 + defaultValue="It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife. However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters." 162 + /> 163 + <TextBlock 164 + lines={2} 165 + defaultValue="“My dear Mr. Bennet,” said his lady to him one day, “have you heard that Netherfield Park is let at last?”" 166 + /> 167 + <TextBlock lines={1} defaultValue="Mr. Bennet replied that he had not." /> 168 + <TextBlock 169 + lines={2} 170 + defaultValue="“But it is,” returned she; “for Mrs. Long has just been here, and she told me all about it.”" 171 + /> 172 + <TextBlock lines={1} defaultValue="Mr. Bennet made no answer." /> 173 + <TextBlock 174 + lines={2} 175 + defaultValue="“Do not you want to know who has taken it?” cried his wife, impatiently." 176 + /> 177 + <TextBlock 178 + lines={1} 179 + defaultValue="“You want to tell me, and I have no objection to hearing it.”" 180 + /> 181 + <TextBlock lines={1} defaultValue="" /> 182 + <h3>Related Images</h3> 183 + <ImageBlock src="./test-image.jpg" cardHeight={props.cardHeight} /> 184 + <ImageBlock src="./test-image-2.jpg" cardHeight={props.cardHeight} /> 157 185 158 - <div className="flex flex-col"> 159 - <TextBlock 160 - lines={6} 161 - defaultValue="It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife. However little known the feelings or views of such a man may be on his first entering a neighbourhood, this truth is so well fixed in the minds of the surrounding families, that he is considered as the rightful property of some one or other of their daughters." 162 - /> 163 - <TextBlock 164 - lines={2} 165 - defaultValue="“My dear Mr. Bennet,” said his lady to him one day, “have you heard that Netherfield Park is let at last?”" 166 - /> 167 - <TextBlock 168 - lines={1} 169 - defaultValue="Mr. Bennet replied that he had not." 170 - /> 171 - <TextBlock 172 - lines={2} 173 - defaultValue="“But it is,” returned she; “for Mrs. Long has just been here, and she told me all about it.”" 174 - /> 175 - <TextBlock lines={1} defaultValue="Mr. Bennet made no answer." /> 176 - <TextBlock 177 - lines={2} 178 - defaultValue="“Do not you want to know who has taken it?” cried his wife, impatiently." 179 - /> 180 - <TextBlock 181 - lines={1} 182 - defaultValue="“You want to tell me, and I have no objection to hearing it.”" 183 - /> 184 - <TextBlock lines={1} defaultValue="" /> 185 - <ImageBlock> 186 - <img src="./test-image.jpg" alt="An image" /> 187 - </ImageBlock> 188 - <ImageBlock> 189 - <img src="./test-image-2.jpg" alt="An image" /> 190 - </ImageBlock> 191 - </div> 186 + <CardBlock fontSize="h1" imgSrc="./test-image-2.jpg"> 187 + Chapter 2 188 + </CardBlock> 189 + <CardBlock fontSize="h2">Notes</CardBlock> 190 + <CardBlock fontSize="h3">Footnote #3</CardBlock> 191 + 192 + <CardBlock fontSize="p" imgSrc="./test-image.jpg"> 193 + This was invitation enough. “Why, my dear, you must know, Mrs. Long says 194 + that Netherfield is taken by a young man of large fortune from the north 195 + of England; that he came down on Monday in a chaise and four to see the 196 + place, and was so much delighted with it that he agreed with Mr. Morris 197 + immediately; that he is to take possession before Michaelmas, and some 198 + of his servants are to be in the house by the end of next week.” 199 + </CardBlock> 192 200 </div> 193 201 ); 194 202 };
+2 -1
app/test/page.tsx
··· 12 12 }; 13 13 14 14 export default function Index() { 15 - let [cardRef, { width: cardWidth }] = useMeasure(); 15 + let [cardRef, { width: cardWidth, height: cardHeight }] = useMeasure(); 16 16 let [cards, setCards] = useState([0, 1]); 17 17 let [focusedCardIndex, setFocusedCardIndex] = useState(0); 18 18 let [pageBGImage, setPageBGImage] = useState({ ··· 59 59 cards={cards} 60 60 card={card} 61 61 cardWidth={cardWidth} 62 + cardHeight={cardHeight} 62 63 > 63 64 Card {card} 64 65 </Card>
+20
components/Icons.tsx
··· 79 79 ); 80 80 }; 81 81 82 + export const CloseTiny = (props: Props) => { 83 + return ( 84 + <svg 85 + width="16" 86 + height="16" 87 + viewBox="0 0 16 16" 88 + fill="none" 89 + xmlns="http://www.w3.org/2000/svg" 90 + {...props} 91 + > 92 + <path 93 + fillRule="evenodd" 94 + clipRule="evenodd" 95 + d="M13.8372 4.31196C14.3059 3.84333 14.3059 3.08353 13.8372 2.6149C13.3686 2.14627 12.6088 2.14627 12.1402 2.6149L8.18872 6.56637L4.23725 2.6149C3.76862 2.14627 3.00882 2.14627 2.54019 2.6149C2.07156 3.08353 2.07156 3.84333 2.54019 4.31196L6.49166 8.26343L2.54019 12.2149C2.07156 12.6835 2.07156 13.4433 2.54019 13.912C3.00882 14.3806 3.76862 14.3806 4.23725 13.912L8.18872 9.96048L12.1402 13.912C12.6088 14.3806 13.3686 14.3806 13.8372 13.912C14.3059 13.4433 14.3059 12.6835 13.8372 12.2149L9.88578 8.26343L13.8372 4.31196Z" 96 + fill="currentColor" 97 + /> 98 + </svg> 99 + ); 100 + }; 101 + 82 102 export const SearchTiny = (props: Props) => { 83 103 return ( 84 104 <svg