rentalutions / elements

Design kit for Avail rental management software
https://design.avail.co
10 stars 3 forks source link
design-system lerna monorepo react styled-components styled-system ui-components ui-kit

Avail Design Kit

Avail Design Kit

A set of components built to be composable, extendable, and usable

Documentation

Setup

  1. Clone the repo with gh repo clone rentalutions/elements.
  2. Install dependencies with yarn install.
  3. Start a storybook container that builds all the packages and watches for changes with:
    • yarn build:storybook
    • yarn dev:storybook

Project Structure

This project is structured as a monorepo managed by lerna and yarn workspaces.

.storybook
docs
└── pages
|   └── packages
|   |   └── [package-documentation].mdx
└── next.config.js
packages
└── [package]
│   └── dist
│   └── src
│   └── __tests__
│   └── [package].stories.js
│   └── package.json
│   └── CHANGELOG.md
@testing.js

Getting Started

The best way to contribute to this library is to look at open issues or file an issue yourself if one doesn't already exist.

To suggest a component be added to the library open an issue and spec out the component with it's API. No component will be added without proper documentation. You can tag @pkrawc or @wade00 with reviewing the issue and weighing in when necessary.

To finish, create a pull request that solves the issue. At least one commit in the PR should be resolves #[ISSUE_NUMER], this will auto-close the issue when the PR is merged into master.

Development

This system uses storybook to maintain documentation. Use yarn dev to run a development enviroment. While creating or updating a component, check your work using the story files in the same package. Updating stories will build and publish a new dev build to vercel on every commit thats part of a PR.

Conventional Commits

This system uses conventional commits to tag and track updates. This method automatically creates and updates change logs for each package based on the name of a commit. The basis of this is that the commit message should contain the following structure.

<type>([optional scope]): <description>

[optional body]

[optional footers]

Commit Types

build, ci, chore, docs, feat, fix, perf, refactor, revert, style, test

Releases

Current release process, it's kind of involved, but github actions does most of the heavy lifting and it creates a nice release cadence. These scripts assume you're already on the release branch. If you're on a feature branch, create a pull request to merge your code. create a release in confluence and attach the fix version to stories worked on as part of elements repo

run the below commands to release a new version

git checkout release
git pull
git checkout -b graduate-YYYY.MM.DD.ELEMENTS.PROD

# run a build and make sure everything compiles, and run tests to make sure all are passing
yarn build && yarn test
# Create new versions of the packages worked on, git tag, and create a CHANGELOG for those package.
yarn graduate

create a PR to release, this will kick off a test github action merging the release will publish the package upgrade

Beta releases

Sometimes you'll want to release a beta version of a package before upgrading to production level. This process is slightly more manual but made pretty easy with lerna and yarn workspaces.

# Update the packages to a prerelease
yarn workspace [package-name] version [--preminor | --premajor | --prepatch]

# Publish the package on the npm registry
yarn workspace [package-name] publish --tag [alpha | beta]

Adding Packages

Use the command yarn create-package [package-name] [package description].

yarn create-package footer "A footer package for the avail design system"

Code Preferences

Separate component logic from layout when possible.

// Good
function useComponent({ ref, ...props }) {
  const innerRef = useRef()
  const [bg, setBg] = useState("#000")
  useEffect(() => {
    if (window.innerWidth > 900) setBg("#FFF")
  }, [])
  return {
    ...props,
    bg,
    ref: mergeRefs(innerRef, ref),
  }
}

function Component(props, ref) {
  const { bg, ...htmlProps } = useComponent({ ...props, ref })
  return <Box {...htmlProps} sx={{ bg }} />
}

// Bad
function Component(props, ref) {
  const innerRef = useRef()
  const [bg, setBg] = useState("#000")
  useEffect(() => {
    if (window.innerWidth > 900) setBg("#FFF")
  }, [])
  return <Box {...props} ref={mergeRefs(innerRef, ref)} sx={{ bg }} />
}

Yes it's more lines for a trivial example like this but in my experience it makes the component so much more refactorable.

Prefer function declarations over assignments for component definition.

// Good
function MyComponent(props) {
  return <div />
}

// Bad
const MyComponent = (props) => <div />

Prefer named exports.

// Good
export function Section() {}
export function SectionItem() {}

// Bad
export default function Section() {}
export function SectionItem() {}

Naming Conventions

Name files in lowercase with hyphen seperation for spaces.

# Good
touch components/file-upload.js

# Bad
touch components/FileUpload.js