Skip to content

Latest commit

 

History

History
642 lines (454 loc) · 44 KB

codebase-overview.md

File metadata and controls

642 lines (454 loc) · 44 KB

Codebase Overview

This page will give you an overview of the library codebase organization, conventions, and implementation. Components will always be moving toward this specification, but may not comply currently.

If you want to contribute, we hope that this overview will help you feel more comfortable.

Top-Level folders

  • components - React components
    • [COMPONENT] - components that are part of the public API
      • __tests__ - Mocha and Jest tests
      • __examples__ Examples used in storybook and documentation website
      • __docs__ - storybook and documentation website imports of examples
      • private - components that are not a part of the public API
    • utilities - components that are shared between other components (not public API)
  • icons - Inline icons [legacy]
  • preset - Babel preset published to @salesforce/babel-preset-design-system-react
  • scripts - Build and release tasks
  • styles - Temporary location for styles (use sparingly)
  • utilities - Scripts that are not React components including checkProp warnings, DOM, and event helpers. (not public API)

Introduction to presentational components

If you are new to React, you may be trained to design components in a more complicated way than they need to be. The goal is for engineers to not have to think about markup and stylesheets. Please prioritize the simple and the flexible.

The gist of presentational components is to be a template that takes in data and passes out user events and related data to callback functions. One over-simplified way to approach it is to consider these components as Handlebars templates with event listeners.

  • Take data and UI data, such as disabled buttons, from parent via props to display data and UI state correctly. Don't manipulate props with string concatenations, array pushes, and sorting within components.
  • Pass mouse and keyboard events and related event data, such as the item data for the item that was clicked, up to parent state machine, so it can decide how to manipulate it's child components' props.
  • Parent components should be the only components that change data. Components should be data stateless and only reflect the data they have been given. Only UI state, such as "is this dialog open?" or "is this option active/focused" should be within components. Focus and active state should be maintained internally in order to not introduce these into your state engine store (e.g.- Redux).

Your audience is intermediate to advanced engineers

This project is not Bootstrap, and we've built frameworks on top of Bootstrap. The primary audience for this project is software engineers wanting to easily implement the design artifact handed to them. Yes, contributors should over-document and explain as much as you need to, but you do not need to have components just work when you drop them on the page. In short, think functionally and limiting internal component state.

Write clear prop comment descriptions for documentation website

"I just updated. What just broke and why?" Why does the React child component become the DOM parent node? Write as long of a prop description comment that is needed to understand the concept. These comments are used for the prop tables on the library documentation website.

Prop changes need console warnings

Need to sunset a prop or change the variable type accepted? Write backward compatible code and add console warnings that will only run in development. Use a checkProp function to communicate to the developer that they are not using the library correctly. If the warning can become an independent module and work in multiple components, add it to the design-system-react/utilities folder. Some examples include:

  • A component has children without a specified displayName
  • Determine if the trigger can be tabbed to
  • Require one of multiple props, but not both or only one of the specified properties
  • Warnings of property deprecation, sunsetting, and future changes

External architecture

No prop breaking changes without backward compatibility

Except on rare occasions with considerable thought breaking changes will be denied. Non-backward compatible changes to component props or a new design system version that has breaking changes within it is a breaking change and this library will have to release a major version.

SLDS markup alignment and class changes within the current design system release cycle are not considered breaking changes in this library although they may break markup queries. When upgrading the design system CSS, please create an archive/stale branch labeled similar to spring-17-2.2.x, except using the correct Salesforce release date and SLDS version that the code was intended to support.

If you need an existing prop changes, please consider some alternatives such as deprecated the old prop and proposing a new prop name (onChange to onRowChange for instance).

Review similar components before proposing a feature

Familiarize yourself with concepts used in the rest of the library.

Rendered text needs a prop. Group assistive text and labels

Be inclusive of non-English users. Any text the user can read (including hidden assistive text for screenreaders) should be able to be set via a prop for internationalization purposes. Within the component, do not concatenate strings. This assumes that you know the word order of all languages. Strings should be passed into props in their entirety. Non-visible programmatic keys can be concatenated.

