Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: Support for Fluent UI contrib packages #27480

Open
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

ling1726
Copy link
Member

@ling1726 ling1726 commented Apr 6, 2023

This RFC lays out the architectural requirements that will need to be finalized to be able to support non-core components in the Fluent UI umbrella. Once enough feedback has been collected the RFC will be updated to include the final decision

PREVIEW

This RFC lays out the architectural requirements that will need to be
finalized to be able to support non-core components in the Fluent UI
umbrella. Once enough feedback has been collected the RFC will be
updated to include the final decision
@github-actions github-actions bot added this to the April Project Cycle Q2 2023 milestone Apr 6, 2023
@github-actions github-actions bot added the Type: RFC Request for Feedback label Apr 6, 2023
@fabricteam
Copy link
Collaborator

fabricteam commented Apr 6, 2023

📊 Bundle size report

🤖 This report was generated against f0b05741d812ad90c52754b0b4035d5554cf2aa0

@size-auditor
Copy link

size-auditor bot commented Apr 6, 2023

Asset size changes

Size Auditor did not detect a change in bundle size for any component!

Baseline commit: f0b05741d812ad90c52754b0b4035d5554cf2aa0 (build)

@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 6, 2023

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 3280c49:

Sandbox Source
@fluentui/react 8 starter Configuration
@fluentui/react-components 9 starter Configuration

- 👎 Manage the infra for another domain and publish
- 👎 Needs work to support independently versioned packages

### Parnter ownership and collaboration
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
### Parnter ownership and collaboration
### Partner ownership and collaboration

@layershifter layershifter marked this pull request as ready for review April 12, 2023 09:02
@layershifter layershifter requested a review from a team as a code owner April 12, 2023 09:02
@mltejera
Copy link
Contributor

This is great Ling! My two cents - coming from 4+ years of working on a fluent extension library. We know most consumers of fluent consume it through an extension library, so better supporting that story is a win for everyone.

I think there are a lot of benefits to having the extension component packages living in the same repo. I see a bunch of benefits:

  • Better visibility for everyone - easier to see/discover existing components
  • Easier for core team members to help shepherd the extension components
  • Makes it easier for contributors to learn from core fluent folks. Being in the same repo reduces friction and makes searching easier.
  • Common tooling and release cadence.

As far as breaking changes go, I do think these extension components have a tendency to break more often (for good reason) so we should plan for that. What worked well for us in admin-controls:

  • Component packages were NOT re-exported through a central package. This isolated breaking changes to a single or few packages.
  • Every package took a breaking change when we upgraded fluent. This was always done carefully, conscientiously and rarely.
  • If a breaking change was drastic enough (re-writing a whole component) - we just spun up a separate sibling package, and called it fluentui/fancy-component-v3.

Something we'll want to weigh the pros and cons for on a monorepo approach is the cost of breaking changes in core fluent. I think the core team will have to assume responsibility for upgrading all the extension packages when we decide to break. This is good in that all those extensions will stay current, and it forces us to empathize with consumers when we're making breaking changes. Bad in that we'll hesitate more when making breaking changes that we probably should. Incentivizes us to shepherd best practices in contributions.

One issue we'd run into was ownership. An enthusiastic engineer might spend 2-3 months contributing a component from their app, and then (due to circumstances outside their control) not be able to support it going forward. Core team members would then have to assume responsibility for a component that was architected inconsistently with the rest of the library. Handling that learning curve is hard and requires a LOT of training and documentation on our part. Most of out contributors were surprised and frustrated by how much time it took compared to when they wrote it in their product. I don't really have a great solution for this yet. Really really strong conformance tests?

The other untapped potential we have is theme tooling, creation and hosting. Admin-controls ended up being sought after for teams to go create their fluent themes because we'd optimized around that task. Many of those consumers/contributors weren't even using admin-controls. Most only needed slight tweaks to an existing theme. The result was a library of themes that many teams benefitted from.

I also think we need to consider cleaning up the fluent repo to make this successful. It has grown a TON over the years and I'm not sure all the packages are relevant to it's core mission. Having both v8 and v9 in the same branch confuses searching.

We create components that will not be shipped as a part of our 'core' components under the `@fluentui/react-components`
library but other packages. We will have to finalize the following requirements:

