Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

react-polymorph

input-output-hk2.8kApache-2.01.0.4

React components with highly customizable logic, markup and styles.

react, components, composable, customizable, extendable, flexible, hackable, render prop, skins, themes

readme

React Polymorph

React Polymorph is a UI framework for React, that separates logic, markup and theming of components. It's inspired by react-toolbox (but more flexible), powered by CSS Modules and harmoniously integrates with your webpack workflow, although you can use any other module bundler.

Why?

  • Existing React UI frameworks are too hard to customize.
  • Overriding css styles is not enough for complex components.
  • You need multiple variations of a component with shared logic.
  • You need multiple, completely unique themes for your components.

How:

Separate monolithic React components into:

  1. Component (logic) - Only handle UI logic, do not render markup.
  2. Skin (markup) - Only render the markup, delegate to component.
  3. Theme (styling) - Only concerned about styling your skin.

Installation & Usage

React Polymorph can be installed as an npm package:

$ npm install --save react-polymorph

Usage in Webpack Projects

npm install --save style-loader css-loader sass-loader
module: {
  loaders: [
    {
      test: /\.scss$/,
      loaders: [
        'style?sourceMap',
        'css?sourceMap&modules&localIdentName=[name]_[local]&importLoaders=1',
        'sass?sourceMap'
      ]
    },
    // your other loaders …
  ]
},

Now you can import and use components like this in your app:

import React from "react";
import { Input } from "react-polymorph/lib/components";
import { InputSkin } from "react-polymorph/lib/skins/simple/InputSkin";
import { InputTheme } from "react-polymorph/lib/themes/simple/InputTheme";

const MyInput = () => (
  <Input // <- Logic
    skin={InputSkin} // <- Markup
    theme={InputTheme} // <- Styling
    label="My Input" // <- Component prop
  />
);

Each component needs a skin to render markup and will receive its styles (css/scss) via a theme.

Theme Provider

Of course this would be a lot of code just to render a simple input. That's why you should always use a theme provider to inject skins and themes into all components below the ThemeProvider automatically (components can be arbitrarily deep nested).

import React from "react";
import { Input } from "react-polymorph/lib/components";
import { SimpleSkins } from "react-polymorph/lib/skins/simple";
import { SimpleTheme } from "react-polymorph/lib/themes/simple";

// Notice that we don't have to pass any skin or theme to the inputs:
const MyForm = () => (
  <div>
    <Input label="First Name" />
    <Input label="Last Name" />
  </div>
);

const SimpleFormApp = () => (
  <ThemeProvider skins={SimpleSkins} theme={SimpleTheme}>
    <MyForm />
  </ThemeProvider>
);

Release Managament

  • Starting with 1.0.0 all future releases will follow semver semantics:

    • patch (eg: 1.0.x) for API compatible bug fixes
    • minor (eg.: 1.x.0) for API compatible new features
    • major (eg: 2.0.0) for API breaking changes
  • For early integration of upcoming release changes we use the following conventions:

    • [current version]-next.x to tag changes for upcoming releases (as we cannot know the necessary semver for the final release including all the changes). x in this case is simply a number that is increased and can be thought of like "slots" for temporary releases

    • All temporary releases should be published with the next npm dist tag via: npm publish --tag next so that they are not automatically tagged with the default latest npm tag.

  • The master branch only includes commits of final releases

  • release/x.x.x branches are created as soon as we cut a release and know the correct semver - they are always targeting the master branch + should be well documented. They can include many release candidates which should be tagged like [next releaes]-rc.X where you increment X per release candidate until we are confident that the release is ready to be published under its normal version.

How to publish a temporary release

Temporary releases are useful for testing specific changes in your project PRs without making public releases that might confuse others and are not following semver.

  1. Create a dedicated branch for your bug/feature/chore
  2. Run npm view react-polymorph dist-tags.next to see the latest release version the next npm dist-tag is currently pointing to (this will look something like this: 1.0.0-next.1)
  3. Increase the next.X number by one (e.g: npm version 1.0.0-next.2) to create a new git tag via.
  4. Publish the release candidate with npm publish --tag next (to assign the next dist-tag instead of latest)
  5. Reference your release candidate version in your project PR

How to publish a stable release

Stable releases are the next public version change of react-polymorph combining all previous temporary releases into a semver based release:

  1. Create a new release/x.x.x branch based on develop (following semver based on changelog)
  2. Update the version in package.json to the planned release version (do not tag it)
  3. Update the CHANGELOG.md to assign the new release version to the last changes and upcoming changes
  4. Setup a PR targetting master for the relase branch on Github and document the changes since last release
  5. Publish a release candidate to npm (e.g: 1.0.1-rc.1)
  6. Integrate and test the release candidate
  7. Iterate on the release via release candidates until its ready to be merged
  8. Merge the release PR into master on Github and then master back into develop

