-
Notifications
You must be signed in to change notification settings - Fork 2.9k
docs(rfcs): Recipes #25139
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
docs(rfcs): Recipes #25139
Changes from 3 commits
9517185
3345b45
f2a0fbb
a8b124a
8a8180b
4e3c000
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| # RFC: Component recipes | ||
|
|
||
| --- | ||
|
|
||
| @sopranopillow | ||
|
|
||
| ## Summary | ||
|
|
||
| Decide how to implement components that could be built with already created components. | ||
|
|
||
| ## Background | ||
|
|
||
| Currently Persona's spec calls for a media slot that allows the use of an Avatar, image, icon, and a PresenceBadge. When implementing Persona we considered what Persona provides, it is a grid that aligns its text and media based on the given label position. This is also known as a media object by other libraries. | ||
|
|
||
| There's one key aspect that Persona adds that makes creating the component compelling, unifying the look and feel across apps. To achieve this, we don't need the image and icon media options, we only need the Avatar and PresenceBadge (it also makes more sense that a persona only showcases person-related information). This then is the reason why the already implemented Persona only supports these slots. But there's still the question about how to add the look and feel of Fluent to media objects that have an image or icon. | ||
|
|
||
| This is where this RFC will decide how to proceed with this portion of the problem. | ||
|
|
||
| ## Problem statement | ||
|
|
||
| As we start working on new components, there might be some components that are simple and could be built with a simple layout and the already finished components. When creating these components, we currently don't have a guidance on whether to let the user build the component or we provide the component. This RFC offers three options, one that will require the user to build the components using instructions (recipes), another where we will provide the implementation of the component, and a combination of both option 1 and 2 providing a partial implementation and a recipe. | ||
|
|
||
| #### What makes a component a candidate for this RFC's solution? | ||
|
|
||
| - It should encourage components that provide high value beyond general purpose layout. | ||
| - It should promote the use of our composition model and already created components. This will help us achieve a consistent look and feel across apps. | ||
| - It should be generic enough to be used in multiple scenarios. This is to avoid creating a component that is only used in one place. | ||
| - It should provide more than a blurb of code snippets that the users might just copy and paste. | ||
|
|
||
| ## Detailed Design or Proposal | ||
|
|
||
| ### Option 1: Recipes section in docsite | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love the idea of recipes. I have found that the migration shims didn't work very well as recipes because people want to keep up to date with the latest and best version. A recipe should have lots of stuff left as work for the reader to fill in. If we find that people are just cut-and-pasting the code as-is everywhere, then it should probably be a component. |
||
|
|
||
| In this option we will add a section to our docs detailing how to create a component/layout/composition using already created components in a Fluent way. We could think of it as showing how to Fluentify known patterns or layouts. | ||
|
|
||
| It is also important to note that this option doesn't mean we will provide code snippets that you have to copy paste, but rather guide the user on what's the important part of the component and leave the rest to the user. | ||
|
|
||
| #### Folder structure inside docs | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Storybook doesn't make recipes easy to show as the code-behind is limited to what is within the story. Maybe we need to figure out ways to better show recipe code in storybook or find a better way to publish them. |
||
|
|
||
| ``` | ||
| \- Concepts | ||
| |- Introduction | ||
| |- Developer | ||
| |- Migration | ||
| |- Recipes | ||
| |- Recipe #1 | ||
| |- Recipe #2 | ||
| \- Theme | ||
| |- Color | ||
| |- Motion and Size | ||
| |- Typography | ||
| \- Components | ||
| |- ... | ||
| \- Preview Components | ||
| |- ... | ||
| ``` | ||
|
|
||
| #### Pros | ||
|
|
||
| - No need for a new package in our repo. | ||
| - In the case of a component like persona where its design requires us to change the icon's size, we would provide best practices section that could include a size table for reference. | ||
|
|
||
| #### Cons | ||
|
|
||
| - Allows for issues where the user-created component doesn't look like the design. | ||
| - Could increase a11y issues in user-created components. | ||
| - Could be overwhelming for the user to follow the recipe. | ||
|
|
||
| ### Option 2: We provide the component | ||
|
|
||
| For this option, we would implement the component and provide it like any other component. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just to clarify, do you mean that we would implement
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we go with this option, we will provide a Media Layout component and a Persona component.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have we checked with design if there is an appetite for a reusable media layout on their side? It would requirement commitmment from both us (to implement and maintain it) and design (to design with it in mind) |
||
|
|
||
| #### Pros | ||
|
|
||
| - We can ensure the design follows the design spec. | ||
| - Makes it easier for the user. | ||
|
|
||
| #### Cons | ||
|
|
||
| - Another component package for a simple component. | ||
| - More code to maintain. | ||
sopranopillow marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - More design figmas. | ||
|
|
||
| ### Option 3: Option 1 + Option 2 `@fluentui/react-recipe-hooks` | ||
|
|
||
| We provide style hooks such as `useMediaObjectStyles()` or `useMediaObjectClassNames()`. The hook's options would contain what would be the props in a regular component and it would return its classnames so the user can apply them respectively. These hooks could be housed in a package such as `@fluentui/react-recipe-hooks`. A simple example could be: | ||
|
|
||
| ```jsx | ||
| import { Text } from '@fluentui/react-text'; | ||
| import { Image } from '@fluentui/react-image'; | ||
| import { useMediaObjectClassNames } from '@fluentui/react-recipe-hooks'; | ||
|
|
||
| const MyMediaObject = () => { | ||
| const mediaObjectClassNames = useMediaObjectClassNames({ labelPosition: 'below' }); | ||
|
|
||
| return ( | ||
| <div className={mediaObjectClassNames.mediaObject}> | ||
| <Image | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Design can sometimes have specific requirements on the inner components (i.e. Avatar), how do we handle such cases with a style hook based solution ?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be an example a part of the recipe we leave up to the user. While option 3 gives a hook, there might be some things we cannot provide, and this could be confusing. |
||
| className={mediaObjectClassNames.media} | ||
| block | ||
| src="https://fabricweb.azureedge.net/fabric-website/placeholders/100x100.png" | ||
| /> | ||
| <Text className={mediaObjectClassNames.text}>Lorem Ipsum</Text> | ||
| <Text className={mediaObjectClassNames.text}>Dolorem</Text> | ||
| </div> | ||
| ); | ||
| }; | ||
| ``` | ||
|
|
||
| There will still be parts of the component that the user will have to implement, these hooks will not be a full implementation. | ||
|
|
||
| #### Pros | ||
|
|
||
| - We can add more design guidance. | ||
| - While the user still has to do more work than option 2, it's way easier than option 1. | ||
| - Simpler to maintain than option 2. | ||
| - Can make option 1 easier to follow. | ||
|
|
||
| #### Cons | ||
|
|
||
| - More code to maintain. | ||
| - Could bring more issues by being hard to follow. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mentioned accessibility issues for Option 1, but I think it's still an issue for this option as it provides only styling. |
||
|
|
||
| ## Discarded Solutions | ||
|
|
||
| ## Open Issues | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider detailing the core considerations you think the team should use to make a decision of one approach vs. another. Here's some examples:
For example, v9 deprecated and did not reimplement Stack. Stack provides low value over using flexbox directly and was very general purpose.
Components like Field provide label, error message, and input component layout and coordination that can be used in many form scenarios. Components like a SharePoint file-list specific Card might not be reusable by others easily and maybe should live outside the core of Fluent and be implemented by the team that uses them. This brings up a secondary question of should our decision favor a pattern that other developers building on top of fluent should use?
We have a composition models that leverages slots, hooks, and context to make customization and replacement possible. Which solutions leverage the existing composition model the best to maintain developer productivity and extensibility.