If the text has a mix of data and words, use a before/after key name or a callback with a return value. All assistive text for accessibility and visible text should be grouped in an object and passed in with a prop, assistiveText and labels respectively. This will allow consuming developers to easily find and map text to localize it. All visible text labels should allow a propType of node. This allows for italics, bold, other inline styling, and adding tooltips.

Use isRequired PropType when possible

Similar to limiting internal state, isRequired is explicit and determines the minimal API of each component. It simplifies a component's internal code and removes conditionals.

Prefix onRequest[ACTION] to pre-state-change callbacks functions

Pre-state-change events are events that request a state change from the parent component. Pre-state-change events callbacks should check for an invalid state and prevent the invalid state. For example

  • Pill's onRequestRemove would be called before the Pill is removed. A pill is requesting that itself be removed, but it hasn't been removed yet. * onRemove would be called after the Pill is removed.
  • "Native" events, like onClick, onKeyDown, onFocus do not have the prefix onRequest, since the callback occurs after the specified event.
  • onRequestRemove occurs before the event of removal, while onKeyDown (delete or backspace) on a Pill occurs after a key is pressed down.

Prefix on[EVENT] to post-event callback functions

This is fairly standard React convention. Post-state-change or post-user-action events are called after a state change or a user event and should have the on prefix.

No return values in event callback functions

Event callback props should not communicate with the parent component through return values. To increase clarity, do use event.preventDefault() or return false within a callback prop to communicate information back to the component. Trapping event bubbling is good, but components should only be communicated with by props cycling back through the state engine. All data needed to change the state or communicate an invalid state should be explicitly provided by a key in the data object of the function parameter. The data object is always the second parameter of the callback.

Allow id to be set and unique to the page

All id attributes in a component's DOM should be unique to the page, especially if the same component is used multiple times. A top-level component's id prop should be shortid generated by default and also be able to be controlled by the consuming developer. shortid generated id attributes are needed to enable accessibility and sometimes used for a React key. Letting the developer set a component's id allows library and consuming application DOM snapshots tests to be deterministic. Sub-component id props and nodes within a component can be concatenated strings such as <div id={`tab-panel-${props.componentId}-${props.panelId}`} role="tabpanel" />. Every id should contain the component's id prop, since multiple components on the same page could use the same data objects and all HTML element id's should be unique to the page.

Callback props should be tested to see if they exist

Public callback/handler function props should be tested to see if they exist before execution. Within private child components use .isRequired PropType if the callback is needed internally for the component to function.

Prefix render props with onRender

Render props are essentially a callback function that occurs at render and should be given all data that the default render function has access to. Use an onRender prefix to signal that it is a standard render prop function (e.g.- onRender[nodeOrComponentName]). In a menu item render, this would be the options object. This functional is always swapped out with a DOM node.

Reuse existing component props by using component. No <Button iconClassName />.

Another kind of render prop is when a prop accepts an existing Design System React component class with a prop API such as the dropdown prop of DataTableRowActions. Component composition with prop spread is a similar pattern to render props, but differs in that it does an element clone with a shallow prop/object merge in which it is assumed that the prop component passed in overrides any props from its parent.

In a way, this is "grandparent control" in that it surfaces the internal API of sub-components to the consuming developer in a way that the parent of the parent can control it. The parent component (such as DataTableRowActions) shallow merges the props from itself with the component props provided from the developer. The developer's passed in component controlled by the "grandparent" takes precedence and *merges in last which is what you typically want, since a grandparent component controls the parent. That said, overriding internal logic can easily break a component. Use with caution.

This pattern creates a separation of concern and a more declarative approach that relies on child components with their own documented props instead of additional props on the parent component such as <Button iconClassName />. Passing in <Dropdown options={} /> to a dropdown prop limits the aliasing of props for child components that already exist (dropdownOptions is discouraged) and reduces duplication of PropType documentation and increases library maintainability.