Components and Skins

React-polymorph comes with simple themes & skins out of the box, but anything is customizable.

Imagine you need a standard text Input component for text and a NumericInput for floating point numbers. The only difference is the logic of the component, in both cases it is "just" an input field showing some text:


Input

Represents a single-line input field.

Standard Input

Example Usage:
import React from "react";
import { Input } from "react-polymorph/lib/components";

// Standard input component:
const MyStandardInput = () => (
  <Input
    label="Input with max. 5 Characters"
    maxLength={5}
  />
);
Input Props:
type InputProps = {
  autoFocus: boolean,
  className?: ?string,
  disabled?: boolean,
  error: string | Element<any>,
  label?: string | Element<any>,
  maxLength?: number,
  minLength?: number,
  onBlur?: Function,
  onChange?: Function,
  onFocus?: Function,
  onKeyPress?: Function,
  placeholder?: string,
  readOnly: boolean,
  setError?: Function,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object,
  value: string
};

Numeric Input

Component specialized in guiding the user to enter correct floating point numbers.

Standard Input

Example Usage:
import React from "react";
import { NumericInput } from "react-polymorph/lib/components";
import { InputSkin } from "react-polymorph/lib/skins/simple";

const MyNumericInput = () => (
  <NumericInput
    label="Amount"
    placeholder="0.000000"
    decimalPlaces={6}
    bigNumberFormat={{ decimalSeparator: '.', groupSeparator: ',' }}
  />
);
Expected Behavior:

Since there is no web standard on how to build numeric input components, here is the specification we came up with that serves our purposes in the best way:

  • Only numeric digits [0-9] and decimal separators (configurable via bigNumberFormat prop) can be entered.
  • When invalid characters are pasted as input, nothing happens
  • When a second decimal separators is entered it replaces the existing one and updates the fraction part accordingly
  • Group separators cannot be deleted but the cursor should jump over them when DEL or BACKSPACE keys are used
  • It's possible to replace the whole number or parts of it (even the decimal separator) by inserting another number.
Props:

The NumericInput is based on the Input component and extends it's functionality:

type NumericInputProps = {
  // Input props:
  autoFocus?: boolean,
  className?: string,
  context: ThemeContextProp,
  disabled?: boolean,
  error?: string,
  label?: string | Element<any>,
  onBlur?: Function,
  onChange?: Function,
  onFocus?: Function,
  placeholder?: string,
  readOnly?: boolean,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeId: string,
  themeOverrides: Object,
  // Numeric input specific props:
  allowSigns?: boolean,
  bigNumberFormat?: BigNumber.Format,
  decimalPlaces?: number,
  roundingMode?: BigNumber.RoundingMode,
  value: ?BigNumber.Instance,
};
value

Must be an instance of BigNumber onChange also returns an instance of BigNumber after any user changes.

allowSigns

Is true by default, if false the user cannot enter negative numbers.

decimalPlaces

No restriction by default (any number of decimal places allowed). Can be set to fix the decimal places to a specific amount.

bigNumberFormat

You can configure the number format by passing in any valid bignumber.js FORMAT option

roundingMode

You can configure the rounding mode by passing in any valid bignumber.js ROUNDING_MODE option


Textarea

Simple component that represents an input which can receive multiple lines of text.

Standard Input

Example Usage:
import React from "react";
import { TextArea } from "react-polymorph/lib/components";

const MyTextArea = () => (
  <TextArea
    label="Textarea with fixed amount of rows to start with"
    placeholder="Your description here"
    rows={5}
  />
);
TextArea Props:
type TextAreaProps = {
  autoFocus: boolean,
  autoResize: boolean,
  className?: string,
  context: ThemeContextProp,
  disabled?: boolean,
  label?: string | Element<any>,
  error?: string | Node,
  maxLength?: number,
  minLength?: number,
  onBlur?: Function,
  onChange?: Function,
  onFocus?: Function,
  placeholder?: string,
  rows?: number,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeId: string,
  themeOverrides: Object,
  value: string
};

Button

Represents a clickable area.

Standard Input

Example Usage:
import React from "react";
import { Button } from "react-polymorph/lib/components";

const MyButton = () => (
  <Button label="Button label" />
);
Button Props:
type ButtonProps = {
  className?: string,
  disabled?: boolean,
  label?: string | Element<any>,
  loading: boolean,
  onClick?: Function,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object
};

Select

The select component is like standard select but with additional logic for adding custom option renderer and opening directions (upward / downward).

Standard Input

Example Usage:
import React from "react";
import { Select } from "react-polymorph/lib/components";

const COUNTRIES_WITH_FLAGS = [
  { value: 'EN-gb', label: 'England', flag: flagEngland },
  { value: 'ES-es', label: 'Spain', flag: flagSpain },
  { value: 'TH-th', label: 'Thailand', flag: flagThailand },
  { value: 'EN-en', label: 'USA', flag: flagUSA }
];

