Skip to content

Commit 441cec8

Browse files
feat: rebrand conditional rendering and update titles (#44)
* feat: change conditional rendering to be pokemon themed * chore: update all stories * chore: update error boundary
1 parent 1968558 commit 441cec8

File tree

44 files changed

+149
-145
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+149
-145
lines changed

src/course/02- lessons/03-Gold/ErrorBoundary/exercise/exercise.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Final } from './exercise';
44

55
const meta: Meta<typeof Final> = {
6-
title: 'Lessons/🥇 Gold/Error Boundaries/02-Exercise',
6+
title: 'Lessons/🥇 Gold/🛡️ Error Boundaries Pattern/02-Exercise',
77
component: Final
88
};
99

src/course/02- lessons/03-Gold/ErrorBoundary/final/final.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Final } from './final';
44

55
const meta: Meta<typeof Final> = {
6-
title: 'Lessons/🥇 Gold/Error Boundaries/03-Final',
6+
title: 'Lessons/🥇 Gold/🛡️ Error Boundaries Pattern/03-Final',
77
component: Final
88
};
99

src/course/02- lessons/03-Gold/ErrorBoundary/lesson.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Meta } from '@storybook/blocks';
22

3-
<Meta title="Lessons/🥇 Gold/Error Boundaries/01-Lesson" />
3+
<Meta title="Lessons/🥇 Gold/🛡️ Error Boundaries Pattern/01-Lesson" />
44

5-
# Error Boundaries Pattern
5+
# 🛡️ Error Boundaries Pattern
66

77
React makes it easy to build interactive UIs, but what happens when something goes wrong during rendering? Without safeguards, an error in one part of the UI can crash the entire application.
88

src/course/02-lessons/01-Bronze/ConditionalRendering/exercise/exercise.stories.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import type { Meta, StoryObj } from '@storybook/react';
22

33
import { userEvent, within, expect } from '@storybook/test';
44

5-
import { ComponentOne } from './exercise';
5+
import { PokemonTrainerStatus } from './exercise';
66

