@aivenio/aquarium
v2.8.1
Published
Aiven Aquarium design system
Downloads
10,715
Maintainers
Keywords
Readme
Aiven Aquarium Design System
Implementation of Aiven Aquarium design system, released as an npm package. Quick tour:
- We use Figma to design the system. The design tokens are controlled in a Figma page (see example page), which are synced automatically to tokens.json
- Component implementation uses design tokens to define their visual look. This will make updating the visuals easier in the future by changing the tokens.
- Aquarium design system implementation is exposed as React components via npm
- Tailwind is used for styling
Installation
To install Aquarium to your app:
npm install --save @aivenio/aquarium
Make sure to add the correct fonts in your app. Inter for Aiven theme.
Import the CSS to your app
- Aiven theme with
import '@aivenio/aquarium/dist/styles.css'
- If you used
THEME=X npm run build
for building, useimport '@aivenio/aquarium/dist/styles_X.css'
- Aiven theme with
Add React context component to the root of your React app
import MyApp from './MyApp'; + import { Context } from '@aivenio/aquarium'; const Root = () => ( return ( + <Context> <MyApp /> + </Context> ) )
If you encounter problems resolving EcmaScript modules disable "fullySpecified" mode using this Webpack config:
webpack: { configure: { module: { rules: [ { test: /\.m?js/, resolve: { fullySpecified: false, }, }, ] }, } }, };
Development
Use npm 7! With older npm versions, install peerDependencies manually. If you encounter "Cannot find module..." errors, try rm -rf node_modules && npm i
. This seems to be a bug introduced in npm@7.
Prerequisites
This project requires certain environment variables to be set before commands such as npm run build
will work. Most can be copy/pasted with the help of your teammates, but you will need to generate a NPM token yourself in order.
Create an npm account here if you don't already have one.
Generate a token for your account. You can read about how to do so here. For the purposes of building the project, read-only access will suffice.
Copy the sample environment file:
cp .env.sample .env
Add the necessary data into the newly-created
.env
file.Source the
.env
file for the environment variables to be set:source .env
Note that any time a new shell instance is created (for example, when you restart your computer), you need to run
source .env
again, or the variables won't be set. Consider using a solution such asautoenv
to automatically apply the.env
file.
Optional DX improvements
- For VSCode
- Install Tailwind CSS IntelliSense extension. See https://github.com/tailwindlabs/tailwindcss-intellisense#recommended-vs-code-settings
- Install ESLint extension and optionally enable auto-format on save. See "Step 4 — Formatting on Save" from https://www.digitalocean.com/community/tutorials/linting-and-formatting-with-eslint-in-vs-code
Common commands
npm ci
to install dependenciesnpm run build
to build the production build of the librarynpm start
to start Storybook
Developing in the context of your app
To develop Aquarium components in the context of an application, it is easier to run a locally modified version of Aquarium in your application. There are two ways to do this: npm link, or copying the module into your app. This allows you to make changes to components and instantly see the change in the context of the app.
npm link
❌ TODO: This doesn't currently work out of the box. Revise the instructions
- In design-system directory, run
npm link
- In design-system directory, run
npm link <path to your app>/node_modules/react
to avoid running into conflict of having two react instances. This will otherwise break the rules of hooks and crash the app. More info on the issue here. If the command fails with errors about peer dependencies, re-run the command, adding--force
at the end. - In the app directory, run
npm link @aivenio/aquarium
- Now
<path to your app>/node_modules/@aivenio/aquarium
is a symlink to your local Aquarium directory. - In design-system directory, run
npm run watch
- Done! Now you should be able to develop DS locally, and changes are reflected to the application which depends on
@aivenio/aquarium
- When you want to stop using the npm link, and go back to the regular imported version, in your app directory, run
npm unlink --no-save @aivenio/aquarium
, thennpm i
to reinstall the dependency.
Copy module
⚠️ If you've installed new dependencies on the DS side, this doesn't work. See instructions for npm pack instead.
npm link can be tricky to get working. A simpler approach is to build a production build of the DS and copy it into your application's node-modules
directory. Remember to restart the build process of your app once DS has been built and copied over. Here's a snippet to do all that:
cd <path to ds> \
&& npm run build \
&& cd <path to your app> \
&& rm -rf ./node_modules/@aivenio/aquarium/dist \
&& cp -R <path to ds>/dist ./node_modules/@aivenio/aquarium # && <the dev/build command of your app>
npm pack
Copy module is a hack which doesn't work when the dependencies have changed on the DS side since the last install in your app side.
You can use pack-and-install.sh
utility script to create local release package and install it to your local application.
APP_PATH=<path to your app> ./pack-and-install.sh && <run dev/build command for your app>
Or if you want, you can also run npm pack
command manually and then install that to your app.
cd <path to ds> \
&& npm run build \
&& jq --arg file_name $(npm pack 2>&1 | tail -1) '.dependencies["@aivenio/aquarium"] = "file:<path to ds>/\($file_name)"' <path to your app>/package.json > <path to your app>/package-json-new.tmp \
&& cd <path to your app> \
&& mv package-json-new.tmp package.json \
&& npm install # && <the dev/build command of your app>
Make sure you replace all <path to ds>
and <path to your app>
strings with the exact absolute paths.
Running tests
Remember that source .env
is needed before NPM commands.
npm test
to run all tests oncenpm test -- Button
to run only tests matchingButton
npm run test:watch
to run tests in watch modenpm run test:coverage
to run all tests and see the coverage
Note! It's good idea to run tests in watch mode when developing. If for example snapshot tests fail due to some code changes it's easy to update those with the jest commandline tool. If you want to just update the snapshots that can be done with jest --updateSnapshot
. More information here
Other useful commands
THEME=<brand> npm start
to start local storybook with a themeTHEME=<brand> npm run build
to build DS module with a themenpm run figma -- sync -i .figma-file.json
to generate./tokens.json
but using previously fetched local file instead of fetching the huge Figma file from API.npm run figma -- sync --debug
to enable more verbose outputnpm run figma -- sync --foundation-page-name 'my foundations'
to override options.jq '.document.children[] | select(.id == "8916:120229")' .cache/figma-file.json
to slice Foundations page from whole Figma file JSON.
There is more documentation for the Figma sync tool.
Build and release process
Storybook
To build storybook locally
Run npm run build:storybook
.
Storybook deploy
Storybook is deployed to Cloudflare Pages everytime new code is merged to main.
Aquarium package
How to build Aquarium package locally
- run
npm run build
- see
dist
for the built code
How to create a release
Run
npm run release -- --bump <bump>
(all the dashes are needed) where bump is one ofmajor
,minor
orpatch
.This command will automatically checkout a release branch, commit the version bump, and open your browser to submit a PR.
Review the PR created, and merge it to main. GH actions will handle the rest.
Any API breaking change should be a major version bump and should be mentioned in release notes!
Breaking changes
Breaking change examples:
- Rename a prop in Button component
- Rename Card component to Box
- Remove a prop
- Remove a component
These are not breaking changes:
- Add a new prop for Button
- Add a new component
- Changing storybook
- Changing tests
Background
A lot of research was done into existing design systems, and if we could reuse parts of them. The conclusion was that we take mostly inspiration of the good ideas, and maybe use individual components by copy pasting code to our system.
Evaluation of existing React libraries
Some of the projects are huge, the link most commonly points directly to the part of the code base which defines the components. For tests, I checked that tests for a few components look OK, no coverage or deeper analysis done.
Next things to consider:
- Is treeshaking possible when using just parts of the library? Size of the dist is also important factor, but after treeshaking the footprint should be quite similar across libraries
- Maturity and activeness (commits, recent activity, contributor distribution, closed vs open issues, PR merging activity)
- Are they migrating to another tech ? JS -> TS, Sass -> styled-components, etc
- Owners, is it community driven or company driven? Project with 13 stars can be super mature if it's been developed internally in a company for 20k commits for N years
- Accessibility
- Customizability, do you need to fork or can you customise while getting upstream updates?
| Link | Commits* | JS/TS | Styling | License | Tests | Other | | --------------------------------------------------------------------------------------------------------------- | --------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------ | | Ant Design | 18.6k | TS | Less. example | MIT | ☑️ | | Aragon UI | 0.8k | JS | styled-components | MIT | Not much | | Baseweb by Uber | 2.3k | JS (Flow) | style-tron | MIT | ☑️ | | Basis | 0.3k | JS | emotion | MIT | ☑️ | | Blueprint | 1.8k | TS | Sass | Apache 2.0 | ☑️ | | Carbon | 6.8k | JS | CSS classnames linking to Sass | Apache 2.0 | ☑️ | ☑️ Storybook | | Fluent UI by Microsoft | 8.6k | TS | CSS in JS, seems to be a custom one | MIT | ☑️ | | Grommet | 5.2k | JS | styled-components | Apache 2.0 | ☑️ | ☑️ Storybook | | Material UI | 11.9k | JS | CLSX, CSS in JS. Example | MIT | ☑️ | | MongoDB design | 0.4k | JS | CSS | package.json says MIT, no LICENSE file | No | | Pivotal UI | 4.0k | JS | Sass | MIT | ☑️ | | Polaris by Shopify | 6.1k | TS | Sass | Modified MIT, see more | ☑️ | | Primer by GitHub | 4.5k | JS | styled-components | MIT | ☑️ | | React Bootstrap | 3.8k | JS | Bootstrap CSS classes | MIT (also Bootstrap is MIT) | ☑️ | | Reactstrap | 0.8k | JS | Bootstrap CSS classes | MIT | ☑️ | | RMWC | 1.9k | JS | CSS classnames using material-components-web by Google (source is Sass) | MIT (also material-components-web is MIT) | ☑️ | | Salesforce Design System | 9.5k | JS | Sass | Code BSD 3-Clause, see: https://github.com/salesforce-ux/design-system#licenses | ☑️ | | Thumbprint | 0.7k | TS | Sass | Apache 2.0 | ☑️ | | VTEX Styleguide | 4.3k | JS | Custom Tachyons classes + CSS. Example implementation and CSS | Unlicensed | Not much | | Zendesk Garden | 0.8k | TS | styled-components | Apache 2.0 | ☑️ | ☑️ Storybook |
- Most of these repos are monorepos managed with Lerna. Commit count is just to give rough estimate of how much the code has been iterated.
For further investigation, you can find plenty of components in GitHub: https://github.com/search?l=&p=99&q=created%3A%3E2015-01-01+extension%3Ajs+extension%3Ajsx+extension%3Ats+extension%3Atsx+size%3A%3E100+filename%3AButton.js+filename%3AButton.ts+filename%3AButton.jsx+filename%3AButton.tsx+filename%3Abutton.js+filename%3Abutton.ts+filename%3Abutton.jsx+filename%3Abutton.tsx&ref=advsearch&type=Code
You can find more design systems here: https://github.com/alexpate/awesome-design-systems. Not all of them have open source code.