const MySelect = () => (
  <Select
    label="Countries"
    options={COUNTRIES_WITH_FLAGS}
    optionRenderer={option => {
      return (
        <div className={styles.customOptionStyle}>
          <img src={option.flag} />
          <span>{option.label}</span>
        </div>
      );
    }}
  />
);
Select Props:
type SelectProps = {
  allowBlank: boolean,
  autoFocus: boolean,
  className?: string,
  error?: string | Element<any>,
  label?: string | Element<any>,
  isOpeningUpward: boolean,
  onBlur?: Function,
  onChange?: Function,
  onFocus?: Function,
  optionRenderer?: Function,
  options: Array<any>,
  placeholder?: string,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object,
  value: string
};

Checkbox

Represents a component which can toggle between checked and unchecked state.

Standard Input

Example Usage:
import React from "react";
import { Checkbox } from "react-polymorph/lib/components";

const MyCheckbox = () => (
  <Checkbox label="My checkbox" />
);
Checkbox Props:
type CheckboxProps = {
  checked: boolean,
  className?: string,
  context: ThemeContextProp,
  disabled?: boolean,
  label?: string | Element<any>,
  labelLeft?: string | Element<any>,
  labelRight?: string | Element<any>,
  onChange?: Function,
  onBlur?: Function,
  onFocus?: Function,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeId: string,
  themeOverrides: Object
};

Switch

Like checkbox but uses a different skin part.

Standard Input

Example Usage:
import React from "react";
import { Checkbox } from "react-polymorph/lib/components";

const MySwitch = () => (
  <Checkbox label="My switch" />
);
Switch Props -> see Checkbox (above)

Toggler

Like checkbox but uses a different skin part.

Standard Input

Example Usage:
import React from "react";
import { Checkbox } from "react-polymorph/lib/components";

const MyToggler = () => (
  <Checkbox
    labelLeft="Included"
    labelRight="Excluded"
  />
);
Toggler Props -> see Checkbox (above)

The modal is component which wraps its children as standard dialog. As is shown in example, modal can have multiple other polymorph components:

Standard Input

Example Usage:
import React from "react";
import { Modal, Button } from "react-polymorph/lib/components";

const MyModal = props => (
  <Modal triggerCloseOnOverlayClick={false}>
    <h1 className={styles.modalTitle}>
      Are you sure you want to delete this thing?
    </h1>
    <div className={styles.buttonsContainer}>
      <Button
        label="Cancel"
        onClick={closeModalCallback}
      />
      <Button
        label="Delete"
        onClick={closeModalCallback}
      />
    </div>
  </Modal>
);
type ModalProps = {
  contentLabel: string | Element<any>,
  isOpen: boolean,
  onClose?: Function,
  skin?: ComponentType<any>,
  triggerCloseOnOverlayClick: boolean,
  theme: ?Object,
  themeOverrides: Object
};

Autocomplete

The autocomplete input is specialized to help users to select between multiple suggested words depending on entered letters:

Standard Input

Example Usage:
import React from "react";
import { Autocomplete } from "react-polymorph/lib/components";

const MyAutocomplete = props => (
  <Autocomplete
    label="Recovery phrase"
    placeholder="Enter recovery phrase"
    suggestedWords={SUGGESTED_WORDS}
    placeholder="Enter mnemonic..."
    maxSelections={12}
    maxVisibleSuggestions={5}
    invalidCharsRegex={/[^a-zA-Z]/g}
  />
);
Autocomplete Props:
type AutocompleteProps = {
  className?: string,
  error: ?string,
  invalidCharsRegex: RegExp,
  isOpeningUpward: boolean,
  label?: string | Element<any>,
  maxSelections?: number,
  maxVisibleOptions: number,
  multipleSameSelections: boolean,
  onChange?: Function,
  options: Array<any>,
  preselectedOptions?: Array<any>,
  placeholder?: string,
  renderSelections?: Function,
  renderOptions?: Function,
  skin?: ComponentType<any>,
  sortAlphabetically: boolean,
  theme: ?Object,
  themeOverrides: Object
};

Bubble

The bubble component will open up an absolutely positioned speech bubble. This is position in respect to it's closest relatively positioned parent.

Standard Input

Example Usage:
import React from "react";
import { Bubble } from "react-polymorph/lib/components";

const MyBubble = props => (
  <div className={{ position: "relative" }}>
    <Bubble>
      plain bubble
    </Bubble>
  </div>
);
Bubble Props:
type BubbleProps = {
  className?: string,
  isHidden: boolean,
  isFloating: boolean,
  isOpeningUpward: boolean,
  isTransparent: boolean,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object,
  targetRef?: Ref<*>, // ref to the target DOM element used for positioning the bubble
};