7-
const meta: Meta<typeof ComponentOne> = {
7+
const meta: Meta<typeof PokemonTrainerStatus> = {
88
title:
9-
'Lessons/🥉 Bronze/Conditional Rendering Pattern/02-Exercise',
10-
component: ComponentOne
9+
'Lessons/🥉 Bronze/🔀 Conditional Rendering Pattern/02-Exercise',
10+
component: PokemonTrainerStatus
1111
};
1212

1313
export default meta;
14-
type Story = StoryObj<typeof ComponentOne>;
14+
type Story = StoryObj<typeof PokemonTrainerStatus>;
1515

16-
const username = 'John Doe';
16+
const trainerName = 'Ash';
1717

1818
/*
1919
* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas
@@ -24,28 +24,28 @@ export const Default: Story = {
2424
const canvas = within(canvasElement);
2525

2626
await userEvent.click(
27-
canvas.getByRole('button', { name: 'Login' })
27+
canvas.getByRole('button', { name: '🎯 Challenge Gym Leader' })
2828
);
2929

3030
await expect(
31-
canvas.getByText(`Welcome ${username}`)
31+
canvas.getByText(`Welcome Gym Leader ${trainerName}! 🏆`)
3232
).toBeInTheDocument();
3333
await expect(
34-
canvas.queryByRole('button', { name: 'Login' })
34+
canvas.queryByRole('button', { name: '🎯 Challenge Gym Leader' })
3535
).toBeNull();
3636

3737
await userEvent.click(
38-
canvas.getByRole('button', { name: 'Logout' })
38+
canvas.getByRole('button', { name: '🔄 Reset Journey' })
3939
);
4040

4141
await expect(
42-
canvas.queryByText(`Welcome ${username}`)
42+
canvas.queryByText(`Welcome Gym Leader ${trainerName}! 🏆`)
4343
).toBeNull();
4444
await expect(
45-
canvas.queryByRole('button', { name: 'Logout' })
45+
canvas.queryByRole('button', { name: '🔄 Reset Journey' })
4646
).toBeNull();
4747
},
4848
args: {
49-
username
49+
trainerName
5050
}
51-
};
51+
};
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import { Button } from '@shared/components/Button/Button.component';
22

3-
interface IComponentProps {
4-
username: string;
3+
interface ITrainerProps {
4+
trainerName: string;
55
}
66

77
// 1g - 💣 The ignore lint rules can be removed now
88
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
99
// @ts-expect-error
1010
// eslint-disable-next-line @typescript-eslint/no-unused-vars
11-
export const ComponentOne = (props: IComponentProps) => {
12-
// 1a - 👨🏻💻 add a useState that has false as default. Name the variable [isAuthenticated, setIsAuthenticated]
11+
export const PokemonTrainerStatus = (props: ITrainerProps) => {
12+
// 1a - 👨🏻💻 add a useState that has false as default. Name the variable [hasGymBadges, setHasGymBadges]
1313

14-
// 1b - 👨🏻💻 create me a onLogin function which setIsAuthenticated to be true
14+
// 1b - 👨🏻💻 create me a onEarnBadge function which setHasGymBadges to be true
1515

16-
// 1c - 👨🏻💻 create me a onLogout function which setIsAuthenticated to be false
16+
// 1c - 👨🏻💻 create me a onLoseBadges function which setHasGymBadges to be false
1717

18-
// 1d - 👨🏻💻 if authenticated, return a button called "Logout" with the onClick of onLogout
19-
// 1e - 👨🏻💻 if authenticated, return some text called "Welcome {props.username}"
18+
// 1d - 👨🏻💻 if hasGymBadges, return a button called "Reset Journey" with the onClick of onLoseBadges
19+
// 1e - 👨🏻💻 if hasGymBadges, return some text called "Welcome Gym Leader {props.trainerName}! 🏆"
2020

21-
// 1f - 👨🏻💻 add onClick function onLogin to the button
22-
return <Button>Login</Button>;
23-
};
21+
// 1f - 👨🏻💻 add onClick function onEarnBadge to the button
22+
return <Button>🎯 Challenge Gym Leader</Button>;
23+
};
Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import type { Meta, StoryObj } from '@storybook/react';
22

33
import { userEvent, within, expect } from '@storybook/test';
4-
import { ComponentOne } from './final';
54

6-
const meta: Meta<typeof ComponentOne> = {
7-
title: 'Lessons/🥉 Bronze/Conditional Rendering Pattern/03-Final',
8-
component: ComponentOne
5+
import { PokemonTrainerStatus } from './final';
6+
7+
const meta: Meta<typeof PokemonTrainerStatus> = {
8+
title:
9+
'Lessons/🥉 Bronze/🔀 Conditional Rendering Pattern/03-Final',
10+
component: PokemonTrainerStatus
911
};
1012

1113
export default meta;
12-
type Story = StoryObj<typeof ComponentOne>;
14+
type Story = StoryObj<typeof PokemonTrainerStatus>;
1315

14-
const username = 'John Doe';
16+
const trainerName = 'Ash';
1517

1618
/*
1719
* See https://storybook.js.org/docs/writing-stories/play-function#working-with-the-canvas
@@ -22,28 +24,22 @@ export const Default: Story = {
2224
const canvas = within(canvasElement);
2325

2426
await userEvent.click(
25-
canvas.getByRole('button', { name: 'Login' })
27+
canvas.getByRole('button', { name: '🎯 Challenge Gym Leader' })
2628
);
2729

2830
await expect(
29-
canvas.getByText(`Welcome ${username}`)
31+
canvas.getByText(`Welcome Gym Leader ${trainerName}! 🏆`)
3032
).toBeInTheDocument();
31-
await expect(
32-
canvas.queryByRole('button', { name: 'Login' })
33-
).toBeNull();
3433

3534
await userEvent.click(
36-
canvas.getByRole('button', { name: 'Logout' })
35+
canvas.getByRole('button', { name: '🔄 Reset Journey' })
3736
);
3837

3938
await expect(
40-
canvas.queryByText(`Welcome ${username}`)
41-
).toBeNull();
42-
await expect(
43-
canvas.queryByRole('button', { name: 'Logout' })
44-
).toBeNull();
39+
canvas.getByRole('button', { name: '🎯 Challenge Gym Leader' })
40+
).toBeInTheDocument();
4541
},
4642
args: {
47-
username
43+
trainerName
4844
}
49-
};
45+
};
Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
11
import { useState } from 'react';
22
import { Button } from '@shared/components/Button/Button.component';
33

4-
interface IComponentProps {
5-
username: string;
4+
interface ITrainerProps {
5+
trainerName: string;
66
}
77

8-
export const ComponentOne = (props: IComponentProps) => {
9-
const [isAuthenticated, setIsAuthenticated] = useState(false);
8+
export const PokemonTrainerStatus = (props: ITrainerProps) => {
9+
const [hasGymBadges, setHasGymBadges] = useState(false);
1010

11-
const onLogin = () => {
12-
setIsAuthenticated(true);
11+
const onEarnBadge = () => {
12+
setHasGymBadges(true);
1313
};
1414

15-
const onLogout = () => {
16-
setIsAuthenticated(false);
15+
const onLoseBadges = () => {
16+
setHasGymBadges(false);
1717
};
1818

1919
return (
20-
<header>
21-
{/* Other components */}
22-
{!isAuthenticated && <Button onClick={onLogin}>Login</Button>}
23-
{isAuthenticated && (
24-
<>
25-
<Button onClick={onLogout}>Logout</Button>
26-
<h1>Welcome {props.username}</h1>
27-
</>
20+
<div className="p-6 bg-blue-50 rounded-lg border-2 border-blue-200">
21+
{!hasGymBadges && (
22+
<div className="text-center">
23+
<h2 className="text-xl mb-4">🎒 Pokemon Trainer</h2>
24+
<p className="mb-4">Ready to challenge the Gym Leader?</p>
25+
<Button onClick={onEarnBadge}>🎯 Challenge Gym Leader</Button>
26+
</div>
2827
)}
29-
</header>
28+
{hasGymBadges && (
29+
<div className="text-center">
30+
<h1 className="text-2xl font-bold text-yellow-600 mb-2">
31+
Welcome Gym Leader {props.trainerName}! 🏆
32+
</h1>
33+
<p className="mb-4">🥇 You've earned your gym badges!</p>
34+
<Button onClick={onLoseBadges}>🔄 Reset Journey</Button>
35+
</div>
36+
)}
37+
</div>
3038
);
31-
};
39+
};