- Should non-core components be able to deviate from V9 core concepts?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think yes. they will be owned by other teams, we should give them trust to make the right decisions. they might need to opt out of compliance checks.

Copy link
Member

@micahgodbolt micahgodbolt Apr 24, 2023

Choose a reason for hiding this comment

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

define 'deviate'...are we talking about slots, or file structure, or styling or what.

I think there is a good question here as to 'how much can a component deviate from the v9 concepts while still being at all related to v9'

If I write a quick (props)=> <div>{props.children}</div>

is this a fluent ui component as long as it matches a design somewhere in a figma?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't think we should try to be too restrictive here for non-core components. For non-core, I'd even propose that no one needs our permission to call something part of the Fluent ecosystem.

I do think, however, there are some guidelines.

  • It should follow the Fluent design guidelines
  • It should depend on the Fluent/v9 core SDK, which means respecting design tokens
  • It should not re-invent existing primitives, but it may not depend on any primitives

library but other packages. We will have to finalize the following requirements:

- Should non-core components be able to deviate from V9 core concepts?
- Should non-core components have a faster breaking change cadence?
Copy link
Contributor

Choose a reason for hiding this comment

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

I think yes, they should be versioned independently. They should have a peer dependency on core components.

Copy link
Member

Choose a reason for hiding this comment

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

in Fluent AI (copilot) we are building sub 1.0 controls, so we can break going from 0.2.0 to 0.3.0

I think there is still value in moving towards a stable release and using semver properly, but I could see some extended control sitting at 0.215.1 for a while

Copy link
Contributor

Choose a reason for hiding this comment

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

If scenario where fluent extension adhere to fluent core standards, based on recent discussions there should be no breaking changes ( breaking changes may/will happen after particular major bumps - removal of APIs etc ).

We already started go 1.0 route within core so that should probably be followed. Ideally this will also drive us to establish fluent core which will be used within react-components suite and extensions.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Our breaking change policy for core/v9 is highly restrictive, for the reason that primitives that everyone builds on and builds shared experience based on needs to be highly stable. I would not expect any other teams to follow it, and if we don't need to follow it for higher-level experiences we should not restrict ourselves to it (but also remember that it's very important for primitives, or components that other teams build on heavily).

I think the leaf nodes, and non-core components could, and honestly should, have breaking changes more often. They should, of course, follow semver. And whether it's 0.x.y or x.y.z versioning they should follow semver and rev appropriate when they have breaking changes.

- Should non-core components live in a separate repo?
- Should non-core components still be under the `@fluentui` scope?
- How should users consume non-core packages?
- How should non-core components be documented?
Copy link
Contributor

Choose a reason for hiding this comment

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

preferably in storybook, which can be federated with core storybook.

Copy link
Contributor

Choose a reason for hiding this comment

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

storybook is not the best public documentation kinda of thing. might be good opportunity to explore something more robust and nicely polished like docusaurus/astro - also I assume those extensions should be part of official Fluent docsite we are building right (having storybook is a serious performance pain )?

Copy link
Member

Choose a reason for hiding this comment

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

I would +1 not using storybook for public documentation if there is scope - it was built as a playground experience and has been co-opted into docsites. We have been using it for acs ui library and it got us of the ground fast, but we've found it limiting, clunky and hacky to get it to a good state.

That said, whatever Fluent sticks with should be what is available in the infrastructure package by default for others. So to me this is tangential to this RFC and a question on if Fluent are sticking with Storybook in the long term.

@khmakoto
Copy link
Member

Thanks for writing this up, this is an increasingly important thing to consider as v9 is adopted more broadly. Below are my thoughts and preferences for each section outlined in the RFC:

  1. Deviating from v9 core concepts: I like @micahgodbolt's idea that any deviation should be an "earned difference". Taking this approach allows us to maintain a level of quality in the code while also helping us realize where our approach is falling short for partners and if it is something we can improve on the core library or something where what we want and what they want is just not compatible.
  2. Breaking change cadence: I think I'm on the camp of "different than core components". Notice how I purposefully abstained from using the word "faster" here. My main reason for being behind this approach is that things might want to iterate quickly at the beginning and break a lot, not being tied to the core cadence. Another reason is that some non-core library might not be invested in anymore after a certain point, at which time we might want to not keep releasing it everything we have a breaking change release in the core library.
  3. Choosing a repo for: I don't have any preferences here, I leave this decision completely up to the people managing our CI and build systems.
  4. Package scope: I like the idea of putting all non-core packages under something like @fluentui/contrib/*. That way, we indicate that they are still part of the Fluent UI family, but we make a clear distinction against our core packages.
  5. How users should consume components: This is another one where I don't have a strong preference. Although I do have a question, is there a possibility of multiple non-core suite packages existing (grouping different sets of non-core components).
  6. How to depend on core components: I think the more vetted and less con-prone solution is having non-core packages depend on the suite package as a core dependency.
  7. Documentation: Again, I don't have a strong preference here and would prefer to leave the decision to people working on our CI and build systems. Furthermore, our decision on this might be partially informed by our decision of in which repo to host these components.
  8. Partner ownership and collaboration: One more in which I don't have a strong preference over just preferring GitHub's UI than ADO's 😄.

library but other packages. We will have to finalize the following requirements:

- Should non-core components be able to deviate from V9 core concepts?
- Should non-core components have a faster breaking change cadence?
Copy link
Contributor

Choose a reason for hiding this comment

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

If scenario where fluent extension adhere to fluent core standards, based on recent discussions there should be no breaking changes ( breaking changes may/will happen after particular major bumps - removal of APIs etc ).

We already started go 1.0 route within core so that should probably be followed. Ideally this will also drive us to establish fluent core which will be used within react-components suite and extensions.


- Should non-core components be able to deviate from V9 core concepts?
- Should non-core components have a faster breaking change cadence?
- Should non-core components live in a separate repo?
Copy link
Contributor

Choose a reason for hiding this comment

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

no silver bullet here, it depends :)

- Should non-core components live in a separate repo?
- Should non-core components still be under the `@fluentui` scope?
- How should users consume non-core packages?
- How should non-core components be documented?
Copy link
Contributor

Choose a reason for hiding this comment

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

storybook is not the best public documentation kinda of thing. might be good opportunity to explore something more robust and nicely polished like docusaurus/astro - also I assume those extensions should be part of official Fluent docsite we are building right (having storybook is a serious performance pain )?


#### @fluentui scope

Non-core packages would be published under the same `@fluentui/` NPM scope.
Copy link
Contributor

Choose a reason for hiding this comment

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

yes


#### New package scope

Creates a new package scope, `@fluentui-banana/` (name pending) for all components/packages that are non-core.
Copy link
Contributor

Choose a reason for hiding this comment

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

new scope might make sense only when its out of FUI domain - eg system that builds on core controlls but provides completely different UI


#### Current monorepo

Non-core packages should still live in the monorepo.
Copy link
Contributor

Choose a reason for hiding this comment

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

extensions that adhere to FUI family should live within one monorepo.

- 👎 Our partners might still want to customize to the max
- 👎 Approaches could be heavily biased on a subset of partners

### Breaking change cadence
Copy link
Contributor

Choose a reason for hiding this comment

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

  • breaking changes in none FUI family extensions can happen as their maintainer need
  • breaking changes in FUI family extensions if possible, should adopt patterns we "plan" to adopt within core -> major version bump is not really a breaking as we maintain old apis and remove those after particular major bumps or defined time period

@Hotell
Copy link
Contributor

Hotell commented Apr 26, 2023

Appreciate this great write-up @ling1726 @layershifter 🙌

Besides in code comments I'd like to add some things and share my POV on this topic.

Based on the convo and content of this RFC we should probably differentiate extensions into 2 categories:

  1. FUI family
  2. non FUI family

to elaborate on this

FUI family extension

  • they live in fluent (mono)repo/s
  • they are published under the same scope as core, differentiated via prefix @fluentui/x-chat etc
  • they adhere strictly to all v9 standards
  • they follow strictly FLUENT design language

non FUI family extension

  • they live in separate repo
  • they are published under different scope. they dont even have to have fluentui as part of the scope
  • they adhere to standards set by their owner/maintainer
  • they should use tools and practices from fluent core monorepo to start with
  • they use v9 core SDK
  • they create breaking change as they need

@ling1726 ling1726 changed the title RFC: Support for components in the Fluent UI umbrella that are not core RFC: Support for Fluent UI contrib packages Apr 26, 2023
@miroslavstastny
Copy link
Member

@ling1726 owns this RFC on behalf of @microsoft/teams-prg

@behowell
Copy link
Contributor

@khmakoto owns this RFC on behalf of @microsoft/cxe-red

@chrisdholt
Copy link
Member

I think there is one higher level consideration that I'm curious about which I think may need resolution prior to landing the implementation details and considerations outlined in this PR.

One of the side-effects of opening up the Fluent repo to include contributions from Fluent partners is how the design and API considerations get resolved when there are either competing implementations or competing requirements. Something being under the Fluent UI umbrella implies that it is the "blessed" implementation. What is the working model for determining the "base" implementation of what ends up in the Fluent repository and the breadth of it's API? Consider a scenario where two teams have a similar Foo Component but their core requirements are different? Consider that Team A may not have bundle size considerations but Team B does. Team A would prefer to ensure all their scenarios can be met with this one component (as it does in their own repo) but Team B due to perf considerations wants a slimmer API? Team A wants pre-configured implementations for convenience but Team B has no use for any of those and instead needs a more compositional approach. Where do we bend or how do we resolve? Do we have multiple versions and if so how do we name given these are essentially the same?

The above is a quick example, but I think the larger question of how we determine what gets hoisted into the "blessed" implementation is key to this discussion and a resolution. For instance, if the goal isn't to have a single "blessed" implementation of Foo Component but to allow various teams to make their implementation more readily available to others and get close to the ecosystem, where the work is done and how things are broken up should reflect that. If the expectation is that there be a single instance of Foo Component, that should be reflected in where the contribution goes with a clear process and working model to ensure that it scales as broadly as possible to as many teams as possible.

If there's an answer to this already, I'd love to see it guide this discussion! I might have missed it, but it seems like some of the questions raised within this RFC could be more easily resolved with clarity around this.

@levithomason
Copy link
Member

levithomason commented Apr 26, 2023

Adding to @chrisdholt's comments, I also see this RFC will affect more than just v9's decisions. The answers to the RFC are at the heart of how Fluent UI thinks about components, determines component boundaries, and how we define of a "Fluent" component. This also touches the scaling strategy for including more products in publishing, maintaining, and discovering Fluent UI components across the company.

There are some historical decisions that have been made and are operating by assumption and default right now. We probably need to refresh and document those. I've listed some of them below. I plan to make a trip to Redmond soon so our US folks can collab in person. We can do some earlier US mornings to catch Prague evenings as well.

In no particular order, some important guiding statements for Fluent UI today (that we need to explain, document, and build from):

  1. Fluent UI does not plan to include partner code (Fluent UI "Conformant" components) in our repo
  2. Fluent UI plans to keep distribute Conformant component development around the company, keeping code/issues/PRs in the contributor's repo
  3. Fluent UI does plan to allow "Conformant" implementations to publish to an official Fluent package namespace
  4. Storybook composition will be used to surface, discover, and consume Conformant components around MS
  5. Design specs drive all official implementations. Engineering and product needs are funneled through this process before development begins. No code is shipped without going through this wholistic process. The process can/should be expanded as Fluent UI grows (overdue).
  6. Fluent UI has a component model that was designed over years to service the longevity and durability we need to support partners. Currently, Conformant reusable components would need to adhere to this model. There are other types of component cases, HVCs (high value components), that are very product specific and do not have the same reuse needs and therefore have more restrictive APIs and features. We have needs and proposals for other component models, but these are the main two models we need to support right now.

This is a short, top of mind, list of the direction we're currently pursuing. It is also not exhaustive. Apologies for not giving the context, constraints, and reasoning behind each but this comment would be pages long. That is what I propose we do when we get together to formulate a solution to this RFC. I'm also really looking forward to that.

@ling1726
Copy link
Member Author

@levithomason thanks for the feedback, looking forward to working to get more context around these decisions so we can come to a concrete working solution.

Fluent UI does not plan to include partner code (Fluent UI "Conformant" components) in our repo

Fluent UI does plan to allow "Conformant" implementations to publish to an official Fluent package namespace

These points are already encapsulated in one of the proposals of this RFC - create a separate repo for extension packages and publish them under a different scope. I've taken the approach to let us keep some kind of link to these 'conformant' extension packages. This will make sure that we are in a position to give guidance to partners who might not have the experience that this team has with creating reusable components and also formalizes a 'conformant' implementation for customers so that there is a boundary of trust there. I'd like to know your thoughts on that.

Fluent UI plans to keep distribute Conformant component development around the company, keeping code/issues/PRs in the contributor's repo

This seems to me like contributors should host their own code, but we own the distribution vector? This is not encapsulated by the RFC and I'd like to incorporate it once I know more about the context behind this. Looking forward to discuss further.

Storybook composition will be used to surface, discover, and consume Conformant components around MS

Yes storybook composition is also proposed in this RFC, however @Hotell has shown some reservations there.

Design specs drive all official implementations. Engineering and product needs are funneled through this process before development begins. No code is shipped without going through this wholistic process. The process can/should be expanded as Fluent UI grows (overdue).

Agreed, I'll incorporate this in to the RFC

Fluent UI has a component model that was designed over years to service the longevity and durability we need to support partners. Currently, Conformant reusable components would need to adhere to this model. There are other types of component cases, HVCs (high value components), that are very product specific and do not have the same reuse needs and therefore have more restrictive APIs and features. We have needs and proposals for other component models, but these are the main two models we need to support right now.

I've mentioned the need to deviate from core principals in this RFC. I'm not sure how we could go about formalizing other design models especially as requirements for 'conformant' implementations are expected to vary based on specific needs. Let's discuss this further

@ling1726
Copy link
Member Author

One of the side-effects of opening up the Fluent repo to include contributions from Fluent partners is how the design and API considerations get resolved when there are either competing implementations or competing requirements.

@chrisdholt That's a really good point. I've updated the RFC to add a clear position on this but here is the short version.

  1. Any UI control should be design driven so that there is a single design source of truth - this builds on @levithomason's points
  2. Competing technical implemetations are fine, they are also good since it allows faster iteration for customers and can foster innovation in component design
  3. Any attempts to converge should come from the owners of competing implementations. The Fluent UI team should be there to help guide those owners to converge implementations
  4. If we decide to elevate any package from an extension to core - the convergence of any competing implementations would be required.

I would like to keep the position that the core team should be a guiding influence, and not an extra requirement on these teams. However, it's perfectly reasonable to build on the work of others, so we should have an elevation process to the 'blessed' implemetation

WDYT?

- build
- type check
- linting
- unt tests
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
- unt tests
- unit tests

@levithomason
Copy link
Member

@ling1726 Thanks for the replies. We're in agreement. There is much to discuss in detail and document and we will do that, maybe next week. We'll set up some time with you and @Hotell.

I'd like to formalize something like 3 or 4 consumer groups (users + use cases) for Fluent UI. I believe the dimensions that define each consumer group are something like:

A: Audience (1st/2nd/3rd party)
B: Reuse (low-high)
C: Customization (min-max)

These dimensions drive the decisions about the component model and distribution model. Example, the Fluent UI core library primarily serves the "1st party, high reuse, maximum customization" consumer group which drives a different set of needs than HVCs which are primarily "1st/2nd party, lower reuse, min customization".

Once we formally document these groups (already implicitly defined in OKRs and such), we can then assign the right Fluent UI Conformance criteria to each group. Our current conformance tests, which need updating, are targeted only at the Fluent UI core consumer group and isn't useful in its current form for what we're discussing here.

I think this is now where your RFC lands, it is asking for answers which will solve the above. What is the Fluent UI Conformance criteria which we will use to service all our consumer groups? How do we define it? How do we manage conformance? How do we handle contribution and distribution for each group? I think we first start with defining our consumer groups, then the criteria for each, then we can map all our current work and efforts around implementation to these needs.

Really looking forward to this 😄


#### Self code hosting

Code for `@fluentui/contrib` packages should be self hosted. The Fluent UI team will provide bootstraping utilities
Copy link
Member

Choose a reason for hiding this comment

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

Will these bootstrapping utilities have an update path? If Fluent improves the pipelines/storybook/etc. can we ensure downstream bootstrappers can easily update to get new behavior also?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes it's what is mentioned with the intention to use NX to work on these bootstrapping utilities, since the tool supports migrations which can be run when upgrading

@levithomason
Copy link
Member

Noting that I met with @ling1726 and @miroslavstastny on this topic in depth. @ling1726 will be posting an update to propose 3 or more package scopes for us to release components to. Each scope will serve a certain customer need and component model requirement. Details to follow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: RFC Request for Feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.