vscode-elements / elements

Web component library for developing Visual Studio Code extensions
https://vscode-elements.github.io
MIT License
156 stars 27 forks source link

Adding Vue support #195

Open typed-sigterm opened 1 month ago

typed-sigterm commented 1 month ago

While the React integration is released, is there a plan to make a Vue wrapper? If so, would like to help:)

bendera commented 1 month ago

Hi,

Thank you for your offer!

Is a wrapper even necessary for Vue? In theory, Vue supports web components very well. (Source: https://custom-elements-everywhere.com) But I don't know that's the case in practice. What would be nice to test is whether two-way binding works. I read somewhere the v-model only works with native form inputs. In UI5 Web Components they add "type" attribute to components: https://sap.github.io/ui5-webcomponents/docs/frameworks/Vue/ It seems a bit hacky for me, but it's ok. Shoelace has its own type definition: https://shoelace.style/frameworks/vue#types and a custom directive: https://github.com/shoelace-style/vue-sl-model

An easy to use solution would be great. Or an example project. But I think porting the wrapper library as-is is unnecessary.

neko-para commented 1 month ago

I've tried for some, but I just didn't manage to perfectly forward vue slots into web component named slots (e.g. into collapsible's actions) 🤔

bendera commented 1 month ago

I've tried for some, but I just didn't manage to perfectly forward vue slots into web component named slots (e.g. into collapsible's actions) 🤔

Could you provide a reproducible example?

neko-para commented 1 month ago

I've tried for some, but I just didn't manage to perfectly forward vue slots into web component named slots (e.g. into collapsible's actions) 🤔

Could you provide a reproducible example?

You may check this question. https://stackoverflow.com/questions/75300558/how-to-delegate-content-from-vue-slots-to-web-components-slots

In short, I have to either spread name attribute outside, or use a div to wrap the slot (which breaks the element structure)

neko-para commented 1 month ago

I believe this should be a bug of vue, maybe🤔 I've raised a discussion. Hope a workaround exists.

bendera commented 1 month ago

Sidebar component definiton:

<script setup lang="ts">
defineProps<{ title: string; }>()
</script>

<template>
  <div class="sidebar">
    <h2>{{ title }}</h2>
    <vscode-collapsible title="Sidebar Collapsible">
      <slot name="content"></slot>
    </vscode-collapsible>
  </div>
</template>

In the consumer component:

<Sidebar title="Sidebar Title">
    <template #content>
      <vscode-badge slot="actions">99</vscode-badge>
      <p>FFFUUU</p>
    </template>
  </Sidebar>

Is this a solution to the case you are struggling with?

neko-para commented 1 month ago

Yes


@bendera Sorry, I've missed your idea. What you've provided only fowards the default slots, which do work for now. What I'm struggling is to forward into named slots, like the actions slot.

neko-para commented 1 month ago

I've managed to achieve it via jsx.

export function VCollapsible(
    props: {
        description?: string
        open?: boolean
        title?: string
    },
    context: SetupContext<{
        'update:open': [boolean]
    }>
) {
    const defaultSlot = context.slots.default?.() ?? []
    const actionsSlot = (context.slots.actions?.() ?? []).map(vnode => {
        return cloneVNode(vnode, {
            slot: 'actions',
        })
    })

    return (
        <vscode-collapsible
            description={props.description}
            open={props.open}
            title={props.title}
            onVscCollapsibleToggle={(e: VscCollapsibleToggleEvent) => {
                context.emit('update:open', e.detail.open)
            }}
        >
            {[...defaultSlot, ...actionsSlot]}
        </vscode-collapsible>
    )
}

With the help of cloneVNode, I can add the extra slot prop.

hifron commented 2 days ago

https://kermanx.github.io/reactive-vscode/