Put private components in private folder

React components not in a private folder are considered public and are considered within the scope of semantic versioning for breaking changes.

No global DOM or window access

Encapsulate your components. No DOM queries. If window, document and event listeners are needed for events, you should test for their existence. Their existence is not guaranteed.

Limit global event listeners usage

The component should not be listening to window events directly. If a menu needs to be smaller to be responsive, consuming applications should listen for the resize event and change the correct props to make the component responsive--or a CSS solution should be found.

Limit use of DOM ref

DOM references should only be used for tasks such as measurement.

Use refs object for external DOM callbacks

If you need to provide a DOM node reference, create an object called refs with keys that are semantic names of DOM nodes: refs: { triggerButton: ()=>{}, triggerInput: ()=>{} }. ref is a reserved prop name. This will return the component React object, not the DOM node. If you use a refs object, you may need shallow merge the object with default props. For more information, please review Exposing DOM Refs to Parent Components.

const CustomTextInput (props) => (
  <div><input ref={props.refs.input} /></div>
);

const Parent () => (
  <CustomTextInput
    refs={{
      input: (el) => {
        this.inputElement = el;
      },
    }}
  />
);

className class is rendered on .slds-[COMPONENT]

The className prop should be on a consistent node. The classes passed into className should be present on the .slds-[COMPONENT] node and not on a container node--nor on a child of .slds-[COMPONENT]. All other className props should be suffixed--such as classNameMenu or classNameContainer.

Use className[NODE] prefix for other nodes

Use classNameInput for the classname on an input within a component.

Boolean props: Use is, has, and can prefixes or -able suffix

If a prop is a boolean, please prefix with is or can, has, or suffix it with -able. Never default a prop to true.

No truthy defaults for boolean type props

This will prevent consumers from having to write propName={false}. HTML defaults many attributes to true if no value is provided, such as checked instead of checked="true". To maintain JSX's HTML-like syntax, please avoid asking a developer to use propName={false}. This may require using the opposite word, such as isInline instead of isModal.

Adding a default prop may be a breaking change

If adding a default prop changes the component visually from what it was without the default prop, it is considered a breaking change. Default props are very helpful and welcome if there are no changes to the component or are part of a new component. One alternative option is to create a value not specified by the design system that results in the originally rendered markup.

Use event, { key: value } in callback parameters

Use consistent callback parameters and names. All render callbacks, that is callbacks that determine what to render, should pass a data object with named key/values as the second parameter. Event callbacks should pass in the synthetic event, then a data object with named key/values that relate to the event. If an event callback doesn't have a user event that triggered it, pass undefined as the event. This will look something like this.props.onCallback(event, { extraInfo: true }).

Transpile this library before using

This library will not, and is not, intended to be run in a browser as-is. This library is targeted at engineers that can optimize their builds for performance and target the browsers and environments they need to support with appropriate polyfills. Polyfills should be added at application build time.

Only propose SLDS components

This library should include only components which have approved patterns in Salesforce's design system. If there is a use case from a designer that conforms to a design pattern, that component should be able to be implemented with this library. This library does NOT conform to Salesforce production per se, but is open to being customized to support patterns in production if they remain generic and flexible. If you are a Salesforce employee and need a component not in SLDS, please email Stephen James.

Internal Architecture

Internal architecture should promote readability and easy maintainance.

Example Class

import React from 'react';
import PropTypes from 'prop-types';
import shortid from 'shortid';
import checkProps from './check-props';
import { EXTERNAL_CONSTANT } from '../../utilities/constants';

const propTypes = {
	/**
	 * The description of this prop (will appear in the documentation site).
	 */
	title: PropTypes.string.isRequired,
};

// These values will also be visible in the documentation site.
const defaultProps = {};

/**
 * The description of this component (will appear in the documentation site).
 */
class DemoComponent extends React.Component {
	static displayName = EXTERNAL_CONSTANT_NAME;
	static propTypes = propTypes;
	static defaultProps = defaultProps;