src/course/02-lessons/01-Bronze/ConditionalRendering/lesson.mdx

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,82 @@
11
import { Meta } from '@storybook/blocks';
22

3-
<Meta title="Lessons/🥉 Bronze/Conditional Rendering Pattern/01-Lesson" />
3+
<Meta title="Lessons/🥉 Bronze/🔀 Conditional Rendering Pattern/01-Lesson" />
44

5-
# Conditional Rendering Pattern
5+
# 🔀 Conditional Rendering Pattern
66

7-
The conditional rendering pattern is a way to dynamically change UI based what values are set at that time. The most common way that this is done is by using an if statement. For example:
7+
The conditional rendering pattern is a way to dynamically change UI based on what values are set at that time. The most common way that this is done is by using an if statement. For example:
88

99
```jsx
10-
const Component = (props) => {
11-
if (props.isAuthenticated) {
12-
return <h1>Welcome {props.username}!</h1>;
10+
const TrainerStatus = (props) => {
11+
if (props.hasGymBadges) {
12+
return <h1>Welcome Gym Leader {props.trainerName}!</h1>;
1313
} else {
14-
return <h1>Not logged in.</h1>;
14+
return <h1>Welcome Pokemon Trainer!</h1>;
1515
}
1616
};
1717
```
1818

1919
There are many syntactical ways you can do the same as above such as the ternary:
2020

2121
```jsx
22-
const Component = (props) => {
23-
return props.isAuthenticated ? (
24-
<h1>Welcome {props.username}!</h1>
22+
const TrainerStatus = (props) => {
23+
return props.hasGymBadges ? (
24+
<h1>Welcome Gym Leader {props.trainerName}!</h1>
2525
) : (
26-
<h1>Not logged in.</h1>
26+
<h1>Welcome Pokemon Trainer!</h1>
2727
);
2828
};
2929
```
3030

3131
Or you can use the AND syntax:
3232

