Files
blog-astro/src/components/notion/TableOfContents.astro
2026-01-19 17:41:22 +08:00

73 lines
1.7 KiB
Plaintext

---
import { buildHeadingId } from '../../lib/blog-helpers.ts'
import * as interfaces from '../../lib/interfaces.ts'
import { snakeToKebab } from '../../lib/style-helpers.ts'
import '../../styles/notion-color.css'
export interface Props {
block: interfaces.Block
headings: interfaces.Block[]
}
const { block, headings }: Props = Astro.props
if (!block.TableOfContents) {
return null
}
---
<div class="table-of-contents">
{
headings.map((headingBlock: interfaces.Block) => {
const heading =
headingBlock.Heading1 || headingBlock.Heading2 || headingBlock.Heading3
if (!heading) return null
let indentClass = ''
if (headingBlock.Type === 'heading_2') {
indentClass = 'indent-1'
} else if (headingBlock.Type === 'heading_3') {
indentClass = 'indent-2'
}
return (
<a
href={`#${buildHeadingId(heading)}`}
class={`table-of-contents ${snakeToKebab(
block.TableOfContents.Color,
)} ${indentClass}`}
>
{heading.RichTexts.map(
(richText: interfaces.RichText) => richText.PlainText,
).join('')}
</a>
)
})
}
</div>
<style>
.table-of-contents {
}
.table-of-contents > a {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
line-height: 1.8rem;
font-size: 0.9rem;
font-weight: 500;
text-decoration: underline;
}
.table-of-contents > a:hover {
background: var(--notion-gray-background) !important;
}
.table-of-contents > a.indent-1 {
padding-left: 1.5rem;
}
.table-of-contents > a.indent-2 {
padding-left: 3rem;
}
</style>