	constructor(props) {
		super(props);

		// useful for unique DOM IDs
		this.generatedId = this.props.id || shortid.generate();

		// initial state
		this.state = {};

		// Not required. This function issues console warnings to developers about props and is helpful in upgrading. All breaking changes to props must have a warning for developers when they upgrade.
		checkProps(EXTERNAL_CONSTANT, this.props);
	}

	// Class property bound to instance. Class methods that are not React lifecycle methods should use "fat-arrow" syntax if `this` binding is needed.
	toggleOpen = (event, { eventDataKey }) => {
		// you can use `this` here
	};

	// Minimize use of multiple renders. More HTML-like JSX is preferred with ternary statements
	renderSubComponent = () => null;

	// Render should be last
	render() {
		return null;
	}
}

export default DemoComponent;

Limit component state

If the parent application's state engine can handle it with a prop, then don't use state. New components should always start out as controlled by their parent and only be uncontrolled (that has state) if a use case presents itself. It's better to have a component that needs 20 props set and outputs the correct markup, than to have a component that works with no props set, yet maintains multiple internal states. We like to think of this project as design system templates with minimal logic that happen to work with the React framework. Let the library consumer create a simple container component with state. Read more about controlled components.

Use controlled components

  • Components should be able to be "controlled"--that exposes a callback and expect their parent to control them with props. Components should be controlled at first and then uncontrolled support added later if needed.
  • Prefix callbacks that occur before an event with onRequest. Prefix callbacks that occur as a result of an event with on. The close button in a Popover will call onRequestClose while the Popover will call onClose after the Popover has been closed. This is because closing isn't guaranteed with onRequestClose, since the parent component will decide.
  • Please note that if controlled by its parent, a component will appear broken if just copied and pasted into an application without a parent to control its props.
  • Controlled components can be stateless components, but entirely stateless components do complicate DOM selectors for the consuming applications.

A controlled <input> has a value prop. Rendering a controlled <input> will reflect the value of the value prop.

  render() {
    return <input type="text" value="Hello!" />;
  }

User input will have no effect on the rendered element because React has declared the value to be Hello!. To update the value in response to user input, you could use the onChange event:

class MyForm extends React.Component {
	constructor(props) {
		super(props);
		this.state = { value: 'Hello!' };
	}

	handleChange = (event) => {
		this.setState({ value: event.target.value });
	};

	render() {
		return (
			<input
				type="text"
				value={this.state.value}
				onChange={this.handleChange}
			/>
		);
	}
}

In this example, we are accepting the value provided by the user and updating the value prop of the <input> component. This pattern makes it easy to implement interfaces that respond to or validate user interactions. For example:

handleChange = (event) => {
	this.setState({ value: event.target.value.substr(0, 140) });
};

This would accept user input and truncate the value to the first 140 characters.

A Controlled component does not maintain its own internal state; the component renders purely based on props.

from Controlled Components in the React documentation.

  • If a component needs the ability to also manage its own state (that is to be an "uncontrolled" component) in particular situations the parent should still be able to take over and make it controlled simply by passing in a value for the prop. For instance, an onModalClose callback could change isModalOpen to false when it is ready to close the modal.
  • For more detail and examples of this pattern, visit DIMOC: Do It Myself or Callback.

React component can differ from DOM hierarchy

React component hierarchy doesn't always mean HTML tag hierarchy. Sometimes children become the wrapping component.

Group form elements in the same component

Unless only style changes are needed, variants of form elements types such as checkboxes, radios, and inputs should be grouped in the same component. The underlying structure of a radio or checkbox do not change. All input type=checkbox nodes should be in the Checkbox component as a variant. This should be done, so that implementations of the same form elements that have different visual design can more easily be debugged. Bugs in one visual design of a form element are often found in another visual design.

Use loose coupling and weak connascence