3333
```jsx
34-
const Component = (props) => {
35-
return props.isAuthenticated && <h1>Welcome {props.username}!</h1>;
34+
const TrainerStatus = (props) => {
35+
return props.hasGymBadges && <h1>Welcome Gym Leader {props.trainerName}!</h1>;
3636
};
3737
```
3838

39-
If I had a lot of complexity in this component that still would be getting executed but the component will just return nothing if it's not authenticated. The best way to return something like this is to do the conditional render outside of the component, for example:
39+
If I had a lot of complexity in this component that still would be getting executed but the component will just return nothing if the trainer doesn't have badges. The best way to return something like this is to do the conditional render outside of the component, for example:
4040

4141
```jsx
42-
const ComponentOne = (props) => {
43-
return <h1>Welcome {props.username}</h1>;
42+
const GymLeaderWelcome = (props) => {
43+
return <h1>Welcome Gym Leader {props.trainerName}</h1>;
4444
};
4545

46-
const ComponentTwo = (props) => {
46+
const TrainerDashboard = (props) => {
4747
return (
4848
<header>
4949
{/* Other components */}
50-
{props.isAuthenticated && <ComponentOne username="JohnDoe" />}
50+
{props.hasGymBadges && <GymLeaderWelcome trainerName="Ash" />}
5151
</header>
5252
);
5353
};
5454
```
5555

5656
### Event driven rendering
5757

58-
There may be times when you need to conditionally render a component based on an event that has been changed. This example conditionally renders a box when you click the button.
58+
There may be times when you need to conditionally render a component based on an event that has been changed. This example conditionally renders a wild Pokemon encounter when you click the explore button.
5959

6060
```jsx
61-
const Component = () => {
62-
const [displayBox, setDisplayBox] = useState(false);
61+
const PokemonExplorer = () => {
62+
const [wildPokemonFound, setWildPokemonFound] = useState(false);
6363

64-
const showBox = () => {
65-
setDisplayBox(true);
64+
const startExploring = () => {
65+
setWildPokemonFound(true);
6666
};
6767

68-
const hideBox = () => {
69-
setDisplayBox(false);
68+
const stopExploring = () => {
69+
setWildPokemonFound(false);
7070
};
7171

7272
return (
7373
<>
74-
<button type="button" onClick={displayBox ? hideBox : showBox}>
75-
Toggle Box
74+
<button type="button" onClick={wildPokemonFound ? stopExploring : startExploring}>
75+
{wildPokemonFound ? 'Stop Exploring' : 'Explore Tall Grass'}
7676
</button>
77-
{displayBox && (
78-
<div>
79-
<p>Box</p>
77+
{wildPokemonFound && (
78+
<div className="wild-encounter">
79+
<p>🌿 A wild Pikachu appeared!</p>
8080
</div>
8181
)}
8282
</>
@@ -86,7 +86,7 @@ const Component = () => {
8686

8787
## Exercise
8888

89-
In the first exercise we are going to look into building a login and logout toggle which will render a username when they have logged in. Go to the exercise.tsx inside the ConditionalRendering folder and start the exercise. Once completed, the Tests will show as passed in the storybook "Interactions" addon section.
89+
In the first exercise we are going to look into building a Pokemon trainer status system that shows different content based on whether the trainer has earned gym badges. Go to the exercise.tsx inside the ConditionalRendering folder and start the exercise. Once completed, the Tests will show as passed in the storybook "Interactions" addon section.
9090

9191
## Feedback
9292

src/course/02-lessons/01-Bronze/Hooks/exercise/exercise.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Exercise } from './exercise';
44

55
const meta: Meta<typeof Exercise> = {
6-
title: 'Lessons/🥉 Bronze/Hooks Pattern/02-Exercise',
6+
title: 'Lessons/🥉 Bronze/🎣 Hooks Pattern/02-Exercise',
77
component: Exercise
88
};
99

src/course/02-lessons/01-Bronze/Hooks/final/final.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
33
import { Final } from './final';
44

55
const meta: Meta<typeof Final> = {
6-
title: 'Lessons/🥉 Bronze/Hooks Pattern/03-Final',
6+
title: 'Lessons/🥉 Bronze/🎣 Hooks Pattern/03-Final',
77
component: Final
88
};
99

0 commit comments

Comments
 (0)