BpClickable is a renderless vue component for making a larger, parent element work as a link in places where it’s not semantic or appropriate to simply use an <a>
tag.
BpClickable exposes once method to its slot, click
, that should be called and passed both the click event as we ll as reference to the actual <a>
element. For example,
<bp-clickable v-slot="{ click }">
<div @click="click($event, $refs.link)">
<!-- ... -->
<a ref="link" href="...">...</a>
</div>
</bp-clickable>
<bp-clickable selector=".card__action">
<div class=" card -wide -clickable">
<div class="card__container">
<div class="card__background">
<picture class="">
<img src="data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="1920" width="1920"></svg>" alt="Placeholder Image" class="lazyload card__backgroundImg" data-srcset="https://placeimg.com/640/640 640w, https://placeimg.com/1000/1000 1024w" data-sizes="auto" />
</picture>
</div>
<h3 class="card__heading">One Great Heading</h3>
<p class="card__content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dignissimos et voluptatum aliquam neque beatae.
<a href="#nope">nope</a>
</p>
<div class="card__actions -attached">
<a href="#example" class="card__action button -primary">Learn More</a>
</div>
</div>
</div>
</bp-clickable>
<bp-clickable>
<div class=" card -wide -clickable">
<div class="card__container">
<div class="card__background">
<picture class="">
<img src="data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="1920" width="1920"></svg>" alt="Placeholder Image" class="lazyload card__backgroundImg" data-srcset="https://placeimg.com/640/640 640w, https://placeimg.com/1000/1000 1024w" data-sizes="auto" />
</picture>
</div>
<h3 class="card__heading">One Great Heading</h3>
<p class="card__content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dignissimos et voluptatum aliquam neque beatae.
<a href="#nope2">nope</a>
</p>
<div class="card__actions -attached">
<a data-clickable href="#example2" class="card__action button -primary">Learn More</a>
</div>
</div>
</div>
</bp-clickable>
/**
* BpClickable is a functional component for making the clickable target for a
* link or button tied to more elements.
*/
const BpClickable = function (props, { slots }) {
const click = () => querySelector(props.selector)?.click()
const vnodes = slots.default({ click })
const querySelector = selector => {
for (const vnode of vnodes) {
const el = vnode.el?.querySelector?.(selector)
if (el) {
return el
}
}
}
vnodes.forEach(vnode => {
vnode.props.onClick = click
})
return vnodes
}
BpClickable.props = {
selector: {
type: String,
default: () => '[data-clickable]',
},
}
export default BpClickable