npm package: @oda-omaolo/oda-ui-common
Description: Shared UI components for ODA-projects
Author: Juhani Kumara
Latest version: 3.2.45
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# ODA 2 common UI library

This repository contains common UI components for ODA-applications, created with React and styled-components. This repository also acts as a living style guide for the ODA project.

## Key technologies

Here are the key libraries used in the project.

| Library | Description |
| --- | --- |
| [react](https://facebook.github.io/react/) | UI-component library |
| [styled-components](https://www.styled-components.com/) | React primitives |
| [storybook](https://storybook.js.org/) | A UI to preview the components |

## Usage

### Installation from NPM

Install the latest version of oda-ui-common as a dependency to your project by running:

`npm install @omahoito/oda-ui-common`

#### Usage

oda-ui-common components require a wrapping ThemeProvider-component, to inject theming-related props to the UI-components. A ThemeProvider passes theme properties to their children UI-components (all children, not just direct children).

You can have as many ThemeProviders in your application as you want, but you should probably have one at the top-level of your app. By default, ThemeProvider uses the ODA-theme bundled with the app, but you can also pass a custom theme, which is just an object.

Here is an example of using the themeProvider with the default theme:

```javascript
import React from 'react'
import {render} from 'react-dom'
import {ThemeProvider, P} from '@omahoito/oda-ui-common'

render(
    <ThemeProvider>
        <P>Hello, world!</P>
    </ThemeProvider>,
    document.querySelector('#app')
)
```

And here with a custom theme:
```javascript
import React from 'react'
import {render} from 'react-dom'
import {ThemeProvider, P, defaultTheme} from '@omahoito/oda-ui-common'

const customTheme = {
    ...defaultTheme:
    myCustomComponent: {
        text: 'pink'
    }
}

render(
    <ThemeProvider theme={customTheme}>
        <P>Hello, world!</P>
    </ThemeProvider>,
    document.querySelector('#app')
)
```

#### Recommended global styles

While the vast majority of styles in this repository are self contained, some styles are intentionally left out of repository, such as fonts and normalizations.

We recommend the following global styles to be used with the defaultTheme:

```css
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: 'Gill Sans', sans-serif;
  font-size: 16px;
  font-weight: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
```

Using __normalize.css__  or equivalent is also highly recommended.

#### Fonts

We recommend the font [Gill Sans](https://www.myfonts.com/fonts/mti/gill-sans/) to be used with the default theme. This font is not included in the package, and it must be downloaded and licensed separately.

These are the font-weight mappings used in oda-web-front:

| Font-weight | Font |
| ------------- | ------------- |
| 300 | Gill Sans Light |
| 500 / normal | Gill Sans Book |
| 700 / bold | Gill Sans Medium |


### Local installation

If you want to contribute to oda-ui-common, you should clone the repository and compile the components locally.

Node.js is needed to run the front-end build. You can download it [from here](https://nodejs.org/en/). Version 8.0.0 or above is recommended.

All project dependencies are listed in package.json. To install them you need NPM (installed automatically with Node.js).

Once you have installed Node.js, run this command in the root folder (the one that contains file package.json) of the project to install project's dependencies:

```
npm install
```

Some dependencies are marked as peer dependencies. These need to be installed separately. You can either install each one or use a utility, like npm-install-peers:

```
npm install -g npm-install-peers
npm-install-peers
```

### Building the project

To build the project run

```
npm run build
```

### Storybook

To launch the style guide UI locally, run

```
npm run storybook
```

This will start a local server on port 6006.

### Other scripts

All of these scripts can be run with "npm run [script name]"

| Script | Description |
| --- | --- |
| lint | Runs eslint linter (see .eslinrc.json for linting settings) |
| lint:css | Runs stylelint linter (see .stylelintrc.json for linting settings) |
| clean  | Removes dist/-folder |
| start | Runs babel build in watch-mode |
| deploy-storybook | Push master to gh-pages branch |
| prettier | Runs prettier |

## Contributing to the project

### Guidelines

1. Follow [atomic web design](http://bradfrost.com/blog/post/atomic-web-design/) principles
2. All inputs should be [controlled components](https://facebook.github.io/react/docs/forms.html#controlled-components)
3. Avoid writing stateful components

### Folder structure

| Folder | Description |
| --- | --- |
| / | Project root, build configuration files |
| /src | Application source codes |
| /src/atoms | Primitive components |
| /src/atoms/[type] | Atomic components of similar type (e.g. "button") |
| /src/molecules/ | Components, combinations of atoms |
| /src/molecules/[type] | Molecular components of similar type (e.g. "form") |
| /src/themes | Default theme and themeProvider-component |

### Code formatting

[Prettier](https://prettier.io) is used for code formatting. File `.prettierrc` contains configuration.

### Naming conventions

Here is an example of file naming conventions. For example, the contents of an imaginary /src/atoms/button -folder might look like this

| File | Description |
| --- | --- |
| buttonWithIcon.js | Exports ButtonWithIcon-component as default |
| bigRoundButton.js | Exports BigRoundButton-component as default |
| button.story.js | Story file for the components of this folder |
| index.js | Exports ButtonWithIcon and BigRoundButton as **named exports** |

## Publishing to NPM

To publish the package to NPM, you must be a member of the [oda-omaolo-organization](https://www.npmjs.com/org/oda-omaolo) in NPM.

If you already are a member of the organization, you can publish the package using these commands:

```
npm version patch
npm publish
git push
```

NPM version patch will increase the version and automatically create a Git-tag for the new version. The tag should be pushed to git after a succesful publish.

### Versioning

Versioning follows [SemVer guidelines](https://semver.org/).

### Theming

You can create your own theme, and pass it to the ThemeProvider instead of the ODA-theme. The theme must be a JSON object with the following structure:

```json
{
  "palette": {
    "basic": {
      "black": "#000",
      "grey5": "#0d0d0d",
      "grey10": "#1a1a1a",
      "grey20": "#333",
      "grey30": "#4d4d4d",
      "grey40": "#666",
      "grey50": "#808080",
      "grey60": "#999",
      "grey70": "#b3b3b3",
      "grey80": "#ccc",
      "grey90": "#e6e6e6",
      "grey95": "#f2f2f2",
      "white": "#FFF"
    },
    "variant": {
      "primary": {
        "main": "<color>",
        "dark": "<color>",
        "light": "<color>",
        "readableColor": "<color>"
      },
      "secondary": {
        "main": "<color>",
         "dark": "<color>",
         "light": "<color>",
         "readableColor": "<color>"
      },
      "info": {
        "main": "<color>",
        "dark": "<color>",
        "light": "<color>",
        "readableColor": "<color>"
      },
      "error": {
        "main": "<color>",
         "dark": "<color>",
         "light": "<color>",
         "readableColor": "<color>"
        },
      "warning": {
        "main": "<color>",
        "dark": "<color>",
        "light": "<color>",
        "readableColor": "<color>"
      },
      "success": {
        "main": "<color>",
        "dark": "<color>",
        "light": "<color>",
        "readableColor": "<color>"
      }
    },
    "progress": {
      "primary": "<color>",
      "secondary": "<color>",
      "tertiary": "<color>"
    },
    "graph": {
      "primary": "<color>",
      "secondary": "<color>",
      "tertiary": "<color>",
      "quaternary": "<color>"
    },
    "priority": {
      "primary": "<color>",
      "secondary": "<color>",
      "tertiary": "<color>"
    }
  },

  "font": {
    "primary": "<font family>",
    "secondary" "<font family>"
  },

  "breakpoint": {
    "xs": "<size>",
    "sm": "<size>",
    "md": "<size>",
    "lg": "<size>",
    "xl": "<size>"
  },

  "size": {
    "padding": {
      "xl": "<size>",
      "lg": "<size>",
      "md": "<size>",
      "sm": "<size>",
      "xs": "<size>"
    },
    "margin": {
      "xl": "<size>",
      "lg": "<size>",
      "md": "<size>",
      "sm": "<size>",
      "xs": "<size>"
    },
    "font": {
      "xxxl": "<size>",
      "xxl": "<size>",
      "xl": "<size>",
      "lg": "<size>",
      "md": "<size>",
      "sm": "<size>",
      "xs": "<size>"
    }
  }
}
```