From 4a4974577784cf593e5cb1a3e9a86d0f29117cf4 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Tue, 20 Jun 2023 11:25:17 +0800
Subject: [PATCH 1/9] Docs: Add opt-in Table of Contents

---
 code/ui/blocks/package.json                   |   1 +
 code/ui/blocks/src/blocks/DocsContainer.tsx   |  12 +-
 code/ui/blocks/src/components/DocsPage.tsx    |  31 +++-
 .../blocks/src/components/TableOfContents.tsx | 162 ++++++++++++++++++
 code/yarn.lock                                |   8 +
 5 files changed, 208 insertions(+), 6 deletions(-)
 create mode 100644 code/ui/blocks/src/components/TableOfContents.tsx

diff --git a/code/ui/blocks/package.json b/code/ui/blocks/package.json
index c3cc1a90c0c9..6a345d8ebd60 100644
--- a/code/ui/blocks/package.json
+++ b/code/ui/blocks/package.json
@@ -63,6 +63,7 @@
     "polished": "^4.2.2",
     "react-colorful": "^5.1.2",
     "telejson": "^7.0.3",
+    "tocbot": "^4.20.1",
     "ts-dedent": "^2.0.0",
     "util-deprecate": "^1.0.2"
   },
diff --git a/code/ui/blocks/src/blocks/DocsContainer.tsx b/code/ui/blocks/src/blocks/DocsContainer.tsx
index 8640f06a68f1..e2141a2b370c 100644
--- a/code/ui/blocks/src/blocks/DocsContainer.tsx
+++ b/code/ui/blocks/src/blocks/DocsContainer.tsx
@@ -9,6 +9,7 @@ import type { DocsContextProps } from './DocsContext';
 import { DocsContext } from './DocsContext';
 import { SourceContainer } from './SourceContainer';
 import { scrollToElement } from './utils';
+import { useOf } from './useOf';
 
 const { document, window: globalWindow } = global;
 