Tooltip

The tooltip opens a bubble relative to it's children, containing text or html to display.

Standard Input

Example Usage:
import React from "react";
import { Tooltip } from "react-polymorph/lib/components";

const MyTooltip = props => (
  <Tooltip
    tip="Description of the child element"
  >
    hover over me
  </Tooltip>
);
Tooltip Props:
type TooltipProps = {
  className?: string,
  isAligningRight?: boolean,
  isBounded?: boolean,
  isOpeningUpward: boolean,
  isTransparent: boolean,
  arrowRelativeToTip: boolean,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object,
  tip?: string | Element<any>
};

Radio

The radio is as simple as possible and does not have much logic:

Standard Input

Example Usage:
import React from "react";
import { Radio } from "react-polymorph/lib/components";
import { RadioSkin } from "react-polymorph/lib/skins/simple";
import { RadioTheme } from "react-polymorph/lib/themes/simple";

const MyRadio = props => (
  <Radio label="My radio" skin={SimpleRadioSkin} theme={RadioTheme} />
);
Radio Props:
type RadioProps = {
  disabled?: boolean,
  label?: string | Element<any>,
  onBlur?: Function,
  onChange?: Function,
  onFocus?: Function,
  selected: boolean,
  skin?: ComponentType<any>,
  theme: ?Object,
  themeOverrides: Object
};

Customizing Component Skins

Theme API

Each component has a theme API. This is a plain object which exposes the shape of a component's theme. Each property on the theme API object is a class name assigned to an element within the component's skin and a class definition within the component's theme. Below is the Button's theme API.

{
  root: '',
  disabled: ''
}

Every component accepts an optional themeOverrides property intended to provide a CSS Module import object which is used by the component to assign a user's local classnames to its DOM nodes. If the component has already been passed a theme prop, the css/scss properties passed via themeOverrides will be merged with the injected theme object. This automatic composition saves the user from manually piecing together custom styles with those of the injected theme that the user may wish to retain. If you want to customize a component's theme, the themeOverrides object must contain the appropriate classname mapping to its documented theme API. In this way, you can add or override classnames on the nodes of a specific component.

Overriding styles in a theme

For example, if you want to override the background-color of Button's injected theme with green:

import React from "react";
import { Button } from "react-polymorph/lib/components";
import { ButtonSkin } from "react-polymorph/lib/skins/simple";
import { ButtonTheme } from "react-polymorph/lib/themes/simple";
import themeOverrides from "./GreenButton.css";

const GreenButton = props => (
  <Button
    {...props}
    skin={ButtonSkin}
    theme={ButtonTheme}
    themeOverrides={themeOverrides}
  />
);

export default GreenButton;
themeOverrides
.root {
  background-color: green;
}
ButtonTheme
.root {
  background-color: blue;
  color: white;
  border-radius: 5px;
}
Result
.root {
  background-color: green;
  color: white;
  border-radius: 5px;
}

The user's custom background color overrides Simple theme's blue background.

Compose

Similarly, you can compose your own custom styles with an injected theme

themeOverrides
.root {
  text-transform: uppercase;
}

will be composed with

ButtonTheme
.root {
  background-color: blue;
  color: white;
  border-radius: 5px;
}
Result
.root {
  text-transform: uppercase;
  background-color: blue;
  color: white;
  border-radius: 5px;
}

In this case we are composing custom styles with an instance of Button where the Simple ButtonTheme was already injected. If a theme isn't passed to a component, a theme object implementing that component's full theme API is necessary. When implementing a component's full theme, take into account that every classname is there for a reason. You can either provide a component's theme as a prop or pass it through context as described in the next section.

ThemeProvider HOC

ThemeProvider allows you to pass a theme to multiple instances of a component without explicitly passing them a theme prop. Wrap your component tree with ThemeProvider at the desired level in your component hierarchy. You can maintain different themes and themeOverrides for specific portions of your app's tree.

Example Usage:

import React, { Component } from "react";

// components
import {
  ThemeProvider,
  Modal,
  FormField,
  Input,
  Button
} from "react-polymorph/lib/components";

// skins
import {
  ModalSkin,
  FormFieldSkin,
  InputSkin,
  ButtonSkin
} from "react-polymorph/lib/skins/simple";

// themes
import {
  ModalTheme,
  FormFieldTheme,
  InputTheme,
  ButtonTheme
} from "react-polymorph/lib/themes/simple";

class App extends Component {
  state = {
    isOpen: true,
    value: ""
  };

  setValue = value => this.setState({ value });

