Changed Applayout from fixed to grid + using custom tooltip
This commit is contained in:
		
							parent
							
								
									f4217a597c
								
							
						
					
					
						commit
						4b30dac878
					
				| @ -54,27 +54,6 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|     }, | ||||
|   }); | ||||
| 
 | ||||
|   const mainPanelClass = `fixed desktop:left-0 desktop:top-0 desktop:bottom-0 ${ | ||||
|     appLayout.mainPanelReduced ? "desktop:w-[6rem]" : "desktop:w-[20rem]" | ||||
|   }`;
 | ||||
|   const subPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:w-[20rem] ${ | ||||
|     appLayout.mainPanelReduced ? " desktop:left-[6rem]" : "desktop:left-[20rem]" | ||||
|   }`;
 | ||||
|   let contentPanelClass = ""; | ||||
|   if (subPanel) { | ||||
|     contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 ${ | ||||
|       appLayout.mainPanelReduced | ||||
|         ? "desktop:left-[26rem]" | ||||
|         : "desktop:left-[40rem]" | ||||
|     }`;
 | ||||
|   } else if (contentPanel) { | ||||
|     contentPanelClass = `fixed desktop:top-0 desktop:bottom-0 desktop:right-0 ${ | ||||
|       appLayout.mainPanelReduced | ||||
|         ? "desktop:left-[6rem]" | ||||
|         : "desktop:left-[20rem]" | ||||
|     }`;
 | ||||
|   } | ||||
| 
 | ||||
|   const turnSubIntoContent = subPanel && !contentPanel; | ||||
| 
 | ||||
|   const titlePrefix = "Accord’s Library"; | ||||
| @ -115,6 +94,21 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|     // eslint-disable-next-line react-hooks/exhaustive-deps
 | ||||
|   }, [currencySelect]); | ||||
| 
 | ||||
