#Re-usable Astro components with <script> tags

15 messages · Page 1 of 1 (latest)

lapis siren
#

Hey, I'm wondering, is there any way to deterministically pass selectors/ids for a script tag to locate?

Consider this basic component, that needs to access a specific element for animation.

---
export interface Props {
  x: number
}
const { x } = Astro.props
---

<div id="slide" data-x={x}>
  <slot />
</div>

<script>
  import { animate } from 'motion'
  const el = document.getElemetById('slide')
 animate(el!, { x: +el!.dataset.x })
</script>

This works very well for a single component i.e.

---
import Slide from '@/components/Slide.astro'
---
<!-- ✅ works fine -->
<Slide x={100}>
 <p>weee i slide right</p>
</Slide>

However, as soon as I try to have the component be re-usable, I run into an issue (logically) of not having unique element ids. That's the easy part of the fix, could either explicitly pass it as a prop, or (even better, especially for the lazy) I just added uuuid.v4 to generate a unique id for the component, i.e.

id=`slide-${uuid.v4()}`

However I can't think of a way of reliably accessing the id in the script tag for the selector.

I know astro exposes the define:vars front-matter passing, but that's obviously not ideal, since it enforces the is:inline directive and breaks module imports.


I'm sure with this seemingly being a fairly common pattern, someone had to run into a similar issue. Is there really no better way of doing this in astro/vanilla js (ts) with a deterministic selector, rather than having to defer everything to a client hydration library like react or solid?

Thanks in advance 🙏

viral helm
#

define:args is the proposed replacement for define:vars which would allow using typescript and npm packages

#

it would help if you could leave a reaction, or thoughts about the api

#

as for now, you could use the astro-scope package to get an id unique to each file

#

it would be the same for both the frontmatter and a script tag, but different between two astro files

#

you could then use it as a class

lapis siren
#

Will definitely have a read through the RFC

#

As for the astro-scope, could you just confirm if I'm looking at the correct one? Googling yields nothing of value, neither did bundlephobia/npmcompare.

Closest I could find is the direct name in the npm registry, https://www.npmjs.com/package/astro-scope just not sure if I'm looking at the right thing

viral helm
#

yes, that's the one!

#

its not a commonly-encountered problem but i made it because i had a few requests

lapis siren
#

Yeah I presume majority of users just defer to an island with a script, normally I would too, but trying to create a landing page for my portfolio and want the results to be as fast as possible for the FCP & LCP, although we honestly are talking unnoticable miliseconds if I were to use something like solid with the motion adapter, though just felt like doing it natively in astro since it's a hobby project anyways and I wanted to have some fun and tinker

#

Still, I think the define:args would be very powerful addition to the future, as it's probably the biggest missing link for writing pure astro components

viral helm
#

youre exactly right, its possible to pass props to a component's client-side code but not to a client-side script