  render() {
    // Custom Theme
    const SimpleTheme = {
      modal: { ...ModalTheme },
      formfield: { ...FormFieldTheme },
      input: { ...InputTheme },
      button: { ...ButtonTheme }
    };
    // Custom Skins
    const SimpleSkins = {
      modal: ModalSkin,
      formfield: FormFieldSkin,
      input: InputSkin,
      button: ButtonSkin,
    };

    return (
      <ThemeProvider skins={SimpleSkins} theme={SimpleTheme}>
        <Modal
          isOpen={this.state.isOpen}
          triggerCloseOnOverlayClick={false}
        >
          <div>
            <FormField
              label="FormField in Modal"
              render={props => (
                <Input
                  {...props}
                  value={this.state.value}
                  onChange={this.setValue}
                />
              )}
            />
          </div>

          <div>
            <Button
              onClick={this.props.handleClick}
              className="primary"
              label="Submit"
            />
          </div>
        </Modal>
      </ThemeProvider>
    );
  }
}
export default App;

Customizing all instances of a Component using ThemeProvider

Create a CSS Module theme file for the component you wish to customize, for example for Input & FormField:

input.css
.input {
  width: 25%;
}

.input:focus {
  border-color: green;
  width: 50%;
}

.input:hover {
  border-color: green;
}
formfield.css
.label {
  color: green;
  font-family: "Lato", sans-serif;
}

Create a theme file that imports each component's custom styles as CSS-Modules object(s). Apply the styles according to the root theme API structure. The root theme API is simply an object whose keys are named after each component in the react-polymorph library. For example, the styles you assign to the input key will be applied to all instances of the Input component nested within ThemeProvider. The same goes for the formfield key and all nested instances of the FormField component.

customInputs.js
import MyCustomInputTheme from "./css/input.css";
import MyCustomFormFieldTheme from "./css/formfield.css";

export default {
  input: MyCustomInputTheme,
  formfield: MyCustomFormFieldTheme
};

Import your custom theme to pass ThemeProvider's themeOverrides property. This will apply your custom css/scss to all of its nested react-polymorph components. In this example, all 3 instances of the Input and FormField components will have the user's custom css definitions composed with Simple InputTheme and FormFieldTheme.

import React from "react";

// components
import {
  ThemeProvider,
  FormField,
  Input,
  NumericInput
} from "react-polymorph/lib/components";

// skins
import { SimpleSkins } from "react-polymorph/lib/skins/simple";

// themes
import { FormFieldTheme, InputTheme } from "react-polymorph/lib/themes/simple";

// the user's custom Input and FormField styles
import CustomInputsTheme from "./styles/customInputs.js";

const CustomInputs = props => {
  const SimpleTheme = {
    input: { ...InputTheme },
    formfield: { ...FormFieldTheme }
  };

  return (
    <ThemeProvider skins={SimpleSkins} themeOverrides={CustomInputsTheme} theme={SimpleTheme}>
      <FormField
        label="Recipient's First Name"
        render={props => (
          <Input {...props} placeholder="Avery" />
        )}
      />

      <FormField
        label="Recipient's Last Name"
        render={props => (
          <Input {...props} placeholder="McKenna" />
        )}
      />

      <FormField
        label="Amount to Send"
        render={props => (
          <NumericInput {...props} placeholder="10.000" />
        )}
      />
    </ThemeProvider>
  );
};

export default CustomInputs;

You may also pass the entire SimpleTheme object to ThemeProvider and maintain the same functionality without having to import themes specific to the components you're using.

import React from "react";

// components
import { ThemeProvider } from "react-polymorph/lib/components";

// skins
import { SimpleSkins } from "react-polymorph/lib/skins/simple";

// themes
import { SimpleTheme } from "react-polymorph/lib/themes/simple";

const App = () => (
  <ThemeProvider skins={SimpleSkins} theme={SimpleTheme}>
    <div>...</div>
  </ThemeProvider>
);

export default App;

changelog

Changelog

The history of all changes to react-polymorph.

1.0.4

Fixes

  • Fixed overlapping PopOver triangle container (PR 210)
  • Fixed double triggering of checkbox onChange handler (PR 206)

Chores

  • Bumped the version of create-react-context (PR 208)
  • Replace node-sass with sass package (PR 205)

1.0.3

  • Add disabled state to Select component (PR 196)

1.0.2

  • Support data-* attributes on input field component (PR 2841)

1.0.1

  • Replaced external link icons and styling (PR 191)
  • Fixed replacing fixed decimal numbers with another fixed decimal (PR 189)

1.0.0

Breaking Changes :boom:

  • Input now shows errors on hover and focus by default which can be configured via two new props:
isShowingErrorOnFocus: boolean;
isShowingErrorOnHover: boolean;

Features :sparkles:

  • Input now accepts a new prop themeVariables which can be used to override css variables (PR 173)
  • Implemented the search functionality to the Options component (PR 165)
  • Improved PIN entry component UX (PR 166)
  • Enabled pasting of multiple words into Autocomplete (PR 163)

