Coder Social home page Coder Social logo

janosh / svelte-toc Goto Github PK

View Code? Open in Web Editor NEW
108.0 108.0 6.0 470 KB

Sticky responsive table of contents component

Home Page: https://janosh.github.io/svelte-toc

License: MIT License

Svelte 39.72% JavaScript 3.49% HTML 3.35% CSS 15.56% TypeScript 37.89%
component responsive-web-design sticky svelte sveltekit table-of-contents toc

svelte-toc's People

Contributors

amerlander avatar comefled avatar janosh avatar oskar-gmerek avatar pre-commit-ci[bot] avatar roualdes avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

svelte-toc's Issues

Getting error about resolving `$app/stores`

Hi, I've tried setting up the module as described in the README, but getting the following error when starting the app. I'm using webpack instead of SvelteKit, not sure if the error is due to an incompatibility of some sort:

Module not found: Error: Can't resolve '$app/stores' in '/Users/alex/work/personal/app/node_modules/svelte-toc'
resolve '$app/stores' in '/Users/alex/work/personal/app/node_modules/svelte-toc'
  Parsed request is a module
  using description file: /Users/alex/work/personal/app/node_modules/svelte-toc/package.json (relative path: .)
    Field 'browser' doesn't contain a valid alias configuration
    resolve as module
...

I did find the relevant line in Toc.svelte, I just don't understand how this $app/stores import works, I don't see it as a library in package.json, so I'm guessing it's some sort of magic that's not properly setup on my project?

Thanks

Strange behaviour

Hi there,

I trying to implement svelte-toc to my current work. Unfortunately, I experiencing strange behaviour.

When I navigating by a link to: /article