The goal should be that a contributor can understand one piece of code without understanding another and be able to easily make updates in the future. You want weak connascence between components or components and the application (such as events) and not strong connascence. This makes it easier to update one component when modifying another in the future. How easy it will be to change in the future depends on which of the nine types of connascence is being used. For instance, Connascence of Name can be simply updated with Find/Replace. PropTypes and type systems help with Connascence of Type. Connascence of Position with parameters is bad because it relies on the correct order of parameters. Objects with named keys should be used to avoid Connascence of Position.

Use a single return

Please do not short-circuit functions with multiple returns.

Define defaults in one location

Default props or any default variable value should be defined in one location. Many objects are merged in this library and this simplifies the logic and ensures defaults are not overriding non-defaults.

Use functions instead of loops

const getKittenNames = (cats) => cats.filter(isKitten).map(getName) is a great example of how to get a list of kitten names from a cats collection without a for, while, or until loop while only modifying variables within the functional scope.

No mixins

Avoid implied mixins. Instead, import and use shared code and external libraries as libraries, or use higher-order components in order to more easily trace the code execution.

Use one stateful component and many stateless sub-components

It is preferable to only have one stateful top-level class per component in this library. For these top-level components, it’s preferable to use class. All sub-components should be stateless and manipulated with props if possible.

  • A Tree should have state. A TreeNode should not.

  • A DataTable should have state, a TableColumn should not.

  • Frequently used items such as badges, pills, buttons or icons should probably not have state.

  • Know how smart/stateful React components work together with pure/dumb stateless function components.

No DOM node queries

A ref callback is React's link to a DOM node. It is triggered on render and allows access to the DOM node asynchronously. In most cases within a component, you only need a ref for setting focus, but refs make testing easier. If you find yourself using querySelectorAll() to query parts of this library within your application tests, please stop and submit a contribution that surfaces the DOM node you are needing to test. If you control the contents or children yourself, please use a ref bound to your own JSX DOM node to test. For an example, review the renderDialog method of Popover and its body ref. Once surfaced, a DOM ref becomes part of the public API and will be treated as such.

Limit external production dependencies.

Do not add external dependencies to production dependencies list unless absolutely necessary. Always consider the "total cost of ownership" for all dependencies.

Avoid inline styles and non-SLDS classes.

We are blessed to have a team of great CSS developers working on our design system. Use their CSS or contribute code back to them. Some rare or temporary implementations will be approved.

Only extend from React.Component

Use class/extend, but only extend from React.Component and never another class. This prevents class hierarchies and tight coupling being created beyond the basic React.Component. This completely avoids the gorilla-banana problem (“what you wanted was a banana, what you got was a gorilla holding the banana, and the entire jungle” - Joe Armstrong).

Use classnames for conditional CSS classes

This library makes extensive use of the classnames library for feeding conditional CSS classes into className attributes and allows a variety of types such as string, object, and arrays. Although longer, static classname strings are preferred more than dynamic classnames (dynamic object keys) due to searchability when updating markup. See Classnames section for more details.

Use design tokens for inline styles

Inline styles should be kept to a minimum. The best option is to file a bug either in the internal bug system or at the SLDS repository. This library contains a copy of design tokens available on the SLDS site. See here for more details.

500+ line files should be avoided

These files should be broken into sub-components or utility libraries.

Render style preference: 1) ?:, 2) &&, 3) Enum, 4) Sub-component

Once your data is in a correct structure, your rendering should just respond to changes in your data. Here is a list of ways to render:

  1. Inline ternary operator
    • Preferred more than a simple if-else statement
    • It is more concise than if-else and can be used within JSX since it’s an expression
  2. Logical && operator
    • Alternative to ternary. Use when one side of the ternary operation would return null
    • Be careful that you don’t run into bugs when using multiple conditions (truthy/falsey values, especially array length of zero)
  3. Inline Enum objects
    • Great to map different states
    • Great to map nested conditions ({prop1: { }}[prop1][prop2])
  4. Higher Order Components or Sub-components
    • Create another stateless component and use it to shield away complex conditional rendering
    • Components can focus on their main purpose
    • This is an abstraction and can only return one node (in React 15)
  5. Switch case
    • Verbose (break!)
    • Can only be JSX-inlined with self-invoking function
    • Avoid it, enums are preferred
  6. If-else
    • Is the most basic conditional rendering
    • Beginner friendly
    • Cannot be inlined in JSX (needs variables)
  7. Multi-level/nested conditional renderings
    • Avoid them for the sake of readability
    • Split up components into stateless components with their own simple conditional rendering
    • Use HOCs instead
  8. External templating components
    • Avoid them and be comfortable with JSX and JavaScript

