Skip to content

Latest commit

 

History

History
195 lines (137 loc) · 11 KB

CONTRIBUTING.md

File metadata and controls

195 lines (137 loc) · 11 KB

Contributing to @fluentui/react-northstar (and others under packages/fluentui)

NOTE: This document currently only applies to the packages located under packages/fluentui, such as @fluentui/react-northstar. For other packages, see this wiki page instead!

Getting started

If you would like to contribute to packages besides the ones under packages/fluentui, see this wiki page instead!

To contribute to packages in this folder, follow these setup instructions.

Useful Commands

This list contains the most useful commands. You should run yarn run to see all scripts.

From repo root:

yarn start                 # start doc site: choose `@fluentui/docs`

yarn test                  # run all packages' tests once

yarn build                 # build all packages
yarn build:fluentui:docs   # build docs

gulp deploy:docs           # deploy gh-pages doc site

yarn lint                  # lint all packages

yarn prettier              # run prettier on changed files

From an individual under packages/fluentui, such as packages/fluentui/react-northstar:

yarn test                  # test once
yarn test:watch            # test on file change

yarn build                 # build all files in package

yarn lint                  # lint once
yarn lint:fix              # lint and attempt to fix

Workflow

These guides will walk your through various activities for contributing:

Accessibility

@fluentui/react-northstar implements accessibility using accessibility behaviors. The behaviors add attributes to the DOM elements (mainly role and aria-* properties) as well as handle keyboard interaction and focus. Every accessible component has a default behavior, which can be overridden using the accessibility prop. You can choose a behavior from the ones provided by Fluent UI or you can implement a new behavior.

Behaviors apply properties, focus handling and keyboard handlers to the component slots. When developing a component, the properties and keyboard handlers need to be spread to the corresponding slots.

Role and aria props

ARIA roles and attributes provide necessary semantics for assistive technologies that allow persons with disabilities to navigate in the page/application.

In addition to behaviors, ARIA landmarks and naming props need to be added to the components/elements to form the page structure and provide textual information.

For example, to make an icon-only Button accessible, aria-label prop needs to be used:

<button icon="star" iconOnly aria-label="Favorites" primary />

Focus

An application should always have an element with focus when in use. The user can change the focused element by:

  • pressing tab/shift+tab keys to navigate through the components
  • pressing arrow keys to navigate through children (for example menu items in menu)
  • using the screen reader with or without virtual cursor

@fluentui/react-northstar uses the FocusZone component for basic tab and arrow key focus handling. To use the focus zone, you can use the focusZone configuration in the behavior (for example see MenuItemBehavior).

Focused component needs to be clearly visible. This is handled in @fluentui/react-northstar by focus indicator functionality. Focus indicator will be displayed only if the application is in keyboard mode. Application switches to keyboard mode when a key relevant to navigation is pressed. It disables keyboard mode on mouse click events.

To style the focused component, you can use the isFromKeyboard utility and prop. See Button component and Button style for reference.

Keyboard handling

In addition to basic focus handling, specific keyboard handlers can be added to the behaviors. These keyboard handlers call actions defined in the components, when corresponding keys are pressed by the user. For reference, see keyActions in MenuItemBehavior and actionHandlers in MenuItem component.

Packages

We are using Lerna to manage our packages and Yarn Workspaces to link them.

Add a new package

For now, you must copy the structure and boilerplate files of an existing package under packages/fluentui when adding a new package. packages/fluentui/accessibility is a good basic example.

  • choose a name and update the name field (keep the @fluentui scope)
    • it can be prefixed with the library name if the implementation is not framework-agnostic.
  • the directory name should match the unscoped part of the package name
  • please provide a meaningful description to a package in the matched field
  • use https://github.com/microsoft/fluentui/tree/master/packages/fluentui/__DIRECTORY_NAME__ as homepage
  • our packages are currently published with MIT license, please follow it until you will have specific legal requirements

Run syncpack format

Organise a new package.json according to a conventional format, where fields appear in a predictable order and nested fields are ordered alphabetically.

yarn syncpack format

Add a new dependency

Please always use lerna add to manage all dependencies including internal packages. The command below will add @fluentui/react-proptypes as a production dependency to the @fluentui/react-northstar package.

lerna add @fluentui/react-proptypes packages/fluentui/react-northstar

Development Notes

I (@rymeskar) have been part of the FluentUI framework team for the past two months. During these months, I have tried to collect ideas, rules, guidelines and best practices that are not otherwise captured. Generally, the recommendation is that code and conformant test is the best way to learn up-to-date FluentUI idioms.

Collection of Little Ideas

  • Changelog has a special format.
  • Always try to find the most relevant and similar component to get inspired by.
  • Try to extract pure functions outside of component's body; possibly into special files.
  • Don't name boolean flags with 'is' prefix.
  • Yarn build is not necessary when working with FluentUI. You should just call yarn (resolve packages) and then yarn start (start application).
  • For benchmarking JavaScript, one can use the https://jsperf.com .
  • The useAutoControlled hook description:
    • defaultValue comes from an outer scope and be defined by user, i.e. defaultChecked.
    • initialValue is internal and will be used if there is no defaultValue or value.
    • value should come from outer space and always wins.

Collection of Concrete Topics

  • Testing
    • For majority of components, visual test in combination with isConformant test is enough.
    • Visual tests are based off examples. You can extend the examples by also providing 'steps' action tests.
  • Props
    • Props should be a flattened object.
    • Props should take advantage of optional properties in combination with defaultValues.
  • Event Handlers
    • Going forward, we should use onChange?: (e: React.SOME_EVENT<EL_TYPE>, data: DatepickerProps & { value: IDay }>). The currently used ComponentEventHandler uses React.SyntheticEvent and is able to reason about the proper type then.
    • We use lodash's _.invoke(), the function ensures that the prop actually exists.
    • We should work carefully with event.preventDefault(). Only invoke in necessary cases. In Datepicker, we wish to navigate grid cell navigation only explicitly within our code.
  • Styling
    • When developing with different kind of themes, one should add the style to default theme and add partial classes to dark or high-contrast.
  • Behavior
    • When developing behaviors, one must add proper specification strings. The format of these strings is defined in regexpes in the following file.
    • Focus and navigation should be handled by focusZone section of behaviors. The actual types and definitions are defined here.
    • For sustainable keyboard keys handling, one needs to map actions to key presses. Then within component code, one needs to define handling of these actions.