Newer
Older
hello-programmer-world / src / components / Toc.astro
@h.sakamoto h.sakamoto on 3 Feb 2 KB index
---
import { sections } from "../constants/sections.ts";
const currentPath = Astro.url.pathname;
---

<div class="toc-wrapper">
  <nav class="toc">
    <ul class="toc-list">
      <li class="toc-item">
        <a href="/" class="toc-link">Introduction</a>
      </li>

      {sections.map(section => {
      const isActive = section.items.some(item => currentPath.startsWith(item.url));
      return (
      <li class="toc-item">
        <details open={isActive}>
          <summary class="toc-section-title">{section.title}</summary>
          <ul class="toc-sublist">
            {section.items.map(item => (
            <li class="toc-subitem">
              <a href={item.url} class="toc-link">{item.title}</a>
            </li>
            ))}
          </ul>
        </details>
      </li>
      );
      })}
    </ul>
  </nav>
</div>

<style>
  .toc {
    font-size: 14px;
    position: sticky;
    top: 32px;
  }

  .toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  .toc-item {
    margin: 0;
  }

  .toc-link {
    display: block;
    padding: 4px 8px;
    color: #0969da;
    text-decoration: none;
    border-radius: 6px;
  }

  .toc-link:hover {
    background-color: #f6f8fa;
    text-decoration: none;
  }

  details {
    margin: 4px 0;
  }

  summary {
    cursor: pointer;
    padding: 4px 8px;
    font-weight: 600;
    color: #1f2328;
    border-radius: 6px;
    list-style: none;
  }

  summary::-webkit-details-marker {
    display: none;
  }

  summary::before {
    content: '▶';
    display: inline-block;
    margin-right: 6px;
    font-size: 10px;
    transition: transform 0.2s;
  }

  details[open] summary::before {
    transform: rotate(90deg);
  }

  summary:hover {
    background-color: #f6f8fa;
  }

  .toc-sublist {
    list-style: none;
    padding-left: 16px;
    margin: 4px 0;
  }

  .toc-subitem {
    margin: 0;
  }

  @media (prefers-color-scheme: dark) {
    .toc-link {
      color: #4493f8;
    }

    .toc-link:hover {
      background-color: #161b22;
    }

    summary {
      color: #e6edf3;
    }

    summary:hover {
      background-color: #161b22;
    }
  }
</style>