@instawork/design-system
v4.9.0
Published
The design system for Instawork's web apps
Downloads
118
Readme
Instawork Design System
The Instawork Design System includes a version of Bootstrap 4.3 customized to match the Instawork UI style guide.
It also includes several reusable UI components implemented as jQuery plugins.
This Design System can be viewed via the demo site or via the Storybook.
yarn install @instawork/design-system
Prerequisites
Package consumer
- jQuery ~3.3.1
- Luxon ^1.26.0 (time-related components only)
Authoring / Development
Development
To run the demo locally:
nvm install
yarn
yarn start
This will start an HTTP server on port 8086. Visit http://localhost:8086/ in your browser to load the demo site.
To run the Storybook locally replace yarn start
with yarn storybook
.
Make changes
To make changes to the design system, first start the dev server:
yarn start
CSS / SCSS
For updating CSS styles, the main files to modify are in the scss
directory:
_custom-variables.scss
: Overrides for Bootstrap's variables. To see the full list of variables, seenode_modules/bootstrap/scss_variables.scss
. If you copy any of these to_custom-variables.scss
and modify them, be sure to remove!default
from your version._custom-styles.scss
: Add SASS rules here to override Bootstrap's behaviors or add new behaviors.design-system.scss
: Add or remove components to the final Bootstrap build here. Avoid creating any implementations directly in this file - it is only to be used for combining style implementations from other files.
jQuery Component Plugins
Instawork's jQuery Component plugins can be found in ./components
.
Testing
design-system
uses the following stack to provide testing functionality:
- Karma - Test runner (loads the code, browsers, etc)
- Mocha - Test framework (define specs and tests with
describe
,it
, etc) - Chai - BDD assertion library (
expect(...)
) - Istanbul - Test coverage reports
Authoring tests
- Create a
.spec.ts
file adjacent to the file you intend to test. For example, tests for code a file namedmy-awesome.component.ts
would go in a file namedmy-awesome.component.spec.ts
- Use Mocha's
describe(...)
to group your tests by method / property name, or logical categorization - When defining a test, the text passed to
it(...)
should form a descriptive sentence. Avoid using redundant words like "should" (e.git('returns a string')
instead ofit('should return a string')
) - Use Chai's
expect
assertion style.expect
automatically included as a global variable for tests. - See @instawork/testing for more information on DOM-based testing
Running tests
- From your terminal, run
yarn test:watch
- this will start the test server, and automatically run all tests. Tests will be re-run with every code change. - To run the test suite once (without watching for changes), run
yarn test
- To debug tests, open
http://localhost:9876/debug.html
and use the browser's Dev Tools - Coverage reports are generated automatically and can be found at
.coverage/html/index.html
Note: By default, tests run in a "headless" instance of Chrome. To use other browsers, navigate to
http://localhost:9876
. To run other browsers automatically, or in "headless" mode, install the
appropriate Karma browser launcher plugin.
Tests involving focus state
When testing code involving focus state, be aware that tests may behave differently when running in an interactive browser compared to a headless browser, particularly if you have DevTools open.
This snippet can be used in a before
block to ensure non-interactive tests correctly receive focus:
$('<input>').appendTo('body').focus().remove();
For interactive test runs, be sure to give the body of the test document focus before refreshing / re-running your tests. Using the DevTools panel takes the focus away from the test document.
Demo pages
When creating or making significant changes to components or style features, please update or add a section
to the corresponding demo page in ./demo
. The demo pages are written in the PugJS
template language.
Webpack's dev server will automatically refresh or update CSS in the demo pages as you make changes.
Storybook
When creating or making significant changes to components or style features, you may also need to update the Storybook. This will require updating the stories
directory and checking the results via yarn storybook
.
Before Submitting a PR
- If updating JavaScript / jQuery-based components, ensure there are unit tests covering your changes
- Ensure all changes are included in the demo artifact files by running
yarn build
- Bump
version
in./package.json
(see Semantic Versioning below) - Update
CHANGELOG.md
with a summary of your changes
Semantic Versioning
Like most packages in the NodeJS / JavaScript ecosystem, this package uses Semantic Versioning as its versioning scheme. A quick overview of what this means is:
- The version consists of three parts - major, minor, patch, separated by dots (e.g.
1.2.3
) - The version component getting incremented is determined by the nature of public facing changes being published
- "Major" versions are incremented for incompatible or breaking changes
- "Minor" versions are incremented for new features or other changes that are backwards compatible with the currently published version
- "Patch" versions are incremented for backwards compatible bug fixes
- Pre-release labels can be suffixed to the version as an extension - this project uses the
-pre.#
label for pre-releases (e.g. 3.0.0-pre.0)
Use the yarn next_semver
script to automatically determine the next version based on the desired increment:
# show the next major, minor, patch, or pre-release version
yarn next_semver major # 3.0.0 -> 4.0.0
yarn next_semver minor # 3.0.0 -> 3.1.0
yarn next_semver patch # 3.0.0 -> 3.0.1
yarn next_semver prerelease # 3.0.0-pre.0 -> 3.0.0-pre.1
# show the version for starting a prerelease
yarn next_semver major --prerelease # 3.0.0 -> 4.0.0-pre.0
# add the --write flag to the above commands to also update package.json
yarn next_semver minor --write
yarn next_semver minor --prerelease --write
yarn next_semver prerelease --write
Publishing
Publishing new versions of @instawork/design-system
is currently done manually from a developer's machine.
Publishing prerequisites
In order to publish packages to the @instawork
organization, you must be logged in using Instawork's shared
npmjs.org account. See "Tools and Shared Accounts" in Confluence for authentication information.
- Run
npm adduser --scope @instawork
(note:npm
, notyarn
) - Enter the username, password, and email from Confluence when prompted
- Verify that you see the following message:
Logged in as
(username)
to scope @instawork on https://registry.npmjs.org/.
If you get an error or see a different registry URL, check for stray configuration settings by running
npm config list
.
Publish the package
Stable releases should only be published from master
after a PR is approved and merged.
Pre-releases can be published at any time from any branch.
To publish the @instawork/design-system
package.
Run
yarn build:design-system
.At the command line, switch to the
dist/design-system
directoryRun
yarn publish --access public
from thedist/design-system
directoryWhen prompted for a version, hit enter - the version should already have been incremented as part of your PR (see Before Submitting a PR above) or for a pre-release
The
postpublish
script should automatically give the release a distribution tag, which ensures that anyone installing the package usingnpm install
oryarn install
without a specific version will only ever get a stable release, and not a pre-release- Pre-releases (from a branch other than master) use the
dev
dist-tag. - Stable releases (from master) use the
latest
dist-tag.
- Pre-releases (from a branch other than master) use the
Verify the distribution tag in the console output of the publish command: Pre-releases:
[3/4] Publishing... $ ../../scripts/dist_tag this line -> +dev: @instawork/[email protected] success Published.
Stable releases:
[3/4] Publishing... $ ../../scripts/dist_tag this line -> +latest: @instawork/[email protected] success Published.
If the
dist_tag
command fails for whatever reason, see Manually adding distribution tags
IMPORTANT: If you are publishing a pre-release, you the release MUST be tagging after publishing! Otherwise, the
registry may incorrectly / implicitly treat your pre-release as the "latest", which is used when resolving
versions for yarn install
/ npm install
requests that do not include a version.
Note: The version must be changed between releases, as it is not possible overwrite a previously published release. You will see the following error if this is attempted:
Couldn't publish package: "https://registry.npmjs.org/@instawork%2fdesign-system: You cannot publish over the previously published versions: (version here)
Another note: After the publish command succeeds, there may be a brief delay before you can install the newly released version. If you see a message like this:
Couldn't find any versions for "@instawork/design-system" that matches "(your recently published version)"
...then grab a drink of water, stand up and stretch for a moment, and then try again.
Manually adding distribution tags
- When publishing from
master
:
npm dist-tag add @instawork/design-system@VERSION latest
Example:
npm dist-tag add @instawork/[email protected] latest
- When publishing a pre-release:
npm dist-tag add @instawork/design-system@VERSION dev
Example:
npm dist-tag add @instawork/[email protected] dev
Note: Use
npm
here and notyarn
-yarn
errors when trying to add tags
Removing previously published releases
NPM allows releases to be removed within 72 hours of publishing. This can be done using the npm unpublish command
:
npm unpublish @instawork/[email protected]
Be sure the correct version is specified, as the command will appear to succeed given a non-existent version.
Testing changes in another application
Before publishing a new release, it is recommended to check the changes in a client application.
Local testing
It is possible to test changes to the package locally without publishing a new version to yarn / npm using
the yarn link
command:
- Run
yarn build:design-system
- In the
dist/design-system
directory, runyarn link
- In the project root of the test client application, run
yarn link @instawork/design-system
This will create a symlink between the client application's node_modules
directory for the
@instawork/design-system
package, and the dist/design-system
directory in the design-system
project.
After making changes, you will need to run yarn build:design-system
again to update the build artifacts, but you should not
need to repeat the yarn link
commands.
Running yarn
(yarn install
) in the client project will restore the real package from the npm repository.
To test the local package again, re-run yarn link @instawork/design-system
.
Pre-releases
A pre-release will allow you to test a release as it will be used in the real world by actually publishing it to the npm registry, allowing it to be installed by anyone on any machine.
To create a pre-release:
- Run the appropriate
yarn next_semver
command with the--write
flag (see Semantic Versioning above for details) - Follow the instructions in Publish the package
Build commands
The commands use a convention such that the shorter commands run all commands that use their name as a prefix. So
for example, yarn build:design-system
will run all commands that start with build:design-system:
.
yarn build
: Builds both the@instawork/design-system
and@instawork/testing
packagesyarn build:design-system
: Builds all bundles and files required to publish@instawork/design-system
yarn build:design-system:lib
: Builds the ES module files that go into the/lib
subdirectoryyarn build:design-system:lib:ts
: Compiles TypeScript source to individual JS files in/lib
, generates type definition files (.d.ts
)yarn build:design-system:lib:scss
: Generates empty stand-in JS files for each SCSS file (see Package structure below for details)yarn build:design-system:lib:templates
: Compiles PUG templates to ES modules (see Package structure below for details)yarn build:design-system:web
: Compiles SCSS to CSS, builds browser-ready JavaScript bundlesyarn build:design-system:cp
: Copies other required files likepackage.json
,README
, andCHANGELOG
yarn build:testing
: Compiles and collects all files required to publish the@instawork/testing
packageyarn build:testing:ts
: Compiles TypeScript source to individual JS files, generates type definition files (.d.ts
)yarn build:testing:cp
: Copies other required files likepackage.json
,README
, andCHANGELOG
yarn build:storybook
: Builds the storybook.
Package structure
@instawork/design-system
./components.js
- browser-ready bundle for jQuery plugin components./components.css
- Styles supporting jQuery plugin components./design-system.css
- Themed Bootstrap styles./marketing.css
- Specialized styles for the marketing website./select2.css
- Styles supporting our customizedselect2
implementation./fonts
- font file assets./lib
- Contains ES module and type declaration files for jQuery plugin components
ES Modules in ./lib
These files are provided to better support using the jQuery plugin components and their respective classes as dependencies in a downstream application. They are intended to be referenced by a bundler like Webpack, or even directly by the TypeScript compiler (as a dependency). They are published as ES modules to support Tree Shaking.
Since several of the components use a PUG templates and/or define their own styles via SCSS, additional processing is done to ensure that these aspects do not break downstream apps or force them to implement their own SCSS or PUG template processing:
PUG Templates
PUG templates are compiled to ES modules that provide the compiled HTML content as their default export. Since they
are saved to the same path as the .pug
source file, except with .js
extension (e.g. time-input.component.pug.js
),
they will automatically be picked up by the downstream application's bundler or compiler, regardless of it configuring
support for PUG. Since this is done without modifying either the source TypeScript file or its compiled ES module output,
it does not negatively the accuracy of the source maps.
SCSS styles
A similar approach is used for SCSS styles - though instead of compiling the SCSS, an empty JavaScript file is created,
effectively resulting in a noop when the downstream app loads the file. This requires that the downstream app uses a
separate method to load the bundled components.css
file at runtime.