skeletonlabs / skeleton

A complete design system and component solution, built on Tailwind.
https://skeleton.dev
MIT License
4.89k stars 305 forks source link

Cookbook: Table of Contents #2362

Open endigo9740 opened 8 months ago

endigo9740 commented 8 months ago

[!WARNING] This issue is a work in progress.

This will act as a hub to centralize this information.

Maintainer Requests

The following requests are coming straight from the Skeleton team. These are highly likely be implemented:

Community Requests

The following requests have come from the community and are under consideration:

Bugs and Issues

Feedback

If you have additional updates or requests for this feature, please do so in the comments section below.

DJMogens commented 5 months ago

The docs describe a default and apparently hardcoded tocCrawler method that takes h2-h6, however an option to tweak the generator so it could also generate entries for h1, and other custom elements, would help. Currently working with a markdown renderer where it it essential that h1 elements are part of the Table of Contents.

image

The language in the docs saying that it supports h2-h6 "by default", suggest that this is already something we can modify, but i have not found that to be the case, as it is hardcoded in crawler.ts as variable queryElements

export function tocCrawler(node: HTMLElement, args?: TOCCrawlerArgs) {
    let queryElements = 'h2, h3, h4, h5, h6';
    let scrollTarget = 'body';
    let headings: NodeListOf<HTMLElement> | undefined;
    let permalinks: TOCHeadingLink[] = [];

    function init(): void {
        // Set accepted list of query elements
        // (IMPORTANT: must proceed resetting `headings` below)
        if (args?.queryElements) queryElements = args.queryElements;
        // Set the desired scroll target to monitor
        if (args?.scrollTarget) scrollTarget = args.scrollTarget;

        // Reset local values
        headings = node.querySelectorAll(queryElements);
        permalinks = [];

        // Query and process the headings
        queryHeadings();
    }
endigo9740 commented 5 months ago

@DJMogens Two things here:

First, you should avoid including multiple h1 tags in your pages. This is considered an anti-pattern. This is considered an accessibility concern. Given this, in most cases these won't be relevant to your Table of Contents. You can set a custom title - just note our example doesn't follow our own advice here and uses an h1 incorrectly. We'll need to fix that soon!

While using multiple <h1> elements on one page is allowed by the HTML standard (as long as they are not nested, this is not considered a best practice. A page should generally have a single <h1> element that describes the content of the page (similar to the document's <title> element.

Second, you can configure the list of queryElements in the Crawler, our website documentation is just lacking this information. You pointed out the default list of elements, shown here:

However, this can be overwritten by arguments passed to the Action:

To use this, you would do something like this:

<div use:tocCrawler={{ queryElements: 'h1, h2, h3' }}

Sorry those two bits of confusion in the docs. We gladly welcome a new issue or PR to resolve this for Skeleton v2:

https://github.com/skeletonlabs/skeleton/issues/new?assignees=&labels=documentation&projects=&template=docs_issue.yml

Also note that this ticket is discussing tasks during the transition to Skeleton v3. In v3 we may take a very different approach to Table of Contents, given the mix of Frameworks (Svelte/React) and Meta-Frameworks (SvelteKit/Next/Astro) that we plan to support. See this example from Astro for example, which uses an MDX plugin to generate the headings automatically:

https://kld.dev/building-table-of-contents/

We'll be taking this information into account for our next generation of this feature!

towel commented 2 months ago

Please consider https://github.com/skeletonlabs/skeleton/issues/2738 also for the ToC replacement.