mefechoel / svelte-navigator

Simple, accessible routing for Svelte
Other
504 stars 39 forks source link

Can't stylize Link component #21

Closed marroquinsamy closed 3 years ago

marroquinsamy commented 3 years ago

Hi. I'm using Svelte with Typescript. I'm using the Link component to navigate through my SPA.

I'm trying to write a class attribute to the Link component to stylize it but Typescript says it can't be. Does exist any solution for it? I've read the whole documentation but I didn't found anything. Thank you for your time.

Samuel,

mefechoel commented 3 years ago

Hey Samuel, That's definitely a bug. Theoretically you can pass any props you can pass to an <a> to a <Link> as well. I'll need to figure out if the declaration for <a> cam be reused somehow. Otherwise I'll make sure to add at least the class prop. In the meantime something like <Link {...({ class: 'my-class' } as any)} /> should do the trick, although thats super ugly :'D

mefechoel commented 3 years ago

This is fixed in 3.1.4. The types for the <a> tag are taken from the svelte2tsx package, that the svelte language server uses.

marroquinsamy commented 3 years ago

Thank you, really thank you. Happy coding! :D

marroquinsamy commented 3 years ago

Hi again 😅. Now I'm able to write a class attribute on the Link component. However, I have a problem with the style tag. It doesn't recognize that class and its selector appears as 'unused'. Do you believe it is another bug or I have a bad configuration? Screenshot from 2020-12-07 10-52-07

mefechoel commented 3 years ago

Unfortunately this is a svelte thing... Since a component could theoretically have class prop, that does not have anything to do with a css class, svelte does not treat it as such. The style scoping only works with html elements in svelte. I'd prefer it the way vue does it and just treat all class props as css classnames, but I do understand the design decision of giving the users full control over their component's props.

To work around this, you can either rely on the css scope of an outer component and then use a global selector like so:

<style>
  .my-wrapper :global(.my-class) {
    /* ... */
  }
</style>

<div class="my-wrapper">
  <Link to="my-route" class="my-class" />
</div>

Or you can use the link action:

<script>
  import { link } from "svelte-navigator";
</script>

<style>
  .my-class {
    /* ... */
  }
</style>

<a href="/my-route" class="my-class" use:link />

Using link has a couple of drawbacks though. It does not resolve relative links, like <Link> does and the href is not dynamic, so you cannot change it. Therefore <Link> is the better choice in most cases.

I'm working on another api to try to marry the two approaches, so stay tuned for v4 ;)

mefechoel commented 3 years ago

Looking at your code snippet another option would be to add the class to the inner span inside the Link. Might not be too practical though...

marroquinsamy commented 3 years ago

Thank you very much. I didn't know this. Now I'm using the .my-wrapper :global(.my-class) to give it styles. I appreciate so much your work and your time. Waiting too much for the v4 :) Happy day!