Skip to content
Merged
Changes from 3 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
126 changes: 126 additions & 0 deletions rfcs/react-components/components/simple-component-implementation.md
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.

Copy link
Member

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:

  • The decision should encourage components that provide high value beyond general purpose layout.

For example, v9 deprecated and did not reimplement Stack. Stack provides low value over using flexbox directly and was very general purpose.

  • The decision should encourage components that are general purpose enough to be core to Fluent

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?

  • The decision should prefer a solution that builds on top of our composition model.

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.

## Detailed Design or Proposal

### Option 1: Recipes section in docsite
Copy link
Member

Choose a reason for hiding this comment

The 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
Copy link
Member

Choose a reason for hiding this comment

The 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.
Copy link
Contributor

Choose a reason for hiding this comment

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

just to clarify, do you mean that we would implement Persona or a generic Media layout component ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.

Copy link
Contributor

Choose a reason for hiding this comment

The 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.
- 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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 ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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.
Copy link
Member

@layershifter layershifter Oct 26, 2022

Choose a reason for hiding this comment

The 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