fix(callout): Grid-based callout collapsible animation (#1944)
* Fixed broken nested callout maxHeight calculation * Implemented grid-based callout collapsible
This commit is contained in:
		
							parent
							
								
									78e13bcb40
								
							
						
					
					
						commit
						4bd714b7be
					
				| @ -1,25 +1,10 @@ | ||||
| function toggleCallout(this: HTMLElement) { | ||||
|   const outerBlock = this.parentElement! | ||||
|   outerBlock.classList.toggle("is-collapsed") | ||||
|   const content = outerBlock.getElementsByClassName("callout-content")[0] as HTMLElement | ||||
|   if (!content) return | ||||
|   const collapsed = outerBlock.classList.contains("is-collapsed") | ||||
|   const height = collapsed ? this.scrollHeight : outerBlock.scrollHeight | ||||
|   outerBlock.style.maxHeight = height + "px" | ||||
| 
 | ||||
|   // walk and adjust height of all parents
 | ||||
|   let current = outerBlock | ||||
|   let parent = outerBlock.parentElement | ||||
|   while (parent) { | ||||
|     if (!parent.classList.contains("callout")) { | ||||
|       return | ||||
|     } | ||||
| 
 | ||||
|     const collapsed = parent.classList.contains("is-collapsed") | ||||
|     const height = collapsed ? parent.scrollHeight : parent.scrollHeight + current.scrollHeight | ||||
|     parent.style.maxHeight = height + "px" | ||||
| 
 | ||||
|     current = parent | ||||
|     parent = parent.parentElement | ||||
|   } | ||||
|   content.style.gridTemplateRows = collapsed ? "0fr" : "1fr" | ||||
| } | ||||
| 
 | ||||
| function setupCallout() { | ||||
| @ -27,15 +12,15 @@ function setupCallout() { | ||||
|     `callout is-collapsible`, | ||||
|   ) as HTMLCollectionOf<HTMLElement> | ||||
|   for (const div of collapsible) { | ||||
|     const title = div.firstElementChild | ||||
|     if (!title) continue | ||||
|     const title = div.getElementsByClassName("callout-title")[0] as HTMLElement | ||||
|     const content = div.getElementsByClassName("callout-content")[0] as HTMLElement | ||||
|     if (!title || !content) continue | ||||
| 
 | ||||
|     title.addEventListener("click", toggleCallout) | ||||
|     window.addCleanup(() => title.removeEventListener("click", toggleCallout)) | ||||
| 
 | ||||
|     const collapsed = div.classList.contains("is-collapsed") | ||||
|     const height = collapsed ? title.scrollHeight : div.scrollHeight | ||||
|     div.style.maxHeight = height + "px" | ||||
|     content.style.gridTemplateRows = collapsed ? "0fr" : "1fr" | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -464,6 +464,30 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>> | ||||
|                   }) | ||||
|                 } | ||||
| 
 | ||||
|                 // For the rest of the MD callout elements other than the title, wrap them with
 | ||||
|                 // two nested HTML <div>s (use some hacked mdhast component to achieve this) of
 | ||||
|                 // class `callout-content` and `callout-content-inner` respectively for
 | ||||
|                 // grid-based collapsible animation.
 | ||||
|                 if (calloutContent.length > 0) { | ||||
|                   node.children = [ | ||||
|                     node.children[0], | ||||
|                     { | ||||
|                       data: { hProperties: { className: ["callout-content"] }, hName: "div" }, | ||||
|                       type: "blockquote", | ||||
|                       children: [ | ||||
|                         { | ||||
|                           data: { | ||||
|                             hProperties: { className: ["callout-content-inner"] }, | ||||
|                             hName: "div", | ||||
|                           }, | ||||
|                           type: "blockquote", | ||||
|                           children: [...calloutContent], | ||||
|                         }, | ||||
|                       ], | ||||
|                     }, | ||||
|                   ] | ||||
|                 } | ||||
| 
 | ||||
|                 // replace first line of blockquote with title and rest of the paragraph text
 | ||||
|                 node.children.splice(0, 1, ...blockquoteContent) | ||||
| 
 | ||||
| @ -485,21 +509,6 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<Options>> | ||||
|                     "data-callout-metadata": calloutMetaData, | ||||
|                   }, | ||||
|                 } | ||||
| 
 | ||||
|                 // Add callout-content class to callout body if it has one.
 | ||||
|                 if (calloutContent.length > 0) { | ||||
|                   const contentData: BlockContent | DefinitionContent = { | ||||
|                     data: { | ||||
|                       hProperties: { | ||||
|                         className: "callout-content", | ||||
|                       }, | ||||
|                       hName: "div", | ||||
|                     }, | ||||
|                     type: "blockquote", | ||||
|                     children: [...calloutContent], | ||||
|                   } | ||||
|                   node.children = [node.children[0], contentData] | ||||
|                 } | ||||
|               } | ||||
|             }) | ||||
|           } | ||||
|  | ||||
| @ -7,11 +7,19 @@ | ||||
|   border-radius: 5px; | ||||
|   padding: 0 1rem; | ||||
|   overflow-y: hidden; | ||||
|   transition: max-height 0.3s ease; | ||||
|   box-sizing: border-box; | ||||
| 
 | ||||
|   & > .callout-content > :first-child { | ||||
|     margin-top: 0; | ||||
|   & > .callout-content { | ||||
|     display: grid; | ||||
|     transition: grid-template-rows 0.3s ease; | ||||
| 
 | ||||
|     & > .callout-content-inner { | ||||
|       overflow: hidden; | ||||
| 
 | ||||
|       & > :first-child { | ||||
|         margin-top: 0; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   --callout-icon-note: url('data:image/svg+xml; utf8, <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="2" x2="22" y2="6"></line><path d="M7.5 20.5 19 9l-4-4L3.5 16.5 2 22z"></path></svg>'); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user