Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions rfcs/0005-fabric-elements-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# RFC: Fabric Elements API

## Background

When building our Web Component library (Fabric Elements) it's good to think of the overall picture of how the API should be structured.
With the right conventions, it would be easier to maintain consistency when adding new components, which should result in the library being easy to work with for both authors and users.

This RFC attempts to start a discussion on how to structure the Fabric Elements API in a way that aims to minimise confusion and complexity of various components.

## Concepts/Principles to discuss

### Customization of components

To what degree should web components be customized with respective attributes if they return just one main HTML element,
e.g. when `<f-textarea>` returns `<textarea>`, `<f-button>` returns `<button>` or `<f-textfield>` returns `<input>`?
Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit on the side of your question, but I wonder if there's a minimal requirement for components we implement in Fabric. If a f-button web component only wraps a button element with a class attribute, does it add enough value to justify the added complexity?

The DOM is already capable of rendering <button class="button button--primary">, if that is all <f-button type="primary"> would do. Adding a layer of JS around this will complicate SSR or force client-side rendering for behaviour that already exist.

Many web components will probably implements some extra behaviour, like form validation for input fields, and custom styling for checkboxes. And I clearly see the usefulness of having web components for that.

I'm sorry if this is off topic, but I would like to hear your thoughts on this. My main concern is that we use web components (and components in general) where it makes sense to encapsulate specific behaviour, and I believe there is a lower and upper bounds on the complexity it makes sense to implement with web components.

WDYT?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Should we bind all possible attributes to respective WC properties in case the user wants to change these?
If we render multiple components on a page, each binding all possible attributes + being placed within shadow DOM,
would that affect page performance much?

### Naming of component attributes

In most web component libraries the component attributes are called the same as native element attributes, e.g. `disabled`, `target`, `aria-label`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my limited experience with web components, I can only say that it looks like WC libs try to be as transparent as possible, mimicing the behaviour and attributes of native HTML elements. That could also be a good strategy for components in other frameworks, to expose eg. an onChange prop in a Combobox component where an change event would be expected in a conceptually related select element.

Given Fabric Elements can contain both small and complex web components, what would be a good naming convention for the attributes?
Should we avoid native element attribute names like `href`, `target`, `value` in the API in case there were components with multiple elements to assign those attributes to?
Would it make sense to rename attributes even though they are clearly associated with the returned element,
like `<f-button focused>` instead of `<f-button autofocus>` or `<f-textfield input-type="number">` instead of `<f-textfield type="number">`

### One component, one responsibility

Let's take `Button` as an example. In some libraries ([Material components web](https://github.com/material-components/material-web), [Shoelace WC library](https://shoelace.style/), [Ionic](https://ionicframework.com/docs/api/button)) a `Button` component can return either a `button` element, or an `anchor`.
This however requires the component to handle attributes related to both elements.
In addition, the `button` element is a form-associated element while the `a` element is not, so we'd need to figure out how to only form-associate the button.

With that in mind, maybe it would make sense to have a separate `Link/Anchor` component that can have the same design variants as `Button` and that handles attributes related to anchors (ref. [Vaadin WC library](https://vaadin.com/docs/latest/components/button/#related-components), [Microsoft's Fast WC library](https://github.com/microsoft/fast/tree/master/packages/web-components/fast-foundation))?


## Sources
* [Microsoft's Fast WC library](https://github.com/microsoft/fast/tree/master/packages/web-components/fast-foundation)
* [Shoelace WC library](https://shoelace.style/)
* [Material components web](https://github.com/material-components/material-web)
* [Ionic WC library](https://ionicframework.com/docs/api/button)
* [Vaadin WC library](https://vaadin.com/docs/latest/components/button/#related-components)
* [Best practices to build web components by Carlos Muñoz](https://medium.com/ing-blog/best-practices-to-build-web-components-6d517923fba4)