@@ -22,6 +23,15 @@ export const DocsContainer: FC<PropsWithChildren<DocsContainerProps>> = ({
   theme,
   children,
 }) => {
+  let toc;
+  try {
+    const meta = useOf('meta', ['meta']);
+    toc = meta.preparedMeta.parameters?.docs?.toc || {};
+  } catch (err) {
+    // No meta, falling back to project annotations
+    toc = context?.projectAnnotations?.parameters?.docs?.toc || {};
+  }
+
   useEffect(() => {
     let url;
     try {
@@ -44,7 +54,7 @@ export const DocsContainer: FC<PropsWithChildren<DocsContainerProps>> = ({
     <DocsContext.Provider value={context}>
       <SourceContainer channel={context.channel}>
         <ThemeProvider theme={ensureTheme(theme)}>
-          <DocsPageWrapper>{children}</DocsPageWrapper>
+          <DocsPageWrapper toc={toc}>{children}</DocsPageWrapper>
         </ThemeProvider>
       </SourceContainer>
     </DocsContext.Provider>
diff --git a/code/ui/blocks/src/components/DocsPage.tsx b/code/ui/blocks/src/components/DocsPage.tsx
index 6b097e66063e..c4cc84f7266e 100644
--- a/code/ui/blocks/src/components/DocsPage.tsx
+++ b/code/ui/blocks/src/components/DocsPage.tsx
@@ -1,9 +1,11 @@
+import type { FC } from 'react';
+import React from 'react';
+import { transparentize } from 'polished';
 import { withReset } from '@storybook/components';
 import type { CSSObject } from '@storybook/theming';
 import { styled } from '@storybook/theming';
-import { transparentize } from 'polished';
-import type { FC } from 'react';
-import React from 'react';
+import { TableOfContents } from './TableOfContents';
+import type { TocParameters } from './TableOfContents';
 
 /**
  * This selector styles all raw elements inside the DocsPage like this example with a `<div/>`:
@@ -433,12 +435,31 @@ export const DocsWrapper = styled.div(({ theme }) => ({
   [`@media (min-width: ${breakpoint}px)`]: {},
 }));
 
+const TocWrapper = styled.div`
+  display: flex;
+  gap: 0rem;
+
+  @media only screen and (min-width: 1200px) {
+    gap: 3rem;
+  }
+`;
+
+const ContentWrapper = styled.div`
+  width: 100%;
+`;
+
 interface DocsPageWrapperProps {
   children?: React.ReactNode;
+  toc?: TocParameters;
 }
 
-export const DocsPageWrapper: FC<DocsPageWrapperProps> = ({ children }) => (
+export const DocsPageWrapper: FC<DocsPageWrapperProps> = ({ children, toc }) => (
   <DocsWrapper className="sbdocs sbdocs-wrapper">
-    <DocsContent className="sbdocs sbdocs-content">{children}</DocsContent>
+    <DocsContent className="sbdocs sbdocs-content">
+      <TocWrapper>
+        <ContentWrapper>{children}</ContentWrapper>
+        {toc ? <TableOfContents className="sbdocs sbdocs-toc--custom" {...toc} /> : null}
+      </TocWrapper>
+    </DocsContent>
   </DocsWrapper>
 );
diff --git a/code/ui/blocks/src/components/TableOfContents.tsx b/code/ui/blocks/src/components/TableOfContents.tsx
new file mode 100644
index 000000000000..bbea7ff84df1
--- /dev/null
+++ b/code/ui/blocks/src/components/TableOfContents.tsx
@@ -0,0 +1,162 @@
+import React, { useEffect } from 'react';
+import type { FC, ReactElement } from 'react';
+import { styled } from '@storybook/theming';
+import tocbot from 'tocbot';
+
+export interface TocParameters {
+  /** CSS selector for the container to search for headings. */
+  contentsSelector?: string;
+
+  /**
+   * When true, hide the TOC. We still show the empty container
+   * (as opposed to showing nothing at all) because it affects the
+   * page layout and we want to preserve the layout across pages.
+   */
+  disable?: boolean;
+
+  /** CSS selector to match headings to list in the TOC. */
+  headingSelector?: string;
+
+  /** Headings that match the ignoreSelector will be skipped. */
+  ignoreSelector?: string;
+
+  /** Custom title ReactElement or string to display above the TOC. */
+  title?: ReactElement | string | null;
+
+  /**
+   * TocBot options, not guaranteed to be available in future versions.
+   * See [tocbot docs](https://tscanlin.github.io/tocbot/#usage)
+   */
+  unsafeTocbotOptions?: tocbot.IStaticOptions;
+}
+
+const space = (n: number) => `${n * 10}px`;
+
+const Container = styled('div')`
+  font-family: ${(p) => p.theme.typography.fonts.base};
+  height: 100%;
+  display: none;
+  width: 10rem;
+
+  @media only screen and (min-width: 1200px) {
+    display: block;
+  }
+`;
+
+const Content = styled('div')`
+  position: fixed;
+  top: 0;
+  width: 10rem;
+  padding-top: 4rem;
+
+  & > .toc-wrapper > .toc-list {
+    padding-left: 0;
+    border-left: solid 2px ${(p) => p.theme.color.mediumlight};
+
+    .toc-list {
+      padding-left: 0;
+      border-left: solid 2px ${(p) => p.theme.color.mediumlight};
+
+      .toc-list {
+        padding-left: 0;
+        border-left: solid 2px ${(p) => p.theme.color.mediumlight};
+      }
+    }
+  }
+  & .toc-list-item {
+    position: relative;
+    list-style-type: none;
+    margin-left: ${space(2)};
+  }
+  & .toc-list-item::before {
+    content: '';
+    position: absolute;
+    height: 100%;
+    top: 0;
+    left: 0;
+    transform: translateX(calc(-2px - ${space(2)}));
+    border-left: solid 2px ${(p) => p.theme.color.mediumdark};
+    opacity: 0;
+    transition: opacity 0.2s;
+  }
+  & .toc-list-item.is-active-li::before {
+    opacity: 1;
+  }
+  & .toc-list-item > a {
+    color: ${(p) => p.theme.color.defaultText};
+  }
+  & .toc-list-item.is-active-li > a {
+    font-weight: 600;
+    color: ${(p) => p.theme.color.secondary};
+  }
+`;
+
+const Heading = styled('p')`
+  font-weight: 600;
+  font-size: 0.875em;
+  color: ${(p) => p.theme.textColor};
+  text-transform: uppercase;
+  margin-bottom: ${space(1)};
+`;
+
+type TableOfContentsProps = React.PropsWithChildren<
+  TocParameters & {
+    className?: string;
+  }
+>;
+
+const OptionalTitle: FC<{ title: TableOfContentsProps['title'] }> = ({ title }) => {
+  if (title === null) return null;
+  if (typeof title === 'string') return <Heading>{title}</Heading>;
+  return title;
+};
+
+export const TableOfContents = ({
+  title,
+  disable,
+  headingSelector,
+  contentsSelector,
+  ignoreSelector,
+  unsafeTocbotOptions,
+}: TableOfContentsProps) => {
+  console.log({ title, disable, headingSelector, ignoreSelector, unsafeTocbotOptions });
+  useEffect(() => {
+    const configuration = {
+      tocSelector: '.toc-wrapper',
+      contentSelector: contentsSelector ?? '.sbdocs-content',
+      headingSelector: headingSelector ?? 'h3',
+      ignoreSelector: ignoreSelector ?? '.skip-toc',
+      headingsOffset: 40,
+      scrollSmoothOffset: -40,
+      /**
+       * Ignore headings that did not
+       * come from the main markdown code.
+       */
+      // ignoreSelector: ':not(.sbdocs), .hide-from-toc',
+      orderedList: false,
+      /**
+       * Prevent default linking behavior,
+       * leaving only the smooth scrolling.
+       */
+      onClick: () => false,
+      ...unsafeTocbotOptions,
+    };
+    console.log({ configuration });
+
+    /**
+     * Wait for the DOM to be ready.
+     */
+    setTimeout(() => tocbot.init(configuration), 100);
+  }, [disable]);
+
+  return (
+    <Container>
+      {!disable && (
+        <Content>
+          <OptionalTitle title={title || null} />
+          <div className="toc-wrapper" />
+        </Content>
+      )}
+    </Container>
+  );
+};
diff --git a/code/yarn.lock b/code/yarn.lock
index b5e567ea951c..f6e79c1bcc5d 100644
--- a/code/yarn.lock
+++ b/code/yarn.lock
@@ -5802,6 +5802,7 @@ __metadata:
     polished: ^4.2.2
     react-colorful: ^5.1.2
     telejson: ^7.0.3
+    tocbot: ^4.20.1
     ts-dedent: ^2.0.0
     util-deprecate: ^1.0.2
   peerDependencies:
@@ -29196,6 +29197,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"tocbot@npm:^4.20.1":
+  version: 4.21.0
+  resolution: "tocbot@npm:4.21.0"
+  checksum: 877d99df40c07ec5e5c2259b820be9c8af9a9f52d582a61b7bed3d43daff820f23031bc613a5cc3bb14ecc34b79c1a45349dcbae8f3a79de7ecc127f366ed3c6
+  languageName: node
+  linkType: hard
+
 "toggle-selection@npm:^1.0.6":
   version: 1.0.6
   resolution: "toggle-selection@npm:1.0.6"

From bd15fe715dfe8ce954dbeda6e400fdc7d4bd544c Mon Sep 17 00:00:00 2001
From: Norbert de Langen <ndelangen@me.com>
Date: Tue, 20 Jun 2023 17:01:03 +0200
Subject: [PATCH 2/9] make changes

---
 code/ui/.storybook/preview.tsx                |   1 +
 code/ui/blocks/src/blocks/DocsContainer.tsx   |   7 +-
 code/ui/blocks/src/components/DocsPage.tsx    |  25 +--
 .../blocks/src/components/TableOfContents.tsx | 181 ++++++++++--------
 4 files changed, 111 insertions(+), 103 deletions(-)

diff --git a/code/ui/.storybook/preview.tsx b/code/ui/.storybook/preview.tsx
index 7c52ad023776..c89c15e85db4 100644
--- a/code/ui/.storybook/preview.tsx
+++ b/code/ui/.storybook/preview.tsx
@@ -277,6 +277,7 @@ export const parameters = {
   },
   docs: {
     theme: themes.light,
+    toc: {},
   },
   controls: {
     presetColors: [
diff --git a/code/ui/blocks/src/blocks/DocsContainer.tsx b/code/ui/blocks/src/blocks/DocsContainer.tsx
index e2141a2b370c..ea49c6d57b1d 100644
--- a/code/ui/blocks/src/blocks/DocsContainer.tsx
+++ b/code/ui/blocks/src/blocks/DocsContainer.tsx
@@ -10,6 +10,7 @@ import { DocsContext } from './DocsContext';
 import { SourceContainer } from './SourceContainer';
 import { scrollToElement } from './utils';
 import { useOf } from './useOf';
+import { TableOfContents } from '../components/TableOfContents';
 
 const { document, window: globalWindow } = global;
 
@@ -54,7 +55,11 @@ export const DocsContainer: FC<PropsWithChildren<DocsContainerProps>> = ({
     <DocsContext.Provider value={context}>
       <SourceContainer channel={context.channel}>
         <ThemeProvider theme={ensureTheme(theme)}>
-          <DocsPageWrapper toc={toc}>{children}</DocsPageWrapper>
+          <DocsPageWrapper
+            toc={toc ? <TableOfContents className="sbdocs sbdocs-toc--custom" {...toc} /> : null}
+          >
+            {children}
+          </DocsPageWrapper>
         </ThemeProvider>
       </SourceContainer>
     </DocsContext.Provider>
diff --git a/code/ui/blocks/src/components/DocsPage.tsx b/code/ui/blocks/src/components/DocsPage.tsx
index c4cc84f7266e..796bbb563f90 100644
--- a/code/ui/blocks/src/components/DocsPage.tsx
+++ b/code/ui/blocks/src/components/DocsPage.tsx
@@ -4,7 +4,6 @@ import { transparentize } from 'polished';
 import { withReset } from '@storybook/components';
 import type { CSSObject } from '@storybook/theming';
 import { styled } from '@storybook/theming';
-import { TableOfContents } from './TableOfContents';
 import type { TocParameters } from './TableOfContents';
 
 /**
@@ -431,35 +430,19 @@ export const DocsWrapper = styled.div(({ theme }) => ({
   padding: '4rem 20px',
   minHeight: '100vh',
   boxSizing: 'border-box',
+  gap: '3rem',
 
   [`@media (min-width: ${breakpoint}px)`]: {},
 }));
 
-const TocWrapper = styled.div`
-  display: flex;
-  gap: 0rem;
-
-  @media only screen and (min-width: 1200px) {
-    gap: 3rem;
-  }
-`;
-
-const ContentWrapper = styled.div`
-  width: 100%;
-`;
-
 interface DocsPageWrapperProps {
   children?: React.ReactNode;
-  toc?: TocParameters;
+  toc?: React.ReactNode;
 }
 
 export const DocsPageWrapper: FC<DocsPageWrapperProps> = ({ children, toc }) => (
   <DocsWrapper className="sbdocs sbdocs-wrapper">
-    <DocsContent className="sbdocs sbdocs-content">
-      <TocWrapper>
-        <ContentWrapper>{children}</ContentWrapper>
-        {toc ? <TableOfContents className="sbdocs sbdocs-toc--custom" {...toc} /> : null}
-      </TocWrapper>
-    </DocsContent>
+    <DocsContent className="sbdocs sbdocs-content">{children}</DocsContent>
+    {toc}
   </DocsWrapper>
 );
diff --git a/code/ui/blocks/src/components/TableOfContents.tsx b/code/ui/blocks/src/components/TableOfContents.tsx
index bbea7ff84df1..c5ee1a6048b6 100644
--- a/code/ui/blocks/src/components/TableOfContents.tsx
+++ b/code/ui/blocks/src/components/TableOfContents.tsx
@@ -30,74 +30,85 @@ export interface TocParameters {
   unsafeTocbotOptions?: tocbot.IStaticOptions;
 }
 
-const space = (n: number) => `${n * 10}px`;
-
-const Container = styled('div')`
-  font-family: ${(p) => p.theme.typography.fonts.base};
-  height: 100%;
-  display: none;
-  width: 10rem;
-
-  @media only screen and (min-width: 1200px) {
-    display: block;
-  }
-`;
-
-const Content = styled('div')`
-  position: fixed;
-  top: 0;
-  width: 10rem;
-  padding-top: 4rem;
-
-  & > .toc-wrapper > .toc-list {
-    padding-left: 0;
-    border-left: solid 2px ${(p) => p.theme.color.mediumlight};
-
-    .toc-list {
-      padding-left: 0;
-      border-left: solid 2px ${(p) => p.theme.color.mediumlight};
-
-      .toc-list {
-        padding-left: 0;
-        border-left: solid 2px ${(p) => p.theme.color.mediumlight};
-      }
-    }
-  }
-  & .toc-list-item {
-    position: relative;
-    list-style-type: none;
-    margin-left: ${space(2)};
-  }
-  & .toc-list-item::before {
-    content: '';
-    position: absolute;
-    height: 100%;
-    top: 0;
-    left: 0;
-    transform: translateX(calc(-2px - ${space(2)}));
-    border-left: solid 2px ${(p) => p.theme.color.mediumdark};
-    opacity: 0;
-    transition: opacity 0.2s;
-  }
-  & .toc-list-item.is-active-li::before {
-    opacity: 1;
-  }
-  & .toc-list-item > a {
-    color: ${(p) => p.theme.color.defaultText};
-  }
-  & .toc-list-item.is-active-li > a {
-    font-weight: 600;
-    color: ${(p) => p.theme.color.secondary};
-  }
-`;
-
-const Heading = styled('p')`
-  font-weight: 600;
-  font-size: 0.875em;
-  color: ${(p) => p.theme.textColor};
-  text-transform: uppercase;
-  margin-bottom: ${space(1)};
-`;
+const Wrapper = styled.div(({ theme }) => ({
+  width: '10rem',
+
+  '@media (max-width: 768px)': {
+    display: 'none',
+  },
+}));
+
+const Content = styled.div(({ theme }) => ({
+  position: 'fixed',
+  top: 0,
+  width: '10rem',
+  paddingTop: '4rem',
+
+  fontFamily: theme.typography.fonts.base,
+  fontSize: theme.typography.size.s2,
+
+  WebkitFontSmoothing: 'antialiased',
+  MozOsxFontSmoothing: 'grayscale',
+  WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)',
+  WebkitOverflowScrolling: 'touch',
+
+  '& *': {
+    boxSizing: 'border-box',
+  },
+
+  '& > .toc-wrapper > .toc-list': {
+    paddingLeft: 0,
+    borderLeft: `solid 2px ${theme.color.mediumlight}`,
+
+    '.toc-list': {
+      paddingLeft: 0,
+      borderLeft: `solid 2px ${theme.color.mediumlight}`,
+
+      '.toc-list': {
+        paddingLeft: 0,
+        borderLeft: `solid 2px ${theme.color.mediumlight}`,
+      },
+    },
+  },
+  '& .toc-list-item': {
+    position: 'relative',
+    listStyleType: 'none',
+    marginLeft: 20,
+    paddingTop: 3,
+    paddingBottom: 3,
+  },
+  '& .toc-list-item::before': {
+    content: '""',
+    position: 'absolute',
+    height: '100%',
+    top: 0,
+    left: 0,
+    transform: `translateX(calc(-2px - 20px))`,
+    borderLeft: `solid 2px ${theme.color.mediumdark}`,
+    opacity: 0,
+    transition: 'opacity 0.2s',
+  },
+  '& .toc-list-item.is-active-li::before': {
+    opacity: 1,
+  },
+  '& .toc-list-item > a': {
+    color: theme.color.defaultText,
+    textDecoration: 'none',
+  },
+  '& .toc-list-item.is-active-li > a': {
+    fontWeight: 600,
+    color: theme.color.secondary,
+    textDecoration: 'none',
+  },
+}));
+
+const Heading = styled.p(({ theme }) => ({
+  fontWeight: 600,
+  fontSize: '0.875em',
+  color: theme.textColor,
+  textTransform: 'uppercase',
+  marginBottom: 10,
+}));
 
 type TableOfContentsProps = React.PropsWithChildren<
   TocParameters & {
@@ -106,8 +117,12 @@ type TableOfContentsProps = React.PropsWithChildren<
 >;
 
 const OptionalTitle: FC<{ title: TableOfContentsProps['title'] }> = ({ title }) => {
-  if (title === null) return null;
-  if (typeof title === 'string') return <Heading>{title}</Heading>;
+  if (title === null) {
+    return null;
+  }
+  if (typeof title === 'string') {
+    return <Heading>{title}</Heading>;
+  }
   return title;
 };
 
@@ -119,7 +134,6 @@ export const TableOfContents = ({
   ignoreSelector,
   unsafeTocbotOptions,
 }: TableOfContentsProps) => {
-  console.log({ title, disable, headingSelector, ignoreSelector, unsafeTocbotOptions });
   useEffect(() => {
     const configuration = {
       tocSelector: '.toc-wrapper',
@@ -141,22 +155,27 @@ export const TableOfContents = ({
       onClick: () => false,
       ...unsafeTocbotOptions,
     };
-    console.log({ configuration });
 
     /**
      * Wait for the DOM to be ready.
      */
-    setTimeout(() => tocbot.init(configuration), 100);
+    const timeout = setTimeout(() => tocbot.init(configuration), 100);
+    return () => {
+      clearTimeout(timeout);
+      tocbot.destroy();
+    };
   }, [disable]);
 
   return (
-    <Container>
-      {!disable && (
-        <Content>
-          <OptionalTitle title={title || null} />
-          <div className="toc-wrapper" />
-        </Content>
-      )}
-    </Container>
+    <>
+      <Wrapper>
+        {!disable ? (
+          <Content>
+            <OptionalTitle title={title || null} />
+            <div className="toc-wrapper" />
+          </Content>
+        ) : null}
+      </Wrapper>
+    </>
   );
 };

From 054630104fc8198977754f640f20091c1dfc6f62 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 22 Jun 2023 00:18:04 +0800
Subject: [PATCH 3/9] Fix build

---
 code/ui/blocks/src/components/DocsPage.tsx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/code/ui/blocks/src/components/DocsPage.tsx b/code/ui/blocks/src/components/DocsPage.tsx
index 796bbb563f90..112025269863 100644
--- a/code/ui/blocks/src/components/DocsPage.tsx
+++ b/code/ui/blocks/src/components/DocsPage.tsx
@@ -4,7 +4,6 @@ import { transparentize } from 'polished';
 import { withReset } from '@storybook/components';
 import type { CSSObject } from '@storybook/theming';
 import { styled } from '@storybook/theming';
-import type { TocParameters } from './TableOfContents';
 
 /**
  * This selector styles all raw elements inside the DocsPage like this example with a `<div/>`:

From fe01f47500b6de56c99826e8da9f49930a6d5eee Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 00:12:39 +0800
Subject: [PATCH 4/9] Addon-docs: Fix bug where TOC is always showing

---
 code/ui/blocks/src/blocks/DocsContainer.tsx | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/code/ui/blocks/src/blocks/DocsContainer.tsx b/code/ui/blocks/src/blocks/DocsContainer.tsx
index ea49c6d57b1d..60756a7ae25a 100644
--- a/code/ui/blocks/src/blocks/DocsContainer.tsx
+++ b/code/ui/blocks/src/blocks/DocsContainer.tsx
@@ -25,12 +25,13 @@ export const DocsContainer: FC<PropsWithChildren<DocsContainerProps>> = ({
   children,
 }) => {
   let toc;
+
   try {
     const meta = useOf('meta', ['meta']);
-    toc = meta.preparedMeta.parameters?.docs?.toc || {};
+    toc = meta.preparedMeta.parameters?.docs?.toc;
   } catch (err) {
     // No meta, falling back to project annotations
-    toc = context?.projectAnnotations?.parameters?.docs?.toc || {};
+    toc = context?.projectAnnotations?.parameters?.docs?.toc;
   }
 
   useEffect(() => {

From 43a5531da3457f7500d1c32e397299de6c6ea678 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 00:13:04 +0800
Subject: [PATCH 5/9] Remove spurious console.log

---
 code/builders/builder-manager/src/index.ts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/code/builders/builder-manager/src/index.ts b/code/builders/builder-manager/src/index.ts
index 3597a206ec46..e2bdf248be82 100644
--- a/code/builders/builder-manager/src/index.ts
+++ b/code/builders/builder-manager/src/index.ts
@@ -190,7 +190,6 @@ const starter: StarterFunction = async function* starterGeneratorFn({
     }
   });
   router.use(`/index.html`, ({ path }, res) => {
-    console.log({ path });
     res.status(200).send(html);
   });
 

From e09f436a8a661cdcfa1a68fb5e0a6cfcecff2cfd Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 00:14:55 +0800
Subject: [PATCH 6/9] Addon-docs: Add TOC stories

---
 .../template/stories/toc/basic.stories.ts     | 22 +++++++++++++++++++
 .../stories/toc/custom-selector.stories.ts    | 13 +++++++++++
 .../stories/toc/custom-title.stories.ts       | 13 +++++++++++
 .../stories/toc/ignore-selector.stories.ts    | 13 +++++++++++
 4 files changed, 61 insertions(+)
 create mode 100644 code/addons/docs/template/stories/toc/basic.stories.ts
 create mode 100644 code/addons/docs/template/stories/toc/custom-selector.stories.ts
 create mode 100644 code/addons/docs/template/stories/toc/custom-title.stories.ts
 create mode 100644 code/addons/docs/template/stories/toc/ignore-selector.stories.ts

diff --git a/code/addons/docs/template/stories/toc/basic.stories.ts b/code/addons/docs/template/stories/toc/basic.stories.ts
new file mode 100644
index 000000000000..c66fe554aa34
--- /dev/null
+++ b/code/addons/docs/template/stories/toc/basic.stories.ts
@@ -0,0 +1,22 @@
+import { global as globalThis } from '@storybook/global';
+
+export default {
+  component: globalThis.Components.Button,
+  tags: ['autodocs'],
+  parameters: {
+    chromatic: { disable: true },
+    docs: { toc: {} },
+  },
+};
+
+export const One = {
+  args: { label: 'One' },
+};
+
+export const Two = {
+  args: { label: 'Two' },
+};
+
+export const Three = {
+  args: { label: 'Two' },
+};
diff --git a/code/addons/docs/template/stories/toc/custom-selector.stories.ts b/code/addons/docs/template/stories/toc/custom-selector.stories.ts
new file mode 100644
index 000000000000..f000675593d8
--- /dev/null
+++ b/code/addons/docs/template/stories/toc/custom-selector.stories.ts
@@ -0,0 +1,13 @@
+import { global as globalThis } from '@storybook/global';
+import { One, Two, Three } from './basic.stories';
+
+export default {
+  component: globalThis.Components.Button,
+  tags: ['autodocs'],
+  parameters: {
+    chromatic: { disable: true },
+    docs: { toc: { headingSelector: 'h1, h2, h3' } },
+  },
+};
+
+export { One, Two, Three };
diff --git a/code/addons/docs/template/stories/toc/custom-title.stories.ts b/code/addons/docs/template/stories/toc/custom-title.stories.ts
new file mode 100644
index 000000000000..6b079cf36659
--- /dev/null
+++ b/code/addons/docs/template/stories/toc/custom-title.stories.ts
@@ -0,0 +1,13 @@
+import { global as globalThis } from '@storybook/global';
+import { One, Two, Three } from './basic.stories';
+
+export default {
+  component: globalThis.Components.Button,
+  tags: ['autodocs'],
+  parameters: {
+    chromatic: { disable: true },
+    docs: { toc: { title: 'Contents' } },
+  },
+};
+
+export { One, Two, Three };
diff --git a/code/addons/docs/template/stories/toc/ignore-selector.stories.ts b/code/addons/docs/template/stories/toc/ignore-selector.stories.ts
new file mode 100644
index 000000000000..9a3721b5742b
--- /dev/null
+++ b/code/addons/docs/template/stories/toc/ignore-selector.stories.ts
@@ -0,0 +1,13 @@
+import { global as globalThis } from '@storybook/global';
+import { One, Two, Three } from './basic.stories';
+
+export default {
+  component: globalThis.Components.Button,
+  tags: ['autodocs'],
+  parameters: {
+    chromatic: { disable: true },
+    docs: { toc: { ignoreSelector: '#one' } },
+  },
+};
+
+export { One, Two, Three };

From 90c9929d32f24700612d70ec8d92a9914ec244c1 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 00:23:38 +0800
Subject: [PATCH 7/9] Addon-docs: Fix TOC context bug

---
 code/ui/blocks/src/blocks/DocsContainer.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/code/ui/blocks/src/blocks/DocsContainer.tsx b/code/ui/blocks/src/blocks/DocsContainer.tsx
index 60756a7ae25a..58e4d2b3a824 100644
--- a/code/ui/blocks/src/blocks/DocsContainer.tsx
+++ b/code/ui/blocks/src/blocks/DocsContainer.tsx
@@ -27,7 +27,7 @@ export const DocsContainer: FC<PropsWithChildren<DocsContainerProps>> = ({
   let toc;
 
   try {
-    const meta = useOf('meta', ['meta']);
+    const meta = context.resolveOf('meta', ['meta']);
     toc = meta.preparedMeta.parameters?.docs?.toc;
   } catch (err) {
     // No meta, falling back to project annotations

From 76ca248055cda84f1204e1c07c19c35800effc54 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 00:27:53 +0800
Subject: [PATCH 8/9] Cleanup

---
 code/addons/docs/template/stories/toc/custom-selector.stories.ts | 1 +
 code/addons/docs/template/stories/toc/custom-title.stories.ts    | 1 +
 code/addons/docs/template/stories/toc/ignore-selector.stories.ts | 1 +
 code/ui/blocks/src/blocks/DocsContainer.tsx                      | 1 -
 4 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/code/addons/docs/template/stories/toc/custom-selector.stories.ts b/code/addons/docs/template/stories/toc/custom-selector.stories.ts
index f000675593d8..48f1ee785156 100644
--- a/code/addons/docs/template/stories/toc/custom-selector.stories.ts
+++ b/code/addons/docs/template/stories/toc/custom-selector.stories.ts
@@ -6,6 +6,7 @@ export default {
   tags: ['autodocs'],
   parameters: {
     chromatic: { disable: true },
+    // Select all the headings in the document
     docs: { toc: { headingSelector: 'h1, h2, h3' } },
   },
 };
diff --git a/code/addons/docs/template/stories/toc/custom-title.stories.ts b/code/addons/docs/template/stories/toc/custom-title.stories.ts
index 6b079cf36659..2fde6ebcabf3 100644
--- a/code/addons/docs/template/stories/toc/custom-title.stories.ts
+++ b/code/addons/docs/template/stories/toc/custom-title.stories.ts
@@ -6,6 +6,7 @@ export default {
   tags: ['autodocs'],
   parameters: {
     chromatic: { disable: true },
+    // Custom title label
     docs: { toc: { title: 'Contents' } },
   },
 };
diff --git a/code/addons/docs/template/stories/toc/ignore-selector.stories.ts b/code/addons/docs/template/stories/toc/ignore-selector.stories.ts
index 9a3721b5742b..d355ac9ae966 100644
--- a/code/addons/docs/template/stories/toc/ignore-selector.stories.ts
+++ b/code/addons/docs/template/stories/toc/ignore-selector.stories.ts
@@ -6,6 +6,7 @@ export default {
   tags: ['autodocs'],
   parameters: {
     chromatic: { disable: true },
+    // Skip the first story in the TOC
     docs: { toc: { ignoreSelector: '#one' } },
   },
 };
diff --git a/code/ui/blocks/src/blocks/DocsContainer.tsx b/code/ui/blocks/src/blocks/DocsContainer.tsx
index 58e4d2b3a824..07b855295f10 100644
--- a/code/ui/blocks/src/blocks/DocsContainer.tsx
+++ b/code/ui/blocks/src/blocks/DocsContainer.tsx
@@ -9,7 +9,6 @@ import type { DocsContextProps } from './DocsContext';
 import { DocsContext } from './DocsContext';
 import { SourceContainer } from './SourceContainer';
 import { scrollToElement } from './utils';
-import { useOf } from './useOf';
 import { TableOfContents } from '../components/TableOfContents';
 
 const { document, window: globalWindow } = global;

From 995732e0a7a47d107010219fdfa3cc9ff5cebc96 Mon Sep 17 00:00:00 2001
From: Michael Shilman <shilman@users.noreply.github.com>
Date: Thu, 6 Jul 2023 17:31:38 +0800
Subject: [PATCH 9/9] Update code/ui/blocks/src/components/TableOfContents.tsx

Co-authored-by: Jeppe Reinhold <jeppe@chromatic.com>
---
 code/ui/blocks/src/components/TableOfContents.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/code/ui/blocks/src/components/TableOfContents.tsx b/code/ui/blocks/src/components/TableOfContents.tsx
index c5ee1a6048b6..892f1e137f20 100644
--- a/code/ui/blocks/src/components/TableOfContents.tsx
+++ b/code/ui/blocks/src/components/TableOfContents.tsx
@@ -25,7 +25,7 @@ export interface TocParameters {
 
   /**
    * TocBot options, not guaranteed to be available in future versions.
-   * See [tocbot docs](https://tscanlin.github.io/tocbot/#usage)
+   * @see tocbot docs {@link https://tscanlin.github.io/tocbot/#usage}
    */
   unsafeTocbotOptions?: tocbot.IStaticOptions;
 }