Skip to content

Commit

Permalink
Merge pull request #4 from openameba/feature/ui
Browse files Browse the repository at this point in the history
feat(spindle-ui): create UI library for Spindle
  • Loading branch information
herablog authored Aug 4, 2020
2 parents a19c44e + 510c936 commit 7b74ef6
Show file tree
Hide file tree
Showing 23 changed files with 9,023 additions and 226 deletions.
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
"name": "spindle",
"private": true,
"scripts": {
"test": "run-p lint:*",
"test": "run-p lint test:packages",
"test:packages": "lerna run test",
"lint": "run-p lint:*",
"lint:script": "eslint .",
"lint:yaml": "yamllint .github/workflows/*.yml",
"format": "eslint . --fix",
"lint:packages": "lerna run lint",
"format": "run-p format:*",
"format:script": "eslint . --fix",
"format:packages": "lerna run format",
"bootstrap": "lerna bootstrap",
"build": "lerna run build"
},
Expand Down
21 changes: 21 additions & 0 deletions packages/spindle-ui/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
stories: ['../src/index.stories.ts', '../src/**/*.stories.tsx'],
addons: [
'@storybook/addon-actions',
'@storybook/addon-a11y',
],
webpackFinal(config) {
config.module.rules.push({
test: /\.tsx?$/,
use: [
{
loader: require.resolve('ts-loader'),
},
],
});

config.resolve.extensions.push('.ts', '.tsx');

return config;
},
};
4 changes: 4 additions & 0 deletions packages/spindle-ui/.storybook/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { addDecorator } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';

addDecorator(withA11y);
2 changes: 2 additions & 0 deletions packages/spindle-ui/.stylelintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dist/
public/
22 changes: 22 additions & 0 deletions packages/spindle-ui/.stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"extends": "stylelint-config-prettier",
"plugins": [
"stylelint-prettier",
"stylelint-order",
"stylelint-selector-bem-pattern"
],
"rules": {
"prettier/prettier": true,
"order/properties-alphabetical-order": true,
"plugin/selector-bem-pattern": {
"implicitComponents": "src/**/*.css",
"preset": "suit",
"presetOptions": {
"namespace": "spui"
}
},
"value-keyword-case": ["lower", {
"ignoreKeywords": ["/^--/"]
}]
}
}
10 changes: 10 additions & 0 deletions packages/spindle-ui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Spindle UI (In development)

- [Design Doc](design-doc.md)

## 開発する

```
yarn install
yarn dev # storybookが起動します
```
12 changes: 12 additions & 0 deletions packages/spindle-ui/bundlesize.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"files": [
{
"path": "./dist/**/*.js",
"maxSize": "1 kB"
},
{
"path": "./dist/index.css",
"maxSize": "3 kB"
}
]
}
135 changes: 135 additions & 0 deletions packages/spindle-ui/design-doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
## 前提 / Context
Spindle(スピンドル)は「Amebaらしさ」を一貫してユーザーに届けるための仕組みです。Spindle UIはその手段の一つとして、開発者と利用者をつなぐための、Web UIライブラリです。

## 目指すこと / Goals
このリポジトリでは、各Webアプリケーションで再作成する必要のない小さな単位のコンポーネントを作成し、ライブラリとして配信することを目指します。

## 目指さないこと / Non-goals
このリポジトリでは、このコンポーネントだけでWebアプリケーションを作れるような、大きなライブラリを提供することを目指していません。

## 概要 / Overview
Amebaの開発での利用実績を踏まえ、以下の点を考慮してライブラリを提供します。

- **Reactコンポーネントの提供**: Amebaで最も利用されているUIライブラリのReactで作られたミニマムなコンポーネントを提供します
- **スタイルが定義されたCSSの提供**: UIライブラリを使用しないLPなどのプロジェクトにCSSで表現できる範囲の振る舞いを提供します
- **UIコンポーネントカタログ中心の開発**: 作られたコンポーネントはすぐにテストされ、表示を確認します
- **管理されたファイルサイズ**: 共通処理が集まるため、大きくなりがちなUIライブラリのファイルサイズが規定を超さないようにします

