solidjs / solid-docs

SolidJS Docs.
https://docs.solidjs.com/
217 stars 247 forks source link

[Request]: Add Web Components Typing to the TypeScript guide #823

Open ryansolid opened 2 months ago

ryansolid commented 2 months ago

What is this request related to?

Request

📋 Suggested

https://docs.solidjs.com/configuration/typescript#typescript

📋 General description or bullet points

It's come to my attention that we don't talk about how to use webcomponents in the new docs anywhere. There was an old discussion here: https://github.com/solidjs/solid/issues/616 that sheds some light but the answer is little bit lost.

It doesn't necessarily need to go in the TS section but it does feel like it makes sense because it uses similar overrides to custom events, props etc..

🖥️ Reproduction of code samples in StackBlitz

No response

trusktr commented 2 weeks ago

Here's what I do for Lume elements for example:

https://github.com/lume/lume/blob/b5242eb39d1f3613c1071f6db40d954ca559faf6/src/lights/PointLight.ts#L163-L175

declare module 'solid-js' {
    namespace JSX {
        interface IntrinsicElements {
            'lume-point-light': ElementAttributes<PointLight, PointLightAttributes>
        }
    }
}

declare global {
    interface HTMLElementTagNameMap {
        'lume-point-light': PointLight
    }
}

That declare module 'solid-js' {...} adds the element type only for Solid JSX. As these elements are written with Solid, I chose for them to have out-of-the-box JSX types for Solid.

If you want to also support other frameworks like React, Preact, Vue, Svelte, etc (they all use JSX type defs) then you can make separate files for each framework (because they may have different JSX type layouts) that someone can import to gain the types. For example here's the React JSX definition for that same lume-point-light element, which someone can import in a React app to gain those types in their React JSX templates:

https://github.com/lume/lume/blob/b5242eb39d1f3613c1071f6db40d954ca559faf6/src/lights/PointLight.react-jsx.d.ts

import type {ReactElementAttributes} from '@lume/element/src/react'

// React users can import this to have appropriate types for the element in their JSX markup.
declare global {
    namespace JSX {
        interface IntrinsicElements {
            'lume-point-light': ReactElementAttributes<PointLight, PointLightAttributes>
        }
    }
}

ElementAttributes and ReactElementAttributes are helpers for my way of defining elements with @lume/element, but the gist is that they pluck properties off of the element class type for use in JSX (for example, you don't want everything including for example addEventListener or appendChild to appear as a prop in your JSX template. So I create a list of which props to pluck, f.e.:

export type PointLightAttributes = LightWithShadowAttributes | 'distance' | 'decay'

where LightWithShadowAttributes is the list of properties inherited from the base class.

atilafassina commented 2 days ago

Hey, folks. I have been talking on the side with @DBozhinovski about him helping us getting these docs across the finish line. He works at SuperToken and they also use SolidElement. So, between @trusktr , @titoBouzout , and @DBozhinovski I feel we have enough usage and experience to write an abstract guide for the docs and put the everything in the right place.

Right out of the bat, I feel WebComponents shouldn't live within a TypeScript section. For 2 reasons:

  1. It's way more than just TypeScript usage.
  2. We have support for multilingual code snippets, so we can cater for both JS and TS when things get trickier. Then, of course, we can add some TS specifics and quirks if needed - like the env.d.ts changes mentioned above.

So, my initial hunch (and it really is a hunch, I haven't worked seriously with WebComponents in a long time), the bulk of the guide should fit in Solid's core, at the Learn section and either in "Advanced Concepts", "Guides", and/or "Configuration". Do y'all have thoughts?


All that mentioned above considered, @DBozhinovski has volunteered (or maybe I pushed him, not sure) to write the first PR for it.

DBozhinovski commented 2 days ago

:wave: Hey all!

Happy to pitch in :)

My 2c, and something I've discussed with @atilafassina already - when we discuss "web components", we are fundamentally discussing two different things - authoring them (as most modern UI libs/frameworks are already capable of doing, Solid included via SolidElement) and using third-party web components inside a UI lib/framework.

In the case of Solid, from my experience so far, the latter mostly comes down to:

  1. Import some web component/web component lib
  2. Hope it ships types you can use (usually not the case)
  3. Negotiate with .d.ts files until TS stops complaining about not knowing anything about a given element.

We could possibly improve this by providing some examples of how to use web components inside Solid (popular libs with types, without types etc.)

The former (authoring web components via Solid Element), could use some docs and guides IMO. The README in the solid-element repo does a good job of getting you started, but it can be improved. For more advanced stuff, I had to do a bit of digging and experimentation on my own - which I don't mind doing, but documenting that in some way would surely be helpful.

Plus, making it more public that Solid can be used to author web components is kind of a big deal, given their rise in popularity.


I promise I volunteered :wink: