--- robots: noindex, nofollow tags: pitch --- For instructions on shaping a project see here: [Shaping a Project](/kX02SXVbS6KzMOQd56i6Cg) # Convergence - May ### Problem *From: [Problem guidance](https://basecamp.com/shapeup/1.5-chapter-06#ingredient-1-problem)* *The best problem definition consists of a single specific story that shows why the status quo doesn’t work.* v0 and vNext do not share components. This creates user confusion and frustration and generates very awkward guidance to use one or another. We can't simply merge the two libraries into one, or even get both to use one thing without sharing basic fundamentals. In each component, there are many differences: * styling system * theming system * compositional patterns * slots (onRender vs shorthand) * props (small differences) We plan to resolve these iteratively in steps, with special consideration of prioritizing customer needs. These being: * Don't break me (SharePoint (SPFX devs) 3rd parties) * Nothing changes without clear what/why/how guidance and ideally codemods) * Make runtime faster and bundle smaller (WAC, OWA, ODSP, Office.com) * Let me use strict mode (OWA, WAC) * Better theming solution that works for more than vNext or v0 (Fluid ask) * Let me bring my own styles (WAC, ODSP) ### Appetite *From: [Appetite guidance](https://basecamp.com/shapeup/1.5-chapter-06#ingredient-2-appetite)* In order to time box this work into 3 weeks, we will take an aggressive approach to scope the work to feasible chunks spread by our v-team of devs: | Driver | Areas | |-|-| | Mak | Button, Link | | Ben | Pivot (Tabs) | | Jon | Slider | | Xu | Checkbox, Toggle | | Levi | theming packages with tokens | | David | Avatar, ThemeProvider, sass pipeline, token help | Convergence is a spectrum more than a boolean state. Let's review our checklist of component convergence. We can't achieve all of these in 3 weeks. Designers have changes they want to make. We need to make progress moving the towers and proving out our architecture. May: * Components use static css leveraging css variables * IE 11 backwards compat with css variables is proven * Components use compose * Components which have slots use converged shorthand syntax We will operate under these conditions: * For these components, we will want them to ship in vNext * Proves out the static styling (Addresses performance ask) * Theming and tokens concepts shared * Converts to function components (Addresses strict mode ask) * Adds shorthand slots * Proves out shared compose and shorthand * `Button` will stem from the v0 `Button`. * We will separate out Menu/Split for the next iteration due to dependencies. * All tests will pass TBD (coordinate with Juraj) * Internal accessibility test pass June: * Move component to new package * both v0 and v7 components named the same * both have the same props following the one open ui spec * both use the same code * both use the same documentation * both have the same schema and are integrated into the designer experience #### Why are we not converging everything at once? 1. Keep things realistic and scoped 2. Focus on vetting compose and static styles 3. Address critical customer needs without breaking partners 4. Standardize on shorthand 5. Pave the way for unstyled base components and recomposition We WILL be converging components. We will be vetting api surface, and applying designer updates. Getting them to a common architecture is the first step. Once we are at this point we can proceed to the next batch of updates. ### Solution *From: [Rabbit hole guidance](https://basecamp.com/shapeup/1.5-chapter-06#ingredient-4-rabbit-holes)* Our goal for May is to make minimal API surface changes and focus specifically on ensuring we can move to compose and static styling. In the process we will be addressing many of our top customer complaints for the most fundamental components. #### Steps per component Each of the components we're targeting for convergence will go through these steps: - [ ] Convert to function component (if not already) to be leveraged by compose. - [ ] Convert css in js to static css with variables reflecting shared theme tokens for configurability (doesn't required `compose` updates.) - [ ] Convert component to use `compose` with agreed on converged slots, moving state into a component hook. - [ ] Split out base component - [ ] Split out use{Component} hook - [ ] Export styled component - [ ] Uses shared `ThemeProvider` to get styles - [ ] Existing tests pass (with updates if needed) ### ThemeProvider work (David, Levi) * Sass pipeline must be updated to export stylesheet content * ThemeProvider and StylesheetProvider must be integrated into both suites * Universal theme format (what we share, what partners can leverage and build on) * Theme packages * Teams -> universal theme converter * Fabric -> universal theme converter ### Packaging and origin Every component will be exported in either `next` or `northstar`. `Button` will originate from the `northstar` version and will be moved to `react-button`, but we'd like it to ship in both. * Question: is this possible? How would this work with fela vs static styling? Could we export a fela friendly recomposed version and use that in northstar? All other components will incubate in `react-next`, with the expectation they will be a part of v8 released later in the summer. We plan to move these out into sub packages, but it isn't required to start the conversion, which is already happening right now. #### Scss conversion details Most of this is covered in the scss conversion guide here: https://hackmd.io/PksrTwyYQpuzhXf94YaKjA#Content-of-the-scss-file Today, stylesheets in v7 are functions which take in style props and dynamically build classes per slot. When a prop modifier like `primary` is true, the given changes would be applied directly to each slot class. Using a static stylesheet means that we don't have the luxury of merging only slot classes and must rely on modifer and enum class names to be conditionally added to the `root` slot. **Slot classes** should be named the same as the slot, and the root element should always be named `root`. **Modifier classes** such as `primary` should be named the same as the modifier passed into props, or managed by state. **Enum classes** which represent when a `prop` equates to a particular `string` value should consist of the prop name and the prop value, delimited by an underscore. For example: `size_large`. This follows BEM syntax, but is also compatible with css modules which will export the class name as a TypeScript variable. When theme values are referenced, we will need to use css variables to both provide and reference them. Today the `ITheme` interface defines a number of palette colors and semantic colors. We will do 2 things: 1. Discuss what the right token names are for the shared universal theme, which will be defined in the `@fluentui/theme-provider` package with the intent to share between v0 and vNext. 2. Create a theme converter from old to shared theme so that Fabric themes providing old ITheme values will still apply to the component. Out of this process we will construct a list of needed tokens per component to ensure consistency, and guidelines for documenting tokens: https://hackmd.io/DLoVd4XcQ1aS8BYStaaC2w #### Token inline support In v0 we have `variables` props. Proposal is to snap this to `tokens` props to support providing type safe values for the css variables. As we gather dependencies for each component, we will be constructing interfaces which define these variables. We should be able to auto convert tokens into style objects using a generalized helper called within `mergeProps` so that we don't redefine this logic over and over. #### State/hook conversion details Each component is expected to abstract their existing state management in a `use{Component}` hook. This will call `mergeProps` once state has been reconciled. Marija and David will work on getting `mergeProps` supporting all v0 shorthand details and will be available through the `@fluentui/react-compose` package. See details in the convergence guide: https://hackmd.io/PksrTwyYQpuzhXf94YaKjA#State #### Compose conversion Each function component should fairly easily be translated into compose: ```tsx const ToggleBase = compose<...types>( (props, ref, options) => { // rendering goes here }, { // options go here } ) ``` #### Shorthand slots For each component: 1. If the code originates from v0, use v0 slot names 2. If the code originates from v7, use the slot names defined in the I{Component}Styles Post the design spec updates and research added to open ui, we will not change api surface until we know what we want to change, why, and how customers will upgrade. #### Work: Preserving `styles` prop (Xu) Our biggest concern in API surface change is the `styles` prop, which lets customers inject their own rules using mergeStyles. We will continue to support the prop and use `merge-styles` to mix in rules to the given slots, but will not call `merge-styles` at all. (Xu investigating a fix in `styled` and `classNameFunction` helpers to move us a little closer.) Today, you can target a component using `Customizer` to provide style overrides. We will need to create a hook to inject custom `styles` props into the component. #### Work: Ensure IE11 polyfill will work with the static sheet injection (David) https://github.com/nuxodin/ie11CustomProperties Things we will be testing: * Will this work with our StylesheetsProvider injection? * Will this work with merge-styles or fela (which uses `insertRule`)? * Test prop mutations which cause new rules to be inserted? * Will scoping work correctly #### Known breaking changes being introduced in vNext *Button* will not be starting with the v7 Button mess and will instead start with the v0 api surface. That means `PrimaryButton` usage will be deprecated. Proposed solution: move code into `react-button` package using a `/v7` path import. Final TBD. #### Package moves In this iteration we will primarily focus on just getting `compose` and static stylesheets going in the shipping components. We will save package moves for components which are closer to being shared between the two. This primarily includes `Button`, which will live in `react-button`. ### Risks (Rabbit holes) *From: [Rabbit hole guidance](https://basecamp.com/shapeup/1.5-chapter-06#ingredient-4-rabbit-holes)* Avoid unneeded api churn for now. One step at a time. Deprecating too many things at once bears one risk. Deprecating things over time bears additional risks. Any api churn needs a lot of communication: * react-next release notes need clear definition of: * What changed * Why it changed * How the user should update things * a codemod should be considered. If possible, release note should call out that it can be updated through a codemod. * Breaking changes should have signoff from leads and communicated with partners. Some work is dependent on other work. `compose`, while checked in, will still need modifications which we'll tack as needed. `mergeProps` and `ThemeProvider` are still pending PRs. Dependencies are a risk to weed out, which is why we should save package shuffles once we've made progress on the other customer-impacting goals. ### Out of scope (No-gos) *From: [No-gos guidance](https://basecamp.com/shapeup/1.5-chapter-06#ingredient-5-no-gos)* Writing components from scratch. We will avoid making a 3rd thing which does not ship in either suite. We will be shipping all components in vNext, and hope to ship the unified Button in v0 as well. We will not have time to address all API surface updates to make both suites conform to a common API. However, this is what we're moving towards as we unify theming, composition, and slots. We DO plan to have Open UI specs for all components. We DO plan to converge API. They will only be out of scope for the initial phase of just converging our tooling and fixing our perf. This is what our customers want now.