Fixes :muscle:

  • Fixed replacing fixed decimal numbers with another fixed decimal (PR 189)
  • Fixed Select search issues(PR 179)
  • Fixed Select Search styles and minor code issues (PR 175)
  • Fixed a wrong variable name for the select search highlight color (PR 170)
  • Fixed an issue related to Numeric Input when entering numbers after having selected the decimal separator (PR 167)
  • Fixed issues related to controlled/uncontrolled Tippy state (PR 160)
  • Fixed NumericInput to support DEBUG mode (PR 159)

    0.9.7

Features

  • Improve NumericInput component to support big numbers (PR 152)
  • Improve autocomplete required selections ux (PR 154)
  • Improve FormField UX by using pop overs to show errors (PR 151

    0.9.6

Features

  • Added PopOver component (aka Smart Tooltips) (PR 150

    0.9.5

Fixes

  • Replaced deprecated postinstall-build package with npm prepare lifecycle PR 146

    0.9.4

Features

Features

  • Adds new PasswordInput component (PR 134)

Fixes

  • Fixed Option component, optionHeight property, override from parent components PR 135
  • Fixed global listener mouseIsOverRoot event handler PR 135

    0.9.2

Features

  • Adds new ScrollBar component and integrates it into existing react-polymorph components. Refactors all snapshot tests to use enzyme for full DOM node rendering. PR 129

    0.9.1

Features

Fixes

  • Fixes error in GlobalListeners and Dropdown when Daedalus window is resized PR 125

    0.9.0

Features

  • New Dropdown component PR 122

Breaking Changes

  • NumericInput component was completely rewritten to be more flexible and straight forward. PR 114 and allow configurable number formats PR 123

  • Adds a new prop arrowRelativeToTip to tooltips which allows to center the arrow relative to the size of the tooltip and not the parent element. PR 113

    • (BREAKING) none is no longer a valid option for $bubble-border-color and it should instead be transparent
    • (BREAKING) Any library that directly calls the arrow mixin directly has to be updated to take into account the change in parameter to use width and height instead of a single size. If you use Bubble or any component that instead of a direct use of the mixin, no change is needed.

Chores

  • Updates contributors in package.json PR 117

    0.8.7

Features

  • Adds selected option render prop on Select component to override default input value format. Adds Stepper component, theme, skin, and stories. PR 115

    0.8.6

Fixes

  • Adds 20px extra space between the top of Options pop-up bubble and the top of the window. This prevents the Options bubble from slightly running underneath the application menu bar at the top of the window. PR 110

    0.8.5

Fixes

  • Resets scroll position of Options when Autocomplete or Select transition from opened to closed. PR 109

Chores

  • Automatic storybook builds & previews have been setup with netlify. PR 107

    0.8.4

Fixes

  • Fixes bug where Options does not close properly when scroll event occurs. PR 108

    0.8.3

Fixes

  • Fixed breaking change regression in 0.8.2 where IDENTIFIERS was moved from theme to components

    0.8.2

Chores

  • Adds CSS variable in SimpleButton's theme allowing configuration of button text color when disabled. PR 103

Fixes

  • Fixes minor bug with caret positioning in NumericInput component that happened when entering two decimal points PR 105

  • Upgrades react, react-dom, and react-test-renderer to version 16.8.6 and addresses Github warning on repo. PR 103

  • Sets max height of Options drop down based on window height and offset of Options' target ref. Changes flow type Ref to ElementRef in components and skins. PR 102

  • Updates vulnerable packages found by Github's automatic security audit. Fixes Checkbox component's render method to use the themeId prop for accessing a skin in context when one isn't provided via props instead of hardcoding the fallback to use CheckboxSkin PR 101

    0.8.1

Features

  • Provide simple skins by default via ThemeProvider but allow customization PR 96

    0.8.0

Chores

  • Adds --rp prefixed css variables to all component themes allowing comprehensive custom configuration. Renames existing scss variables using a uniform convention that matches the names of the new --rp css variables. PR 92

  • Fixes the implementation of withTheme helper to represent the wrapped components instead of a generic React component. This fix ensures the entire library is type checked correctly and resolves all resulting flow errors. PR 93

Fixes

  • Fixes NumericInput's value processing logic to only return integer numbers before the decimal when maxAfterDot is 0. Adds a behavior test and a story for this functionality. PR 91

  • Fixes a bug where ThemeProvider failed to compose its theme prop with the user's custom styles passed as the themeOverrides prop. Adds a check to all components using context for when themeOverrides or theme changes in context. If there is a change, the component's theme and themeOverrides will be composed again and local state will update. Adds a themeOverrides story to ThemeProvider's stories to show intended functionality of theme composition and dynamic theme switching. PR 90

Features

  • Adds displayName static property to all components PR 89

  • Adds InfiniteScroll component, InfiniteScrollSkin to simple skins, and SimpleInfiniteScroll to SimpleTheme. PR 88

  • Adds Grid and GridItem components to layout components. PR 87

  • Adds Gutter component to layout components and SimpleGutter to SimpleTheme. PR 86

  • Adds Flex and FlexItem components to layout components. PR 85

  • Adds Header component, Header skin, and adds SimpleHeader to SimpleTheme. PR 84

  • Adds Base component to layout components PR 83

  • Adds ProgressBar component to library with stories. PR 78

  • Adds LoadingSpinner component, LoadingSpinnerSkin, and SimpleLoadingSpinner theme. Adds reusable loading-spinner mixin to themes. Adds 5 LoadingSpinner stories. PR 75

  • Adds ButtonSpinnerSkin to simple skins to show LoadingSpinner within the Button component when page data is loading. Adds new button story to exemplify this skin and functionality. PR 76

    0.7.2

Fixes

  • Fixed two minor issues in the NumericInput component where the carrot didn't move right to the decimal spaces when the entered value contained 4 digits and a comma, and also fixed an issue where integers were displayed in the wrong order after a value is selected and deleted. PR 94

    0.7.1

Fixes

  • Fixed wrong border color for errored & focused textareas PR 73

  • De-nests the class definitions in SimpleInput.scss. Ensures the border color of both Input and NumericInput remain the correct color when in an errored state. Improves composability when theme overrides is used with both Input components. Updates stories to reflect fixes. PR 71

  • Adds a new HOC GlobalListeners which is used in Select and Autocomplete that attaches document and window listeners for closing the window. Fixes bubble and arrow positioning when Bubble is rendered via Select and Autocomplete. NumericInput does not execute the user's onChange prop unless the value changes internally after being processed. Removes index.js in components and skins directories to reduce size of library. PR 69

  • Wraps TextAreaSkin's render method in FormField so labels and errors are rendered the same as in Input and NumericInput. Fixes Input, NumericInput, and TextArea components so they pass a prop called inputRef or textareaRef to FormField in their skins. This properly makes use of React v16.3.1+'s ref API instead of using the onRef callback. Adds autoFocus, onBlur, and onFocus props to NumericInput and TextArea. PR 67

  • Fixed wrong positioning of select options when opening upward PR 68

  • Fixed vertical positioning of select arrow when opened PR 68

Chores

  • Replaces all default exports in the theme directory with constants and exports them. Additionally, all import statements previously importing a default export are replaced with an appropriate named import. Defines all properties of the SimpleTheme and ROOT_THEME_API objects using IDENTIFIERS and arranges their properties in ABC order for better readability. 77

  • Adds support for React v15 - v16.4.1. Upgrades devDependencies to latest versions of react, jest, and enzyme related libraries. Adds Autocomplete simulation test for deleting a selected option via backspace key. PR 65

  • Refactor npm scripts to colon style PR 66

Features

  • Bubble takes an optional targetRef for positioning now PR 68

    0.7.0

Fixes

  • Fixed broken right-to-left positiong of selected option checkmark PR 62

Chores

  • Adds keydown and click simulation tests for Autocomplete using jest and enzyme. Removes helper skins from test directory and refactors the way in which components are wrapped in a ThemeContext Consumer HOC before they're exported in order to handle a test environment. PR 63

  • Adds polyfills for React's new context API and ref API released in v16.3.0. Drops support for React versions less than v16.PR 61

  • Add snapshot test coverage from using jest and enzyme. Add event simulation tests for NumericInput. Adds story for ThemeProvider. PR 60

Features

  • Add checkmark for selected option PR 54

    0.6.5

Major breaking changes due to large refactoring of component architecture: PR 47

Features

  • Add Autocomplete clear feature PR 49

Chores

  • Refactors library to use render prop architecture PR 58
    • Removes source/skins/simple/raw directory and the raw pattern from the library
    • Removes skin parts
    • Manages refs by passing them from parent to child
    • Removes inheritance architecture
    • Adds ESLint config from Daedalus and integrates flow library & static type declarations. Refactors
    • components to declare refs using createRef from React v16.3^. Removes propTypes from all components and removes prop-types lib from dependencies.

Features

  • React 16 Context API with various improvements PR 53

    • Implements React's new context API available in react & react*dom v16.3.0^
    • Implements new ref forwarding API for use with Autocomplete's clear feature.
    • New context API allows for setting the default theme of every component to SimpleTheme (see withTheme.js)
    • Adds renderSelections & renderOptions (render prop architecture) to Autocomplete for delegating custom rendering to the user while still giving the user access to the the component's logic and styles. (think "writing a custom skin on the fly", see Autocomplete stories).
    • Adds render prop to Options component
  • Add checkmark for selected option PR 54

  • Add Autocomplete clear feature PR 49

  • Implements a theme API for each component. This is a plain object which exposes the shape of a component's theme. Each property on the theme API object corresponds with a class name assigned to an element within the component's skin and a class definition within the component's theme.

  • Adds ThemeProvider HOC for applying a theme to all its nested react-polymorph children. ThemeProvider exonerates the user from explicitly declaring theme as a prop on every instantiated component. A complete theme, an object containing full theme definitions for every component in the library, may also be passed to ThemeProvider. The complete theme object may be deconstructed to contain only the necessary theme definitions used by the components nested within a particular instance of ThemeProvider, yet deconstruction is not required.

  • Adds themeOverrides as an optional prop on ThemeProvider and on all components within the library. themeOverrides composes the user's custom css/scss with the component's base theme. This automatic composition saves the user from the tedium of manually piecing together custom styles with those of the component's theme that the user wishes to retain, yet themeOverrides is flexible enough to restyle a component's theme in a nontrivial way. themeOverrides may be passed directly to one instance of a component or passed to all instances nested within ThemeProvider via context. This composition of styles relies on css-modules.

  • Adds a composed theme story to most component stories to exemplify the relationship between ThemeProvider and themeOverrides.

  • Adds autofocus prop to all applicable input based components.

  • Adds index file to source/utils, source/themes/API, source/themes/simple, source/skins/simple, and source/components for the use of named and default exports. Makes it easier for the user to import a full theme object for ThemeProvider, or simply one component's theme. Also makes it easier to import multiple skins and components on one line.

    0.6.4

Fixes

  • Add border-radius CSS property to Autocomplete component PR 45

    0.6.3

Fixes

  • Fix Options component window resize event handling, Add border-radius CSS property to Textarea component PR 44

    0.6.2

Fixes

  • Fixes dependencies to be React 16 compatible PR 41
  • Fixes broken options positioning logic that was accidentally removed when bubble was introduced PR 42

    0.6.1

Features

  • Add Radio component PR 34

Fixes

  • Fix broken theming setup for InputSkin, BubbleSkin and SelectSkin PR 36

    0.6.0

Features

  • Add Bubble component PR 31
  • Use Bubble component in Options component PR 31
  • Add Tooltip component PR 32

Fixes

  • Fix bug causing crash when hitting backspace in an Autocomplete component PR 31

    0.5.5

Fixes

  • Allow string or element props for FormField errors PR 25

    0.5.4

Fixes

  • Fix isOpeningUpwards feature on Select and Autocomplete Options component (PR 24)

    0.5.3

Chores

  • Add noResultsMessage property to Options component, Code cleanup and standardization (PR 23)

    0.5.2

Features

  • Extract Options component (PR 22)

    0.5.1

Fixes

  • Fix autocomplete input issues (PR 21)

    0.5.0

Features

  • Update storybook to latest version (PR 20)
  • Also support React 16 (PR 20)

    0.4.1

Fixes

  • Expose raw component skins (PR 19)

    0.4.0

Features

  • Autocomplete input control (PR 18)

    0.3.5

Features

  • Allow React element as label for checkboxes and form fields (PR 17)

    0.3.4

Fixes

  • Updated simple theme styled for SimpleSelect (PR 16)

    0.3.3

  • Toggle dropdown on label clicks (PR 15)

    0.3.2

Fixes

  • Toggle dropdown on label clicks (PR 15)

    0.3.2

Features

  • Add toggler component (PR 14)

    0.3.1

Fixes

  • Updated simple theme styles
  • Prevent CSS-classes inheritance on TextAreaSkin textarea element
  • Fixed caret positioning bug on NumericInput component re-render

Features

  • Add checkbox component
  • Add switch component

    0.2.7

Fixes

  • fixed storybook webpack config
  • fixed caret position logic in numeric input
  • fixed selection stealing bug found in Daedalus

    0.2.6

Fixes

  • Fixed a bug in NumericInput when illegal chars have been entered but the old valid value was still null.

    0.2.5

Fixes

  • Fixed a bug in NumericInput where caret was reset on every re-render of the component.

Improvements

  • Added .npmignore file to remove source and dev files and folders from npm repo.

    0.2.4

Fixes

  • Fixed broken build step that was missing the new utils folder.

    0.2.3

Fixes

  • Fixed bug with NumericInput that passed unknown DOM properties to the underlying <input> component.

Improvements

  • Removed the need to manage metaProps that should be omitted when passing on props to standard DOM elements. You can now use pickDOMProps which filters the props down to the one that are allowed by React.

  • Updated readme with better example for the idea of react-polymorph.

    0.2.2

Chores

  • add new package-lock.json file generated by npm 5

    0.2.1

Chores

  • Reuse the normal InputSkin and SimpleInput theme for the NumericInput component.

    0.2.0

Features

  • Allow to render disabled options in select component
  • New NumericInput component for floating point numbers.

    0.1.0

Initial release with basic features.