|   let gridCol = ""; | ||||
|   if (props.subPanel) { | ||||
|     if (appLayout.mainPanelReduced) { | ||||
|       gridCol = "grid-cols-[6rem_20rem_1fr]"; | ||||
|     } else { | ||||
|       gridCol = "grid-cols-[20rem_20rem_1fr]"; | ||||
|     } | ||||
|   } else { | ||||
|     if (appLayout.mainPanelReduced) { | ||||
|       gridCol = "grid-cols-[6rem_0px_1fr]"; | ||||
|     } else { | ||||
|       gridCol = "grid-cols-[20rem_0px_1fr]"; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <div | ||||
|       className={`${ | ||||
| @ -127,7 +121,7 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|     > | ||||
|       <div | ||||
|         {...handlers} | ||||
|         className="fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black" | ||||
|         className={`fixed inset-0 touch-pan-y p-0 m-0 bg-light text-black grid [grid-template-areas:'main_sub_content'] ${gridCol} mobile:grid-cols-[1fr] mobile:grid-rows-[1fr_5rem] mobile:[grid-template-areas:'content''navbar']`} | ||||
|       > | ||||
|         <Head> | ||||
|           <title>{`${titlePrefix} - ${ogTitle}`}</title> | ||||
| @ -157,9 +151,32 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|           <meta name="twitter:image" content={metaImage.image}></meta> | ||||
|         </Head> | ||||
| 
 | ||||
|         {/* Background when navbar is opened */} | ||||
|         <div | ||||
|           className={`[grid-area:content] mobile:z-10 absolute inset-0 transition-[backdrop-filter] duration-500 ${ | ||||
|             (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile | ||||
|               ? "[backdrop-filter:blur(2px)]" | ||||
|               : "pointer-events-none touch-none " | ||||
|           }`}
 | ||||
|         > | ||||
|           <div | ||||
|             className={`absolute bg-shade inset-0 transition-opacity duration-500 
 | ||||
|         ${turnSubIntoContent ? "" : ""} | ||||
|         ${ | ||||
|           (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile | ||||
|             ? "opacity-60" | ||||
|             : "opacity-0" | ||||
|         }`}
 | ||||
|             onClick={() => { | ||||
|               appLayout.setMainPanelOpen(false); | ||||
|               appLayout.setSubPanelOpen(false); | ||||
|             }} | ||||
|           ></div> | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Content panel */} | ||||
|         <div | ||||
|           className={`top-0 left-0 right-0 bottom-20 overflow-y-scroll bg-light texture-paper-dots ${contentPanelClass}`} | ||||
|           className={`[grid-area:content] overflow-y-scroll bg-light texture-paper-dots`} | ||||
|         > | ||||
|           {contentPanel ? ( | ||||
|             contentPanel | ||||
| @ -173,38 +190,15 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
|           )} | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Background when navbar is opened */} | ||||
|         <div | ||||
|           className={`fixed inset-0 transition-[backdrop-filter] duration-500 ${ | ||||
|             (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile | ||||
|               ? "[backdrop-filter:blur(2px)]" | ||||
|               : "pointer-events-none touch-none " | ||||
|           }`}
 | ||||
|         > | ||||
|           <div | ||||
|             className={`fixed bg-shade inset-0 transition-opacity duration-500 
 | ||||
|         ${turnSubIntoContent ? "z-10" : ""} | ||||
|         ${ | ||||
|           (appLayout.mainPanelOpen || appLayout.subPanelOpen) && isMobile | ||||
|             ? "opacity-60" | ||||
|             : "opacity-0" | ||||
|         }`}
 | ||||
|             onClick={() => { | ||||
|               appLayout.setMainPanelOpen(false); | ||||
|               appLayout.setSubPanelOpen(false); | ||||
|             }} | ||||
|           ></div> | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Sub panel */} | ||||
|         {subPanel && ( | ||||
|           <div | ||||
|             className={`${subPanelClass} border-r-[1px] mobile:bottom-20 mobile:border-r-0 mobile:border-l-[1px] border-black border-dotted top-0 bottom-0 right-0 left-12 overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
 | ||||
|             className={`[grid-area:sub] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%] mobile:justify-self-end border-r-[1px] mobile:border-r-0 mobile:border-l-[1px] border-black border-dotted overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
 | ||||
|           ${ | ||||
|             turnSubIntoContent | ||||
|               ? "mobile:translate-x-0 mobile:left-0 mobile:border-l-0" | ||||
|               ? "mobile:border-l-0 mobile:w-full" | ||||
|               : !appLayout.subPanelOpen | ||||
|               ? "mobile:translate-x-full" | ||||
|               ? "mobile:translate-x-[100vw]" | ||||
|               : "" | ||||
|           }`}
 | ||||
|           > | ||||
| @ -214,28 +208,14 @@ export default function AppLayout(props: AppLayoutProps): JSX.Element { | ||||
| 
 | ||||
|         {/* Main panel */} | ||||
|         <div | ||||
|           className={`${mainPanelClass} border-r-[1px] mobile:bottom-20 border-black border-dotted top-0 bottom-0 left-0 right-12 overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 z-20 bg-light texture-paper-dots
 | ||||
|           className={`[grid-area:main] mobile:[grid-area:content] mobile:z-10 mobile:w-[90%] mobile:justify-self-start border-r-[1px] border-black border-dotted overflow-y-scroll webkit-scrollbar:w-0 [scrollbar-width:none] transition-transform duration-300 bg-light texture-paper-dots
 | ||||
|         ${appLayout.mainPanelOpen ? "" : "mobile:-translate-x-full"}`}
 | ||||
|         > | ||||
|           <MainPanel langui={langui} /> | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Main panel minimize button*/} | ||||
|         <div | ||||
|           className={`mobile:hidden translate-x-0 fixed top-1/2 z-20 ${ | ||||
|             appLayout.mainPanelReduced ? "left-[4.65rem]" : "left-[18.65rem]" | ||||
|           }`}
 | ||||
|           onClick={() => | ||||
|             appLayout.setMainPanelReduced(!appLayout.mainPanelReduced) | ||||
|           } | ||||
|         > | ||||
|           <Button className="material-icons bg-light !px-2"> | ||||
|             {appLayout.mainPanelReduced ? "chevron_right" : "chevron_left"} | ||||
|           </Button> | ||||
|         </div> | ||||
| 
 | ||||
|         {/* Navbar */} | ||||
|         <div className="fixed inset-0 z-30 top-auto h-20 border-t-[1px] border-black border-dotted grid grid-cols-[5rem_1fr_5rem] place-items-center desktop:hidden bg-light texture-paper-dots"> | ||||
|         <div className="[grid-area:navbar] border-t-[1px] border-black border-dotted grid grid-cols-[5rem_1fr_5rem] place-items-center desktop:hidden bg-light texture-paper-dots"> | ||||
|           <span | ||||
|             className="material-icons mt-[.1em] cursor-pointer" | ||||
|             onClick={() => { | ||||
|  | ||||
| @ -1,12 +1,18 @@ | ||||
| import { MouseEventHandler } from "react"; | ||||
| 
 | ||||
| type ChipProps = { | ||||
|   className?: string; | ||||
|   children: React.ReactNode; | ||||
|   onMouseEnter?: MouseEventHandler<HTMLDivElement>; | ||||
|   onMouseLeave?: MouseEventHandler<HTMLDivElement>; | ||||
| }; | ||||
| 
 | ||||
| export default function Chip(props: ChipProps): JSX.Element { | ||||
|   return ( | ||||
|     <div | ||||
|       className={`grid place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,border-color] ${props.className} `} | ||||
|       className={`grid place-content-center place-items-center text-xs pb-[0.14rem] px-1.5 border-[1px] rounded-full opacity-70 transition-[color,_opacity,_border-color] hover:opacity-100 ${props.className} `} | ||||
|       onMouseEnter={props.onMouseEnter} | ||||
|       onMouseLeave={props.onMouseLeave} | ||||
|     > | ||||
|       {props.children} | ||||
|     </div> | ||||
|  | ||||
| @ -55,7 +55,7 @@ export default function LibraryItemsPreview( | ||||
|             <h3 className="mobile:text-xs leading-3">{item.subtitle}</h3> | ||||
|           </div> | ||||
| 
 | ||||
|           <div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:w-0 [scrollbar-width:none] place-content-start"> | ||||
|           <div className="w-full grid grid-flow-col gap-1 overflow-x-scroll webkit-scrollbar:h-0 [scrollbar-width:none] place-content-start"> | ||||
|             {item.categories.data.map((category) => ( | ||||
|               <Chip key={category.id} className="text-sm"> | ||||
|                 {category.attributes.short} | ||||
|  | ||||
| @ -22,10 +22,18 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { | ||||
|           slugify: slugify, | ||||
|           overrides: { | ||||
|             h2: { | ||||
|               component: (props: { id: string; children: React.ReactNode }) => { | ||||
|               component: (props: { | ||||
|                 id: string; | ||||
|                 style: React.CSSProperties; | ||||
|                 children: React.ReactNode; | ||||
|               }) => { | ||||
|                 return ( | ||||
|                   <div className="flex flex-row place-items-center place-content-center gap-3 hover:[--anchor-opacity:100] [--anchor-opacity:0]"> | ||||
|                     <h2 id={props.id}>{props.children}</h2> | ||||
|                   <h2 | ||||
|                     id={props.id} | ||||
|                     className="flex flex-row place-items-center place-content-center gap-3 hover:[--anchor-opacity:100] [--anchor-opacity:0]" | ||||
|                     style={props.style} | ||||
|                   > | ||||
|                     {props.children} | ||||
|                     <abbr title="Copy anchor link"> | ||||
|                       <span | ||||
|                         className="material-icons opacity-[var(--anchor-opacity)] transition-all hover:text-dark cursor-pointer" | ||||
| @ -41,7 +49,7 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { | ||||
|                         link | ||||
|                       </span> | ||||
|                     </abbr> | ||||
|                   </div> | ||||
|                   </h2> | ||||
|                 ); | ||||
|               }, | ||||
|             }, | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import { useRouter } from "next/router"; | ||||
| import Link from "next/link"; | ||||
| import { MouseEventHandler } from "react"; | ||||
| import { MouseEventHandler, useState } from "react"; | ||||
| import ToolTip from "components/ToolTip"; | ||||
| 
 | ||||
| type NavOptionProps = { | ||||
|   url: string; | ||||
| @ -22,11 +23,15 @@ export default function NavOption(props: NavOptionProps): JSX.Element { | ||||
|     props.border ? border : "" | ||||
|   } ${isActive ? divActive : ""}`;
 | ||||
| 
 | ||||
|   const [hovered, setHovered] = useState(false); | ||||
| 
 | ||||
|   return ( | ||||
|     <Link href={props.url} passHref> | ||||
|       <div | ||||
|         onClick={props.onClick} | ||||
|         className={`grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${ | ||||
|         onMouseEnter={() => props.reduced && setHovered(true)} | ||||
|         onMouseLeave={() => setHovered(false)} | ||||
|         className={`relative grid grid-flow-col grid-cols-[auto] auto-cols-fr justify-center ${ | ||||
|           props.icon ? "text-left" : "text-center" | ||||
|         } ${divCommon}`}
 | ||||
|       > | ||||
| @ -40,6 +45,11 @@ export default function NavOption(props: NavOptionProps): JSX.Element { | ||||
|             {props.subtitle && <p className="col-start-2">{props.subtitle}</p>} | ||||
|           </div> | ||||
|         )} | ||||
| 
 | ||||
|         <ToolTip hovered={hovered} direction="right" offset="3.5rem"> | ||||
|           <h3 className="text-2xl">{props.title}</h3> | ||||
|           {props.subtitle && <p className="col-start-2">{props.subtitle}</p>} | ||||
|         </ToolTip> | ||||
|       </div> | ||||
|     </Link> | ||||
|   ); | ||||
|  | ||||
| @ -24,6 +24,20 @@ export default function MainPanel(props: MainPanelProps): JSX.Element { | ||||
|         appLayout.mainPanelReduced && isDesktop && "px-4" | ||||
|       }`}
 | ||||
|     > | ||||
|       {/* Reduce/expand main menu */} | ||||
|       <div | ||||
|         className={`mobile:hidden top-1/2 fixed ${ | ||||
|           appLayout.mainPanelReduced ? "left-[4.65rem]" : "left-[18.65rem]" | ||||
|         }`}
 | ||||
|         onClick={() => | ||||
|           appLayout.setMainPanelReduced(!appLayout.mainPanelReduced) | ||||
|         } | ||||
|       > | ||||
|         <Button className="material-icons bg-light !px-2"> | ||||
|           {appLayout.mainPanelReduced ? "chevron_right" : "chevron_left"} | ||||
|         </Button> | ||||
|       </div> | ||||
| 
 | ||||
|       <div> | ||||
|         <div className="grid place-items-center"> | ||||
|           <Link href="/" passHref> | ||||
|  | ||||
| @ -4,7 +4,7 @@ type SubPanelProps = { | ||||
| 
 | ||||
| export default function SubPanel(props: SubPanelProps): JSX.Element { | ||||
|   return ( | ||||
|     <div className="flex flex-col p-8 gap-y-2 justify-items-center text-center mobile:h-full"> | ||||
|     <div className="grid pt-10 pb-20 px-6 desktop:py-8 desktop:px-10 gap-y-2 justify-items-center text-center"> | ||||
|       {props.children} | ||||
|     </div> | ||||
|   ); | ||||
|  | ||||
| @ -3,6 +3,9 @@ import { | ||||
|   GetContentTextQuery, | ||||
|   GetWebsiteInterfaceQuery, | ||||
| } from "graphql/operations-types"; | ||||
| import { useState } from "react"; | ||||
| import Img, { ImageQuality } from "./Img"; | ||||
| import ToolTip from "./ToolTip"; | ||||
| 
 | ||||
| type RecorderChipProps = { | ||||
|   className?: string; | ||||
| @ -13,11 +16,59 @@ type RecorderChipProps = { | ||||
| export default function RecorderChip(props: RecorderChipProps): JSX.Element { | ||||
|   const recorder = props.recorder; | ||||
|   const langui = props.langui; | ||||
| 
 | ||||
|   const [hovered, setHovered] = useState(false); | ||||
| 
 | ||||
|   return ( | ||||
|     <Chip key={recorder.id}> | ||||
|     <Chip | ||||
|       key={recorder.id} | ||||
|       onMouseEnter={() => setHovered(true)} | ||||
|       onMouseLeave={() => setHovered(false)} | ||||
|     > | ||||
|       {recorder.attributes.anonymize | ||||
|         ? `Recorder#${recorder.attributes.anonymous_code}` | ||||
|         : recorder.attributes.username} | ||||
| 
 | ||||
|       <ToolTip | ||||
|         hovered={hovered} | ||||
|         direction="top" | ||||
|         offset="1.5rem" | ||||
|         delayShow={150} | ||||
|       > | ||||
|         <div className="p-2 py-5 grid gap-2"> | ||||
|           <div className="grid grid-flow-col gap-2 place-items-center place-content-start"> | ||||
|             {recorder.attributes.avatar.data && ( | ||||
|               <Img | ||||
|                 className="w-8 rounded-full" | ||||
|                 image={recorder.attributes.avatar.data.attributes} | ||||
|                 quality={ImageQuality.Small} | ||||
|                 rawImg | ||||
|               /> | ||||
|             )} | ||||
|             <h3 className="text-xl">{recorder.attributes.username}</h3> | ||||
|           </div> | ||||
|           {recorder.attributes.languages.data.length > 0 && ( | ||||
|             <div className="flex flex-row flex-wrap gap-1"> | ||||
|               <p>{langui.languages}:</p> | ||||
|               {recorder.attributes.languages.data.map((language) => ( | ||||
|                 <Chip key={language.attributes.code}> | ||||
|                   {language.attributes.code.toUpperCase()} | ||||
|                 </Chip> | ||||
|               ))} | ||||
|             </div> | ||||
|           )} | ||||
|           {recorder.attributes.pronouns && ( | ||||
|             <div className="flex flex-row flex-wrap gap-1"> | ||||
|               <p>{langui.pronouns}:</p> | ||||
|               <Chip>{recorder.attributes.pronouns}</Chip> | ||||
|             </div> | ||||
|           )} | ||||
|           <p> | ||||
|             {recorder.attributes.bio.length > 0 && | ||||
|               recorder.attributes.bio[0].bio} | ||||
|           </p> | ||||
|         </div> | ||||
|       </ToolTip> | ||||
|     </Chip> | ||||
|   ); | ||||
| } | ||||
|  | ||||
							
								
								
									
										80
									
								
								src/components/ToolTip.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								src/components/ToolTip.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| import { useEffect, useState } from "react"; | ||||
| 
 | ||||
| type ToolTipProps = { | ||||
|   hovered: boolean; | ||||
|   children: React.ReactNode; | ||||
|   delayShow?: number; | ||||
|   direction: "right" | "bottom" | "top" | "left"; | ||||
|   offset: string; | ||||
| }; | ||||
| 
 | ||||
| export default function ToolTip(props: ToolTipProps): JSX.Element { | ||||
|   const { children, hovered, direction, offset } = props; | ||||
|   let { delayShow } = props; | ||||
|   if (delayShow === undefined) delayShow = 500; | ||||
| 
 | ||||
|   const [show, setShow] = useState(false); | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     let timeout = setTimeout(() => {}); | ||||
|     if (hovered) { | ||||
|       timeout = setTimeout(() => hovered && setShow(true), delayShow); | ||||
|     } else { | ||||
|       setShow(false); | ||||
|     } | ||||
|     return () => clearTimeout(timeout); | ||||
|   }, [delayShow, hovered]); | ||||
| 
 | ||||
|   let tooltipCSS = ""; | ||||
|   let transformCSS = ""; | ||||
|   let arrowParentCSS = ""; | ||||
|   let arrowCSS = ""; | ||||
| 
 | ||||
|   switch (direction) { | ||||
|     case "left": | ||||
|       tooltipCSS = "[justify-self:end] [align-self:center]"; | ||||
|       transformCSS = `translateX(-${offset})`; | ||||
|       arrowParentCSS = "w-4 -right-4 top-0 bottom-0"; | ||||
|       arrowCSS = "border-l-light"; | ||||
|       break; | ||||
| 
 | ||||
|     case "right": | ||||
|       tooltipCSS = "[justify-self:start] [align-self:center]"; | ||||
|       transformCSS = `translateX(${offset})`; | ||||
|       arrowParentCSS = "w-4 -left-4 top-0 bottom-0"; | ||||
|       arrowCSS = "border-r-light"; | ||||
|       break; | ||||
| 
 | ||||
|     case "top": | ||||
|       tooltipCSS = "[align-self:end]"; | ||||
|       transformCSS = `translateY(-${offset})`; | ||||
|       arrowParentCSS = "h-4 -bottom-4 left-0 right-0"; | ||||
|       arrowCSS = "border-t-light"; | ||||
|       break; | ||||
| 
 | ||||
|     case "bottom": | ||||
|       tooltipCSS = "[align-self:start]"; | ||||
|       transformCSS = `translateY(${offset})`; | ||||
|       arrowParentCSS = "h-4 -top-4 left-0 right-0"; | ||||
|       arrowCSS = "border-b-light"; | ||||
|       break; | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <div | ||||
|       className={`fixed z-[100] drop-shadow-shade-xl transition-opacity max-w-sm ${ | ||||
|         show | ||||
|           ? "opacity-100 pointer-events-auto" | ||||
|           : "opacity-0 pointer-events-none" | ||||
|       } ${tooltipCSS}`}
 | ||||
|       style={{ transform: transformCSS }} | ||||
|     > | ||||
|       <div className={`absolute grid ${arrowParentCSS}`}> | ||||
|         <div | ||||
|           className={`w-0 h-0 border-8 border-[transparent] place-self-center ${arrowCSS}`} | ||||
|         /> | ||||
|       </div> | ||||
|       <div className="p-2 px-4 bg-light rounded-md">{children}</div> | ||||
|     </div> | ||||
|   ); | ||||
| } | ||||
| @ -15,6 +15,11 @@ export default function Home(props: HomeProps): JSX.Element { | ||||
|   const { post } = props; | ||||
|   const contentPanel = ( | ||||
|     <ContentPanel> | ||||
|       <div className="grid place-items-center place-content-center w-full gap-5 text-center"> | ||||
|         <div className="[mask:url('/icons/accords.svg')] [mask-size:contain] [mask-repeat:no-repeat] [mask-position:center] w-32 aspect-square mobile:w-[50vw] bg-black" /> | ||||
|         <h1 className="text-5xl mb-0">Accord’s Library</h1> | ||||
|         <h2 className="text-xl -mt-5">Discover • Analyse • Translate • Archive</h2> | ||||
|       </div> | ||||
|       {post.translations.length > 0 && ( | ||||
|         <Markdawn text={post.translations[0].body} /> | ||||
|       )} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 DrMint
						DrMint