GithubHelp home page GithubHelp logo

react-robits's Introduction

React Robits

A library of sharable React components, by the Frontend Team at Robots & Pencils in an effort to challenge ourselves to think reusable/themeable across client projects, so we can bootstrap development and build off each other.
Broken up into two main concepts:
  • Core: atomic level components in which a standardized setup can support a majority of the possible use cases
  • Periphery: components that are either harder to standarize or have stronger opinions baked in. These are things that may have external dependencies (plugins), or might require different layout structures, making it hard to mandate any one setup cross client or cross use case. So there may end up with multiple variations over time (e.g. - one Upload component built on Dropzone, one on Uppy). For these reasons, these components don't "ship" with the deployed package but are present in the Storybook and accessible directly for manual benefit

Areas of Focus

Examples of "Core" components:

  • Form components
  • Buttons
  • Generic Modals
  • Status indicators (progress bars, loaders)
  • UI Elements (badges, tags, pills)
  • Generic Cards
  • Incremental content (dropdowns, popovers, tooltips)

Examples of "Periphery" components:

  • Sliders/Carousels
  • Item Tiles
  • Video?
  • Maps?
  • Data Tables?
  • Masonry?
Component Aspirations

Think reusable. Components should be built with as much abstraction as possible, leaning on optional component properties to govern the rendered output.

Think cross-client/cross-use-case. Try to support as many permutations of the component as possible, which means thinking outside the box in which you're building it. How might others want to leverage this component?

Think customizable. Every component should have an "unstyled" stylesheet that normalizes it and allows for full control. But even within your own theme stylesheet, it's helpful to put major aesthetic tokens as top level sass variables, so that if/when people eject-to-tweak, it quickens their ability to toggle things.

Directory Structure

├── src
│   ├── core                    # the library of core files that will be importable into a project
│       ├── components          # core shared components
│       ├── constants           # core shared constants
│       ├── utils               # core shared utility functions
│       ├── styles              # core shared stylesheets
│           ├── tokens          # style tokens that are shared across themes (sass variables and mixins)
│           ├── themes          # the various themes that can be leveraged
│               ├── unstyled    # the unstyled theme provides (virtually) no CSS, to make it easier to customize
│   ├── periphery               # components outside the core standardized set
│   ├── stories                 # Storybook story files
│       ├── pages               # Supporting files for stories

Contributing

We'll lean on Github Issues and PR's for tracking and managing problems and enhancements, but the higher level branching/merging/publish strategy is still TBD. Reach out to David Fagan if you want to get involved.

In order to properly maintain the library, there are a set of conventions that MUST be upheld. Read the Tech Doc to learn more

Available Scripts

  • npm run storybook: runs the Storybook for easy preview, play, and investigation of components
  • npm run build-storybook: builds a distributable version of Storybook for publishing
  • npm run lint: runs prettier-standard linting
  • npm run format: runs the prettier formatting

Using Robits in Your Project

To pull the library into your project, run the following command line in the root of your project directory:

npm i --save @robotsandpencils/react-robits

Note: this package will need reinstalled to grab updates. To do so, it's recommended to set up a shortcut script in your project's package.json for ease-of-use:

  "install-robits": "npm i --save @robotsandpencils/react-robits"

Webpack Config

There are a few key pieces to include in your project's webpack config.

  1. Point a Sass Resources Loader configuration to the files contained within the package's ./src/core/styles/tokens directory and ./src/core/styles/themes/[themeName]/tokens.scss file. Order matters here, take care to be intentional with the ordering of the pointers in the array
{
    loader: 'sass-resources-loader',
    options: {
        resources: [
          ...project tokens...
          `${path.resolve(
            __dirname,
            'node_modules/@robotsandpencils/react-robits/src/core/styles/tokens'
          )}/**/*.scss`,
          path.resolve(
            __dirname,
            'node_modules/@robotsandpencils/react-robits/src/core/styles/themes/talentPortal/tokens.scss'
          )
          ...additional project overrides as needed...
        ] // the ordering here is important, just like normal SCSS
    }
}

Note: project level mixins, if they have the exact same name, will override design system level mixins. This is both something to be careful about and a lever you can pull to create project level customizations

  1. You will also then need to make sure your project level webpack properly tranpiles the components being pulled in. Many external libraries come pre-transpiled, but for this, the approach is to defer to project level babel configurations.

So to make sure babel runs against the components being imported from React Robits, you'll need to augment or add loader configurations to your webpack like either of the following:

{
  test: /\.(js|jsx)$/,
  include: `${path.resolve(__dirname, 'node_modules/@robotsandpencils/react-robits')}`,
  loader: 'babel-loader'
}

or