## どのようにやっていくか / Approach, Detailed design

### Reactコンポーネントの提供
各アプリケーションで再作成する必要のない、ミニマムな要素をReactコンポーネントとして提供します。ただし、このコンポーネントに責務が集約されないようできる限り振る舞いに徹し、処理を含まないようにします。

非常に小さなコンポーネントとして作成されるので、プロジェクトで読み込まず、サンプルコードとして利用してもよいでしょう。また、[preact/compatを通じて](https://preactjs.com/guide/v10/switching-to-preact)Preactプロジェクトでも利用できます。

Reactコンポーネントは以下のように、利用します。

```JavaScript
import { Button } from '@openameba/spindle-ui';

export const WakuwakuForm = () => {
return (
<form>
<Button size="large" type="submit" variant="primary">Yoshi!</Button>
</form>
);
}
```

スタイルはCSSファイルとして提供されているため、[PostCSS](https://github.com/postcss/postcss-import)[Sass](https://sass-lang.com/documentation/at-rules/import#importing-css)などでインポートします。

```CSS
@import "spindle-ui/dist/Button.css";
```

#### 他の手段 / Alternative approach
より多くのプロジェクトで利用するために、Vue.jsやWeb Componentsで作成する必要があるかもしれませんが、2020年8月現在では最も利用されているReactで作成しています。Web ComponentsはSpindleで提供するコンポーネントの粒度ではちょうどよさそうですが、Amebaで使い慣れていないのと、Server-side Renderingに強くないため後回しします([lit-ssr](https://github.com/PolymerLabs/lit-ssr)期待か)。

また、スタイルの記述方法はより代替手段が考えられます。[CSS-in-JS](https://speakerdeck.com/vjeux/react-css-in-js)は、コンポーネント作成により適したテクニックかもしれません。本プロジェクトでは以下の条件を満たすため、CSSで記述しています。

- HTMLで使うため、セレクタ名が機械的に生成される前提でなく、そのままCSSファイルに出力できる
- Spindle自体と取り込むプロジェクト両方で、ビルドシステムにできるだけ干渉しない
- [ameba-color-palette.css](https://github.com/openameba/ameba-color-palette.css)を利用する可能性が高いため、CSS Custom propertiesが使いやすい

### スタイルが定義されたCSSの提供
UIライブラリを使用しないLPなどのプロジェクトでも、「Amebaらしさ」を表現した見た目・振る舞いをするために、独立したCSSファイルを提供します。ただし、現時点ではJavaScriptを利用した動的な動作は提供されていないため、自作する必要があります。

```HTML
<!-- CDNから読み込む -->
<link rel="stylesheet" href="https://path-of-CDN/spindle-ui/dist/index.css">

<form>
<button class="spui-Button spui-Button--primary spui-Button--large" type="submit">Submit</button>
</form>
```

or

```CSS
/* PostCSSやSassを利用する */
/* Import all components */
@import "spindle-ui";
```

ファイルサイズをできる限り小さくしたい場合は、必要なコンポーネントのスタイルのみを読み込みます。

```HTML
<!-- CDNから読み込む -->
<link rel="stylesheet" href="https://path-of-CDN/spindle-ui/dist/Button.css">

<form>
<button class="spui-Button spui-Button--primary spui-Button--large" type="submit">Submit</button>
</form>
```

or

```CSS
/* PostCSSやSassを利用する */
/* Import specific component */
@import "spindle-ui/dist/Button.css";
```

## UIコンポーネントカタログ中心の開発
UIライブラリは、様々なプロジェクトで利用される可能性があるため、多くの人にとって簡単に確認できるドキュメントが必要です。また、Spindleが目指している「Amebaらしさ」が満たされているかチェックできる仕組みも求められます。

Spindle UIのコンポーネントは開発中、公開後どちらもStorybookで作られたカタログを中心に確認されます。そこでは、見た目、ソースコードの確認やアクセシビリティ、パフォーマンス、リグレッションなどがテストされます。

### 管理されたファイルサイズ
UIライブラリは、共通処理が集約されたり、様々なバリエーションの実装が求められたりするため、ファイルサイズが増えがちです。それらを検知するために、ファイルサイズを機械的にチェックしています。

各コンポーネントやCSSファイルが指定されたサイズ以上にならないように管理されています。

```JSON
// bundlesize.config.json
{
"files": [
{
"path": "./dist/**/*.js",
"maxSize": "1 kB"
},
{
"path": "./dist/index.css",
"maxSize": "3 kB"
}
]
}
```

## 想定される問題 / Drawback, Risk
UIライブラリを運営していくうえで、以下の問題が想定されます。これらを回避するために、できるだけ短期間に小さく運営を始めるとよいでしょう。

- 運用が大変で適切に更新されない
- 要望が増えすぎて対応しきれない
- 技術要素の利用条件が変化し、作り直さなければならない

## 関連リンク / Related link
- [React](https://reactjs.org/)
- [Preact](https://preactjs.com/)
- [Vue.js](https://vuejs.org/)
- [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components)
- [CSS in JS techniques comparison](https://github.com/MicheleBertoli/css-in-js)
- [postcss/postcss-import](https://github.com/postcss/postcss-import)
- [Sass: Importing CSS](https://sass-lang.com/documentation/at-rules/import#importing-css)
- [Storybook](https://storybook.js.org/)
- [siddharthkp/bundlesize](https://github.com/siddharthkp/bundlesize)
8 changes: 8 additions & 0 deletions packages/spindle-ui/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
verbose: true,
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
setupFiles: ['<rootDir>/setup-tests.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
};
61 changes: 61 additions & 0 deletions packages/spindle-ui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@openameba/spindle-ui",
"version": "0.0.1",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"style": "./dist/index.css",
"scripts": {
"test": "run-p bundlesize lint test:*",
"lint": "yarn lint:style",
"lint:style": "stylelint '**/*.css'",
"format": "yarn lint:style --fix",
"test:interaction": "jest",
"prebundlesize": "yarn build",
"bundlesize": "npx bundlesize",
"dev": "yarn storybook:start",
"storybook:start": "start-storybook -p 6006 -c .storybook",
"clean": "npx rimraf dist",
"prebuild": "yarn clean",
"build": "run-p build:*",
"build:script": "tsc",
"build:style": "postcss src/**/*.css src/*.css --base src -d dist/"
},
"license": "MIT",
"private": true,
"files": [
"dist"
],
"dependencies": {
"@types/react": "^16.9.43",
"ameba-color-palette.css": "openameba/ameba-color-palette.css#v3.0.0-beta.0",
"react": "^16.13.1"
},
"devDependencies": {
"@storybook/addon-a11y": "^5.3.19",
"@storybook/addon-actions": "^5.3.19",
"@storybook/react": "^5.3.19",
"@types/chai": "^4.2.12",
"@types/enzyme": "^3.10.5",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/jest": "^26.0.7",
"@types/sinon": "^9.0.4",
"autoprefixer": "^9.8.5",
"babel-loader": "^8.1.0",
"bundlesize": "^0.18.0",
"chai": "^4.2.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
"jest": "^26.1.0",
"postcss-cli": "^7.1.1",
"postcss-import": "^12.0.1",
"sinon": "^9.0.2",
"stylelint": "^13.6.1",
"stylelint-config-prettier": "^8.0.2",
"stylelint-config-standard": "^20.0.0",
"stylelint-order": "^4.1.0",
"stylelint-prettier": "^1.1.2",
"stylelint-selector-bem-pattern": "^2.1.0",
"ts-jest": "^26.1.4",
"ts-loader": "^8.0.1"
}
}
9 changes: 9 additions & 0 deletions packages/spindle-ui/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
/**
* TODO: cerate .browserslistrc
* - for modern browsers
* - for IE11
*/
// TODO: minify css for production
plugins: [require('autoprefixer'), require('postcss-import')],
};
6 changes: 6 additions & 0 deletions packages/spindle-ui/setup-tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({
adapter: new Adapter(),
});
Loading

0 comments on commit 7b74ef6

Please sign in to comment.