Skip to content

Commit 6d3e523

Browse files
Merge pull request #765 from UHAsikakutou/master
Update intro-to-storybook/ja
2 parents 5e44d46 + 17b2af4 commit 6d3e523

File tree

10 files changed

+551
-399
lines changed

10 files changed

+551
-399
lines changed

content/intro-to-storybook/react/ja/composite-component.md

+98-52
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ commit: '429780a'
99

1010
## TaskList (タスクリスト)
1111

12-
Taskbox はピン留めされたタスクを通常のタスクより上部に表示することで強調します。これにより `TaskList` に、タスクのリストが、通常のタスクのみである場合と、ピン留めされたタスクとの組み合わせである場合という、ストーリーを追加するべき 2 つのバリエーションができます。
12+
Taskbox はピン留めされたタスクを通常のタスクより上部に表示することで強調します。これにより `TaskList` に、タスクのリストが通常のタスクのみである場合と、ピン留めされたタスクとの組み合わせである場合というストーリーを追加するべき 2 つのバリエーションができます。
1313

1414
![通常のタスクとピン留めされたタスク](/intro-to-storybook/tasklist-states-1.png)
1515

16-
`Task` のデータは非同期的に送信されるので、接続がないことを示すため、読み込み中の状態****必要となります。さらにタスクがない場合に備え、空の状態も必要です。
16+
`Task` のデータは非同期に送信されるので、接続がないことを示すため、読み込み中の状態**も併せて**必要となります。さらにタスクがない場合に備え、空の状態も必要です。
1717

1818
![空の状態と読み込み中の状態](/intro-to-storybook/tasklist-states-2.png)
1919

2020
## セットアップする
2121

22-
複合的なコンポーネントも基本的なコンポーネントと大きな違いはありません。`TaskList` のコンポーネントとそのストーリーファイル、`src/components/TaskList.js``src/components/TaskList.stories.js` を作成しましょう。
22+
複合的なコンポーネントも基本的なコンポーネントと大きな違いはありません。`TaskList` のコンポーネントとそのストーリーファイル、`src/components/TaskList.jsx``src/components/TaskList.stories.jsx` を作成しましょう。
2323

2424
まずは `TaskList` の大まかな実装から始めます。前の章で作成した `Task` コンポーネントをインポートし、属性とアクションを入力として渡します。
2525

26-
```js:title=src/components/TaskList.js
26+
```jsx:title=src/components/TaskList.jsx
2727
import React from 'react';
2828

2929
import Task from './Task';
@@ -54,61 +54,61 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
5454

5555
次に `Tasklist` のテスト状態をストーリーファイルに記述します。
5656

57-
```js:title=src/components/TaskList.stories.js
58-
import React from 'react';
59-
57+
```jsx:title=src/components/TaskList.stories.jsx
6058
import TaskList from './TaskList';
59+
6160
import * as TaskStories from './Task.stories';
6261

6362
export default {
6463
component: TaskList,
6564
title: 'TaskList',
66-
decorators: [story => <div style={{ padding: '3rem' }}>{story()}</div>],
65+
decorators: [(story) => <div style={{ padding: '3rem' }}>{story()}</div>],
66+
tags: ['autodocs'],
6767
};
6868

