Merge pull request #2075 from Human-Connection/frontend-migration-plan

🍰 Add migration plan and frontend code guidelines to our docs
This commit is contained in:
mattwr18 2019-11-04 21:10:29 +01:00 committed by GitHub
commit bbd678caa6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 274 additions and 89 deletions

View File

@ -7,15 +7,10 @@
* [Backend](backend/README.md)
* [GraphQL](backend/graphql.md)
* [Webapp](webapp/README.md)
* [COMPONENTS](webapp/components.md)
* [PLUGINS](webapp/plugins.md)
* [STORE](webapp/store.md)
* [PAGES](webapp/pages.md)
* [ASSETS](webapp/assets.md)
* [LAYOUTS](webapp/layouts.md)
* [Styleguide](webapp/styleguide.md)
* [STATIC](webapp/static.md)
* [MIDDLEWARE](webapp/middleware.md)
* [Components](webapp/components.md)
* [HTML](webapp/html.md)
* [SCSS](webapp/scss.md)
* [Vue](webapp/vue.md)
* [Testing Guide](testing.md)
* [End-to-end tests](cypress/README.md)
* [Frontend tests](webapp/testing.md)

View File

@ -33,48 +33,74 @@ $ yarn build
$ yarn start
```
### Storybook
### Run tests
We encourage contributors to use Storybook to test out new components in an isolated way, and benefit from its many features.
See the docs for live examples and answers to FAQ, among other helpful information. ![Storybook docs](https://storybook.js.org/docs/basics/introduction/)
We ensure the quality of our frontend code by using
- [ESLint](https://eslint.org/) for checking our JavaScript code
- [Jest](https://jestjs.io/) and [Vue Test Utils](https://vue-test-utils.vuejs.org/) to unit test our components
- [Storybook](https://storybook.js.org/) to document and manually test our components in an isolated playground
For more information see our [frontend testing guide](testing.md). Use these commands to run the tests:
{% tabs %}
{% tab title="Docker" %}
{% tab title="With Docker" %}
After you have started the application following the instructions above, in another terminal run:
After starting the application following the above guidelines, open new terminal windows for each of these commands:
```bash
# run eslint
$ docker-compose exec webapp yarn lint
```
```bash
# run unit tests
$ docker-compose exec webapp yarn test
```
```bash
# start storybook
$ docker-compose exec webapp yarn storybook
```
The output should look similar to this:
![Storybook output](../.gitbook/assets/storybook-output.png)
Click on the link http://localhost:3002/ to open the browser to your interactive storybook.
You can then visit the Storybook playground on `http://localhost:3002`
{% endtab %}
{% tab title="Without Docker" %}
Run the following command:
After starting the application following the above guidelines, open new terminal windows and navigate to the `/webapp` directory for each of these commands:
```bash
# in webapp/
yarn storybook
# run eslint in /webapp
$ yarn lint
```
Open http://localhost:3002/ in your browser
```bash
# run unit tests in /webapp
$ yarn test
```
```bash
# start storybook in /webapp
$ yarn storybook
```
You can then visit the Storybook playground on `http://localhost:3002`
{% endtab %}
{% endtabs %}
## Styleguide Migration
We are currently in the process of migrating our styleguide components and design tokens from the [Nitro Styleguide](https://github.com/Human-Connection/Nitro-Styleguide) into the main [Human Connection repository](https://github.com/Human-Connection/Human-Connection) and refactoring our components in the process. During this migration, our new components will live in a `view` folder to separate them from the old, yet untouched components.
## Styleguide
### Folder Structure
All reusable Components \(for example avatar\) should be done inside the [Nitro-Styleguide](https://github.com/Human-Connection/Nitro-Styleguide) repository.
The folder structure we are aiming for is based on the [directory setup proposed by Nuxt.js](https://nuxtjs.org/guide/directory-structure):
![Styleguide Screenshot](../.gitbook/assets/screenshot-styleguide%20%281%29.png)
More information can be found here: [https://github.com/Human-Connection/Nitro-Styleguide](https://github.com/Human-Connection/Nitro-Styleguide)
If you need to change something in the styleguide and want to see the effects on the frontend immediately, then we have you covered. You need to clone the styleguide to the parent directory `../Nitro-Styleguide` and run `yarn && yarn run dev`. After that you run `yarn run dev:styleguide` instead of `yarn run dev` and you will see your changes reflected inside the frontend!
- **assets** contains icons, images and logos in `svg` format
- **components** are the generic building blocks of the app small, reusable and usually not coupled to state
- **features** are composed of components but tied to a particular function of the app (e.g. `comment` or `post`)
- **layouts** can use components to create layout templates for pages
- **pages** are the entry points for all `routes` in the app and are composed of layouts, features and components
- **styles** holds all shared SCSS files such as `variables` and `mixins`

View File

@ -1,5 +0,0 @@
# ASSETS
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript in our case SCSS styles.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).

View File

@ -1,5 +1,38 @@
# COMPONENTS
# Components Code Guidelines
The components directory contains your Vue.js Components.
## We adhere to the [single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle)
_Nuxt.js doesn't supercharge these components._
Each component does _exactly one job_. The goal is to end up with many small components that are:
- easy to understand
- easy to maintain
- easy to reuse
**How do you decide what is a separate component?** Try to describe what it does in _one sentence_! When you find yourself using `and` and `or` the code you are talking about should probably be split up into two or more components.
On the other hand, when something is easily expressed in a few lines of HTML and SCSS and not likely to be reused this is a good indicator that it should _not_ go into a separate component.
## We compose with components
Usually `pages` use `layouts` as templates and will be composed of `features`. `features` are composed of `components`, the smallest building blocks of the app. The further down we go in this hierarchy the simpler and more generic the components become. Here is an example:
- The `index` page is responsible for displaying a list of posts. It uses the `default` layout and the `PostList` feature.
- The `PostList` feature uses a `List` component to render `PostTeaser` features.
- The `PostTeaser` feature consists of a `LayoutCard` wrapped around a `CardImage`, `CardTitle` and `CardContent` component.
The `index` page is unique in the app and will never be reused. The `PostList` knows it is handling post data and can therefore not be used for anything else but it can display posts on the `index` as well as the `user` page.
The `Card` on the other hand does not care about the type of data it needs to handle. It just takes whatever it receives and renders it in a certain way, so it can be reused throughout the app for many different features.
## We use two-word names
We follow the W3C rules for naming custom elements as suggested in the [Vue.js docs](https://vuejs.org/v2/guide/components-registration.html#Component-Names) to differentiate our own components from regular HTML elements in our templates.
Names should also be meaningful and unique to avoid confusion and code duplication, and also not too long to make them readable. Therefore: aim for two-word names, such as `layout-card`, `post-list` or `post-teaser`.
## Recommended reads
For a deeper dive into the WHY and HOW have a look at the following resources which the above guidelines are based on:
- [Atomic design](https://bradfrost.com/blog/post/atomic-web-design/)
- [CDD component based design](https://medium.com/@wereheavyweight/how-were-using-component-based-design-5f9e3176babb)
- [Vue.js component styleguide](https://pablohpsilva.github.io/vuejs-component-style-guide/#/)

29
webapp/html.md Normal file
View File

@ -0,0 +1,29 @@
# HTML Code Guidelines
## We write semantic markup
We avoid using `divs` and `spans` and try to choose more meaningful HTML elements instead. If unsure which element to use [this list by MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element) can be of help.
Why?
- semantic markup is crucial for accessibility
- it makes the code more readable for other developers
- it benefits our SEO
For more background [see this article](https://css-tricks.com/why-how-and-when-to-use-semantic-html-and-aria/).
This doesnt mean you cant ever use a `div` just think twice before you do!
## We write as little HTML as possible and as much as necessary
HTML is used to _structure content on the page_ and should therefore reflect its complexity. Not more and not less. Most content does not require deep nesting of HTML elements if you find yourself wrapping `container` around `container` or adding an element just to correctly position another element on the page this calls for the use of CSS instead!
Why?
- deep nesting makes it hard to understand, style and maintain components
- it can lead to performance issues
## Recommended reads
For a deeper dive into the WHY and HOW have a look at the following resources:
- [HTML: a good basis for accessibility](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML)
- [Why, how, and when to use semantic HTML and ARIA](https://css-tricks.com/why-how-and-when-to-use-semantic-html-and-aria/)

View File

@ -1,5 +0,0 @@
# LAYOUTS
This directory contains your Application Layouts.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).

View File

@ -1,5 +0,0 @@
# MIDDLEWARE
This directory contains our application middleware. The middleware lets you define custom functions to be ran before rendering a page or a group of pages \(layouts\).
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).

View File

@ -1,6 +0,0 @@
# PAGES
This directory contains your Application Views and Routes. The framework reads all the `*.vue` files inside this directory and create the router of your application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).

View File

@ -1,5 +0,0 @@
# PLUGINS
This directory contains your Javascript plugins that you want to run before mounting the root Vue.js application.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).

73
webapp/scss.md Normal file
View File

@ -0,0 +1,73 @@
# SCSS - Code Guidelines
## We use classes over tags and ids
Never apply styles to `tags` or `ids` use `classes` instead!
Why?
- HTML tags are responsible for the document _structure_, not the looks
- targeting HTML tags comes with performance issues
- ids are responsible for identifying a unique element, not for styling it
- ids have higher specificity than classes and therefore don't play well together
- classes can be combined and reused while ids are unique
For more background see the following articles on [why not to style tags](https://frontstuff.io/you-need-to-stop-targeting-tags-in-css) and [why not to style ids](https://dev.to/clairecodes/reasons-not-to-use-ids-in-css-4ni4).
## We use design tokens instead of magic numbers
In order to achieve a consistent look and feel we use a set of pre-defined `design tokens` to style our components, for example `colors`, `sizes` and `box-shadows`. These tokens are stored as `SCSS variables` and reused throughout the app.
So, instead of typing _pixel values_ or _hex codes_ make sure you use design tokens such as `height-header` or `color-input-border`.
## We name our classes after components
Our SCSS styles live within the corresponding component (see the [Vue.js docs for single-file components](https://vuejs.org/v2/guide/single-file-components.html) for reference) and should therefore carry the same _unique_ name.
Why?
- it clearly ties the styles to the one component
- having unique class names means styles will not be accidentally overwritten in other files
- we can avoid using `scoped CSS` which [comes with performance caveats](https://vue-loader.vuejs.org/guide/scoped-css.html#also-keep-in-mind)
## We use variants instead of overriding styles
Components will sometimes need to look different depending on the context in which they are used a button might for example be `green` when it represents a call to action and `red` when it triggers a destructive action. Rather than making the `rounded-button` component `green` by default and then overriding the `color` for, say, the `delete-account` action use variants! Pass the `rounded-button` a prop, such as `color: danger`, and then apply the respective `variant class`.
Name variant classes with a dash prefix, such as `-danger`, then target them like this:
```scss
.rounded-button {
/* other css styles */
&.-danger {
color: $color-danger;
}
}
```
## We _style_ within the component, we _position_ when we use it
In order to make components truly reusable it is important to limit their styles to, well, their actual _styling_. What color are they, how big is the text, what happens on `hover`, do they have a rounded border all that is part of it.
Margins, alignment and positioning on the other hand need to be defined in the _parent_ because the same component might sometimes be aligned to the left, sometimes to the right and sometimes float above other content. For more details see the [rscss guidelines](https://rscss.io/layouts.html).
To do that, use the `child selector`, like this:
```scss
.login-form {
/* other css styles */
> .rounded-button {
margin: $margin-small;
justify-self: flex-end;
}
}
```
A special case are dimensions like `width` and `height`. If it is important that a component always has the same dimensions (the height of a button should be consistent, for example) define it _within the component_ itself, if a component should have flexible dimensions (a card, for example, could stretch over the whole screen in one place and be limited to a certain width in another) define the dimensions _in the parent_.
## Recommended reads
For a deeper dive into the WHY and HOW have a look at the following resources which the above guidelines are based on:
- [rscss reasonable system for css stylesheet structure](https://rscss.io/index.html)
- [itcss inverted triangle architecture for css](https://csswizardry.net/talks/2014/11/itcss-dafed.pdf)

View File

@ -1,9 +0,0 @@
# STATIC
This directory contains your static files. Each file inside this directory is mapped to `/`.
Example: `/static/robots.txt` is mapped as `/robots.txt`.
We use it for images.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).

View File

@ -1,7 +0,0 @@
# STORE
This directory contains your Vuex Store files. Vuex Store option is implemented in the Nuxt.js framework.
Creating a file in this directory activates the option in the framework automatically.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).

View File

@ -1,12 +0,0 @@
# Styleguide
For this Projoject we decided to use [Jörg Bayreuther's](https://github.com/visualjerk) _\(visualjerk\)_ fantastic Design System called [CION](https://cion.visualjerk.de/). _\(see a_ [_demo_](https://styleguide.cion.visualjerk.de/)_\)_
![Styleguide in action under https://localhost:8080](../.gitbook/assets/screenshot-styleguide.png)
## Checkout the Styleguide
It's now an npm package. Want to help with it's development or maintenance?
[Head over to the repo](https://github.com/Human-Connection/Nitro-Styleguide)

View File

@ -1,8 +1,38 @@
# Component Testing
We are using `Jest` as our test runner, along with `vue-test-utils`.
## Linting
Head over and check out the documentation on [Jest](https://jestjs.io/docs/en/getting-started.html)
We use [ESLint](https://eslint.org/) to make sure all developers follow certain code guidelines when writing JavaScript.
Also, check out [vue-test-utils](https://vue-test-utils.vuejs.org/)
Most code editors offer an ESLint plugin which helps detect mistakes already while you are writing code. To run the linter manually before pushing up new code type `yarn lint` into your terminal. Most minor issues can be fixed automatically with the command `yarn lint --fix`.
## Unit tests
We write unit tests with the help of [Jest](https://jestjs.io/) and [Vue Test Utils](https://vue-test-utils.vuejs.org/) to make sure our components work in the way they should. In these tests we usually check that a certain input leads to the expected output. They are used to test _functionality_.
To run all tests use the command `yarn test` in the `/webapp` directory. Other useful commands are:
- `yarn test -t test-name` to run tests including `test-name` in their file or test names
- `yarn test -o` to run tests related to files that have been changed since the latest commit
- `yarn run path/to/component.spec.js` to run a single test file
## Documentation and manual testing
[Storybook](https://vue-test-utils.vuejs.org/) is a great tool that performs two important functions in our project:
### Component documentation
With Storybook our components can be documented in detail and offer a visual reference to other developers. When all components are properly documented, Storybook can be used as a big component library where developers can browse through design tokens and components and immediately verify that the component offers the desired functionality.
### Manual testing in an isolated environment
When adding new components or changing existing ones, Storybook can be helpful not only to document the feature for future use, but also to test different use cases (e.g. by passing different types of `props`) in an isolated playground.
With the right addons, Storybook also gives immediate feedback on how well the component complies with accessibility guidelines.
------
To run Storybook, first start the app, then enter the following command in a new terminal window: `yarn storybook`. The output should look similar to this:
![Storybook output](../.gitbook/assets/storybook-output.png)
The Human Connection Storybook will then be available on `http://localhost:3002`.

53
webapp/vue.md Normal file
View File

@ -0,0 +1,53 @@
# Vue Code Guidelines
## We use single-file components
Each component lives in a single file, containing:
- its `template` (the DOM structure)
- its `script` (including `props`, `data` and `methods` among other things)
- its `style` (defining the look of the component)
See the [Vue.js docs](https://vuejs.org/v2/guide/single-file-components.html) for more details.
Placed in the same folder are also:
- the test file (e.g. `MyComponent.spec.js`)
- the storybook file (e.g. `MyComponent.story.js`)
## We use typed props
Vue.js allows us to define component props either as strings or as objects (with `type` and `default` or `required` values). Always go for the second option!
Also: only (and always!) define a `default` for props that are _not required_.
Why?
- it makes our code more robust a warning will be shown when passing a wrong prop type
- it clearly defines the component API and tells other developers how to use it
It is as easy as writing:
```
props: {
title: {
type: String,
required: true,
},
image: {
type: String,
default: 'human-connection-logo.png',
},
}
```
For more complex use cases see the [official Vue.js documentation](https://vuejs.org/v2/guide/components-props.html#Prop-Validation).
## We use shorthands
For better readability we prefer
- `:something` over `v-bind:something`
- `@click` over `v-on:click`
Read more in the [official Vue.js docs](https://vuejs.org/v2/guide/syntax.html#Shorthands)
## Recommended reads
The [Vue.js component style guide](https://pablohpsilva.github.io/vuejs-component-style-guide/#/?id=harness-your-component-props) offers a whole list of best-practices for writing Vue components.