diff --git a/content/intro-to-storybook/react/ar/composite-component.md b/content/intro-to-storybook/react/ar/composite-component.md index a5aa3ff87..c23ca53e0 100644 --- a/content/intro-to-storybook/react/ar/composite-component.md +++ b/content/intro-to-storybook/react/ar/composite-component.md @@ -2,7 +2,7 @@ title: 'جمّع مكون مركب' tocTitle: 'مكون مركب' description: 'جمّع مكون مركب من مكونات بسيطة' -commit: '429780a' +commit: 'cfa25b6' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/data.md b/content/intro-to-storybook/react/ar/data.md index 12a7541ff..e6efd7571 100644 --- a/content/intro-to-storybook/react/ar/data.md +++ b/content/intro-to-storybook/react/ar/data.md @@ -2,7 +2,7 @@ title: 'اربط البيانات' tocTitle: 'البياتات' description: 'تعلم كيفية ربط البيانات مع مكون واجهة المستخدم' -commit: 'c70ec15' +commit: 'f9eaeef' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/deploy.md b/content/intro-to-storybook/react/ar/deploy.md index d25856fb4..6aefff472 100644 --- a/content/intro-to-storybook/react/ar/deploy.md +++ b/content/intro-to-storybook/react/ar/deploy.md @@ -2,7 +2,7 @@ title: 'أطلق ستوريبوك' tocTitle: 'أطلق' description: 'تعلم كيفية إطلاق ستوريبوك أونلاين' -commit: '59da1ac' +commit: '4531813' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/get-started.md b/content/intro-to-storybook/react/ar/get-started.md index 65063637e..bbc0d0e09 100644 --- a/content/intro-to-storybook/react/ar/get-started.md +++ b/content/intro-to-storybook/react/ar/get-started.md @@ -2,7 +2,7 @@ title: 'دروس ستوريبوك مع رياكت' tocTitle: '!ابدأ' description: 'جهّز ستوريبوك في بيئة التطوير الخاصة بك' -commit: 'bf3514f' +commit: '2407c3c' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/screen.md b/content/intro-to-storybook/react/ar/screen.md index a96a44b47..ef8c30d9b 100644 --- a/content/intro-to-storybook/react/ar/screen.md +++ b/content/intro-to-storybook/react/ar/screen.md @@ -2,7 +2,7 @@ title: 'أنشئ واجهة' tocTitle: 'واجهات' description: 'أنشئ واجهة من المكونات' -commit: '2275632' +commit: '6262d7f' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/simple-component.md b/content/intro-to-storybook/react/ar/simple-component.md index 4cca4f49b..5bccc5f65 100644 --- a/content/intro-to-storybook/react/ar/simple-component.md +++ b/content/intro-to-storybook/react/ar/simple-component.md @@ -2,7 +2,7 @@ title: 'قم ببناء مكون بسيط' tocTitle: 'مكون بسيط' description: 'قم ببناء مكون بسيط بشكل منعزل' -commit: '9b36e1a' +commit: 'bc897c5' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/ar/using-addons.md b/content/intro-to-storybook/react/ar/using-addons.md index d2ed0077a..f0d174b7e 100644 --- a/content/intro-to-storybook/react/ar/using-addons.md +++ b/content/intro-to-storybook/react/ar/using-addons.md @@ -2,7 +2,7 @@ title: 'الإضافات' tocTitle: 'الإضافات' description: 'تعلم كيفية دمج و استخدام إضافات ضبط مشهورة' -commit: 'f89cfe0' +commit: '17d3ab9' --- <div style="direction: rtl"> diff --git a/content/intro-to-storybook/react/de/composite-component.md b/content/intro-to-storybook/react/de/composite-component.md index 4c5afe51a..4f924495c 100644 --- a/content/intro-to-storybook/react/de/composite-component.md +++ b/content/intro-to-storybook/react/de/composite-component.md @@ -2,7 +2,7 @@ title: 'Baue eine Komposition' tocTitle: 'Komposition' description: 'Setze eine Komposition aus einfachen Komponenten zusammen' -commit: '429780a' +commit: 'cfa25b6' --- Im letzten Kapitel haben wir unsere erste Komponente entwickelt; in diesem Kapitel erweitern wir das Gelernte, um `TaskList` zu bauen, eine Liste von Aufgaben. Lass uns Komponenten miteinander kombinieren und sehen, was passiert, wenn mehr Komplexität ins Spiel kommt. diff --git a/content/intro-to-storybook/react/de/data.md b/content/intro-to-storybook/react/de/data.md index 8978599b8..d899c783c 100644 --- a/content/intro-to-storybook/react/de/data.md +++ b/content/intro-to-storybook/react/de/data.md @@ -2,7 +2,7 @@ title: 'Daten einbinden' tocTitle: 'Daten' description: 'Lerne, Daten in deine UI-Komponente einzubinden' -commit: 'c70ec15' +commit: 'f9eaeef' --- Bisher haben wir isolierte, zustandslose Komponenten erstellt - perfekt für Storybook, aber letztlich nutzlos, bis wir ihnen einige Daten in unserer App zur Verfügung stellen. diff --git a/content/intro-to-storybook/react/de/get-started.md b/content/intro-to-storybook/react/de/get-started.md index 6539ffd45..3c65a7b4c 100644 --- a/content/intro-to-storybook/react/de/get-started.md +++ b/content/intro-to-storybook/react/de/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook für React Tutorial' tocTitle: 'Leg los' description: 'Richte Storybook in deiner Entwicklungsumgebung ein' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook läuft parallel zu deiner App im Entwicklungs-Modus. Es hilft dir, UI-Komponenten unabhängig von Business-Logik und vom Kontext deiner App zu entwickeln. Diese Edition von "Lerne Storybook" ist für React; es gibt andere Editionen für [Vue](/intro-to-storybook/vue/en/get-started) und [Angular](/intro-to-storybook/angular/en/get-started). diff --git a/content/intro-to-storybook/react/de/screen.md b/content/intro-to-storybook/react/de/screen.md index 68f7f00a4..45de73050 100644 --- a/content/intro-to-storybook/react/de/screen.md +++ b/content/intro-to-storybook/react/de/screen.md @@ -2,7 +2,7 @@ title: 'Einen Screen erstellen' tocTitle: 'Screens' description: 'Stelle einen Screen aus Komponenten zusammen' -commit: '2275632' +commit: '6262d7f' --- Bisher haben wir uns darauf konzentriert, UIs bottom-up zu bauen; klein starten und Komplexität hinzufügen. Das erlaubte uns, jede Komponente in Isolation zu entwickeln, ihre Anforderungen an Daten zu ermitteln und damit in Storybook herumzuspielen. All das, ohne einen Server aufzusetzen oder Screens zu erstellen. diff --git a/content/intro-to-storybook/react/de/simple-component.md b/content/intro-to-storybook/react/de/simple-component.md index b341d4aff..e1b1aa74c 100644 --- a/content/intro-to-storybook/react/de/simple-component.md +++ b/content/intro-to-storybook/react/de/simple-component.md @@ -2,7 +2,7 @@ title: 'Baue eine einfache Komponente' tocTitle: 'Einfache Komponente' description: 'Baue eine einfache Komponente in Isolation' -commit: '9b36e1a' +commit: 'bc897c5' --- Beim Bauen unserer UI werden wir nach der [Component-Driven Development](https://www.componentdriven.org/) (CDD) Methodik vorgehen. Das it ein Vorgehen, in dem UIs "bottom up" entwickelt werden. Man beginnt mit Komponenten und endet mit Screens. CDD hilft dabei, die Komplexität zu begrenzen, mit der man beim Bauen einer UI konfrontiert wird. diff --git a/content/intro-to-storybook/react/en/composite-component.md b/content/intro-to-storybook/react/en/composite-component.md index 81596d5a4..2368c7a96 100644 --- a/content/intro-to-storybook/react/en/composite-component.md +++ b/content/intro-to-storybook/react/en/composite-component.md @@ -2,7 +2,7 @@ title: 'Assemble a composite component' tocTitle: 'Composite component' description: 'Assemble a composite component out of simpler components' -commit: '429780a' +commit: 'cfa25b6' --- Last chapter, we built our first component; this chapter extends what we learned to make TaskList, a list of Tasks. Let’s combine components together and see what happens when we introduce more complexity. @@ -19,14 +19,32 @@ Since `Task` data can be sent asynchronously, we **also** need a loading state t ## Get set up -A composite component isn’t much different from the basic components it contains. Create a `TaskList` component and an accompanying story file: `src/components/TaskList.jsx` and `src/components/TaskList.stories.jsx`. +A composite component isn’t much different from the basic components it contains. Create a `TaskList` component and an accompanying story file: `src/components/TaskList.tsx` and `src/components/TaskList.stories.tsx`. Start with a rough implementation of the `TaskList`. You’ll need to import the `Task` component from earlier and pass in the attributes and actions as inputs. -```jsx:title=src/components/TaskList.jsx +```tsx:title=src/components/TaskList.tsx +import type { TaskData } from '../types'; + import Task from './Task'; -export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { +type TaskListProps = { + /** Checks if it's in loading state */ + loading?: boolean; + /** The list of tasks */ + tasks: TaskData[]; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; +}; + +export default function TaskList({ + loading = false, + tasks, + onPinTask, + onArchiveTask, +}: TaskListProps) { const events = { onPinTask, onArchiveTask, @@ -42,7 +60,7 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { return ( <div className="list-items"> - {tasks.map(task => ( + {tasks.map((task) => ( <Task key={task.id} task={task} {...events} /> ))} </div> @@ -52,25 +70,30 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { Next, create `Tasklist`’s test states in the story file. -```jsx:title=src/components/TaskList.stories.jsx +```tsx:title=src/components/TaskList.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; + import TaskList from './TaskList'; import * as TaskStories from './Task.stories'; -export default { +const meta = { component: TaskList, title: 'TaskList', decorators: [(story) => <div style={{ margin: '3rem' }}>{story()}</div>], - tags: ['autodocs'], + tags: ["autodocs"], args: { ...TaskStories.ActionsData, }, -}; +} satisfies Meta<typeof TaskList>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = { +export const Default: Story = { args: { // Shaping the stories through args composition. - // The data was inherited from the Default story in Task.stories.jsx. + // The data was inherited from the Default story in Task.stories.tsx. tasks: [ { ...TaskStories.Default.args.task, id: '1', title: 'Task 1' }, { ...TaskStories.Default.args.task, id: '2', title: 'Task 2' }, @@ -82,7 +105,7 @@ export const Default = { }, }; -export const WithPinnedTasks = { +export const WithPinnedTasks: Story = { args: { tasks: [ ...Default.args.tasks.slice(0, 5), @@ -91,14 +114,14 @@ export const WithPinnedTasks = { }, }; -export const Loading = { +export const Loading: Story = { args: { tasks: [], loading: true, }, }; -export const Empty = { +export const Empty: Story = { args: { // Shaping the stories through args composition. // Inherited data coming from the Loading story. @@ -129,10 +152,28 @@ Now check Storybook for the new `TaskList` stories. Our component is still rough, but now we have an idea of the stories to work toward. You might be thinking that the `.list-items` wrapper is overly simplistic. You're right – in most cases, we wouldn’t create a new component just to add a wrapper. But the **real complexity** of the `TaskList` component is revealed in the edge cases `withPinnedTasks`, `loading`, and `empty`. -```jsx:title=src/components/TaskList.jsx +```tsx:title=src/components/TaskList.tsx +import type { TaskData } from '../types'; + import Task from './Task'; -export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { +type TaskListProps = { + /** Checks if it's in loading state */ + loading?: boolean; + /** The list of tasks */ + tasks: TaskData[]; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; +}; + +export default function TaskList({ + loading = false, + tasks, + onPinTask, + onArchiveTask, +}: TaskListProps) { const events = { onPinTask, onArchiveTask, @@ -170,8 +211,8 @@ export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { } const tasksInOrder = [ - ...tasks.filter((t) => t.state === 'TASK_PINNED'), - ...tasks.filter((t) => t.state !== 'TASK_PINNED'), + ...tasks.filter((t) => t.state === "TASK_PINNED"), + ...tasks.filter((t) => t.state !== "TASK_PINNED"), ]; return ( <div className="list-items"> @@ -194,80 +235,6 @@ The added markup results in the following UI: Note the position of the pinned item in the list. We want the pinned item to render at the top of the list to make it a priority for our users. -## Data requirements and props - -As the component grows, so do input requirements. Define the prop requirements of `TaskList`. Because `Task` is a child component, make sure to provide data in the right shape to render it. To save time and headache, reuse the `propTypes` you defined in `Task` earlier. - -```diff:title=src/components/TaskList.jsx -+ import PropTypes from 'prop-types'; - -import Task from './Task'; - -export default function TaskList({ loading, tasks, onPinTask, onArchiveTask }) { - const events = { - onPinTask, - onArchiveTask, - }; - const LoadingRow = ( - <div className="loading-item"> - <span className="glow-checkbox" /> - <span className="glow-text"> - <span>Loading</span> <span>cool</span> <span>state</span> - </span> - </div> - ); - if (loading) { - return ( - <div className="list-items" data-testid="loading" key={"loading"}> - {LoadingRow} - {LoadingRow} - {LoadingRow} - {LoadingRow} - {LoadingRow} - {LoadingRow} - </div> - ); - } - if (tasks.length === 0) { - return ( - <div className="list-items" key={"empty"} data-testid="empty"> - <div className="wrapper-message"> - <span className="icon-check" /> - <p className="title-message">You have no tasks</p> - <p className="subtitle-message">Sit back and relax</p> - </div> - </div> - ); - } - - const tasksInOrder = [ - ...tasks.filter((t) => t.state === 'TASK_PINNED'), - ...tasks.filter((t) => t.state !== 'TASK_PINNED'), - ]; - return ( - <div className="list-items"> - {tasksInOrder.map((task) => ( - <Task key={task.id} task={task} {...events} /> - ))} - </div> - ); -} - -+ TaskList.propTypes = { -+ /** Checks if it's in loading state */ -+ loading: PropTypes.bool, -+ /** The list of tasks */ -+ tasks: PropTypes.arrayOf(Task.propTypes.task).isRequired, -+ /** Event to change the task to pinned */ -+ onPinTask: PropTypes.func, -+ /** Event to change the task to archived */ -+ onArchiveTask: PropTypes.func, -+ }; -+ TaskList.defaultProps = { -+ loading: false, -+ }; -``` - <div class="aside"> 💡 Don't forget to commit your changes with git! </div> diff --git a/content/intro-to-storybook/react/en/data.md b/content/intro-to-storybook/react/en/data.md index 64cdb02aa..af7b77efa 100644 --- a/content/intro-to-storybook/react/en/data.md +++ b/content/intro-to-storybook/react/en/data.md @@ -2,7 +2,7 @@ title: 'Wire in data' tocTitle: 'Data' description: 'Learn how to wire in data to your UI component' -commit: 'c70ec15' +commit: 'f9eaeef' --- So far, we have created isolated stateless components-–great for Storybook, but ultimately not helpful until we give them some data in our app. @@ -21,25 +21,34 @@ Add the necessary dependencies to your project with: yarn add @reduxjs/toolkit react-redux ``` -First, we’ll construct a simple Redux store that responds to actions that change the task's state in a file called `store.js` in the `src/lib` directory (intentionally kept simple): +First, we’ll construct a simple Redux store that responds to actions that change the task's state in a file called `store.ts` in the `src/lib` directory (intentionally kept simple): -```js:title=src/lib/store.js +```ts:title=src/lib/store.ts /* A simple redux store/actions/reducer implementation. * A true app would be more complex and separated into different files. */ -import { configureStore, createSlice } from '@reduxjs/toolkit'; +import type { TaskData } from '../types'; + +import { configureStore, createSlice, PayloadAction } from '@reduxjs/toolkit'; + +interface TaskBoxState { + tasks: TaskData[]; + status: 'idle' | 'loading' | 'failed'; + error: string | null; +} /* * The initial state of our store when the app loads. * Usually, you would fetch this from a server. Let's not worry about that now */ -const defaultTasks = [ +const defaultTasks: TaskData[] = [ { id: '1', title: 'Something', state: 'TASK_INBOX' }, { id: '2', title: 'Something more', state: 'TASK_INBOX' }, { id: '3', title: 'Something else', state: 'TASK_INBOX' }, { id: '4', title: 'Something again', state: 'TASK_INBOX' }, ]; -const TaskBoxData = { + +const TaskBoxData: TaskBoxState = { tasks: defaultTasks, status: 'idle', error: null, @@ -54,11 +63,13 @@ const TasksSlice = createSlice({ name: 'taskbox', initialState: TaskBoxData, reducers: { - updateTaskState: (state, action) => { - const { id, newTaskState } = action.payload; - const task = state.tasks.findIndex((task) => task.id === id); - if (task >= 0) { - state.tasks[task].state = newTaskState; + updateTaskState: ( + state, + action: PayloadAction<{ id: string; newTaskState: TaskData['state'] }> + ) => { + const task = state.tasks.find((task) => task.id === action.payload.id); + if (task) { + task.state = action.payload.newTaskState; } }, }, @@ -72,46 +83,48 @@ export const { updateTaskState } = TasksSlice.actions; * Read more about Redux's configureStore in the docs: * https://redux-toolkit.js.org/api/configureStore */ + const store = configureStore({ reducer: { taskbox: TasksSlice.reducer, }, }); +// Define RootState and AppDispatch types +export type RootState = ReturnType<typeof store.getState>; +export type AppDispatch = typeof store.dispatch; + export default store; ``` Then we’ll update our `TaskList` component to connect to the Redux store and render the tasks we are interested in: -```jsx:title=src/components/TaskList.jsx +```tsx:title=src/components/TaskList.tsx import Task from './Task'; import { useDispatch, useSelector } from 'react-redux'; -import { updateTaskState } from '../lib/store'; +import { updateTaskState, RootState, AppDispatch } from '../lib/store'; export default function TaskList() { // We're retrieving our state from the store - const tasks = useSelector((state) => { + const tasks = useSelector((state: RootState) => { const tasksInOrder = [ ...state.taskbox.tasks.filter((t) => t.state === 'TASK_PINNED'), ...state.taskbox.tasks.filter((t) => t.state !== 'TASK_PINNED'), ]; const filteredTasks = tasksInOrder.filter( - (t) => t.state === 'TASK_INBOX' || t.state === 'TASK_PINNED' + (t) => t.state === "TASK_INBOX" || t.state === 'TASK_PINNED' ); return filteredTasks; }); - - const { status } = useSelector((state) => state.taskbox); - - const dispatch = useDispatch(); - - const pinTask = (value) => { + const { status } = useSelector((state: RootState) => state.taskbox); + const dispatch = useDispatch<AppDispatch>(); + const pinTask = (value: string) => { // We're dispatching the Pinned event back to our store dispatch(updateTaskState({ id: value, newTaskState: 'TASK_PINNED' })); }; - const archiveTask = (value) => { + const archiveTask = (value: string) => { // We're dispatching the Archive event back to our store dispatch(updateTaskState({ id: value, newTaskState: 'TASK_ARCHIVED' })); }; @@ -123,9 +136,9 @@ export default function TaskList() { </span> </div> ); - if (status === 'loading') { + if (status === "loading") { return ( - <div className="list-items" data-testid="loading" key={"loading"}> + <div className="list-items" data-testid="loading" key="loading"> {LoadingRow} {LoadingRow} {LoadingRow} @@ -137,7 +150,7 @@ export default function TaskList() { } if (tasks.length === 0) { return ( - <div className="list-items" key={"empty"} data-testid="empty"> + <div className="list-items" key="empty" data-testid="empty"> <div className="wrapper-message"> <span className="icon-check" /> <p className="title-message">You have no tasks</p> @@ -148,13 +161,13 @@ export default function TaskList() { } return ( - <div className="list-items" data-testid="success" key={"success"}> + <div className="list-items" data-testid="success" key="success"> {tasks.map((task) => ( <Task key={task.id} task={task} - onPinTask={(task) => pinTask(task)} - onArchiveTask={(task) => archiveTask(task)} + onPinTask={pinTask} + onArchiveTask={archiveTask} /> ))} </div> @@ -162,7 +175,7 @@ export default function TaskList() { } ``` -Now that we have some actual data populating our component, obtained from the Redux store, we could have wired it to `src/App.js` and render the component there. But for now, let's hold off doing that and continue on our component-driven journey. +Now that we have some actual data populating our component, obtained from the Redux store, we could have wired it to `src/App.tsx` and render the component there. But for now, let's hold off doing that and continue on our component-driven journey. Don't worry about it. We'll take care of it in the next chapter. @@ -174,7 +187,11 @@ Our Storybook stories have stopped working with this change because our `Tasklis We can use various approaches to solve this issue. Still, as our app is pretty straightforward, we can rely on a decorator, similar to what we did in the [previous chapter](/intro-to-storybook/react/en/composite-component) and provide a mocked store-- in our Storybook stories: -```jsx:title=src/components/TaskList.stories.jsx +```tsx:title=src/components/TaskList.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; + +import type { TaskData } from '../types'; + import TaskList from './TaskList'; import * as TaskStories from './Task.stories'; @@ -192,18 +209,24 @@ export const MockedState = { { ...TaskStories.Default.args.task, id: '4', title: 'Task 4' }, { ...TaskStories.Default.args.task, id: '5', title: 'Task 5' }, { ...TaskStories.Default.args.task, id: '6', title: 'Task 6' }, - ], + ] as TaskData[], status: 'idle', error: null, }; // A super-simple mock of a redux store -const Mockstore = ({ taskboxState, children }) => ( +const Mockstore = ({ + taskboxState, + children, +}: { + taskboxState: typeof MockedState; + children: React.ReactNode; +}) => ( <Provider store={configureStore({ reducer: { taskbox: createSlice({ - name: 'taskbox', + name: "taskbox", initialState: taskboxState, reducers: { updateTaskState: (state, action) => { @@ -222,24 +245,27 @@ const Mockstore = ({ taskboxState, children }) => ( </Provider> ); -export default { +const meta = { component: TaskList, title: 'TaskList', decorators: [(story) => <div style={{ margin: '3rem' }}>{story()}</div>], tags: ['autodocs'], excludeStories: /.*MockedState$/, -}; +} satisfies Meta<typeof TaskList>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = { +export const Default: Story = { decorators: [ (story) => <Mockstore taskboxState={MockedState}>{story()}</Mockstore>, ], }; -export const WithPinnedTasks = { +export const WithPinnedTasks: Story = { decorators: [ (story) => { - const pinnedtasks = [ + const pinnedtasks: TaskData[] = [ ...MockedState.tasks.slice(0, 5), { id: '6', title: 'Task 6 (pinned)', state: 'TASK_PINNED' }, ]; @@ -258,7 +284,7 @@ export const WithPinnedTasks = { ], }; -export const Loading = { +export const Loading: Story = { decorators: [ (story) => ( <Mockstore @@ -273,7 +299,7 @@ export const Loading = { ], }; -export const Empty = { +export const Empty: Story = { decorators: [ (story) => ( <Mockstore diff --git a/content/intro-to-storybook/react/en/deploy.md b/content/intro-to-storybook/react/en/deploy.md index 73a879152..7c4384435 100644 --- a/content/intro-to-storybook/react/en/deploy.md +++ b/content/intro-to-storybook/react/en/deploy.md @@ -2,7 +2,7 @@ title: 'Deploy Storybook' tocTitle: 'Deploy' description: 'Learn how to deploy Storybook online' -commit: '59da1ac' +commit: '4531813' --- Throughout this tutorial, we built components on our local development machine. At some point, we'll need to share our work to get team feedback. Let's deploy Storybook online to help teammates review UI implementation. diff --git a/content/intro-to-storybook/react/en/get-started.md b/content/intro-to-storybook/react/en/get-started.md index 9059d7eea..592463c59 100644 --- a/content/intro-to-storybook/react/en/get-started.md +++ b/content/intro-to-storybook/react/en/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook for React tutorial' tocTitle: 'Get started' description: 'Set up Storybook in your development environment' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook runs alongside your app in development mode. It helps you build UI components isolated from the business logic and context of your app. This edition of the Intro to Storybook tutorial is for React; other editions exist for [React Native](/intro-to-storybook/react-native/en/get-started), [Vue](/intro-to-storybook/vue/en/get-started), [Angular](/intro-to-storybook/angular/en/get-started), [Svelte](/intro-to-storybook/svelte/en/get-started) and [Ember](/intro-to-storybook/ember/en/get-started). diff --git a/content/intro-to-storybook/react/en/screen.md b/content/intro-to-storybook/react/en/screen.md index 166d641bd..8249ec433 100644 --- a/content/intro-to-storybook/react/en/screen.md +++ b/content/intro-to-storybook/react/en/screen.md @@ -2,7 +2,7 @@ title: 'Construct a screen' tocTitle: 'Screens' description: 'Construct a screen out of components' -commit: '2275632' +commit: '6262d7f' --- We've concentrated on building UIs from the bottom up, starting small and adding complexity. Doing so has allowed us to develop each component in isolation, figure out its data needs, and play with it in Storybook. All without needing to stand up a server or build out screens! @@ -13,46 +13,55 @@ In this chapter, we continue to increase the sophistication by combining compone As our app is straightforward, the screen we'll build is pretty trivial, simply fetching data from a remote API, wrapping the `TaskList` component (which supplies its own data from Redux), and pulling a top-level `error` field out of Redux. -We'll start by updating our Redux store (in `src/lib/store.js`) to connect to a remote API and handle the various states for our application (i.e., `error`, `succeeded`): +We'll start by updating our Redux store (in `src/lib/store.ts`) to connect to a remote API and handle the various states for our application (i.e., `error`, `succeeded`): -```diff:title=src/lib/store.js +```ts:title=src/lib/store.ts /* A simple redux store/actions/reducer implementation. * A true app would be more complex and separated into different files. */ +import type { TaskData } from '../types'; + import { configureStore, createSlice, -+ createAsyncThunk, + createAsyncThunk, + PayloadAction, } from '@reduxjs/toolkit'; +interface TaskBoxState { + tasks: TaskData[]; + status: 'idle' | 'loading' | 'failed' | 'succeeded'; + error: string | null; +} + /* * The initial state of our store when the app loads. * Usually, you would fetch this from a server. Let's not worry about that now */ - -const TaskBoxData = { +const TaskBoxData: TaskBoxState = { tasks: [], status: 'idle', error: null, }; - /* * Creates an asyncThunk to fetch tasks from a remote endpoint. * You can read more about Redux Toolkit's thunks in the docs: * https://redux-toolkit.js.org/api/createAsyncThunk */ -+ export const fetchTasks = createAsyncThunk('todos/fetchTodos', async () => { -+ const response = await fetch( -+ 'https://jsonplaceholder.typicode.com/todos?userId=1' -+ ); -+ const data = await response.json(); -+ const result = data.map((task) => ({ -+ id: `${task.id}`, -+ title: task.title, -+ state: task.completed ? 'TASK_ARCHIVED' : 'TASK_INBOX', -+ })); -+ return result; -+ }); +export const fetchTasks = createAsyncThunk('taskbox/fetchTasks', async () => { + const response = await fetch( + 'https://jsonplaceholder.typicode.com/todos?userId=1' + ); + const data = await response.json(); + const result = data.map( + (task: { id: number; title: string; completed: boolean }) => ({ + id: `${task.id}`, + title: task.title, + state: task.completed ? 'TASK_ARCHIVED' : 'TASK_INBOX', + }) + ); + return result; +}); /* * The store is created here. @@ -63,11 +72,13 @@ const TasksSlice = createSlice({ name: 'taskbox', initialState: TaskBoxData, reducers: { - updateTaskState: (state, action) => { - const { id, newTaskState } = action.payload; - const task = state.tasks.findIndex((task) => task.id === id); - if (task >= 0) { - state.tasks[task].state = newTaskState; + updateTaskState: ( + state, + action: PayloadAction<{ id: string; newTaskState: TaskData['state'] }> + ) => { + const task = state.tasks.find((task) => task.id === action.payload.id); + if (task) { + task.state = action.payload.newTaskState; } }, }, @@ -75,25 +86,25 @@ const TasksSlice = createSlice({ * Extends the reducer for the async actions * You can read more about it at https://redux-toolkit.js.org/api/createAsyncThunk */ -+ extraReducers(builder) { -+ builder -+ .addCase(fetchTasks.pending, (state) => { -+ state.status = 'loading'; -+ state.error = null; -+ state.tasks = []; -+ }) -+ .addCase(fetchTasks.fulfilled, (state, action) => { -+ state.status = 'succeeded'; -+ state.error = null; -+ // Add any fetched tasks to the array -+ state.tasks = action.payload; -+ }) -+ .addCase(fetchTasks.rejected, (state) => { -+ state.status = 'failed'; -+ state.error = "Something went wrong"; -+ state.tasks = []; -+ }); -+ }, + extraReducers(builder) { + builder + .addCase(fetchTasks.pending, (state) => { + state.status = 'loading'; + state.error = null; + state.tasks = []; + }) + .addCase(fetchTasks.fulfilled, (state, action) => { + state.status = 'succeeded'; + state.error = null; + // Add any fetched tasks to the array + state.tasks = action.payload; + }) + .addCase(fetchTasks.rejected, (state) => { + state.status = 'failed'; + state.error = 'Something went wrong'; + state.tasks = []; + }); + }, }); // The actions contained in the slice are exported for usage in our components @@ -110,24 +121,28 @@ const store = configureStore({ }, }); +// Define RootState and AppDispatch types +export type RootState = ReturnType<typeof store.getState>; +export type AppDispatch = typeof store.dispatch; + export default store; ``` -Now that we've updated our store to retrieve the data from a remote API endpoint and prepared it to handle the various states of our app, let's create our `InboxScreen.jsx` in the `src/components` directory: +Now that we've updated our store to retrieve the data from a remote API endpoint and prepared it to handle the various states of our app, let's create our `InboxScreen.tsx` in the `src/components` directory: -```jsx:title=src/components/InboxScreen.jsx +```tsx:title=src/components/InboxScreen.tsx import { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { fetchTasks } from '../lib/store'; +import { AppDispatch, fetchTasks, RootState } from '../lib/store'; -import TaskList from './TaskList'; +import TaskList from "./TaskList"; export default function InboxScreen() { - const dispatch = useDispatch(); + const dispatch = useDispatch<AppDispatch>(); // We're retrieving the error field from our updated store - const { error } = useSelector((state) => state.taskbox); + const { error } = useSelector((state: RootState) => state.taskbox); // The useEffect triggers the data fetching when the component is mounted useEffect(() => { dispatch(fetchTasks()); @@ -153,11 +168,12 @@ export default function InboxScreen() { </div> ); } + ``` We also need to change our `App` component to render the `InboxScreen` (eventually, we would use a router to choose the correct screen, but let's not worry about that here): -```diff:title=src/App.jsx +```diff:title=src/App.tsx - import { useState } from 'react' - import reactLogo from './assets/react.svg' - import viteLogo from '/vite.svg' @@ -204,24 +220,30 @@ export default App; However, where things get interesting is in rendering the story in Storybook. -As we saw previously, the `TaskList` component is now a **connected** component and relies on a Redux store to render the tasks. As our `InboxScreen` is also a connected component, we'll do something similar and provide a store to the story. So when we set our stories in `InboxScreen.stories.jsx`: +As we saw previously, the `TaskList` component is now a **connected** component and relies on a Redux store to render the tasks. As our `InboxScreen` is also a connected component, we'll do something similar and provide a store to the story. So when we set our stories in `InboxScreen.stories.tsx`: + +```tsx:title=src/components/InboxScreen.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; -```jsx:title=src/components/InboxScreen.stories.jsx import InboxScreen from './InboxScreen'; + import store from '../lib/store'; import { Provider } from 'react-redux'; -export default { +const meta = { component: InboxScreen, title: 'InboxScreen', decorators: [(story) => <Provider store={store}>{story()}</Provider>], tags: ['autodocs'], -}; +} satisfies Meta<typeof InboxScreen>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = {}; +export const Default: Story = {}; -export const Error = {}; +export const Error: Story = {}; ``` We can quickly spot an issue with the `error` story. Instead of displaying the right state, it shows a list of tasks. One way to sidestep this issue would be to provide a mocked version for each state, similar to what we did in the last chapter. Instead, we'll use a well-known API mocking library alongside a Storybook addon to help us solve this issue. @@ -240,20 +262,19 @@ In your terminal, run the following command to generate a generic service worker yarn init-msw ``` -Then, we'll need to update our `.storybook/preview.js` and initialize them: +Then, we'll need to update our `.storybook/preview.ts` and initialize them: + +```diff:title=.storybook/preview.ts +import type { Preview } from '@storybook/react'; + +import { initialize, mswLoader } from 'msw-storybook-addon'; -```diff:title=.storybook/preview.js import '../src/index.css'; // Registers the msw addon -+ import { initialize, mswLoader } from 'msw-storybook-addon'; - -// Initialize MSW -+ initialize(); +initialize(); -//👇 Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI. -/** @type { import('@storybook/react').Preview } */ -const preview = { +const preview: Preview = { parameters: { controls: { matchers: { @@ -262,7 +283,7 @@ const preview = { }, }, }, -+ loaders: [mswLoader], + loaders: [mswLoader], }; export default preview; @@ -270,7 +291,9 @@ export default preview; Finally, update the `InboxScreen` stories and include a [parameter](https://storybook.js.org/docs/writing-stories/parameters) that mocks the remote API calls: -```diff:title=src/components/InboxScreen.stories.jsx +```diff:title=src/components/InboxScreen.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; + import InboxScreen from './InboxScreen'; import store from '../lib/store'; @@ -281,14 +304,17 @@ import store from '../lib/store'; import { Provider } from 'react-redux'; -export default { +const meta = { component: InboxScreen, title: 'InboxScreen', decorators: [(story) => <Provider store={store}>{story()}</Provider>], tags: ['autodocs'], -}; +} satisfies Meta<typeof InboxScreen>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = { +export const Default: Story = { + parameters: { + msw: { + handlers: [ @@ -300,7 +326,7 @@ export const Default = { + }, }; -export const Error = { +export const Error: Story = { + parameters: { + msw: { + handlers: [ @@ -346,7 +372,9 @@ The `@storybook/addon-interactions` helps us visualize our tests in Storybook, p Let's see it in action! Update your newly created `InboxScreen` story, and set up component interactions by adding the following: -```diff:title=src/components/InboxScreen.stories.jsx +```diff:title=src/components/InboxScreen.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; + import InboxScreen from './InboxScreen'; import store from '../lib/store'; @@ -364,14 +392,17 @@ import { Provider } from 'react-redux'; + waitForElementToBeRemoved + } from '@storybook/test'; -export default { +const meta = { component: InboxScreen, title: 'InboxScreen', decorators: [(story) => <Provider store={store}>{story()}</Provider>], tags: ['autodocs'], -}; +} satisfies Meta<typeof InboxScreen>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = { +export const Default: Story = { parameters: { msw: { handlers: [ @@ -395,7 +426,7 @@ export const Default = { + }, }; -export const Error = { +export const Error: Story = { parameters: { msw: { handlers: [ diff --git a/content/intro-to-storybook/react/en/simple-component.md b/content/intro-to-storybook/react/en/simple-component.md index b50750122..07056aa4f 100644 --- a/content/intro-to-storybook/react/en/simple-component.md +++ b/content/intro-to-storybook/react/en/simple-component.md @@ -2,7 +2,7 @@ title: 'Build a simple component' tocTitle: 'Simple component' description: 'Build a simple component in isolation' -commit: '9b36e1a' +commit: 'bc897c5' --- We’ll build our UI following a [Component-Driven Development](https://www.componentdriven.org/) (CDD) methodology. It’s a process that builds UIs from the “bottom-up”, starting with components and ending with screens. CDD helps you scale the amount of complexity you’re faced with as you build out the UI. @@ -20,16 +20,38 @@ As we start to build `Task`, we first write our test states that correspond to t ## Get set up -First, let’s create the task component and its accompanying story file: `src/components/Task.jsx` and `src/components/Task.stories.jsx`. +First, let’s create the task component and its accompanying story file: `src/components/Task.tsx` and `src/components/Task.stories.tsx`. We’ll begin with a baseline implementation of the `Task`, simply taking in the attributes we know we’ll need and the two actions you can take on a task (to move it between lists): -```jsx:title=src/components/Task.jsx -export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { +```tsx:title=src/components/Task.tsx +type TaskData = { + id: string; + title: string; + state: 'TASK_ARCHIVED' | 'TASK_INBOX' | 'TASK_PINNED'; +}; + +type TaskProps = { + task: TaskData; + onArchiveTask: (id: string) => void; + onPinTask: (id: string) => void; +}; + +export default function Task({ + task: { id, title, state }, + onArchiveTask, + onPinTask, +}: TaskProps) { return ( <div className="list-item"> <label htmlFor={`title-${id}`} aria-label={title}> - <input type="text" value={title} readOnly={true} name="title" id={`title-${id}`} /> + <input + type="text" + value={title} + readOnly={true} + name="title" + id={`title-${id}`} + /> </label> </div> ); @@ -40,8 +62,10 @@ Above, we render straightforward markup for `Task` based on the existing HTML st Below we build out Task’s three test states in the story file: -```jsx:title=src/components/Task.stories.jsx -import { fn } from "@storybook/test"; +```tsx:title=src/components/Task.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; + +import { fn } from '@storybook/test'; import Task from './Task'; @@ -50,7 +74,7 @@ export const ActionsData = { onPinTask: fn(), }; -export default { +const meta = { component: Task, title: 'Task', tags: ['autodocs'], @@ -59,9 +83,12 @@ export default { args: { ...ActionsData, }, -}; +} satisfies Meta<typeof Task>; + +export default meta; +type Story = StoryObj<typeof meta>; -export const Default = { +export const Default: Story = { args: { task: { id: '1', @@ -71,7 +98,7 @@ export const Default = { }, }; -export const Pinned = { +export const Pinned: Story = { args: { task: { ...Default.args.task, @@ -80,7 +107,7 @@ export const Pinned = { }, }; -export const Archived = { +export const Archived: Story = { args: { task: { ...Default.args.task, @@ -125,13 +152,14 @@ When creating a story, we use a base `task` arg to build out the shape of the ta We'll need to make a couple of changes to Storybook's configuration files so it notices our recently created stories and allows us to use the application's CSS file (located in `src/index.css`). -Start by changing your Storybook configuration file (`.storybook/main.js`) to the following: +Start by changing your Storybook configuration file (`.storybook/main.ts`) to the following: -```diff:title=.storybook/main.js -/** @type { import('@storybook/react-vite').StorybookConfig } */ -const config = { +```diff:title=.storybook/main.ts +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { - stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], -+ stories: ['../src/components/**/*.stories.@(js|jsx)'], ++ stories: ['../src/components/**/*.stories.@(ts|tsx)'], staticDirs: ['../public'], addons: [ '@storybook/addon-links', @@ -139,21 +167,22 @@ const config = { '@storybook/addon-interactions', ], framework: { - name: '@storybook/react-vite', + name: "@storybook/react-vite", options: {}, }, }; + export default config; ``` -After completing the change above, inside the `.storybook` folder, change your `preview.js` to the following: +After completing the change above, inside the `.storybook` folder, change your `preview.ts` to the following: + +```diff:title=.storybook/preview.ts +import type { Preview } from '@storybook/react'; -```diff:title=.storybook/preview.js + import '../src/index.css'; -//👇 Configures Storybook to log the actions( onArchiveTask and onPinTask ) in the UI. -/** @type { import('@storybook/react').Preview } */ -const preview = { +const preview: Preview = { parameters: { controls: { matchers: { @@ -184,8 +213,27 @@ Now that we have Storybook set up, styles imported, and test cases built out, we The component is still rudimentary at the moment. First, write the code that achieves the design without going into too much detail: -```jsx:title=src/components/Task.jsx -export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { +```tsx:title=src/components/Task.tsx +type TaskData = { + id: string; + title: string; + state: 'TASK_ARCHIVED' | 'TASK_INBOX' | 'TASK_PINNED'; +}; + +type TaskProps = { + /** Composition of the task */ + task: TaskData; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; +}; + +export default function Task({ + task: { id, title, state }, + onArchiveTask, + onPinTask, +}: TaskProps) { return ( <div className={`list-item ${state}`}> <label @@ -200,10 +248,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT id={`archiveTask-${id}`} checked={state === "TASK_ARCHIVED"} /> - <span - className="checkbox-custom" - onClick={() => onArchiveTask(id)} - /> + <span className="checkbox-custom" onClick={() => onArchiveTask(id)} /> </label> <label htmlFor={`title-${id}`} aria-label={title} className="title"> @@ -243,12 +288,41 @@ The additional markup from above combined with the CSS we imported earlier yield ## Specify data requirements -It’s best practice to use `propTypes` in React to specify the shape of data that a component expects. Not only is it self-documenting, but it also helps catch problems early. +As we continue to build out our components, we can specify the shape of the data that the `Task` component expects by defining a TypeScript type. This way, we can catch errors early and ensure the component is used correctly when adding more complexity. Start by creating a `types.ts` file in the `src` folder and move our existing `TaskData` type there: + +```ts:title=src/types.ts +export type TaskData = { + id: string; + title: string; + state: 'TASK_ARCHIVED' | 'TASK_INBOX' | 'TASK_PINNED'; +}; +``` + +Then, update the `Task` component to use our newly created type: -```diff:title=src/components/Task.jsx -+ import PropTypes from 'prop-types'; +```diff:title=src/components/Task.tsx ++ import type { TaskData } from '../types'; -export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { +- type Task = { +- id: string; +- title: string; +- state: 'TASK_ARCHIVED' | 'TASK_INBOX' | 'TASK_PINNED'; +- }; + +type TaskProps = { + /** Composition of the task */ + task: TaskData; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; +}; + +export default function Task({ + task: { id, title, state }, + onArchiveTask, + onPinTask, +}: TaskProps) { return ( <div className={`list-item ${state}`}> <label @@ -263,10 +337,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT id={`archiveTask-${id}`} checked={state === "TASK_ARCHIVED"} /> - <span - className="checkbox-custom" - onClick={() => onArchiveTask(id)} - /> + <span className="checkbox-custom" onClick={() => onArchiveTask(id)} /> </label> <label htmlFor={`title-${id}`} aria-label={title} className="title"> @@ -293,28 +364,9 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT </div> ); } -+ Task.propTypes = { -+ /** Composition of the task */ -+ task: PropTypes.shape({ -+ /** Id of the task */ -+ id: PropTypes.string.isRequired, -+ /** Title of the task */ -+ title: PropTypes.string.isRequired, -+ /** Current state of the task */ -+ state: PropTypes.string.isRequired, -+ }), -+ /** Event to change the task to archived */ -+ onArchiveTask: PropTypes.func, -+ /** Event to change the task to pinned */ -+ onPinTask: PropTypes.func, -+ }; ``` -Now a warning in development will appear if the Task component is misused. - -<div class="aside"> -💡 An alternative way to achieve the same purpose is to use a JavaScript type system like TypeScript to create a type for the component properties. -</div> +Now, an error in development will appear if the Task component is misused. ## Component built! @@ -334,18 +386,19 @@ Let's see how it works! Run the following command to install the addon: yarn add --dev @storybook/addon-a11y ``` -Then, update your Storybook configuration file (`.storybook/main.js`) to enable it: +Then, update your Storybook configuration file (`.storybook/main.ts`) to enable it: + +```diff:title=.storybook/main.ts +import type { StorybookConfig } from '@storybook/react-vite'; -```diff:title=.storybook/main.js -/** @type { import('@storybook/react-vite').StorybookConfig } */ -const config = { - stories: ['../src/components/**/*.stories.@(js|jsx)'], +const config: StorybookConfig = { + stories: ['../src/components/**/*.stories.@(ts|tsx)'], staticDirs: ['../public'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', -+ '@storybook/addon-a11y', ++ '@storybook/addon-a11y' ], framework: { name: '@storybook/react-vite', diff --git a/content/intro-to-storybook/react/en/test.md b/content/intro-to-storybook/react/en/test.md index b0d96ec29..812a21feb 100644 --- a/content/intro-to-storybook/react/en/test.md +++ b/content/intro-to-storybook/react/en/test.md @@ -43,10 +43,26 @@ Start by creating a new branch for this change: git checkout -b change-task-background ``` -Change `src/components/Task.jsx` to the following: - -```diff:title=src/components/Task.jsx -export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { +Change `src/components/Task.tsx` to the following: + +```diff:title=src/components/Task.tsx +import type { TaskData } from '../types'; + +type TaskProps = { + /** Composition of the task */ + task: TaskData; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; +}; + + +export default function Task({ + task: { id, title, state }, + onArchiveTask, + onPinTask, +}: TaskProps) { return ( <div className={`list-item ${state}`}> <label @@ -61,10 +77,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT id={`archiveTask-${id}`} checked={state === "TASK_ARCHIVED"} /> - <span - className="checkbox-custom" - onClick={() => onArchiveTask(id)} - /> + <span className="checkbox-custom" onClick={() => onArchiveTask(id)} /> </label> <label htmlFor={`title-${id}`} aria-label={title} className="title"> @@ -78,7 +91,6 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT + style={{ backgroundColor: 'red' }} /> </label> - {state !== "TASK_ARCHIVED" && ( <button className="pin-button" diff --git a/content/intro-to-storybook/react/en/using-addons.md b/content/intro-to-storybook/react/en/using-addons.md index a1e286f0a..1f4e8f507 100644 --- a/content/intro-to-storybook/react/en/using-addons.md +++ b/content/intro-to-storybook/react/en/using-addons.md @@ -2,7 +2,7 @@ title: 'Addons' tocTitle: 'Addons' description: 'Learn how to integrate and use the popular Controls addon' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook has a robust ecosystem of [addons](https://storybook.js.org/docs/configure/user-interface/storybook-addons) that you can use to enhance the developer experience for everybody in your team. View them all [here](https://storybook.js.org/integrations). @@ -38,10 +38,25 @@ That's not right! It looks like the text overflows beyond the bounds of the Task Controls allowed us to quickly verify different inputs to a component--in this case, a long string--and reduced the work required to discover UI problems. -Now let's fix the issue with overflowing by adding a style to `Task.jsx`: +Now let's fix the issue with overflowing by adding a style to `Task.tsx`: -```diff:title=src/components/Task.jsx -export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { +```diff:title=src/components/Task.tsx +import type { TaskData } from '../types'; + +type TaskProps = { + /** Composition of the task */ + task: TaskData; + /** Event to change the task to archived */ + onArchiveTask: (id: string) => void; + /** Event to change the task to pinned */ + onPinTask: (id: string) => void; +}; + +export default function Task({ + task: { id, title, state }, + onArchiveTask, + onPinTask, +}: TaskProps) { return ( <div className={`list-item ${state}`}> <label @@ -56,10 +71,7 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT id={`archiveTask-${id}`} checked={state === "TASK_ARCHIVED"} /> - <span - className="checkbox-custom" - onClick={() => onArchiveTask(id)} - /> + <span className="checkbox-custom" onClick={() => onArchiveTask(id)} /> </label> <label htmlFor={`title-${id}`} aria-label={title} className="title"> @@ -70,10 +82,9 @@ export default function Task({ task: { id, title, state }, onArchiveTask, onPinT name="title" id={`title-${id}`} placeholder="Input title" -+ style={{ textOverflow: 'ellipsis' }} ++ style={{ textOverflow: "ellipsis" }} /> </label> - {state !== "TASK_ARCHIVED" && ( <button className="pin-button" @@ -98,12 +109,12 @@ Problem solved! The text is now truncated when it reaches the boundary of the Ta In the future, we can manually reproduce this problem by entering the same string via Controls. But it's easier to write a story that showcases this edge case. That expands our regression test coverage and clearly outlines the limits of the component(s) for the rest of the team. -Add a new story for the long text case in `Task.stories.jsx`: +Add a new story for the long text case in `Task.stories.tsx`: -```js:title=src/components/Task.stories.jsx +```js:title=src/components/Task.stories.tsx const longTitleString = `This task's name is absurdly large. In fact, I think if I keep going I might end up with content overflow. What will happen? The star that represents a pinned task could have text overlapping. The text could cut-off abruptly when it reaches the star. I hope not!`; -export const LongTitle = { +export const LongTitle: Story = { args: { task: { ...Default.args.task, diff --git a/content/intro-to-storybook/react/es/composite-component.md b/content/intro-to-storybook/react/es/composite-component.md index 55999ccd6..9ff283e93 100644 --- a/content/intro-to-storybook/react/es/composite-component.md +++ b/content/intro-to-storybook/react/es/composite-component.md @@ -2,7 +2,7 @@ title: 'Ensamblar un componente compuesto' tocTitle: 'Componente Compuesto' description: 'Ensamblar un componente compuesto a partir de componentes simples' -commit: '429780a' +commit: 'cfa25b6' --- En el capítulo anterior, construimos nuestro primer componente; en este capítulo, ampliamos lo que aprendimos para construir TaskList, una lista de Tasks. Vamos a combinar componentes y ver qué sucede cuando introducimos más complejidad. @@ -127,7 +127,7 @@ Ahora hay que revisar Storybook para ver las nuevas historias de `TaskList`. ## Construir los estados -Nuestro componente todavía es rudimentario, pero ahora tenemos una idea de las historias en las que trabajaremos. Puede que estés pensando que el envoltorio de `.list-items` es demasiado simplista. Tienes razón: en la mayoría de los casos no crearíamos un nuevo componente sólo para añadir un envoltorio. Pero la **verdadera complejidad** del componente `TaskList` se revela en los casos extremos `withPinnedTasks`, `loading`, y `empty`. +Nuestro componente todavía es rudimentario, pero ahora tenemos una idea de las historias en las que trabajaremos. Puede que estés pensando que el envoltorio de `.list-items` es demasiado simplista. Tienes razón: en la mayoría de los casos no crearíamos un nuevo componente sólo para añadir un envoltorio. Pero la **verdadera complejidad** del componente `TaskList` se revela en los casos extremos `withPinnedTasks`, `loading`, y `empty`. ```jsx:title=src/components/TaskList.jsx import Task from './Task'; diff --git a/content/intro-to-storybook/react/es/data.md b/content/intro-to-storybook/react/es/data.md index f2f7f1c00..7e2552f13 100644 --- a/content/intro-to-storybook/react/es/data.md +++ b/content/intro-to-storybook/react/es/data.md @@ -2,7 +2,7 @@ title: 'Introducir datos' tocTitle: 'Datos' description: 'Aprende como introducir datos a tus componentes UI' -commit: 'c70ec15' +commit: 'f9eaeef' --- Hasta ahora hemos creado componentes aislados sin estado, muy útiles para Storybook, pero finalmente no son útiles hasta que les proporcionemos algunos datos en nuestra aplicación. diff --git a/content/intro-to-storybook/react/es/deploy.md b/content/intro-to-storybook/react/es/deploy.md index b4c1f3d55..b76e16a02 100644 --- a/content/intro-to-storybook/react/es/deploy.md +++ b/content/intro-to-storybook/react/es/deploy.md @@ -2,7 +2,7 @@ title: 'Desplegar Storybook' tocTitle: 'Desplegar' description: 'Aprender como desplegar Storybook' -commit: '59da1ac' +commit: '4531813' --- En este tutorial, hemos construido componentes en nuestra máquina de desarrollo local. En algún momento, vamos a necesitar compartir nuestro trabajo para obtener feedback del equipo. Vamos a desplegar Storybook para ayudar a nuestros compañeros a revisar la implementación de la interfaz de usuario. diff --git a/content/intro-to-storybook/react/es/get-started.md b/content/intro-to-storybook/react/es/get-started.md index 0e5de8314..d53e744ef 100644 --- a/content/intro-to-storybook/react/es/get-started.md +++ b/content/intro-to-storybook/react/es/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook para React tutorial' tocTitle: 'Empezando' description: 'Configurar React Storybook en tu entorno de desarrollo' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook se ejecuta junto con tu aplicación en modo desarrollo. Te ayuda a crear componentes de UI aislados de la lógica y el contexto de tu aplicación. Esta edición de Aprende Storybook es para React; existe otras ediciones para [React Native](/intro-to-storybook/react-native/es/get-started), [Vue](/intro-to-storybook/vue/es/get-started), [Angular](/intro-to-storybook/angular/es/get-started) y [Svelte](/intro-to-storybook/svelte/es/get-started). diff --git a/content/intro-to-storybook/react/es/screen.md b/content/intro-to-storybook/react/es/screen.md index 111931668..71979f6eb 100644 --- a/content/intro-to-storybook/react/es/screen.md +++ b/content/intro-to-storybook/react/es/screen.md @@ -2,7 +2,7 @@ title: 'Construir una pantalla' tocTitle: 'Pantallas' description: 'Construir una pantalla con componentes' -commit: '2275632' +commit: '6262d7f' --- Nos hemos concentrado en crear interfaces de usuario de abajo hacia arriba; comenzando por lo pequeño y añadiendo complejidad. Esto nos ha permitido desarrollar cada componente de forma aislada, determinar los datos que necesita y jugar con ellos en Storybook. ¡Todo sin necesidad de levantar un servidor o construir pantallas! diff --git a/content/intro-to-storybook/react/es/simple-component.md b/content/intro-to-storybook/react/es/simple-component.md index 655a1adca..c71bebb0d 100644 --- a/content/intro-to-storybook/react/es/simple-component.md +++ b/content/intro-to-storybook/react/es/simple-component.md @@ -2,7 +2,7 @@ title: 'Construye un componente simple' tocTitle: 'Componente Simple' description: 'Construye un componente simple en aislamiento' -commit: '9b36e1a' +commit: 'bc897c5' --- Construiremos nuestra UI siguiendo la metodología (CDD) [Component-Driven Development](https://www.componentdriven.org/). Es un proceso que construye UIs de “abajo hacia arriba”, empezando con los componentes y terminando con las pantallas. CDD te ayuda a escalar la cantidad de complejidad con la que te enfrentas a medida que construyes la UI. diff --git a/content/intro-to-storybook/react/es/using-addons.md b/content/intro-to-storybook/react/es/using-addons.md index f955b9b25..794b41ea2 100644 --- a/content/intro-to-storybook/react/es/using-addons.md +++ b/content/intro-to-storybook/react/es/using-addons.md @@ -2,7 +2,7 @@ title: 'Complementos' tocTitle: 'Complementos' description: 'Aprende como integrar y utilizar el popular complemento Controls' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook tiene un ecosistema sólido de [complementos, o "addons"](https://storybook.js.org/docs/configure/user-interface/storybook-addons) que puedes utilizar para mejorar la experiencia del desarrollador para todos en tu equipo. Puedes ver todo los complementos [aquí](https://storybook.js.org/integrations). diff --git a/content/intro-to-storybook/react/fr/composite-component.md b/content/intro-to-storybook/react/fr/composite-component.md index 25da79f14..25ede1e39 100644 --- a/content/intro-to-storybook/react/fr/composite-component.md +++ b/content/intro-to-storybook/react/fr/composite-component.md @@ -2,7 +2,7 @@ title: 'Assembler un composant complexe' tocTitle: 'Composant complexe' description: 'Assembler un composant complexe à partir de composants plus simples' -commit: '429780a' +commit: 'cfa25b6' --- Dans le précédent chapitre, nous avons construit notre premier composant. Ce chapitre prolonge ce que nous avons appris pour construire une liste de tâches (`Tasklist`). Combinons les composants ensemble et voyons ce qui se passe lorsque nous introduisons plus de complexité. diff --git a/content/intro-to-storybook/react/fr/data.md b/content/intro-to-storybook/react/fr/data.md index 32d5134fc..b82be020f 100644 --- a/content/intro-to-storybook/react/fr/data.md +++ b/content/intro-to-storybook/react/fr/data.md @@ -2,7 +2,7 @@ title: 'Transmettre des données' tocTitle: 'Données' description: "Apprenez comment transmettre des données à votre composant d'interface d'utilisateur" -commit: 'c70ec15' +commit: 'f9eaeef' --- Jusqu'à présent, nous avons créé des composants isolés et sans états - très bien pour Storybook, mais finalement inutiles tant que nous ne fournissons pas de données dans notre application. diff --git a/content/intro-to-storybook/react/fr/deploy.md b/content/intro-to-storybook/react/fr/deploy.md index 692d8c0b0..8fe0ab2db 100644 --- a/content/intro-to-storybook/react/fr/deploy.md +++ b/content/intro-to-storybook/react/fr/deploy.md @@ -2,7 +2,7 @@ title: 'Déployer Storybook' tocTitle: 'Déploiement' description: 'Découvrez comment déployer Storybook en ligne' -commit: '59da1ac' +commit: '4531813' --- Tout au long de ce tutoriel, nous avons construit des composants sur notre machine de développement en local. À un moment donné, nous devrons partager notre travail pour avoir des retours de l'équipe. Déployons Storybook en ligne pour aider nos coéquipiers à examiner l'implémentation de l'interface utilisateur. diff --git a/content/intro-to-storybook/react/fr/get-started.md b/content/intro-to-storybook/react/fr/get-started.md index cecf5f022..db8274929 100644 --- a/content/intro-to-storybook/react/fr/get-started.md +++ b/content/intro-to-storybook/react/fr/get-started.md @@ -2,7 +2,7 @@ title: 'Tutoriel de Storybook pour React' tocTitle: 'Débuter' description: 'Configurer Storybook dans votre environnement de développement' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook s'exécute parallèlement à votre application en mode développement. Il vous aide à construire des composants d'interface utilisateur (User Interface ou UI) isolés de la logique applicative et du contexte de votre application. Cette édition de Learn Storybook est pour React; d'autres éditions existent pour [React Native](/intro-to-storybook/react-native/en/get-started), [Vue](/intro-to-storybook/vue/fr/get-started), [Angular](/intro-to-storybook/angular/en/get-started), [Svelte](/intro-to-storybook/svelte/en/get-started) et [Ember](/intro-to-storybook/ember/en/get-started). diff --git a/content/intro-to-storybook/react/fr/screen.md b/content/intro-to-storybook/react/fr/screen.md index d908823db..e4d9fcf2e 100644 --- a/content/intro-to-storybook/react/fr/screen.md +++ b/content/intro-to-storybook/react/fr/screen.md @@ -2,7 +2,7 @@ title: 'Construire un écran' tocTitle: 'Écrans' description: 'Construire un écran à partir de composants' -commit: '2275632' +commit: '6262d7f' --- Nous nous sommes concentrés sur la création d'une UI de bas en haut, en commençant simplement et en ajoutant de la complexité. Cela nous a permis de développer chaque composant séparément, de déterminer ses besoins en données et de jouer avec dans Storybook. Tout cela sans avoir besoin de mettre en place un serveur ou de construire des écrans! diff --git a/content/intro-to-storybook/react/fr/simple-component.md b/content/intro-to-storybook/react/fr/simple-component.md index 646adfae1..0460e088a 100644 --- a/content/intro-to-storybook/react/fr/simple-component.md +++ b/content/intro-to-storybook/react/fr/simple-component.md @@ -2,7 +2,7 @@ title: 'Créer un simple composant' tocTitle: 'Simple composant' description: 'Créer un simple composant en isolation' -commit: '9b36e1a' +commit: 'bc897c5' --- Nous allons construire notre UI en suivant la méthode [de développement orienté composant](https://www.componentdriven.org/) (CDD). Il s'agit d'un processus qui construit les interfaces utilisateur de "bas en haut" en commençant par les composants et en terminant par les écrans. Le CDD vous permet d'évaluer le degré de complexité auquel vous êtes confronté lors de la construction de l'UI. diff --git a/content/intro-to-storybook/react/fr/using-addons.md b/content/intro-to-storybook/react/fr/using-addons.md index a39406e1d..d6ee78a90 100644 --- a/content/intro-to-storybook/react/fr/using-addons.md +++ b/content/intro-to-storybook/react/fr/using-addons.md @@ -2,7 +2,7 @@ title: 'Addons' tocTitle: 'Addons' description: 'Apprenez comment intégrer et utiliser le populaire addon Controls' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook dispose d'un système robuste d'[addons](https://storybook.js.org/docs/react/configure/storybook-addons) avec lequel vous pouvez améliorer l'expérience de développement de toute votre équipe. Consultez-les tous [ici](https://storybook.js.org/integrations). diff --git a/content/intro-to-storybook/react/it/composite-component.md b/content/intro-to-storybook/react/it/composite-component.md index ccd8b7c68..c79bc16c7 100644 --- a/content/intro-to-storybook/react/it/composite-component.md +++ b/content/intro-to-storybook/react/it/composite-component.md @@ -2,7 +2,7 @@ title: 'Assembla un componente composito' tocTitle: 'Componente composito' description: 'Assembla un componente composito da componenti più semplici' -commit: '429780a' +commit: 'cfa25b6' --- Nell'ultimo capitolo, abbiamo costruito il nostro primo componente; questo capitolo estende ciò che abbiamo imparato per realizzare TaskList, una lista di Task. Uniamoli insieme e vediamo cosa succede quando introduciamo più complessità. diff --git a/content/intro-to-storybook/react/it/data.md b/content/intro-to-storybook/react/it/data.md index 4f4215402..2accb4dbb 100644 --- a/content/intro-to-storybook/react/it/data.md +++ b/content/intro-to-storybook/react/it/data.md @@ -2,7 +2,7 @@ title: 'Collegare i dati' tocTitle: 'Dati' description: 'Impara come collegare i dati al tuo componente UI' -commit: 'c70ec15' +commit: 'f9eaeef' --- Finora, abbiamo creato componenti senza stato isolati, ottimi per Storybook, ma alla fine non utili finché non gli forniamo alcuni dati nella nostra app. diff --git a/content/intro-to-storybook/react/it/deploy.md b/content/intro-to-storybook/react/it/deploy.md index ac12a7047..39d9febc1 100644 --- a/content/intro-to-storybook/react/it/deploy.md +++ b/content/intro-to-storybook/react/it/deploy.md @@ -2,7 +2,7 @@ title: 'Effettuare il deploy di Storybook' tocTitle: 'Deploy' description: 'Impara come effettuare il deploy di Storybook online' -commit: '59da1ac' +commit: '4531813' --- Durante questo tutorial, abbiamo costruito componenti sulla nostra macchina di sviluppo locale. Ad un certo punto, avremo bisogno di condividere il nostro lavoro per ottenere feedback dal team. Effettuiamo il deploy di Storybook online per aiutare i membri del team a revisionare l'implementazione dell'UI. diff --git a/content/intro-to-storybook/react/it/get-started.md b/content/intro-to-storybook/react/it/get-started.md index e34ff7980..3cfbb1fa0 100644 --- a/content/intro-to-storybook/react/it/get-started.md +++ b/content/intro-to-storybook/react/it/get-started.md @@ -2,7 +2,7 @@ title: 'Tutorial di Storybook per React' tocTitle: 'Inizia' description: 'Configura Storybook nel tuo ambiente di sviluppo' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook funziona in parallelo con la tua app in modalità di sviluppo. Ti aiuta a costruire componenti dell'interfaccia utente isolati dalla logica aziendale e dal contesto della tua app. Questa edizione del tutorial Intro to Storybook è per React; esistono altre edizioni per [React Native](/intro-to-storybook/react-native/en/get-started), [Vue](/intro-to-storybook/vue/it/get-started), [Angular](/intro-to-storybook/angular/en/get-started), [Svelte](/intro-to-storybook/svelte/en/get-started) ed [Ember](/intro-to-storybook/ember/en/get-started). diff --git a/content/intro-to-storybook/react/it/screen.md b/content/intro-to-storybook/react/it/screen.md index b55a61171..13a3e58e5 100644 --- a/content/intro-to-storybook/react/it/screen.md +++ b/content/intro-to-storybook/react/it/screen.md @@ -2,7 +2,7 @@ title: 'Costruisci una schermata' tocTitle: 'Schermate' description: 'Costruisci una schermata da componenti' -commit: '2275632' +commit: '6262d7f' --- Ci siamo concentrati sulla costruzione di interfacce utente dal basso verso l'alto, partendo da piccole e aggiungendo complessità. Farlo ci ha permesso di sviluppare ogni componente in isolamento, capire le sue esigenze di dati e giocare con esso in Storybook. Tutto senza dover avviare un server o costruire schermate! diff --git a/content/intro-to-storybook/react/it/simple-component.md b/content/intro-to-storybook/react/it/simple-component.md index 9c4976885..1da037e26 100644 --- a/content/intro-to-storybook/react/it/simple-component.md +++ b/content/intro-to-storybook/react/it/simple-component.md @@ -2,7 +2,7 @@ title: 'Costruisci un componente semplice' tocTitle: 'Componente semplice' description: 'Costruisci un componente semplice in isolamento' -commit: '9b36e1a' +commit: 'bc897c5' --- Costruiremo la nostra UI seguendo una metodologia [Component-Driven Development](https://www.componentdriven.org/) (CDD). È un processo che costruisce le UI dal "basso verso l'alto", partendo dai componenti e terminando con gli schermi. Il CDD ti aiuta a gestire l'ammontare di complessità a cui sei sottoposto mentre costruisci la UI. diff --git a/content/intro-to-storybook/react/it/using-addons.md b/content/intro-to-storybook/react/it/using-addons.md index cb756a5c4..a4a432b57 100644 --- a/content/intro-to-storybook/react/it/using-addons.md +++ b/content/intro-to-storybook/react/it/using-addons.md @@ -2,7 +2,7 @@ title: 'Addons' tocTitle: 'Addons' description: 'Impara come integrare e utilizzare il popolare addon Controls' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook ha un robusto ecosistema di [addons](https://storybook.js.org/docs/react/configure/storybook-addons) che puoi utilizzare per migliorare l'esperienza dello sviluppatore per tutti nel tuo team. Visualizzali tutti [qui](https://storybook.js.org/addons). diff --git a/content/intro-to-storybook/react/ja/composite-component.md b/content/intro-to-storybook/react/ja/composite-component.md index d6d0098b2..170fab962 100644 --- a/content/intro-to-storybook/react/ja/composite-component.md +++ b/content/intro-to-storybook/react/ja/composite-component.md @@ -2,7 +2,7 @@ title: '複合的なコンポーネントを組み立てる' tocTitle: '複合的なコンポーネント' description: '単純なコンポーネントから複合的なコンポーネントを組み立てましょう' -commit: '429780a' +commit: 'cfa25b6' --- 前の章では、最初のコンポーネントを作成しました。この章では、学習した内容を基にタスクのリストである `TaskList` を作成します。それではコンポーネントを組み合わせて、複雑になった場合にどうすればよいか見てみましょう。 diff --git a/content/intro-to-storybook/react/ja/data.md b/content/intro-to-storybook/react/ja/data.md index 8fffabc8a..fdc82a93c 100644 --- a/content/intro-to-storybook/react/ja/data.md +++ b/content/intro-to-storybook/react/ja/data.md @@ -2,7 +2,7 @@ title: 'データを繋ぐ' tocTitle: 'データ' description: 'UI コンポーネントとデータを繋ぐ方法を学びましょう' -commit: 'c70ec15' +commit: 'f9eaeef' --- これまでに、Storybook の切り離された環境で、状態を持たないコンポーネントを作成してきました。しかし、究極的には、アプリケーションからコンポーネントにデータを渡さなければ役には立ちません。 diff --git a/content/intro-to-storybook/react/ja/deploy.md b/content/intro-to-storybook/react/ja/deploy.md index 8add2d0fc..ef2770f89 100644 --- a/content/intro-to-storybook/react/ja/deploy.md +++ b/content/intro-to-storybook/react/ja/deploy.md @@ -2,7 +2,7 @@ title: 'Storybook をデプロイする' tocTitle: 'デプロイ' description: 'Storybook をインターネット上にデプロイする方法を学びましょう' -commit: '59da1ac' +commit: '4531813' --- ここまで、ローカルの開発マシンでコンポーネントを作成してきました。しかし、ある時点で、フィードバックを得るためにチームに作業を共有しなければならないこともあるでしょう。チームメートに UI の実装をレビューしてもらうため、Storybook をインターネット上にデプロイしてみましょう。 diff --git a/content/intro-to-storybook/react/ja/get-started.md b/content/intro-to-storybook/react/ja/get-started.md index 69478512a..45e74d6bc 100644 --- a/content/intro-to-storybook/react/ja/get-started.md +++ b/content/intro-to-storybook/react/ja/get-started.md @@ -2,7 +2,7 @@ title: 'React 向け Storybook のチュートリアル' tocTitle: 'はじめに' description: '開発環境に Storybook を導入しましょう' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook は開発時にアプリケーションと並行して動きます。Storybook を使用することで、UI コンポーネントをビジネスロジックやコンテキストから切り離して開発できるようになります。この文書は React 向けです。他にも [React Native](/intro-to-storybook/react-native/en/get-started)、[Vue](/intro-to-storybook/vue/en/get-started)、[Angular](/intro-to-storybook/angular/en/get-started)、[Svelte](/intro-to-storybook/svelte/en/get-started)、[Ember](/intro-to-storybook/ember/en/get-started) 向けのバージョンがあります。 diff --git a/content/intro-to-storybook/react/ja/screen.md b/content/intro-to-storybook/react/ja/screen.md index b6f8f1bdc..d7af48577 100644 --- a/content/intro-to-storybook/react/ja/screen.md +++ b/content/intro-to-storybook/react/ja/screen.md @@ -2,7 +2,7 @@ title: '画面を作る' tocTitle: '画面' description: 'コンポーネントをまとめて画面を作りましょう' -commit: '2275632' +commit: '6262d7f' --- 今までボトムアップ (小規模な状態から複雑さを追加していく) で UI の作成に集中してきました。ボトムアップで作業することで、Storybook で遊びながら、それぞれのコンポーネントを切り離された環境で、それぞれに必要なデータを考えながら開発することができました。サーバーを立ち上げたり、画面を作ったりする必要はまったくありませんでした! diff --git a/content/intro-to-storybook/react/ja/simple-component.md b/content/intro-to-storybook/react/ja/simple-component.md index af10b9477..ff2bf2120 100644 --- a/content/intro-to-storybook/react/ja/simple-component.md +++ b/content/intro-to-storybook/react/ja/simple-component.md @@ -2,7 +2,7 @@ title: '単純なコンポーネントを作る' tocTitle: '単純なコンポーネント' description: '単純なコンポーネントを切り離して作りましょう' -commit: '9b36e1a' +commit: 'bc897c5' --- それでは、[コンポーネント駆動開発](https://www.componentdriven.org/) (CDD) の手法にのっとって UI を作ってみましょう。コンポーネント駆動開発とは、UI を最初にコンポーネントから作り始めて、最後に画面を作り上げる「ボトムアップ」の開発プロセスです。CDD を用いれば、 UI を作る際に直面する複雑性を軽減できます。 diff --git a/content/intro-to-storybook/react/ja/using-addons.md b/content/intro-to-storybook/react/ja/using-addons.md index 4eac74c78..4516c1135 100644 --- a/content/intro-to-storybook/react/ja/using-addons.md +++ b/content/intro-to-storybook/react/ja/using-addons.md @@ -2,7 +2,7 @@ title: 'アドオン' tocTitle: 'アドオン' description: '人気のコントロールアドオンの使用方法を学びましょう' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook にはチームの開発効率を向上する堅牢な[アドオン](https://storybook.js.org/docs/configure/user-interface/storybook-addons)のエコシステムがあります。[こちら](https://storybook.js.org/integrations) でアドオンのリストが見られます。 diff --git a/content/intro-to-storybook/react/ko/composite-component.md b/content/intro-to-storybook/react/ko/composite-component.md index e54858183..f33ad7d05 100644 --- a/content/intro-to-storybook/react/ko/composite-component.md +++ b/content/intro-to-storybook/react/ko/composite-component.md @@ -2,7 +2,7 @@ title: '복합적 컴포넌트 조합하기' tocTitle: '복합적 컴포넌트' description: '간단한 컴포넌트로 복합적 컴포넌트를 조합해보세요' -commit: '429780a' +commit: 'cfa25b6' --- 지난 챕터에서 첫 번째 컴포넌트를 만들어보았습니다. 이번 챕터에서는 이전에 학습한 내용을 바탕으로 Task의 목록인 TaskList를 만들어보겠습니다. 컴포넌트를 결합하여 복잡성이 커지는 경우 어떤 일이 일어나는지 함께 살펴보겠습니다. diff --git a/content/intro-to-storybook/react/ko/data.md b/content/intro-to-storybook/react/ko/data.md index 178db826c..4414305cc 100644 --- a/content/intro-to-storybook/react/ko/data.md +++ b/content/intro-to-storybook/react/ko/data.md @@ -2,7 +2,7 @@ title: '데이터 연결하기' tocTitle: '데이터' description: 'UI 컴포넌트에 데이터를 연결하는 방법을 배워보세요' -commit: 'c70ec15' +commit: 'f9eaeef' --- 지금까지 우리는 독립된 환경에서 상태를 가지지 않는(stateless) 컴포넌트를 만들어보았습니다. 이는 스토리북(Storybook)에는 적합하지만 앱에 데이터를 제공하기 전까지는 유용하지 않습니다. diff --git a/content/intro-to-storybook/react/ko/deploy.md b/content/intro-to-storybook/react/ko/deploy.md index db0bec0db..e50bcdc30 100644 --- a/content/intro-to-storybook/react/ko/deploy.md +++ b/content/intro-to-storybook/react/ko/deploy.md @@ -2,7 +2,7 @@ title: '스토리북(Storybook) 배포하기' tocTitle: '배포하기' description: 'Storybook을 온라인으로 배포하는 방법을 배워보세요' -commit: '59da1ac' +commit: '4531813' --- 이 튜토리얼을 통해 우리는 로컬 개발 환경에서 컴포넌트를 만들었습니다. 언젠가 팀의 피드백을 얻기 위해 작업을 공유해야 할 필요가 있을 것입니다. 다른 팀원들이 UI 구현을 검토할 수 있도록 스토리북(Storybook)을 온라인으로 배포해봅시다. diff --git a/content/intro-to-storybook/react/ko/get-started.md b/content/intro-to-storybook/react/ko/get-started.md index 28e5f7741..2060baf6c 100644 --- a/content/intro-to-storybook/react/ko/get-started.md +++ b/content/intro-to-storybook/react/ko/get-started.md @@ -2,7 +2,7 @@ title: '리액트(React)를 위한 스토리북(Storybook) 튜토리얼' tocTitle: '시작하기' description: '스토리북(Storybook)을 개발 환경에 설치해보세요' -commit: 'bf3514f' +commit: '2407c3c' --- 스토리북(Storybook)은 개발 모드에서 앱과 함께 실행됩니다. 스토리북은 비즈니스 로직과 맥락(context)으로부터 분리된 UI 컴포넌트를 만들 수 있도록 도와줍니다. 현재 문서는 리액트(React)를 위해 작성되었습니다. 그 밖의 [React Native](/intro-to-storybook/react-native/en/get-started), [Vue](/intro-to-storybook/vue/en/get-started), [Angular](/intro-to-storybook/angular/en/get-started), [Svelte](/intro-to-storybook/svelte/en/get-started) 및 [Ember](/intro-to-storybook/ember/en/get-started)에 대한 다른 문서도 존재합니다. diff --git a/content/intro-to-storybook/react/ko/screen.md b/content/intro-to-storybook/react/ko/screen.md index 140e12cc3..60048e48f 100644 --- a/content/intro-to-storybook/react/ko/screen.md +++ b/content/intro-to-storybook/react/ko/screen.md @@ -2,7 +2,7 @@ title: '화면 구성하기' tocTitle: '화면' description: '컴포넌트로 화면을 구성해봅시다' -commit: '2275632' +commit: '6262d7f' --- 우리는 지금까지 작은 것에서부터 시작하여 복잡성을 점점 더하는 방식으로 UI를 만들었습니다. 이를 통해 각 컴포넌트를 독립적으로 개발하고 데이터의 요구 사항을 파악하며 스토리북(Storybook)에서 사용해 볼 수 있었습니다. 모두 서버를 구축하거나 화면을 만들 필요가 없었습니다! diff --git a/content/intro-to-storybook/react/ko/simple-component.md b/content/intro-to-storybook/react/ko/simple-component.md index 904e48b58..4340fbd8b 100644 --- a/content/intro-to-storybook/react/ko/simple-component.md +++ b/content/intro-to-storybook/react/ko/simple-component.md @@ -2,7 +2,7 @@ title: '간단한 컴포넌트 만들기' tocTitle: '간단한 컴포넌트' description: '간단한 컴포넌트를 독립적으로 만들어봅시다' -commit: '9b36e1a' +commit: 'bc897c5' --- 우리는 [컴포넌트 기반 개발(Component-Driven Development)](https://www.componentdriven.org/)(CDD) 방법론에 따라 UI를 만들어 볼 것입니다. 이는 컴포넌트부터 시작하여 마지막 화면에 이르기까지 상향식(bottom-up)으로 UI를 개발하는 과정입니다. CDD는 UI를 구현할 때 직면하게 되는 규모의 복잡성을 해결하는 데 도움이 됩니다. diff --git a/content/intro-to-storybook/react/ko/using-addons.md b/content/intro-to-storybook/react/ko/using-addons.md index f57df863c..439873b50 100644 --- a/content/intro-to-storybook/react/ko/using-addons.md +++ b/content/intro-to-storybook/react/ko/using-addons.md @@ -2,7 +2,7 @@ title: '애드온(Addon)' tocTitle: '애드온(Addon)' description: '인기있는 Controls 애드온(Addon)을 적용하고 사용하는 방법을 배워봅니다.' -commit: 'f89cfe0' +commit: '17d3ab9' --- 스토리북(Storybook)에는 팀 내 모든 구성원의 개발 경험을 향상시키는 데 사용할 수 있는 강력한 [애드온(addons)](https://storybook.js.org/docs/configure/storybook-addons) 생태계가 있습니다. [여기](https://storybook.js.org/integrations)에서 볼 수 있습니다. diff --git a/content/intro-to-storybook/react/nl/composite-component.md b/content/intro-to-storybook/react/nl/composite-component.md index f126708ea..e7a261824 100644 --- a/content/intro-to-storybook/react/nl/composite-component.md +++ b/content/intro-to-storybook/react/nl/composite-component.md @@ -2,7 +2,7 @@ title: 'Bouw een samengestelde component' tocTitle: 'Samengestelde component' description: 'Bouw een samengestelde component uit eenvoudigere componenten' -commit: '429780a' +commit: 'cfa25b6' --- In het vorige hoofdstuk hebben we onze eerste component gebouwd; dit hoofdstuk gaat voort op wat we geleerd hebben bij het bouwen van `TaskList`, een lijst van taken. Laten we nu een aantal componenten combineren en zien wat er gebeurt wanneer de complexiteit toeneemt. diff --git a/content/intro-to-storybook/react/nl/data.md b/content/intro-to-storybook/react/nl/data.md index 09e0e829f..14eb5a8f4 100644 --- a/content/intro-to-storybook/react/nl/data.md +++ b/content/intro-to-storybook/react/nl/data.md @@ -2,7 +2,7 @@ title: 'Aansluiten data' tocTitle: 'Data' description: 'Leer hoe je data kunt doorgeven aan je UI component' -commit: 'c70ec15' +commit: 'f9eaeef' --- Tot nu toe hebben we geïsoleerde stateless componenten gemaakt - geweldig voor Storybook, maar uiteindelijk niet nuttig totdat we ze wat data geven in onze app. diff --git a/content/intro-to-storybook/react/nl/deploy.md b/content/intro-to-storybook/react/nl/deploy.md index e2fc771f0..c8bb1c1d0 100644 --- a/content/intro-to-storybook/react/nl/deploy.md +++ b/content/intro-to-storybook/react/nl/deploy.md @@ -2,7 +2,7 @@ title: 'Deploy Storybook' tocTitle: 'Deploy' description: 'Leren hoe we Storybook online deployen' -commit: '59da1ac' +commit: '4531813' --- Doorheen deze tutorial hebben we componenten lokaal op onze development machine gebouwd. Er komt een punt waar we ons werk willen delen met het team om zo feedback te verkrijgen. Laten we Storybook online deployen om ons team te helpen met het reviewen van de UI implementatie. diff --git a/content/intro-to-storybook/react/nl/get-started.md b/content/intro-to-storybook/react/nl/get-started.md index 2f33ba470..dd56ba224 100644 --- a/content/intro-to-storybook/react/nl/get-started.md +++ b/content/intro-to-storybook/react/nl/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook voor React tutorial' tocTitle: 'Begin' description: 'Stel Storybook in voor je ontwikkelomgeving' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook wordt naast je app in _development mode_ uitgevoerd. Het helpt je om UI componenten te bouwen die geïsoleerd zijn van de business logica en context van je applicatie. Deze versie van Learn Storybook is voor [React](/intro-to-storybook/react/en/get-started); er zijn andere versies voor [Vue](/intro-to-storybook/vue/en/get-started) en [Angular](/intro-to-storybook/angular/en/get-started). diff --git a/content/intro-to-storybook/react/nl/screen.md b/content/intro-to-storybook/react/nl/screen.md index 150b278f8..7de1b8e57 100644 --- a/content/intro-to-storybook/react/nl/screen.md +++ b/content/intro-to-storybook/react/nl/screen.md @@ -2,7 +2,7 @@ title: 'Bouw een scherm' tocTitle: 'Schermen' description: 'Bouw een scherm uit componenten' -commit: '2275632' +commit: '6262d7f' --- We hebben ons geconcentreerd op het bouwen van UI's van onderaf; klein beginnen en complexiteit toevoegen. Hierdoor konden we elk onderdeel afzonderlijk ontwikkelen, de data behoeften achterhalen en ermee spelen in Storybook. Allemaal zonder een server op te zetten of schermen uit te bouwen! diff --git a/content/intro-to-storybook/react/nl/simple-component.md b/content/intro-to-storybook/react/nl/simple-component.md index b55eed626..5e75f98cc 100644 --- a/content/intro-to-storybook/react/nl/simple-component.md +++ b/content/intro-to-storybook/react/nl/simple-component.md @@ -2,7 +2,7 @@ title: 'Bouw een eenvoudige component' tocTitle: 'Eenvoudige component' description: 'Bouw een eenvoudige component in isolatie' -commit: '9b36e1a' +commit: 'bc897c5' --- We zullen onze gebruikersinterface bouwen volgens de [Component-Driven Development](https://www.componentdriven.org/)-methodologie. Het is een proces dat UI's van onderaf opbouwt, beginnend met losse componenten en eindigend met schermen. CDD helpt je grip te houden op de complexiteit naarmate je de applicatie verder uitbouwt. diff --git a/content/intro-to-storybook/react/pt/composite-component.md b/content/intro-to-storybook/react/pt/composite-component.md index 9832078c5..aaaa76da5 100644 --- a/content/intro-to-storybook/react/pt/composite-component.md +++ b/content/intro-to-storybook/react/pt/composite-component.md @@ -2,7 +2,7 @@ title: 'Construção de um componente composto' tocTitle: 'Componente composto' description: 'Construção de um componente composto a partir de componentes simples' -commit: '429780a' +commit: 'cfa25b6' --- No capitulo anterior, construímos o nosso primeiro componente, neste capitulo iremos estender o que foi dito até agora, para que possamos construir a nossa TaskList, ou seja uma lista de Tasks. Vamos combinar componentes e ver o que irá acontecer quando é adicionada alguma complexidade. diff --git a/content/intro-to-storybook/react/pt/data.md b/content/intro-to-storybook/react/pt/data.md index 150c13dc4..bc2d1ae6a 100644 --- a/content/intro-to-storybook/react/pt/data.md +++ b/content/intro-to-storybook/react/pt/data.md @@ -2,7 +2,7 @@ title: 'Ligação de dados' tocTitle: 'Dados' description: 'Aprenda a efetuar a ligação de dados ao seu componente de interface de utilizador' -commit: 'c70ec15' +commit: 'f9eaeef' --- Até agora foram criados componentes sem estado e isolados, o que é fantástico para Storybook, mas em última análise não são úteis até que for fornecido algum tipo de dados da aplicação diff --git a/content/intro-to-storybook/react/pt/get-started.md b/content/intro-to-storybook/react/pt/get-started.md index c2a0c282b..8c5af938a 100644 --- a/content/intro-to-storybook/react/pt/get-started.md +++ b/content/intro-to-storybook/react/pt/get-started.md @@ -2,7 +2,7 @@ title: 'Tutorial do Storybook para o React' tocTitle: 'Introdução' description: 'Configuração do React Storybook no ambiente de desenvolvimento React' -commit: 'bf3514f' +commit: '2407c3c' --- O Storybook executa paralelamente à aplicação em desenvolvimento. diff --git a/content/intro-to-storybook/react/pt/screen.md b/content/intro-to-storybook/react/pt/screen.md index a60319243..eb1ba62df 100644 --- a/content/intro-to-storybook/react/pt/screen.md +++ b/content/intro-to-storybook/react/pt/screen.md @@ -2,7 +2,7 @@ title: 'Construção de um ecrã' tocTitle: 'Ecrãs' description: 'Construção de um ecrã a partir de componentes' -commit: '2275632' +commit: '6262d7f' --- Tem sido focada a construção de interfaces de utilizador da base para o topo. diff --git a/content/intro-to-storybook/react/pt/simple-component.md b/content/intro-to-storybook/react/pt/simple-component.md index cb08e5173..7be6110a6 100644 --- a/content/intro-to-storybook/react/pt/simple-component.md +++ b/content/intro-to-storybook/react/pt/simple-component.md @@ -2,7 +2,7 @@ title: 'Construção de um componente simples' tocTitle: 'Componente simples' description: 'Construção de um componente simples isolado' -commit: '9b36e1a' +commit: 'bc897c5' --- Iremos construir o interface de utilizador de acordo com a metodologia de [Desenvolvimento orientada a componentes](https://www.componentdriven.org/), ou nativamente por (CDD, Component-Driven Development). É um processo que cria interfaces de utilizador a partir da base para o topo, iniciando com componentes e terminando com ecrãs. O DOC (CDD nativamente) ajuda no escalonamento da complexidade á qual o programador é sujeito á medida que constrói o interface de utilizador. diff --git a/content/intro-to-storybook/react/zh-CN/composite-component.md b/content/intro-to-storybook/react/zh-CN/composite-component.md index cb28b97cb..e29ab340e 100644 --- a/content/intro-to-storybook/react/zh-CN/composite-component.md +++ b/content/intro-to-storybook/react/zh-CN/composite-component.md @@ -2,7 +2,7 @@ title: '组装复合组件' tocTitle: '合成组件' description: '使用更简单的组件 组装复合组件' -commit: '429780a' +commit: 'cfa25b6' --- 上一章节我们构建了第一个组件;本章节扩展学习如何构建一个 Tasks 列表,TaskList 组件。将组件组合在一起,看看当引入更多复杂性时会发生什么。 diff --git a/content/intro-to-storybook/react/zh-CN/data.md b/content/intro-to-storybook/react/zh-CN/data.md index e4cd4e002..7a0ab4e49 100644 --- a/content/intro-to-storybook/react/zh-CN/data.md +++ b/content/intro-to-storybook/react/zh-CN/data.md @@ -2,7 +2,7 @@ title: '连线数据' tocTitle: 'Data' description: '了解如何将数据连接到UI组件' -commit: 'c70ec15' +commit: 'f9eaeef' --- 到目前为止,我们创建了孤立的无状态组件 - Storybook 很棒,但作用不大,除非我们在应用程序中为他们提供一些数据. diff --git a/content/intro-to-storybook/react/zh-CN/deploy.md b/content/intro-to-storybook/react/zh-CN/deploy.md index c5b2bf985..057e9b0c0 100644 --- a/content/intro-to-storybook/react/zh-CN/deploy.md +++ b/content/intro-to-storybook/react/zh-CN/deploy.md @@ -2,7 +2,7 @@ title: '部署 Storybook' tocTitle: '部署' description: '学习如何在线部署 Storybook' -commit: '59da1ac' +commit: '4531813' --- 在本教程中,我们在开发机器上运行了 Storybook. 您可能还想与团队分享该 Storybook,尤其是非技术成员. 值得庆幸的是,在线部署 Storybook 很容易. diff --git a/content/intro-to-storybook/react/zh-CN/get-started.md b/content/intro-to-storybook/react/zh-CN/get-started.md index 928fdbdf3..03fc5eca3 100644 --- a/content/intro-to-storybook/react/zh-CN/get-started.md +++ b/content/intro-to-storybook/react/zh-CN/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook React 教程' tocTitle: '开始吧' description: '在你的开发环境下设置 Storybook' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook 是在开发模式下 与 您的应用程序一起运行的. 它可以帮助您构建 UI 组件,并与 应用程序的 业务逻辑和上下文 隔离开来. 本期"学习 Storybook"适用于 **React**; `Vue和Angular`版本即将推出. diff --git a/content/intro-to-storybook/react/zh-CN/screen.md b/content/intro-to-storybook/react/zh-CN/screen.md index 4cd983d8b..e3b50252a 100644 --- a/content/intro-to-storybook/react/zh-CN/screen.md +++ b/content/intro-to-storybook/react/zh-CN/screen.md @@ -2,7 +2,7 @@ title: '构建一个页面' tocTitle: '页面' description: '用组件构建一个页面' -commit: '2275632' +commit: '6262d7f' --- 我们专注于从下到上构建 UI; 从小做起并增加复杂性. 这样做使我们能够独立开发每个组件,找出其数据需求,并在 Storybook 中使用它. 所有这些都无需 启动服务器或构建出页面! diff --git a/content/intro-to-storybook/react/zh-CN/simple-component.md b/content/intro-to-storybook/react/zh-CN/simple-component.md index 9cc68d41c..ebadc64bb 100644 --- a/content/intro-to-storybook/react/zh-CN/simple-component.md +++ b/content/intro-to-storybook/react/zh-CN/simple-component.md @@ -2,7 +2,7 @@ title: '构建一个简单的组件' tocTitle: '简单 组件' description: '单独构建一个简单的组件' -commit: '9b36e1a' +commit: 'bc897c5' --- 我们将按照[组件驱动开发](https://www.componentdriven.org/) (CDD) 方法论来 构建我们的 UI。这是一个从“自下而上”开始构建 UI 的过程,从组件开始到整个页面结束。CDD 可帮助您在构建 UI 时,摆列您所面临的复杂程度。 diff --git a/content/intro-to-storybook/react/zh-CN/using-addons.md b/content/intro-to-storybook/react/zh-CN/using-addons.md index b21226237..f76048ead 100644 --- a/content/intro-to-storybook/react/zh-CN/using-addons.md +++ b/content/intro-to-storybook/react/zh-CN/using-addons.md @@ -2,7 +2,7 @@ title: '插件' tocTitle: '插件' description: '学习如何集成并使用热门的 Controls 插件' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook 有一个强大的生态系统 [addons](https://storybook.js.org/docs/react/configure/storybook-addons),你能够用来增强你的团队中每个人的开发体验。在 [这里](https://storybook.js.org/addons) 浏览全部。 diff --git a/content/intro-to-storybook/react/zh-TW/composite-component.md b/content/intro-to-storybook/react/zh-TW/composite-component.md index c53e42e15..67e995da1 100644 --- a/content/intro-to-storybook/react/zh-TW/composite-component.md +++ b/content/intro-to-storybook/react/zh-TW/composite-component.md @@ -2,7 +2,7 @@ title: '組裝複合元件' tocTitle: '複合元件' description: '從較為簡易的元件,組裝複合元件' -commit: '429780a' +commit: 'cfa25b6' --- 上個章節,我們打造出第 1 個元件,而在這章延伸已經學到的,做出 TaskList,也就是 1 組 Task。接著,開始動手把元件組裝起來,看看更複雜的時候會發生什麼事情。 diff --git a/content/intro-to-storybook/react/zh-TW/data.md b/content/intro-to-storybook/react/zh-TW/data.md index d3c0c93d6..4620a1711 100644 --- a/content/intro-to-storybook/react/zh-TW/data.md +++ b/content/intro-to-storybook/react/zh-TW/data.md @@ -2,7 +2,7 @@ title: '連結資料' tocTitle: '資料' description: '了解把資料連結到 UI 元件的方法' -commit: 'c70ec15' +commit: 'f9eaeef' --- 目前,我們已經做好沒有狀態的獨立元件:對 Storybook 來說很夠用。但到頭來,在 App 加入資料之前是沒什麼用處的。 diff --git a/content/intro-to-storybook/react/zh-TW/deploy.md b/content/intro-to-storybook/react/zh-TW/deploy.md index ea040eba8..10f36223f 100644 --- a/content/intro-to-storybook/react/zh-TW/deploy.md +++ b/content/intro-to-storybook/react/zh-TW/deploy.md @@ -2,7 +2,7 @@ title: '部署 Storybook' tocTitle: '部署' description: '學習把 Storybook 部署到線上的方法' -commit: '59da1ac' +commit: '4531813' --- 在這套教學的過程中,我們已經在本地端機器打造元件。有一些進展後,要把成果分享出去,藉以獲得回饋。接下來,要把 Storybook 部署到線上,協助隊友檢查 UI 的實作方法。 diff --git a/content/intro-to-storybook/react/zh-TW/get-started.md b/content/intro-to-storybook/react/zh-TW/get-started.md index 4fa955d6a..5243fbee4 100644 --- a/content/intro-to-storybook/react/zh-TW/get-started.md +++ b/content/intro-to-storybook/react/zh-TW/get-started.md @@ -2,7 +2,7 @@ title: 'Storybook 教學:React 篇' tocTitle: '開始' description: '在開發環境設定 Storybook' -commit: 'bf3514f' +commit: '2407c3c' --- Storybook 與 App 的開發模式一起運作,協助將 App 裡 UI 元件的商業邏輯和情境分開來。這裡是 Storybook 入門的 React 版本,其它還有 [React Native](/intro-to-storybook/react-native/en/get-started)、[Vue](/intro-to-storybook/vue/en/get-started)、[Angular](/intro-to-storybook/angular/en/get-started)、[Svelte](/intro-to-storybook/svelte/en/get-started) 和 [Ember](/intro-to-storybook/ember/en/get-started)。 diff --git a/content/intro-to-storybook/react/zh-TW/screen.md b/content/intro-to-storybook/react/zh-TW/screen.md index 19d304b4b..761d2e2c6 100644 --- a/content/intro-to-storybook/react/zh-TW/screen.md +++ b/content/intro-to-storybook/react/zh-TW/screen.md @@ -2,7 +2,7 @@ title: '建構頁面' tocTitle: '頁面' description: '以元件建構頁面' -commit: '2275632' +commit: '6262d7f' --- 先前專注在由下而上的方式打造 UI,小規模著手,再不斷增加複雜度。這樣能夠以互不干擾的方式開發元件、瞭解資料需求,然後在 Storybook 裡把玩。完全不必設立伺服器,或蓋出畫面! diff --git a/content/intro-to-storybook/react/zh-TW/simple-component.md b/content/intro-to-storybook/react/zh-TW/simple-component.md index a117ae815..64b9068e9 100644 --- a/content/intro-to-storybook/react/zh-TW/simple-component.md +++ b/content/intro-to-storybook/react/zh-TW/simple-component.md @@ -2,7 +2,7 @@ title: '打造簡易元件' tocTitle: '簡易元件' description: '打造獨立的簡易元件' -commit: '9b36e1a' +commit: 'bc897c5' --- 我們會按照[元件驅動開發](https://www.componentdriven.org/) (CDD) 方法論來打造 UI,是「由下而上」的流程。從元件開始,一路至各種畫面。CDD 在打造 UI 時,面臨不斷擴大的複雜程度很有幫助。 diff --git a/content/intro-to-storybook/react/zh-TW/using-addons.md b/content/intro-to-storybook/react/zh-TW/using-addons.md index 5395e21ee..757b10e2f 100644 --- a/content/intro-to-storybook/react/zh-TW/using-addons.md +++ b/content/intro-to-storybook/react/zh-TW/using-addons.md @@ -2,7 +2,7 @@ title: '外掛' tocTitle: '外掛' description: '了解整合、使用熱門功能:Control 外掛的方法' -commit: 'f89cfe0' +commit: '17d3ab9' --- Storybook 有精美的[外掛](https://storybook.js.org/docs/react/configure/storybook-addons)生態系,可以用來加強團隊裡的開發者體驗。[在這裡](https://storybook.js.org/addons)可以翻閱。