Sub-render versus ternary example

Keep variables inside the render function.

// bad
renderSmilingStatement () {
  return <div>{this.props.name}{(this.state.isSmiling) ? <span> is smiling</span> : ""}</div>;
},

render () {
  return <div>{this.props.name}{this.renderSmilingStatement()}</div>;
}
// good
render () {
  return (
    <div>
      {this.props.name}
      {this.state.isSmiling
        ? <span> is smiling</span>
        : null
      }
    </div>
  );
}

Use handle prefix on internal callbacks

Name the handler methods after their triggering event. Handler names should:

  • begin with handle
  • end with the name of the event they handle (eg, Click, Change)
  • be present-tense
// bad
punchABadger () { /*...*/ },

render () {
  return <div onClick={this.punchABadger} />;
}
// good
handleClick () { /*...*/ },

render () {
  return <div onClick={this.handleClick} />;
}

If you need to disambiguate handlers, add additional information between handle and the event name. For example, you can distinguish between onChange handlers: handleNameChange and handleAgeChange. When you do this, ask yourself if you should be creating a new component.

Use entire class name string when rendering conditional class names

Use classNames to manage conditional classes. This allows you to search the source code for the entire class name in order to update it. Dynamic classnames are difficult to locate.

// best
render () {
  return (
    <div className={classnames('MyComponent', {
      'MyComponent--active': this.props.active,
      'MyComponent--link': this.props.variant === 'link',
   })} />
}

No variable mutation

React tries to optimize and prevent re-rendering the DOM when possible. Many times this is not what you want. Avoid solitary use of push, pop, shift, unshift, sort, reverse, splice and delete when mutating arrays. If you ever have to ask yourself, why isn't my component rendering with new props, this is likely the reason. Use the spread operator on objects and arrays--or Array.concat() on arrays instead of directly modifying these variables that are accessed by reference. You may consider exploring some new ES6 types such as Set which are collections that help store unique values of any type.

No spread operator on DOM nodes

Be careful with rest operators when passively applying unnamed and unknown props to JSX nodes. This concept allows flexibility to the consuming developer, but is difficult to track for maintainers. If rest operators should be used, be sure to deconstruct each one that is actually needed by the JSX nodes, so that the rest operator only handles "unknown props" passed in from the outside developer. In short, don't utilize any properties in the ...props object within the component. After using const { active, className, ...rest } = props; do not go back to using this.prop.* anywhere in the render function.

No props in initial state

Please review props in getInitialState is an anti-pattern.

Write tests

Test all props

This allows breaking changes to be detected. If a breaking change doesn't cause at least one test to fail, then add a test.

  • All props should be tested. It is OK to test multiple props in the same test for optimization as long as they are isolated and do not affect each other (for instance id, classname, and style).
  • All event callbacks should be tested along with any data object keys outside of the synthetic event to confirm the data. The data object, if present, is typically the second parameter of an event callback.
  • All mouse and keyboard interactions should be tested.

Components should have 90%+ test coverage

Coverage can be determined by reviewing the coverage summary at the end of npm test. High test coverage does not imply correct logic, but low coverage implies low test quality/quantity.

  • Test should run in headless browsers (npm test) and within a "real" browser (npm start -> http://localhost:8001/)
  • Components should be capable to be rendered without a DOM. Test for the existence of document and window before using them.
  • For more specifics about testing please review the testing walkthough.

Components should be accessible

  • Non-accessible component contributions are permitted but discouraged. These are labeled "prototypes" and do not follow an approved accessible user-experience pattern. Please create an additional issue to follow up with the contribution.

  • ARIA-1.1 Authoring Practices guide

  • ARIA 1.1 - Recommendation Candidate for the new ARIA Spec.

  • ARIA in HTML - Reference to answer the question "Should I put ARIA on this?".

  • HTML 5.1 - Please notice the places where it informs of ARIA role for each element.

  • WCAG - SLDS and this library should be AA compliant.

Components should be keyboard accessible

  • Follow the accessibility guidelines for keyboard events on the SLDS website.

Use DOM ref to control focus if needed

  • One of the key aspects of accessibility with React components is managing a DOM node's focus and blur. This should be implemented with callback references to DOM nodes and should not use ReactDOM.findDOMNode(). Use the current DOM node ref prop to create a function that passes the DOM node to a callback that is provided by the parent which will control the focus once the DOM node has been rendered.

  • If a component has a focusable element, such as a button or an input, write a callback function that will pass the ref back to its parent. buttonRef or inputRef are possible prop names.

Writing documentation site examples

  • Documentation site code is located in a private repository.
  • The NPM module for this library is used for component documentation. Therefore, changes to documentation require a new version to be published.
  • Documentation site examples use CodeMirror to eval() site examples from the NPM module. import and export statements are ignored by CodeMirror. Exports from components/index.js are the only variables available to code examples. Do not import any other variables or the site examples will not work.

Converting SLDS to Design System React

  • variant should be used for significant structure and markup or UX pattern changes that cannot exist at the same time. This may include examples, modifiers, but are usually labeled variants in SLDS. In order to clear, never make the presence of an event callback imply a markup change, other than the event attribute specified. Example: Do not make the addition of onClick turn a span into an a tag.
  • theme should be used for a single className change that cannot exist at the same time as another className. These are typically SLDS states or themes, but could be modifiers. Examples: warning, error, offline, success.
  • Modifiers and states that can exist at the same time and should be props by themselves, so that any combination of them is possible.
  • isOpen on dialogs and menus should be able to be controlled by their parent component, but also work with internal state if it is value is undefined
  • SLDS uses styling to hide hidden elements. Please do not render these elements. Examples: menus, dialogs, tab and accordion content panels.
  • In order to promote best practices, if components are used in a wrong or suboptimal way, the component should error. For instance, if id is a required key in option items, then the component should error out and not fall back to an array index. Custom checkProps warnings are the best way to provide a clear error to consuming developers.
  • propType comments are used in the property tables on the documentation site. Please write in markdown paragraphs.
  • ESLint may find errors in SLDS markup. Feel free to ask questions to the SLDS team or core maintainers of this library, but most likely the markup is intentional and well-tested. You may need to disable the error with eslint-disable-line or eslint-disable-next-line. Consider ESlint lint there to catch the rule, but not the well thought-out exception.
  • All filenames should be "kabob case," this-is-the-file. Spaces and camel-case should be converted to hyphens.

Babel Preset folder

/preset folder contains a Babel 6 preset that makes Design System React compatible with Salesforce’s supported browsers. This is a temporary location until a repository is created.

This preset enables a module bundler, such as Webpack, to transpile Design System React. Using this will make it easier to upgrade in the future without having to manually reconfigure your Babel settings to be compatible with new language features Design System React may use.

Benefits of open source software

  • More efficient and effective development
    • Faster Time-to-Market
    • Reduced development costs
  • Overcoming organizational unit boundaries
    • Cost and risk sharing among organizational units
    • Collaboration across organizational unit boundaries
    • Program-wide information exchange
  • More successful reuse
    • Use of competences missing at component providers
    • Independence between re-users and providers
    • Relief of component providers
  • Better software product
    • Increased code quality
    • More innovative development
  • More flexible utilization of developers
    • Simplified developer deployment
    • Collaboration of detached developers
  • Enhanced knowledge management
    • Community-based learning
    • Openness and availability of knowledge
  • Higher employee motivation
    • Shareable work * Opportunity to lead engineering community