learn and share notes on atproto (wip) 馃 malfestio.stormlightlabs.org/
readability solid axum atproto srs
at main 43 lines 1.5 kB view raw
1import type { Heading } from "$lib/wikilink"; 2import { A } from "@solidjs/router"; 3import type { Component } from "solid-js"; 4import { For, Show } from "solid-js"; 5 6type OutlinePanelProps = { headings: Heading[]; onHeadingClick?: (id: string) => void }; 7 8/** 9 * Table of contents panel showing document outline from markdown headings 10 */ 11export const OutlinePanel: Component<OutlinePanelProps> = (props) => { 12 const handleClick = (id: string, e: MouseEvent) => { 13 e.preventDefault(); 14 props.onHeadingClick?.(id); 15 const element = document.getElementById(id); 16 if (element) { 17 element.scrollIntoView({ behavior: "smooth", block: "start" }); 18 } 19 }; 20 21 return ( 22 <div class="space-y-2"> 23 <h3 class="text-sm font-semibold text-slate-400 uppercase tracking-wide">Outline</h3> 24 <Show when={props.headings.length > 0} fallback={<p class="text-sm text-slate-500 italic">No headings found</p>}> 25 <nav class="space-y-1"> 26 <For each={props.headings}> 27 {(heading) => ( 28 <A 29 href={`#${heading.id}`} 30 onClick={(e) => handleClick(heading.id, e)} 31 class="block text-sm text-slate-300 hover:text-blue-400 transition-colors truncate" 32 style={{ "padding-left": `${(heading.level - 1) * 12}px` }}> 33 {heading.text} 34 </A> 35 )} 36 </For> 37 </nav> 38 </Show> 39 </div> 40 ); 41}; 42 43export default OutlinePanel;