Skip to content
This repository was archived by the owner on Apr 28, 2020. It is now read-only.

Restructure styles, improve code and docs #150

Merged
merged 1 commit into from
Jan 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
[![Build Status](https://travis-ci.org/kubevirt/web-ui-components.svg?branch=master)](https://travis-ci.org/kubevirt/web-ui-components)
[![Coverage Status](https://coveralls.io/repos/github/kubevirt/web-ui-components/badge.svg)](https://coveralls.io/github/kubevirt/web-ui-components)
[![npm version](https://img.shields.io/npm/v/kubevirt-web-ui-components.svg?style=flat)](https://npmjs.org/package/kubevirt-web-ui-components)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

# web-ui-components
Set of reusable components identified during [kubevirt/web-ui](https://github.com/kubevirt/web-ui) development.
# KubeVirt UI components

Set of reusable React components identified during [kubevirt/web-ui](https://github.com/kubevirt/web-ui) development.

## Playground

Latest `master` version is deployed at
[kubevirt.io/web-ui-components](https://kubevirt.io/web-ui-components/) ([build info](https://kubevirt.io/web-ui-components/build-info.txt)).

## Documentation

- [Setting up development environment](docs/DevEnvSetup.md)
- [Developer guideline](docs/DevGuide.md)
- [Building & publishing](docs/BuildAndPublish.md)
- [Travis CI](docs/Travis.md)
7 changes: 7 additions & 0 deletions config/eslint.browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,12 @@ module.exports = {
ignoreClassFields: true,
},
],
'import/order': [
'error',
{
'newlines-between': 'always-and-inside-groups',
groups: [['builtin', 'external'], ['internal', 'parent', 'sibling', 'index']],
},
],
},
};
4 changes: 2 additions & 2 deletions config/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ module.exports = {
// files for which to collect coverage information
collectCoverageFrom: [
'src/**/*.js',
'!src/**/fixtures/**/*.js',
'!src/**/index.js',
'!src/**/*.mock.js',
'!src/**/fixtures/**/*.js',
'!src/cosmos/*',
'!src/jest/*',
'!tools/',
'tools/validations/*.js',
],

// coverage output settings
Expand Down
35 changes: 34 additions & 1 deletion config/stylelint.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,39 @@
// https://stylelint.io/user-guide/configuration/

// This project uses the BEM (Block Element Modifier) convention for CSS classes:
// http://getbem.com/naming/
//
// Note that the "kubevirt" prefix is enforced to avoid potential conflicts with
// the consuming application.
//
// For example, a "FancyForm" component could use the following class names:
// - kubevirt-fancy-form
// - kubevirt-fancy-form__submit-button
// - kubevirt-fancy-form__submit-button--disabled

const fragment = '[a-z-]+';
const prefix = 'kubevirt-';

module.exports = {
extends: 'stylelint-config-standard',
plugins: ['stylelint-scss'],
plugins: ['stylelint-scss', 'stylelint-selector-bem-pattern'],
rules: {
'plugin/selector-bem-pattern': {
implicitComponents: 'sass/components/**/*.scss',
componentName: new RegExp(`^${fragment}$`),
componentSelectors: {
// validate CSS selector sequences that occur before combinators,
// for example: ".foo .bar > .baz" => validate ".foo"
initial: componentName => {
const word = `${fragment}(?:--${fragment})*`;
const element = `(?:__${word})?`;
const modifier = `(?:--${word})?`;
return new RegExp(`^\\.${prefix}${componentName}${element}${modifier}$`);
},
// validate CSS selector sequences that occur after combinators,
// for example: ".foo .bar > .baz" => validate ".bar" and ".baz"
combined: () => new RegExp(`^\\.${fragment}(?:\\.${fragment})*$`),
},
},
},
};
7 changes: 7 additions & 0 deletions docs/BuildAndPublish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Building & publishing

To build the project, run `yarn build`. This will regenerate the `dist` directory containing
project's distributable assets.

To publish the project to [npm registry](https://www.npmjs.com) and make it available for use
in consuming applications, run `yarn publish`.
48 changes: 48 additions & 0 deletions docs/DevEnvSetup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Setting up development environment

## Prerequisites

Install the latest [Node.js](https://nodejs.org) Long Term Support (LTS) version.
An easy way to do that is through [Node Version Manager](https://github.com/creationix/nvm),
which allows you to install and switch between multiple Node.js versions:

```sh
nvm install 'lts/*' # install the latest LTS version
nvm alias default 'lts/*' # default version to use for new shells
nvm use default # switch to the default version
node -v # print the current Node.js version
```

Install [Yarn](https://yarnpkg.com) package manager for Node.js (latest stable version).
If you'd like to install Yarn manually, download `yarn-<VERSION>.tar.gz` tarball from their
[releases](https://github.com/yarnpkg/yarn/releases), extract it and add `$YARN_HOME/bin`
directory to your `PATH`.

## Project setup

Install or update project's dependencies with Yarn:

```sh
yarn install
```

### Cosmos

Start [Cosmos](https://github.com/react-cosmos/react-cosmos) server used for testing React
components an in isolated environment which simulates the consuming application:

```sh
yarn cosmos
```

Cosmos will watch the `src` directory for changes and rebuild its playground UI accordingly.

### Jest

Start [Jest](https://jestjs.io) in watch mode for executing tests:

```sh
yarn test:watch
```

Jest will watch all files ending with `.test.js` and rerun the corresponding tests.
122 changes: 122 additions & 0 deletions docs/DevGuide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Developer guideline

## Component file structure

```
src/components/
└── <GroupName>/
├── index.js
├── <Component>.js
├── <AnotherComponent>.js
├── fixtures/
│ ├── <Component>.fixture.js
│ └── <AnotherComponent>.fixture.js
└── tests/
├── <Component>.test.js
└── <AnotherComponent>.test.js
```

Every component group should have an `index.js` file exporting specific components which
are meant to be shipped as part of the project's npm package.

Component sub-groups can be used to represent logical hierarchies, for example:

```
src/components/
└── Dialog/
├── index.js
└── FooDialog/
├── FooComponent.js
├── fixtures/
│ └── FooComponent.fixture.js
└── tests/
└── FooComponent.test.js
```

For every specific component, there should be a corresponding test and a Cosmos fixture.

## Stylesheet file structure

```
sass/
├── components/
│ └── <GroupName>
│ ├── <style-block>.scss
│ └── <another-style-block>.scss
└── patternfly-tweaks/
```

Styles are grouped based on React component groups, e.g. any `Form` component related styles
should be placed under `sass/components/Form` directory. Styles in the `patternfly-tweaks`
directory should be treated as temporary until being backported to the corresponding PF-React
npm package.

This project uses the [BEM (Block Element Modifier)](http://getbem.com/naming/) convention
for CSS classes. Refer to [stylelint configuration](../config/stylelint.config.js) for details
on project-specific BEM format.

For each React component group, there may be multiple logical BEM-style selectors. Taking
`src/components/Form/FormFactory` as an example, this component's render output includes
PF-React's `FormGroup` with CSS class `kubevirt-form-group` added to it. In other words,
different logical parts of the given component may use different CSS classes.

## Cosmos

Use the [Cosmos playground](https://github.com/react-cosmos/react-cosmos) to test and
experiment with React components. Each component is rendered in an `iframe` along with
dependant styling, allowing the component to be tested as a standalone, reusable unit.

Remember to add [fixtures](https://github.com/react-cosmos/react-cosmos#fixtures) to ensure
that components are properly exposed to Cosmos. Keep in mind that Cosmos is effectively the
visual component interface between developers and designers:

- it allows developers to test KubeVirt related UI bits
- it allows designers to review the current implementation
- it shields both groups from having to work with the consuming application

Think of each fixture as a distinct visual test case for the given component, with `props`
(and possibly other contextual information) used to exemplify the tested scenario. This is
similar to testing a regular function from different angles, including known edge cases.

## Jest

Jest is used to run all tests. To detect test failures early, start Jest in watch mode and
keep it open as you develop code.

At the very least, every React component should have an accompanying
[snapshot test](https://jestjs.io/docs/en/snapshot-testing) to guard against regressions
in its render output.

Avoid big `it` blocks. Prefer small, focused test cases which are easy to read and refactor.

## Validations

This project uses a simple validation mechanism driven by `tools/runValidations.js` script.
New validations can be added to `tools/validations` directory as CommonJS modules exporting
a function, for example:

```js
module.exports = () => {
return true; // validation success
};
```

## How to

### Lint, validate and test the project in one go?

```sh
yarn test
```

### Run specific tests?

```sh
yarn jest -t 'TestNameRegexp'
```

### Update snapshots for specific tests?

```sh
yarn jest -t 'TestNameRegexp' -u
```
9 changes: 9 additions & 0 deletions docs/Travis.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Travis CI

This project hooks into the [Travis job lifecycle](https://docs.travis-ci.com/user/job-lifecycle)
through following scripts:

- `before_script`: runs `tools/travis/beforeScript.js`
- `after_success`: runs `tools/travis/afterSuccess.js`

Refer to [Travis configuration](../.travis.yml) for details.
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@
"prevalidate": "yarn lint",
"validate": "node tools/runValidations.js",
"pretest": "yarn validate && shx rm -rf coverage",
"test": "jest --config config/jest.config.js",
"test": "yarn jest",
"test:watch": "yarn test --watch",
"prebuild": "yarn test --ci && shx rm -rf dist",
"build": "yarn build:js && yarn build:sass",
"build:js": "babel src --config-file ./config/babel.config.js --out-dir dist/js --only 'src/**/*.js' --ignore 'src/jest,src/cosmos,**/tests/**,**/fixtures/**'",
"build:sass": "shx cp -r sass dist",
"jest": "jest --config config/jest.config.js",
"cosmos": "cosmos --config config/cosmos.config.js",
"cosmos:export": "shx rm -rf cosmos && NODE_ENV=production cosmos-export --config config/cosmos.config.js",
"coveralls": "shx cat coverage/lcov.info | coveralls"
Expand All @@ -38,7 +39,8 @@
"react-router-dom": "4.x"
},
"dependencies": {
"@patternfly/react-console": "1.10.5",
"@patternfly/react-console": "1.x",
"classnames": "2.x",
"js-yaml": "3.x",
"lodash": "4.x",
"react-dnd": "2.6.x",
Expand Down Expand Up @@ -96,6 +98,7 @@
"stylelint": "9.x",
"stylelint-config-standard": "18.x",
"stylelint-scss": "3.x",
"stylelint-selector-bem-pattern": "2.x",
"webpack": "4.x"
},
"engines": {
Expand Down
37 changes: 22 additions & 15 deletions sass/_components.scss
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
@import './components/HelloWorld';
@import './components/ButtonWithIcon';
@import './components/CreateVmWizard';
@import './components/Dropdown';
@import './components/EditableDraggableTable';
@import './components/FormFactory';
@import './components/NewVmWizard';
@import './components/ResultTab';
@import './components/NetworksTab';
@import './components/StorageTab';
@import './components/VmStatus';
@import './components/VmConsoles';
@import './components/TemplateSource';
@import './components/CreateDiskRow';
@import './components/VmDetails';
/*
KubeVirt UI component styles. Refer to stylelint configuration for details
on project-specific BEM (Block Element Modifier) format for CSS classes.
*/

@import './components/CreateDiskRow/create-disk-row';
@import './components/Form/dropdown';
@import './components/Form/form-group';
@import './components/Form/list-form-factory';
@import './components/Table/editable-table-actions';
@import './components/Table/editable-table';
@import './components/TemplateSource/template-source';
@import './components/VmConsoles/vm-consoles';
@import './components/VmDetails/vm-details';
@import './components/VmStatus/vm-status';
@import './components/Wizard/create-vm-wizard';
@import './components/Wizard/wizard';

/*
TODO: these styles should be backported to the corresponding PF-React package
*/
@import './patternfly-tweaks/vnc-console';
6 changes: 6 additions & 0 deletions sass/_dependencies.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
/*
KubeVirt UI style dependencies. Intended for use by Cosmos playground
when testing React components an in isolated environment which simulates
the consuming application.
*/

$font-path: '~patternfly/dist/fonts/';
$icon-font-path: '~patternfly/dist/fonts/';
$img-path: '~patternfly/dist/img/';
Expand Down
3 changes: 3 additions & 0 deletions sass/components/CreateDiskRow/create-disk-row.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.kubevirt-create-disk-row__action-buttons {
Copy link
Contributor

@rawagner rawagner Jan 7, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was .createDiskRow__actionButtons button previously so the new style should look like .kubevirt-create-disk-row__action-buttons button or .kubevirt-create-disk-row__action-buttons .btn (i think the latter is better). I need to target nested buttons inside .kubevirt-create-disk-row__action-buttons

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct, I've missed that.

Since we need to target specific buttons, we can use .kubevirt-create-disk-row__action-button (singular) class name on <Button> components, if you agree.

We don't have to declare .kubevirt-create-disk-row__action-buttons (plural) if we don't need to style the enclosing <div> (button panel/container).

.kubevirt-create-disk-row__action-buttons button
.kubevirt-create-disk-row__action-buttons .btn

Nested CSS selectors should only be used when we don't have full control over the logical component's parts. In this case, we can simply use .kubevirt-create-disk-row__action-button, since PF-React's <Button> allows us to specify CSS class name.

.block tag selectors should be avoided if possible. CSS rules shouldn't be tied to HTML tags.

.block .nested-part selectors are possible, but unnecessary in this case.

width: 27px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
top: 5px;
}

.kubevirt-dropdownGroup .dropdown-menu {
.kubevirt-dropdown + .dropdown-menu {
width: 100%;
}
24 changes: 24 additions & 0 deletions sass/components/Form/form-group.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
.kubevirt-form-group .dropdown > .dropdown-menu {
display: none;
z-index: 1001;
}

.kubevirt-form-group .dropdown.open > .dropdown-menu {
display: block;
}

.kubevirt-form-group--no-bottom {
margin-bottom: 2px;
}

.kubevirt-form-group--help {
margin-bottom: 0;
}

.kubevirt-form-group--no-help {
margin-bottom: 23px;
}

.kubevirt-form-group__field-help .popover {
max-width: 400px;
}
Loading