This component (shown on the left hand-side, play with it!) was crafted at beam, a browser with a first-class note taking experience. With beam, you can point and shoot elements from the pages you’re browsing and build rich-media notes out of them, complete with references and back-linking.
Click requirements to expand them
idid or noth1 > h2 > h3 should render the same as h1 > h3 > h5The table of contents component was built using React, TypeScript, and (s)CSS. It was designed to be flexible and adaptable to different scenarios. Let’s review some of the requirements and see how we went about.
TableOfContents.Root: the table of contents itself, it’s a simple component that calls a private TocElementcomponent to render each entry in the table of contentTableOfContents.Provider: a context provider that makes the table of contents available to all its childrenTableOfContents.useToc: a hook that returns the table of content context, containing the rootElement and a setter for the rootElementThe table of contents has two states: idle and active. When the table of content is idle, it displays dashes to represent the headings. The dashes length depends on the level of heading it represents. When the table of contents is active, it displays the heading text (truncated if necessary).
Provided the headings have an id, we get this behavior for free by simply linking to the id of the heading using a hash. Should the headings not have an id, we can still provide a clickable element that scrolls to the targeted element, usingelement.scrollIntoView(). In this cas we also apply a temporary class to the targeted element so we can trigger a CSS animation highlighting the targeted element. We use this logic to also enable clicking the dashes when the viewport is too small to display the table of content.
For the automatic updates, we have to take care of two possible events
rootElement itself changes: in the component that renders rootElement, we call th context setter to update it, in case of re-renders that would change the element itselfrootElement changes: to account for modifications of the subtree of the root element, we use a MutationObserver that triggers a re-render of the table of content