Then in svelte-toc I got data from the previous page (on that previous page, svelte-toc wasn't used).
If I refresh the page in the browser, then svelte-doc is loaded with the correct data.
If I just put the URL to the article in the browser and open the page that way, the correct data will be loaded also in that case.

What I see that makes a demo app different from my work is that I do not use mdsvex, I get markdown data from 3rdparty APIs and I parse it with markdown-it.
So my <Toc /> component is not in markdown, but above it (I do not have file +page.svx, I using <Toc /> in +page.svelte)

It's hard for me to reproduce it, as I cannot share backend/frontend data. And at the same time, I have no idea what reason for that behaviour.

I will be grateful for any tips on where to look for the cause

Regards

Issues with highlighting the correct content

when I was in your web page I was trying to move around, and found out that.
when I click on Usage and back on Examples the highlight is still on Usage tables of content. and for another example

when you are on top, try clicking on the bottom line Test Page Navigation it was highlighting on Styling instead.

How to use intersection observer for highlighting active heading

Hi XD

I have my own toc workflow for a sveltkit app i'm making and I have everything taken care of up until the intersection observer to highlight the current on screen headers in the toc...trying to figure out how to do it, but have no knowledge of intersection observers or using them with svelte...looking through your code and I'm not sure where that part begins...

In my toc I am looping through an array objects:

[
  { level: 1, heading: 'Frequencies' },
  { level: 1, heading: 'Notes' },
  { level: 2, heading: 'Equivalence' },
  { level: 2, heading: 'Pitch Classes' },
  { level: 1, heading: 'The Keyboard' },
  { level: 1, heading: 'Two Zones' },
  { level: 2, heading: 'Zone 1' },
  { level: 2, heading: 'Zone 2' },
  { level: 2, heading: 'Zone 1 + Zone 2' },
  // ...etc...
]

that is generated by a custom rehype plugin traversing some markdown...

I then loop through it in my toc.svelte file:

<div class='toc-box'>
  {#each headings as {level, heading}}
    <div class='heading'>
      <a class='toc-link'
        href={`/words/${slugify(title)}#${slugify(heading)}`}
      >
        <span class='toc-link-text'>{removeTags(heading)}</span>
      </a>
    </div>
  {/each}
</div>

...and everything is almost all good when the slugified href matches the current hash and I can click around and go to hash links and all that...still not perfect and prolly should use <ul>'s and <li>'s, making my own slugify() function and it doesn't quite work right yet, but these are other issues...

The last big piece of the toc puzzle is highlighting the toc headers that are currently in the viewport...just not sure how to go about it...

...I'm looking through your code and I'm not sure where that part begins and how to adapt it to my array of objects. I also have a REPL I've put together by lifting a codepen that works and trying to make it work with svelte, but can't figure it out...

Svelte REPL:
https://svelte.dev/repl/7006d7890b964928b8f72622a3d067ac?version=3.42.5

Original Codepen:

https://codepen.io/bramus/pen/ExaEqMJ

If you don't have time or interest for this no worries, totally understand, but if you have any thoughts that you would be willing to share I am all ears :-)

Thank you!

New prop for toc nav overflow-y

First off, thanks for this great package.

I'm interested, though still learning Svelte (and CSS), in adding a prop for the following style

:where(aside.toc > nav) {
overflow-y: scroll;
overscroll-behavior: contain;
max-height: var(--toc-max-height, 90vh);
padding: var(--toc-padding, 1em 1em 0);
}

From issue #32, you say you'll accept PRs adding such features. And I'm happy submit a PR, but I need some guidance.

I assume something like

  :where(aside.toc > nav) {
    overflow-y: var(--toc-nav-overlfow); 
    ...
}

is close to what I'm after. How does one set the default to scroll;?

Thanks in advance for pointing me in the right direction.

Prevents scroll when using smart zoom on macOS

Hi,

When using smart zoom (double-taped mouse) svelte-toc prevents scrolling down to the bottom of the page. The scroll position jumps up when the active header should change instead of scrolling down and changing the active header in svelte-toc.

Nagranie.z.ekranu.2022-09-13.o.10.05.36.mov

I also find out, that if I do not wrap with a fixed position wrapper, then svelte-toc prevents scrolling the page more than the height of the ToC component.

SvelteKit page navigation breaks when svelte-toc is shown

I am having a weird issue on my website.

I've added svelte-toc on a +layout.svelte file, for a specific dynamic route that loads blog posts. It works well when in that page, but things start breaking when I try navigating to others.

Here's how I'm using it:

{#if post.showToc}
    {post.showToc} <!-- added here for debugging purposes -->
    <TableOfContents />
{/if}

And my TableOfContents.svelte component does this:

<Toc breakpoint={767}>
    <strong class="title" slot="title">Table of Contents</strong>
    <ListIcon slot="open-toc-icon" />
</Toc>

You can find the source code to reproduce it on my repo (made sure to use the toc branch), and there's also a live preview of that branch

To reproduce it:

  • open the Zelda post (the first one). It will load the TOC correctly (it should!)
  • scroll down the page and click on the "Conditional Hover Styles" post. It will also load the TOC, but, for that post, showToc is false. Note that, when the variable is printed, it still says true, which means nothing inside that #if block was updated.
    • I thought it was a Svelte issue at first, but if you remove the use of the TOC component, the variable updates correctly.
    • refreshing the page makes TOC go away and loads everything correctly
  • if you are in a post with TOC enabled and try going to another page (like home or Blog), navigation breaks as well

In that specific example, there were console errors related to view transitions, but I've confirmed these are not related to the issue, they're actually caused by it.

I appreciate any help in figuring this out, and let me know if there's anything I can try on my end, or logs to obtain!

[Question] Split into sections

Hi @janosh,

This is not about bugs or issues, but the discussions tab is not active in this repo.

Am I thinking if this will have any sense to add to svelte-toc or if not if you mind helping me do something like that with the current implementation?

What I need:

I need to wrap headers and their contents into HTML tags (preferably of the choice).

So if I have content like this:

<h1>title</h1>
<p>some text in paragraph</p>
<img />
<p>next paragraph</p>
<p>and one more paragraph</p>
<h2>title</h2>
<p>paragraph in subtitle>
<h3>3rd title</h3>
<p>dfdfd</p>

I would need to be wrapped like this:

<tag id='title'>
<h1>title</h1>
<p>some text in paragraph</p>
<img />
<p>next paragraph</p>
<p>and one more paragraph</p>
<tag id='title2>
<h2>title2</h2>
<p>paragraph in subtitle>
</tag>
</tag>
<tag id='last-title'>
<h1>last title</h1>
<p>some paragraph content</p>
</tag>

as that HTML tag of choice
Wrapping each header and its own child.

The biggest problem here is to detect 'child' of the header because, from a technical point of view, this is not the child but unrelated content.
Probably logic will need to be something like this:

  • find all headers
  • wrap all headers with a starting HTML <tag>
  • before starting a new tag check if is not already open, and if is - put </tag> before
  • still have no idea how find out how to close the last section

How do I customize the font-size of each item of the ToC?

I just can't find anything related to font-size on the doc. This is my current codes:

<script>
	import Toc from 'svelte-toc';
	import ListBullets from '~icons/ph/list-bullets';
</script>

<Toc
	breakpoint="992"
	flashClickedHeadingsFor="0"
	--toc-font-size="var(--font-size-small)"
	--toc-width="240px"
	--toc-padding="var(--space-m)"
	--toc-li-border-radius="0"
	--toc-li-hover-bg="transparent"
	--toc-li-hover-color="var(--primary-500)"
	--toc-li-padding="var(--space-2xs) 0"
	--toc-active-bg="transparent"
	--toc-active-color="var(--primary-500)"
	--toc-desktop-bg="var(--black-400)"
	--toc-desktop-sticky-top="var(--scroll-padding)"
	--toc-mobile-bottom="100px"
	--toc-mobile-btn-border-radius="100%"
	--toc-mobile-bg="var(--black-400)"
	--toc-mobile-btn-bg="var(--primary-500)"
	--toc-mobile-btn-padding="var(-space-m)">
	<span class="toc-title mid-text" slot="title">
		<ListBullets color="var(--text-color)" width="24" height="24" />
		Contents</span>

	<span slot="open-toc-icon">
		<ListBullets color="var(--black-500)" width="24" height="24" />
	</span>
</Toc>

<style>
	.toc-title {
		display: flex;
		align-items: center;
		gap: var(--space-xs);
		font-family: 'Fancy';
	}
</style>

Component insists on starting at full height above the text

Thank you for this great tool and plugin!
I've played around with it quite a long time as I am trying to use it for an interactive version of my bachelor thesis ToC.

I have a small issue that I haven't been able to fix in the past few hours and would love your input.
When I enter the component like so:

<Toc
  desktop = {true},
  headingSelector = {":is(h1, h2):not(.toc-exclude)"}
  --toc-desktop-max-width = "300px";
  />

It first starts by using up its full height above the actual content.

wnzXSlr

This is actually also the case for the example code provided:

<Toc
  --toc-desktop-aside-margin="10em 0 0 0"
  --toc-desktop-sticky-top="3em"
  --toc-desktop-width="15em"
/>

Though I am guessing I am too newbie to get it right.

I can make it work by setting it in an absolute positioned div, but then it becomes unsticky.
Any advice on how to correctly do this would be greatly appreciated, thank you so much either way for this component!

Quick questions

Is it possible to:

  • Ye Old Pagination preferably with sort-able header column
  • "Expand" a row upon click any row
  • Nest a table "component" within an "expanded" row
  • Specific row styling upon predicate (on data load, since I'm pre-processing my data)
  • Override all possible styles

Component persisting on page change when not required

Thank you for a great plugin!
I have tried implementing it on my website, but there seems to be a weird issue. When I switch from a page that needs the ToC to a one that doesn't, there is a brief moment where a Table of Contents for the latter page is loaded before the component disappears. The lag is noticeable.

You can try it by going to this page and navigating to the homepage.

Recording:
ezgif com-gif-maker

I have included my component like this

Any thoughts on why this might be happening?

[Question]TypeScript support

Hi, does this library support TypeScript?

I am getting errors when I import this library in my TypeScript project.

Svelte-toc interferes with other anchor links in the document

Hi,
I think it's possible that svelte-toc interferes with other anchor links and smooth scrolling to them in the document.

I add it inside a <body class='flex main-bg'> like so:

<div class='w-50'>
    <div
  on:click="{() => showToc = !showToc}" 
  class='main-bg w-9 h-9 m-2 hover:cursor-pointer sticky top-0'>
      <svg fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
        <path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"></path>
      </svg>
  </div>
  {#if showToc}
  <Toc
    title = {"Table of Contents"},
    desktop = {true},
    headingSelector = {":is(h1, h2, h3):not(.toc-exclude)"}
    --toc-desktop-max-width = "20em"/>
    {/if}
</div>

The former is just an icon-burger button.

If I comment out the above the other anchor links work as expected (smooth scroll to them).
I am using Svelte and Tailwind.

For me this isn't such a big deal due to the nature of my anchor links (just references and I have them on hover anyway) but I thought you might want to be aware of it.

I can provide a link to the document to see it live if you like.

Cheers, and thanks again for this component, it made my project so much nicer.

Hide when intersecting with user-specified DOM nodes

Add a prop hideWhenIntersecting to allow passing in an array of HTML elements or a query selector whose matching DOM nodes cause sveltet-toc to be hidden temporarily for as long as there is non-zero intersection as the user scrolls passed them. Useful for things like full-width banners and images over which a heading list looks out of place.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.