fable-compiler / Fable.Lit

Write Fable Elmish apps with Lit
https://fable.io/Fable.Lit/
MIT License
91 stars 13 forks source link

How to import FluentUI web components #30

Closed JordanMarr closed 2 years ago

JordanMarr commented 2 years ago

Greetings!

I'm trying out Fable.Lit and trying to import and register the FluentUI web components, but I'm not sure how to do it.

I tried JsInterop.importAll "@fluentui/web-components", but according to the install guide it looks like I need to call:

import { allComponents, provideFluentDesignSystem } from '@fluentui/web-components';
provideFluentDesignSystem().register(allComponents);

So I guess I need to create some minimal custom bindings to accomplish this?

AngelMunoz commented 2 years ago

Yes, the second part, fluentui/fast-design components have additional setups in javascript (like the one you found in the docs)

because the way they open their design system to be customizable

I'll try to get you a sample

JordanMarr commented 2 years ago

Yesss! I was hoping you would intercept my distress call! 😄

AngelMunoz commented 2 years ago
let allComponents: obj = importMember "@fluentui/web-components"
let provideFluentDesignSystem: unit -> obj = importMember "@fluentui/web-components"

provideFluentDesignSystem()?register(allComponents)

Slightly hacky but it works of course you can choose do all of that on the JS side (because there's a bunch of JS to configure properly fluent components) or in the fable side with bindings as you go image

Sample here https://github.com/AngelMunoz/FluentSample

For node based projects (vite/webpack) you of course need to install the dependency but the code should be the same on the JS/F# side

JordanMarr commented 2 years ago

Awesome! Thanks!

JordanMarr commented 2 years ago

One other question (not specific to Lit but to FluentUI): I noticed that none of the FluentUI web component controls have any events in the docs. Take the fluent-number-field for example: it has a value property, but no onchange that I can see.

Searching through the repo, I can't find any custom events.

Am I missing some integral concept about how to work with web components?

EDIT: I found @click event purely by luck! So I guess it's just a lack of documentation on the FluentUI side. The web component port must be newer than I realized!

Also found this issue from 5 days ago: SpinButton: add example for input onChange/onBlur behavior

AngelMunoz commented 2 years ago

That goes a small rabbit hole, all of the fluent-ui elements are composed from fast-element which defines $emit(... options ...) https://github.com/microsoft/fast/blob/master/packages/web-components/fast-element/src/components/fast-element.ts#L26-L30

So ideally if you want to know more about fluent-ui elements you can always fall back to the FAST design counterpart https://www.fast.design/docs/category/components and https://github.com/microsoft/fast/tree/master/packages/web-components/fast-foundation/src where most of the components are defined (and likely where you can find the correct events/properties)

examples

AngelMunoz commented 2 years ago

I would also add that fast/fluent elements tend to be as close as possible to their native counterparts so most of the time you'll find that most of the controls that can emit events will try to emit the change event so it's a fair assumption you can try to do <fluent-element @change={handler}></fluent-element>, more advanced controls may emit others like input in the case of the number-field

JordanMarr commented 2 years ago

Nice sleuthing! Sure enough, it works:

let count, setCount  = Hook.useState 50
<div>{count}</div>
<fluent-number-field
    @change={fun _ -> printfn "changed"}
    value={count}
    step={10}>
</fluent-number-field>
AngelMunoz commented 2 years ago

Let me know if you have other issues! I'll close this in the meantime but feel free to re-open if something else is missing