{
  test: /\.(js|jsx)$/,
  exclude: /node_modules\/(?!@robotsandpencils/react-robits)/,
  use: 'babel-loader'
}

Theme Config

Each component then accepts either a themeName string that designates which stylesheet to use, or a themeObj that is already precompiled per CSS Modules.

You can then either specify those props for each instance:

<Button themeName='unstyled'>

Or set up an environment variable in your project to use as the default. This allows you to not have to specify a themeName or themeObj property for each component. The library is set up to digest the following variable name:

export REACT_APP_ROBITS_THEME=unstyled

Note: you can use a combination of the 2, to set up a default and override it at the instance level

Ejecting Robits

Ejecting Robits is lever designed to either a) give you full control over the code for customizations, and/or b) decouple from the library to elimintate the dependency. This could be done at the very beginning of the project, as an initial bootstrap, or at the final stage of a project, after having been wired in for the entirety of development, to avoid giving the magic trick away to a client.

The net result is that the files from this library will be copied over to your project, effectively transferring ownership, and erase any notion of the react-robits as a dependent package.

To do this...

  1. First, you need to manually bypass the package schema bug logged here

  2. Second, run the following script from the root of your project, and follow the prompts. It will cycle through a set of Node scripts to break the ball-and-chain:

node ./node_modules/@robotsandpencils/react-robits/ejectionScripts/eject

For more information on what's happening under the hood with those scripts, see the Tech Doc

Dependency Collisions

The ejection might fail due to an unmanageable semver collision of dependencies between Robits and your project. Because we don't want to break anything within your current project, but at the same time might require a certain dependency version for the Robit in question to work, we therefore don't attempt to automate the decision on who wins. Also, at the moment, there is not a great way for us to interrupt and prompt you for a resolution in real time - nor would a split time decision be advisable.

In light of this, what is recommended is to try each of the conflicting versions offline, within your project and Robits to align on a version that works for both. Once a version is identified, you will need to manually update the appropriate package.json file (either within your project of the react-robits project within node_modules) and rerun the export script.

Hopefully, once NPM supports the new overrides spec (equivalent of yarn's resolutions) there will be a more graceful way to address this.

Note: if a version upgrade works within Robits, please consider opening a PR for it.

After Ejection

After successfully ejecting, you may need to manually massage the integration:

  • If a filename collision was detected, the ejection process will add a _fromRobits suffix to the file copied in. This should be refactored away
  • Depending on the existing file structure of the parent project, and the destination into which you ejected, you may need to relocate some files
  • If using sass-resources-loader, you may have to update the referenced webpack pointer to include the new inbound Robits tokens (if not already aligned), especially if using robits prior to ejecting.
  • If you already had existing styles set up, you may still need to groom the inbound CSS from Robits to dedupe rules, side step collisions, and consolidate files

Storybook Deployment

This is currently deployed to Heroku on a free tier. To deploy from your terminal, you'll need the Heroku CLI installed and logged in to your Heroku account.

Add Heroku git remote if you haven't already:

$ heroku git:remote --app react-robits
$ git remote -v # List available remotes

First, from the root of your project folder, run npm run build-storybook to compile the distributable package from the branch you wish to deploy.

Then, run one of the following commands...

If you are deploying the master branch, run:

$ git push heroku master

Deploy changes from a branch besides master, such as testbranch:

$ git push heroku testbranch:master

Launch Heroku app in browser:

$ heroku open --app react-robits

Or visit https://react-robits.herokuapp.com

Media

Check out the Blog Post for a detailed article of the thought process and journey to this repo

react-robits's People

Contributors

depiction avatar dfagan2 avatar mattmalinao avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-robits's Issues

Ejection errors on package.json validation

Due to nodejs/help#2303, when you run the ejection script, you will see an error regarding invalid package.json syntax.

I've opened an issue with the tool that's running that validation to see if there is something that can be done to work around it: userfrosting/merge-package-dependencies#15

In the meantime, if you manually go into node_modules/@robotsandpencils/react-robits/package.json and change:

  "bundleDependencies": false,

to

  "bundleDependencies": [],

...and then re-run the ejection process, it will allow you to advance

[feature] ESM exports

Problem

Right now Robits have requirements that lock a project into a set structure:

  1. It doesn't support CSS-in-JS
  2. Requires Webpack
  3. Requires Babel
  4. Requires Github Packages (minor)

Solution

We need to update the project to use a modern distribution system and also potentially distribute through both NPM and Github Packages.

Packaging

We can use Rollup to simplify the bundling process and compile the package into both modern ESM and legacy CJS.

Distribution

We can automate the distribution process with a Github action that will send the package to NPM and Github Packages.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.