NOTE: Please see this wiki page for the current feature proposal process. This page is kept for reference until the guidance can be merged.
Before starting on a new feature, be sure it has been approved by the maintainers and community. To do that, please file an RFC under the Issues tab so that a decision can be taken quicker. Doing this will potentially save you wasted time.
Build a minimal prototype showcasing the proposed feature. Do not worry about testing or documentation at this phase, this is just to push some changes for collaborative review.
Review the documentation for the component. Spec out the component's proposed API. The spec should demonstrate how component's API you are proposing will be used by Fluent UI consumer. You can reference this API proposal for the Menu Icons.
Once the component spec is solidified, it's time to write some code. The following sections cover everything you'll need to spec and build your awesome component.
You can create a new component MyComponent
by following the example of an existing component (e.g. Button).
The corresponding component directory trees should be created in correct places:
- the component under
packages/fluentui/{package}/src/components/MyComponent
,- the docs under
packages/fluentui/docs/src/examples/components/MyComponent
,
- the docs under
- the tests under
packages/fluentui/{package}/test/specs/components/MyComponent
{package}
is likely going to stand for react-northstar
if you are contributing a component to the main package.
You can customize the styles of your component by adding necessary variables and styles as part of your theme.
E.g. for update on the teams
theme: /src/themes/
Generally if you're updating a component, push a small change so that your PR could be reviewed quickly.
Stateless components should be written as an arrow function:
const Button: React.FunctionalComponent = props => {
// ...
};
Stateful components should be classes:
import { AutoControlledComponent as Component } from '../../utils';
class Dropdown extends AutoControlledComponent {
// ...
}
You can now iterate on the component code and your doc site example will hot reload your changes. Use this workflow to iterate on the prototype for your proposed feature.
Every component has two static properties called displayName
and className
. The values here are used for generated documentation, generated test cases and some utilities.
Here's an example:
static displayName = 'Accordion'
static className = 'ui-accordion'
Every component must have fully described MyComponentProps
interface and propTypes
.
import * as PropTypes from 'prop-types'
import * as React from 'react'
import {
ChildrenComponentProps,
ContentComponentProps,
UIComponentProps,
commonPropTypes,
} from '../../utils'
export interface DividerProps
extends UIComponentProps,
ChildrenComponentProps,
ContentComponentProps {
/**
* Accessibility behavior if overridden by the user.
*/
accessibility?: Accessibility
/** A divider can be fitted, without any space above or below it. */
fitted?: boolean
/** Size multiplier (default 0) * */
size?: number
/** A divider can appear more important and draw the user's attention. */
important?: boolean
}
// ...
static propTypes = {
...commonPropTypes.createCommon({ color: true }),
fitted: PropTypes.bool,
important: PropTypes.bool,
size: PropTypes.number,
}
Strive to use stateless functional components when possible:
export interface MyComponentProps {}
const MyComponent: React.FunctionalComponent<MyComponentProps> = props => {
return <div {...props} />;
};
If you're component requires event handlers, it is a stateful class component. Want to know why?
export interface MyComponentProps {}
class MyComponent extends AutoControlledComponent<MyComponentProps> {
handleClick = e => {
console.log('Clicked my component!');
};
render() {
return <div onClick={this.handleClick} />;
}
}
Review common tests below. You should now add the isConformant()
common test and get it to pass. This will validate the displayName
and className
and multiple other aspects to help you get your component off the ground.
Add a performance test to set a baseline performance measurement for your component and guard against future regressions.
Create a new documentation example that demonstrates usage of the new feature.
- Create a new example in
packages/fluentui/docs/src/examples/components
under the appropriate component. - Add your example to the
index.ts
in respective directory. - Running
yarn start
should now show your example in the doc site.
Please follow the Angular Git Commit Guidelines format.
Open a PR as soon as possible with as little code as necessary to show the feature. This way, we can iteratively collaborate on the design of the feature.
After iterating on the feature with the maintainers, you will add full test coverage and documentation. See the individual guides for instructions.