69-
const Template = args => <TaskList {...args} />;
70-
71-
export const Default = Template.bind({});
72-
Default.args = {
73-
// Shaping the stories through args composition.
74-
// The data was inherited from the Default story in Task.stories.js.
75-
tasks: [
76-
{ ...TaskStories.Default.args.task, id: '1', title: 'Task 1' },
77-
{ ...TaskStories.Default.args.task, id: '2', title: 'Task 2' },
78-
{ ...TaskStories.Default.args.task, id: '3', title: 'Task 3' },
79-
{ ...TaskStories.Default.args.task, id: '4', title: 'Task 4' },
80-
{ ...TaskStories.Default.args.task, id: '5', title: 'Task 5' },
81-
{ ...TaskStories.Default.args.task, id: '6', title: 'Task 6' },
82-
],
69+
export const Default = {
70+
args: {
71+
// Shaping the stories through args composition.
72+
// The data was inherited from the Default story in Task.stories.jsx.
73+
tasks: [
74+
{ ...TaskStories.Default.args.task, id: '1', title: 'Task 1' },
75+
{ ...TaskStories.Default.args.task, id: '2', title: 'Task 2' },
76+
{ ...TaskStories.Default.args.task, id: '3', title: 'Task 3' },
77+
{ ...TaskStories.Default.args.task, id: '4', title: 'Task 4' },
78+
{ ...TaskStories.Default.args.task, id: '5', title: 'Task 5' },
79+
{ ...TaskStories.Default.args.task, id: '6', title: 'Task 6' },
80+
],
81+
},
8382
};
8483

85-
export const WithPinnedTasks = Template.bind({});
86-
WithPinnedTasks.args = {
87-
// Shaping the stories through args composition.
88-
// Inherited data coming from the Default story.
89-
tasks: [
90-
...Default.args.tasks.slice(0, 5),
91-
{ id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
92-
],
84+
export const WithPinnedTasks = {
85+
args: {
86+
tasks: [
87+
...Default.args.tasks.slice(0, 5),
88+
{ id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' },
89+
],
90+
},
9391
};
9492

95-
export const Loading = Template.bind({});
96-
Loading.args = {
97-
tasks: [],
98-
loading: true,
93+
export const Loading = {
94+
args: {
95+
tasks: [],
96+
loading: true,
97+
},
9998
};
10099

101-
export const Empty = Template.bind({});
102-
Empty.args = {
103-
// Shaping the stories through args composition.
104-
// Inherited data coming from the Loading story.
105-
...Loading.args,
106-
loading: false,
100+
export const Empty = {
101+
args: {
102+
// Shaping the stories through args composition.
103+
// Inherited data coming from the Loading story.
104+
...Loading.args,
105+
loading: false,
106+
},
107107
};
108108
```
109109

110110
<div class="aside">
111-
💡 <a href="https://storybook.js.org/docs/react/writing-stories/decorators"><b>デコレーター</b></a>を使ってストーリーに任意のラッパーを設定できます。上記のコードでは、<code>decorators</code> というキーをデフォルトエクスポートに追加し、描画するコンポーネントの周りに <code>padding</code> を設定してます。ストーリーで使用する「プロバイダー」(例えば、React のコンテキストを設定するライブラリコンポーネントなど) を使うためにも使用します。
111+
💡 <a href="https://storybook.js.org/docs/react/writing-stories/decorators"><b>デコレーター</b></a>を使ってストーリーに任意のラッパーを設定できます。上記のコードでは、<code>decorators</code> というキーをデフォルトエクスポートに追加し、描画するコンポーネントの周りに <code>padding</code> を設定しています。ストーリーで使用する「プロバイダー」(例えば、React のコンテキストを設定するライブラリコンポーネントなど) を使うためにも使用します。
112112
</div>
113113

114114
`TaskStories` をインポートすることで、ストーリーに必要な引数 (args) を最小限の労力で[組み合わせる](https://storybook.js.org/docs/react/writing-stories/args#args-composition)ことができます。そうすることで、2 つのコンポーネントが想定するデータとアクション (呼び出しのモック) の一貫性が保たれます。
@@ -117,16 +117,16 @@ Empty.args = {
117117

118118
<video autoPlay muted playsInline loop>
119119
<source
120-
src="/intro-to-storybook/inprogress-tasklist-states-6-0.mp4"
120+
src="/intro-to-storybook/inprogress-tasklist-states-7-0.mp4"
121121
type="video/mp4"
122122
/>
123123
</video>
124124

125125
## 状態を作りこむ
126126

127-
今のコンポーネントはまだ粗削りですが、ストーリーは見えています。単に `.list-items` だけのためにラッパーを作るのは単純すぎると思うかもしれません。実際にその通りです。ほとんどの場合単なるラッパーのためだけに新しいコンポーネントは作りません`TaskList`**本当の複雑さ**`withPinnedTasks``loading``empty` といったエッジケースに現れているのです
127+
今のコンポーネントはまだ粗削りですが、ストーリーは見えています。単に `.list-items` だけのためにラッパーを作るのは単純すぎると思うかもしれません。実際、その通りです。ほとんどの場合、単なるラッパーのためだけに新しいコンポーネントは作りません`TaskList`**本当の複雑さ**`withPinnedTasks``loading``empty` といったエッジケース(ユーザーが遭遇する可能性のあるまれなバグ)に現れているのです
128128

129-
```js:title=src/components/TaskList.js
129+
```jsx:title=src/components/TaskList.jsx
130130
import React from 'react';
131131

132132
import Task from './Task';
@@ -161,16 +161,16 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
161161
<div className="list-items" key={"empty"} data-testid="empty">
162162
<div className="wrapper-message">
163163
<span className="icon-check" />
164-
<div className="title-message">You have no tasks</div>
165-
<div className="subtitle-message">Sit back and relax</div>
164+
<p className="title-message">You have no tasks</p>
165+
<p className="subtitle-message">Sit back and relax</p>
166166
</div>
167167
</div>
168168
);
169169
}
170170

171171
const tasksInOrder = [
172-
...tasks.filter((t) => t.state === "TASK_PINNED"),
173-
...tasks.filter((t) => t.state !== "TASK_PINNED"),
172+
...tasks.filter((t) => t.state === 'TASK_PINNED'),
173+
...tasks.filter((t) => t.state !== 'TASK_PINNED'),
174174
];
175175
return (
176176
<div className="list-items">
@@ -182,11 +182,11 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
182182
}
183183
```
184184

185-
追加したマークアップで UI は以下のようになります:
185+
追加したマークアップで UI は以下のようになります
186186

187187
<video autoPlay muted playsInline loop>
188188
<source
189-
src="/intro-to-storybook/finished-tasklist-states-6-0.mp4"
189+
src="/intro-to-storybook/finished-tasklist-states-7-0.mp4"
190190
type="video/mp4"
191191
/>
192192
</video>
@@ -197,14 +197,60 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
197197

198198
コンポーネントが大きくなるにつれ、入力の要件も増えていきます。`TaskList` のプロパティの要件を定義しましょう。`Task` が子供のコンポーネントなので、`Task` を表示するのに正しいデータ構造が渡されていることを確認しましょう。時間を節約するため、前の章で `Task` に定義した `propTypes` を再利用しましょう。
199199

200-
```diff:title=src/components/TaskList.js
200+
```diff:title=src/components/TaskList.jsx
201201
import React from 'react';
202202
+ import PropTypes from 'prop-types';
203203

204204
import Task from './Task';
205205

206206
export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) {
207-
...
207+
const events = {
208+
onPinTask,
209+
onArchiveTask,
210+
};
211+
const LoadingRow = (
212+
<div className="loading-item">
213+
<span className="glow-checkbox" />
214+
<span className="glow-text">
215+
<span>Loading</span> <span>cool</span> <span>state</span>
216+
</span>
217+
</div>
218+
);
219+
if (loading) {
220+
return (
221+
<div className="list-items" data-testid="loading" key={"loading"}>
222+
{LoadingRow}
223+
{LoadingRow}
224+
{LoadingRow}
225+
{LoadingRow}
226+
{LoadingRow}
227+
{LoadingRow}
228+
</div>
229+
);
230+
}
231+
if (tasks.length === 0) {
232+
return (
233+
<div className="list-items" key={"empty"} data-testid="empty">
234+
<div className="wrapper-message">
235+
<span className="icon-check" />
236+
<p className="title-message">You have no tasks</p>
237+
<p className="subtitle-message">Sit back and relax</p>
238+
</div>
239+
</div>
240+
);
241+
}
242+
243+
const tasksInOrder = [
244+
...tasks.filter((t) => t.state === 'TASK_PINNED'),
245+
...tasks.filter((t) => t.state !== 'TASK_PINNED'),
246+
];
247+
return (
248+
<div className="list-items">
249+
{tasksInOrder.map((task) => (
250+
<Task key={task.id} task={task} {...events} />
251+
))}
252+
</div>
253+
);
208254
}
209255

210256
+ TaskList.propTypes = {

content/intro-to-storybook/react/ja/conclusion.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,30 +5,30 @@ description: '今までの知識をまとめて、Storybook のテクニック
55

66
Storybook で最初の UI を作成しましたね。お疲れ様でした!ここまでの章で UI コンポーネントを作成し、複合させ、テストし、デプロイする方法を学びました。同じように進めていれば、リポジトリーとデプロイされた Storybook は以下のリンクと同じようになっていることでしょう。
77

8-
[📕 **GitHub のリポジトリー: chromaui/learnstorybook-code**](https://github.com/chromaui/learnstorybook-code)
8+
[📕 **GitHub のリポジトリ: chromaui/learnstorybook-code**](https://github.com/chromaui/learnstorybook-code)
99
<br/>
1010
[🌎 **デプロイされた Storybook**](https://master--5ccbe484c994280020b6d128.chromatic.com)
1111

12-
Storybook は React、React Native、Vue、Angular、Svelte、その他のフレームワークにとって強力なツールです。開発者コミュニティーも活発でアドオンも充実しています。このチュートリアルで紹介した内容は、Storybook で出来ることの一部にすぎません。一度 Storybook を導入すれば、強固な UI を効率的に作れることに驚くことでしょう
12+
Storybook は React、React Native、Vue、Angular、Svelte、その他のフレームワークにとって強力なツールです。開発者コミュニティーも活発でアドオンも充実しています。このチュートリアルで紹介した内容は、Storybook でできることのほんの一部にすぎません。一度 Storybook を導入すれば、強固な UI を効率的に作れることにきっと驚くことでしょう
1313

1414
## さらに学ぶには
1515

16-
もっと深く掘り下げたいですか?役に立つリソースを紹介します
16+
もっと深く掘り下げたい方のために役に立つリソースを紹介します
1717

1818
- [**Storybook の公式ドキュメント**](https://storybook.js.org/docs/react/get-started/introduction)には API ドキュメント、コミュニティのリンク、アドオンのギャラリーがあります。
1919

20-
- [**楽しい Storybook のワークフロー**](https://www.chromatic.com/blog/the-delightful-storybook-workflow)では Squarespace や、メジャーリーグサッカー、ディスカバリーネットワーク、 Apollo GraphQL といった効率の良いチームにおけるワークフローのベストプラクティスを紹介しています
20+
- [**楽しい Storybook のワークフロー**](https://www.chromatic.com/blog/the-delightful-storybook-workflow)では Twilio、Adobe、Peloton、Shopifyといった効率の良いチームにおけるワークフローのベストプラクティスを紹介しています
2121

22-
- [**視覚的なテストのハンドブック**](https://storybook.js.org/tutorials/visual-testing-handbook)では、コンポーネントを Storybook で視覚的にテストする方法を掘り下げています。無料の 31 ページある eBook です。
22+
- [**視覚的なテストのハンドブック (Visual Testing Handbook)**](https://storybook.js.org/tutorials/visual-testing-handbook)では、コンポーネントを Storybook で視覚的にテストする方法を掘り下げています。無料の 31 ページある eBook です。
2323

24-
- [**Storybook Discord**](https://discord.gg/UUt2PJb) では Storybook のコミュニティに参加できます。他の Storybook ユーザーと協力しましょう。
24+
- [**Storybook Discord**](https://discord.gg/UUt2PJb) ではStorybook のコミュニティに参加できます。他の Storybook ユーザーと協力しましょう。
2525

2626
- [**Storybook ブログ**](https://storybook.js.org/blog)ではリリース情報や、UI 開発のワークフローを合理的にするための機能を紹介します。
2727

2828
## 誰が Intro to Storybook チュートリアルを作成しているのでしょうか?
2929

30-
文書や、コード、製作は [Chromatic](https://www.chromatic.com/?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook) の貢献です。このチュートリアルは Chromatic の [GraphQL + React tutorial series](https://www.chromatic.com/blog/graphql-react-tutorial-part-1-6) を参考にしています。
30+
文書や、コード、製作は [Chromatic](https://www.chromatic.com/?utm_source=storybook_website&utm_medium=link&utm_campaign=storybook) の貢献によるものです。このチュートリアルは Chromatic の [GraphQL + React tutorial series](https://www.chromatic.com/blog/graphql-react-tutorial-part-1-6) を参考にしています。
3131

32-
このようなチュートリアルや記事をお望みならば、Storybook のメーリングリストにサインアップしてください
32+
このようなチュートリアルや記事をさらに読みたい場合は、Storybook のメーリングリストに登録することをオススメします
3333

3434
<iframe style="height:400px;width:100%;max-width:800px;margin:0px auto;" src="https://upscri.be/d42fc0?as_embed"></iframe>

content/intro-to-storybook/react/ja/contribute.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ title: '貢献する'
33
description: 'Storybook を世界に広めましょう'
44
---
55

6-
Learn Storybook に協力してください!文法や句読点など小さなことなら、プルリクエストを送ってください。もし大きなことなら [GitHub の issue を追加](https://github.com/chromaui/learnstorybook.com/issues)して議論しましょう。
6+
このチュートリアルの作成にご協力ください!文法や句読点などの些細な問題であれば、プルリクエストを送ってください。もし大規模な問題であれば、 [GitHub の issue を追加](https://github.com/chromaui/learnstorybook.com/issues)して議論しましょう。
77

8-
Learn Storybook はコミュニティによって作成・運営されていますので、最新の状態を保ち、荒い部分を削るには皆さんの協力が必要です。どんな協力でも歓迎します
8+
StoryBookのチュートリアルはコミュニティによって作成・運営されていますので、最新の状態を保ち、荒い部分を削るには皆さんのご協力が不可欠です。どのような協力でも歓迎します
99

1010
## 翻訳
1111

12-
Storybook をすべての人が使用できるように、このチュートリアルを他の言語に翻訳するのを手伝ってください。中国語やスペイン語は特に歓迎します。興味があれば[この issue](https://github.com/chromaui/learnstorybook.com/issues/3) にコメントしてください。
12+
Storybook をすべての人が使用できるように、このチュートリアルの他言語への翻訳にお力を貸してください。中国語やスペイン語はとくに歓迎します。ご興味があれば[この issue](https://github.com/chromaui/learnstorybook.com/issues/3) にコメントしてください。

0 commit comments

Comments
 (0)